@series-inc/stowkit-phaser-loader 0.1.24 → 0.1.25
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.
- package/dist/StowKitPhaserPack.d.ts +8 -0
- package/dist/StowKitPhaserPack.d.ts.map +1 -1
- package/dist/stowkit-phaser-loader.esm.js +34 -32
- package/dist/stowkit-phaser-loader.esm.js.map +1 -1
- package/dist/stowkit-phaser-loader.js +34 -32
- package/dist/stowkit-phaser-loader.js.map +1 -1
- package/package.json +1 -1
- package/skill.md +199 -58
|
@@ -15,7 +15,15 @@ export declare class StowKitPhaserPack {
|
|
|
15
15
|
private tempGl;
|
|
16
16
|
private textureCache;
|
|
17
17
|
private transcodedDataCache;
|
|
18
|
+
private blendModePatched;
|
|
18
19
|
constructor(reader: StowKitReader, transcoder: BasisTranscoder, gl: WebGLRenderingContext | WebGL2RenderingContext);
|
|
20
|
+
/**
|
|
21
|
+
* Patch Phaser's NORMAL blend mode (index 0) to use straight alpha.
|
|
22
|
+
* Phaser defaults to gl.ONE, gl.ONE_MINUS_SRC_ALPHA (premultiplied),
|
|
23
|
+
* but compressed textures always have straight alpha since
|
|
24
|
+
* UNPACK_PREMULTIPLY_ALPHA_WEBGL is ignored for compressed uploads.
|
|
25
|
+
*/
|
|
26
|
+
private ensureBlendMode;
|
|
19
27
|
/**
|
|
20
28
|
* Load a texture by its canonical path/name
|
|
21
29
|
* Returns a Phaser texture
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StowKitPhaserPack.d.ts","sourceRoot":"","sources":["../src/StowKitPhaserPack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAyB,MAAM,4BAA4B,CAAC;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,qBAAa,iBAAiB;IACnB,MAAM,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,MAAM,CAAiD;IAC/D,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,mBAAmB,CAA6I;
|
|
1
|
+
{"version":3,"file":"StowKitPhaserPack.d.ts","sourceRoot":"","sources":["../src/StowKitPhaserPack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAyB,MAAM,4BAA4B,CAAC;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,qBAAa,iBAAiB;IACnB,MAAM,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,MAAM,CAAiD;IAC/D,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,mBAAmB,CAA6I;IAExK,OAAO,CAAC,gBAAgB,CAAS;gBAG7B,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,eAAe,EAC3B,EAAE,EAAE,qBAAqB,GAAG,sBAAsB;IAOtD;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAcvB;;;OAGG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IA2E9D;;;OAGG;IACG,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IA4C/D;;OAEG;YACW,oBAAoB;IAmElC;;OAEG;YACW,gCAAgC;IAiD9C;;;OAGG;IACG,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAgBrF;;OAEG;IACG,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAgBxF;;OAEG;IACG,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoBlE;;;;OAIG;IACG,eAAe,CACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,GAAG,EACV,OAAO,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;QAAE,OAAO,EAAE,GAAG,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAsElD;;OAEG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM;IAMxC;;OAEG;IACH,UAAU;IAIV;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM;IAI1B;;OAEG;IACH,kBAAkB,CAAC,KAAK,EAAE,MAAM;IAIhC;;OAEG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM;IAI9B;;OAEG;IACH,OAAO,IAAI,IAAI;CAQlB"}
|
|
@@ -239,10 +239,31 @@ class StowKitPhaserPack {
|
|
|
239
239
|
constructor(reader, transcoder, gl) {
|
|
240
240
|
this.textureCache = new Map();
|
|
241
241
|
this.transcodedDataCache = new Map();
|
|
242
|
+
this.blendModePatched = false;
|
|
242
243
|
this.reader = reader;
|
|
243
244
|
this.transcoder = transcoder;
|
|
244
245
|
this.tempGl = gl;
|
|
245
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Patch Phaser's NORMAL blend mode (index 0) to use straight alpha.
|
|
249
|
+
* Phaser defaults to gl.ONE, gl.ONE_MINUS_SRC_ALPHA (premultiplied),
|
|
250
|
+
* but compressed textures always have straight alpha since
|
|
251
|
+
* UNPACK_PREMULTIPLY_ALPHA_WEBGL is ignored for compressed uploads.
|
|
252
|
+
*/
|
|
253
|
+
ensureBlendMode(scene) {
|
|
254
|
+
if (this.blendModePatched)
|
|
255
|
+
return;
|
|
256
|
+
const renderer = scene.sys.game.renderer;
|
|
257
|
+
const gl = renderer.gl;
|
|
258
|
+
renderer.blendModes[0] = {
|
|
259
|
+
func: [gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA],
|
|
260
|
+
equation: gl.FUNC_ADD,
|
|
261
|
+
};
|
|
262
|
+
// Force Phaser to re-apply the blend state — it skips if it thinks
|
|
263
|
+
// the current mode hasn't changed, so we pass force=true.
|
|
264
|
+
renderer.setBlendMode(0, true);
|
|
265
|
+
this.blendModePatched = true;
|
|
266
|
+
}
|
|
246
267
|
/**
|
|
247
268
|
* Load a texture by its canonical path/name
|
|
248
269
|
* Returns a Phaser texture
|
|
@@ -290,10 +311,13 @@ class StowKitPhaserPack {
|
|
|
290
311
|
format: transcoded.internalFormat
|
|
291
312
|
};
|
|
292
313
|
const phaserTexture = scene.textures.addCompressedTexture(key, compressedTextureData);
|
|
314
|
+
// Register straight-alpha blend mode for compressed textures
|
|
315
|
+
this.ensureBlendMode(scene);
|
|
316
|
+
const source = phaserTexture?.source?.[0];
|
|
293
317
|
// Apply nearest filtering if metadata specifies it
|
|
294
318
|
const metadata = this.reader.parseTextureMetadata(assetIndex);
|
|
295
319
|
if (metadata?.filtering === 1) {
|
|
296
|
-
const glTexture =
|
|
320
|
+
const glTexture = source?.glTexture;
|
|
297
321
|
if (glTexture) {
|
|
298
322
|
gl.bindTexture(gl.TEXTURE_2D, glTexture);
|
|
299
323
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
@@ -505,47 +529,25 @@ class StowKitPhaserPack {
|
|
|
505
529
|
// Calculate frame dimensions
|
|
506
530
|
const frameWidth = Math.floor(texWidth / meta.columns);
|
|
507
531
|
const frameHeight = Math.floor(texHeight / meta.rows);
|
|
508
|
-
// Add frames directly to the
|
|
509
|
-
// We cannot use addSpriteSheet
|
|
510
|
-
//
|
|
511
|
-
const
|
|
512
|
-
if (!
|
|
513
|
-
// Re-register the same GL source under the spritesheet key
|
|
514
|
-
// so Phaser can look up frames by ssKey
|
|
515
|
-
const ssTexture = scene.textures.addCompressedTexture(ssKey, {
|
|
516
|
-
mipmaps: [],
|
|
517
|
-
width: texWidth,
|
|
518
|
-
height: texHeight,
|
|
519
|
-
internalFormat: source.compressionAlgorithm,
|
|
520
|
-
compressed: true,
|
|
521
|
-
generateMipmap: false,
|
|
522
|
-
format: source.compressionAlgorithm,
|
|
523
|
-
});
|
|
524
|
-
// Share the GL texture from the already-loaded base texture
|
|
525
|
-
if (ssTexture?.source?.[0]) {
|
|
526
|
-
const ssSource = ssTexture.source[0];
|
|
527
|
-
ssSource.glTexture = source.glTexture;
|
|
528
|
-
ssSource.width = texWidth;
|
|
529
|
-
ssSource.height = texHeight;
|
|
530
|
-
ssSource.isCompressedTexture = true;
|
|
531
|
-
}
|
|
532
|
-
// Add individual frames for each cell in the grid
|
|
532
|
+
// Add numbered frames directly to the already-loaded compressed texture.
|
|
533
|
+
// We cannot use addSpriteSheet — it calls texImage2D which fails for
|
|
534
|
+
// compressed GL textures. Instead, add frames to the existing texture.
|
|
535
|
+
const hasFrames = phaserTexture.has(0);
|
|
536
|
+
if (!hasFrames) {
|
|
533
537
|
let frame = 0;
|
|
534
538
|
for (let row = 0; row < meta.rows && frame < meta.frameCount; row++) {
|
|
535
539
|
for (let col = 0; col < meta.columns && frame < meta.frameCount; col++) {
|
|
536
|
-
|
|
537
|
-
0, // source index
|
|
538
|
-
col * frameWidth, row * frameHeight, frameWidth, frameHeight);
|
|
540
|
+
phaserTexture.add(frame, 0, col * frameWidth, row * frameHeight, frameWidth, frameHeight);
|
|
539
541
|
frame++;
|
|
540
542
|
}
|
|
541
543
|
}
|
|
542
544
|
}
|
|
543
|
-
// Create animation
|
|
545
|
+
// Create animation using the base texture key
|
|
544
546
|
const animationKey = animKey ?? `${assetPath}_anim`;
|
|
545
547
|
if (!scene.anims.exists(animationKey)) {
|
|
546
548
|
scene.anims.create({
|
|
547
549
|
key: animationKey,
|
|
548
|
-
frames: scene.anims.generateFrameNumbers(
|
|
550
|
+
frames: scene.anims.generateFrameNumbers(textureKey, {
|
|
549
551
|
start: 0,
|
|
550
552
|
end: meta.frameCount - 1,
|
|
551
553
|
}),
|
|
@@ -553,7 +555,7 @@ class StowKitPhaserPack {
|
|
|
553
555
|
repeat: -1,
|
|
554
556
|
});
|
|
555
557
|
}
|
|
556
|
-
return { texture: phaserTexture, animationKey };
|
|
558
|
+
return { texture: phaserTexture, textureKey, animationKey };
|
|
557
559
|
}
|
|
558
560
|
/**
|
|
559
561
|
* Get spritesheet metadata by asset path
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stowkit-phaser-loader.esm.js","sources":["../src/BasisTranscoder.ts","../src/StowKitPhaserPack.ts","../src/StowKitPhaserLoader.ts"],"sourcesContent":["/**\n * BasisTranscoder - Manually decode KTX2 textures to WebGL textures\n * Used for Phaser which doesn't have built-in KTX2 support\n */\n\ninterface BasisModule {\n initializeBasis: () => void;\n BasisFile: new (data: Uint8Array) => BasisFile;\n KTX2File: new (data: Uint8Array) => KTX2File;\n}\n\ninterface BasisFile {\n getNumImages(): number;\n getNumLevels(imageIndex: number): number;\n getImageWidth(imageIndex: number, level: number): number;\n getImageHeight(imageIndex: number, level: number): number;\n startTranscoding(): boolean;\n getImageTranscodedSizeInBytes(imageIndex: number, level: number, format: number): number;\n transcodeImage(\n dst: Uint8Array,\n imageIndex: number,\n level: number,\n format: number,\n unused: number,\n getAlphaForOpaqueFormats: number\n ): number;\n close(): void;\n delete(): void;\n}\n\ninterface KTX2File {\n isValid(): boolean;\n isUASTC(): boolean;\n isETC1S(): boolean;\n isHDR(): boolean;\n getWidth(): number;\n getHeight(): number;\n getLayers(): number;\n getLevels(): number;\n getFaces(): number;\n getHasAlpha(): boolean;\n getDFDFlags(): number;\n startTranscoding(): boolean;\n getImageLevelInfo(mip: number, layer: number, face: number): any;\n getImageTranscodedSizeInBytes(mip: number, layer: number, face: number, format: number): number;\n transcodeImage(\n dst: Uint8Array,\n mip: number,\n layer: number,\n face: number,\n format: number,\n unused1: number,\n unused2: number,\n unused3: number\n ): number;\n close(): void;\n delete(): void;\n}\n\n// Basis transcoder formats (from Three.js KTX2Loader.TranscoderFormat)\nconst BASIS_FORMAT = {\n ETC1: 0,\n ETC2: 1,\n BC1: 2, // DXT1\n BC3: 3, // DXT5\n BC4: 4,\n BC5: 5,\n BC7_M6_OPAQUE_ONLY: 6,\n BC7_M5: 7, // BC7\n PVRTC1_4_RGB: 8,\n PVRTC1_4_RGBA: 9,\n ASTC_4x4: 10,\n ATC_RGB: 11,\n ATC_RGBA: 12,\n RGBA32: 13,\n RGB565: 14,\n BGR565: 15,\n RGBA4444: 16,\n BC6H: 22,\n RGB_HALF: 24,\n RGBA_HALF: 25,\n};\n\nexport interface TranscodedTexture {\n data: Uint8Array;\n width: number;\n height: number;\n format: number;\n internalFormat?: number;\n compressed: boolean;\n}\n\nexport class BasisTranscoder {\n private module: BasisModule | null = null;\n private initialized = false;\n private initPromise: Promise<void> | null = null;\n private basisPath: string;\n\n constructor(basisPath: string = '/basis/') {\n this.basisPath = basisPath;\n }\n\n /**\n * Initialize the Basis Universal transcoder\n */\n async init(): Promise<void> {\n if (this.initialized) return;\n if (this.initPromise) return this.initPromise;\n\n this.initPromise = (async () => {\n try {\n // Load the basis transcoder\n const scriptPath = `${this.basisPath}basis_transcoder.js`;\n \n // Import the basis module\n const BasisModule = await this.loadBasisModule(scriptPath);\n \n // Initialize\n BasisModule.initializeBasis();\n this.module = BasisModule;\n this.initialized = true;\n } catch (error) {\n console.error('[BasisTranscoder] Failed to initialize:', error);\n throw error;\n }\n })();\n\n return this.initPromise;\n }\n\n /**\n * Load the basis transcoder module\n */\n private async loadBasisModule(scriptPath: string): Promise<BasisModule> {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = scriptPath;\n script.async = true;\n \n script.onload = () => {\n // The basis transcoder exposes a global BASIS function\n if (typeof (window as any).BASIS === 'function') {\n (window as any).BASIS().then((module: BasisModule) => {\n resolve(module);\n }).catch(reject);\n } else {\n reject(new Error('BASIS module not found'));\n }\n };\n \n script.onerror = () => {\n reject(new Error(`Failed to load ${scriptPath}`));\n };\n \n document.head.appendChild(script);\n });\n }\n\n /**\n * Transcode KTX2 data to a WebGL-compatible format\n */\n async transcodeKTX2(data: Uint8Array, gl: WebGLRenderingContext | WebGL2RenderingContext): Promise<TranscodedTexture> {\n if (!this.initialized) {\n await this.init();\n }\n\n if (!this.module) {\n throw new Error('Basis module not initialized');\n }\n\n // Create KTX2File from data\n const ktx2File = new this.module.KTX2File(data);\n \n try {\n // Validate file\n if (!ktx2File.isValid()) {\n throw new Error('Invalid or unsupported KTX2 file');\n }\n\n // Get image dimensions\n const width = ktx2File.getWidth();\n const height = ktx2File.getHeight();\n \n // Check if the texture has alpha\n const hasAlpha = ktx2File.getHasAlpha();\n \n // Check format type (UASTC or ETC1S)\n const isUASTC = ktx2File.isUASTC();\n const isETC1S = ktx2File.isETC1S();\n\n // Start transcoding\n if (!ktx2File.startTranscoding()) {\n throw new Error('Failed to start KTX2 transcoding');\n }\n\n // Use first mip level, first layer, first face\n const mip = 0;\n const layer = 0;\n const face = 0;\n\n // Detect best format for this device and file type\n const targetFormat = this.detectBestFormat(gl, hasAlpha, isETC1S);\n \n // Get transcoded size\n const transcodedSize = ktx2File.getImageTranscodedSizeInBytes(\n mip,\n layer,\n face,\n targetFormat.basisFormat\n );\n\n // Allocate output buffer\n const transcodedData = new Uint8Array(transcodedSize);\n\n // Transcode (parameters: dst, mip, layer, face, format, unused1, unused2, unused3)\n const result = ktx2File.transcodeImage(\n transcodedData,\n mip,\n layer,\n face,\n targetFormat.basisFormat,\n 0,\n -1,\n -1\n );\n\n if (result === 0) {\n throw new Error('KTX2 transcoding failed');\n }\n\n return {\n data: transcodedData,\n width,\n height,\n format: targetFormat.glFormat,\n internalFormat: targetFormat.glInternalFormat,\n compressed: targetFormat.compressed\n };\n\n } finally {\n ktx2File.close();\n ktx2File.delete();\n }\n }\n\n /**\n * Detect the best compression format supported by the device\n */\n private detectBestFormat(gl: WebGLRenderingContext | WebGL2RenderingContext, hasAlpha: boolean = true, isETC1S: boolean = false): {\n basisFormat: number;\n glFormat: number;\n glInternalFormat: number;\n compressed: boolean;\n } {\n const isWebGL2 = gl instanceof WebGL2RenderingContext;\n\n // Check for extensions\n const s3tc = gl.getExtension('WEBGL_compressed_texture_s3tc') || \n gl.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc');\n const bptc = gl.getExtension('EXT_texture_compression_bptc');\n const etc1 = gl.getExtension('WEBGL_compressed_texture_etc1');\n const etc = gl.getExtension('WEBGL_compressed_texture_etc');\n const astc = gl.getExtension('WEBGL_compressed_texture_astc');\n const pvrtc = gl.getExtension('WEBGL_compressed_texture_pvrtc') ||\n gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc');\n\n // For ETC1S: Use BC1 (no alpha support in ETC1S)\n // For UASTC with alpha: Use BC3/BC7\n // For UASTC without alpha: Use BC1\n \n // BC7 on desktop with WebGL2 (requires separate BPTC extension)\n if (isWebGL2 && bptc && hasAlpha) {\n return {\n basisFormat: BASIS_FORMAT.BC7_M5,\n glFormat: gl.RGBA,\n glInternalFormat: (bptc as any).COMPRESSED_RGBA_BPTC_UNORM_EXT,\n compressed: true\n };\n }\n\n // BC3 (DXT5) on desktop - for textures with alpha\n // Basis handles ETC1S alpha via a separate slice transcoded into BC3's alpha block\n if (s3tc && hasAlpha) {\n return {\n basisFormat: BASIS_FORMAT.BC3,\n glFormat: gl.RGBA,\n glInternalFormat: (s3tc as any).COMPRESSED_RGBA_S3TC_DXT5_EXT,\n compressed: true\n };\n }\n\n // BC1 (DXT1) on desktop - for textures without alpha\n if (s3tc) {\n return {\n basisFormat: BASIS_FORMAT.BC1,\n glFormat: gl.RGB,\n glInternalFormat: (s3tc as any).COMPRESSED_RGB_S3TC_DXT1_EXT,\n compressed: true\n };\n }\n\n // ASTC on mobile (best quality)\n if (astc) {\n return {\n basisFormat: BASIS_FORMAT.ASTC_4x4,\n glFormat: gl.RGBA,\n glInternalFormat: (astc as any).COMPRESSED_RGBA_ASTC_4x4_KHR,\n compressed: true\n };\n }\n\n // ETC2 on mobile with WebGL2\n if (isWebGL2 && etc) {\n return {\n basisFormat: BASIS_FORMAT.ETC2,\n glFormat: gl.RGBA,\n glInternalFormat: (etc as any).COMPRESSED_RGBA8_ETC2_EAC || 0x9278,\n compressed: true\n };\n }\n\n // ETC1 on mobile\n if (etc1 || etc) {\n return {\n basisFormat: BASIS_FORMAT.ETC1,\n glFormat: gl.RGB,\n glInternalFormat: (etc1 as any)?.COMPRESSED_RGB_ETC1_WEBGL || 0x8D64,\n compressed: true\n };\n }\n\n // PVRTC on iOS (last resort for compressed)\n if (pvrtc) {\n return {\n basisFormat: hasAlpha ? BASIS_FORMAT.PVRTC1_4_RGBA : BASIS_FORMAT.PVRTC1_4_RGB,\n glFormat: gl.RGBA,\n glInternalFormat: (pvrtc as any).COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,\n compressed: true\n };\n }\n\n // Fallback to uncompressed RGBA\n return {\n basisFormat: BASIS_FORMAT.RGBA32,\n glFormat: gl.RGBA,\n glInternalFormat: gl.RGBA,\n compressed: false\n };\n }\n\n /**\n * Dispose resources\n */\n dispose(): void {\n this.module = null;\n this.initialized = false;\n this.initPromise = null;\n }\n}\n\n","import { StowKitReader, AssetType, PerfLogger } from '@series-inc/stowkit-reader';\nimport { BasisTranscoder } from './BasisTranscoder';\n\nexport interface TextureData {\n texture: WebGLTexture;\n width: number;\n height: number;\n}\n\n/**\n * Represents an opened StowKit pack for Phaser\n * Supports loading images and audio only (no 3D models)\n */\nexport class StowKitPhaserPack {\n public reader: StowKitReader;\n private transcoder: BasisTranscoder;\n private tempGl: WebGLRenderingContext | WebGL2RenderingContext;\n private textureCache: Map<string, any> = new Map();\n private transcodedDataCache: Map<number, { data: Uint8Array, width: number, height: number, compressed: boolean, format: number, internalFormat?: number }> = new Map();\n\n constructor(\n reader: StowKitReader,\n transcoder: BasisTranscoder,\n gl: WebGLRenderingContext | WebGL2RenderingContext\n ) {\n this.reader = reader;\n this.transcoder = transcoder;\n this.tempGl = gl;\n }\n\n /**\n * Load a texture by its canonical path/name\n * Returns a Phaser texture\n */\n async loadTexture(assetPath: string, scene: any): Promise<any> {\n const totalStart = performance.now();\n \n // Check cache first\n if (this.textureCache.has(assetPath)) {\n PerfLogger.log(`[Perf] Texture cache hit: ${assetPath}`);\n return this.textureCache.get(assetPath)!;\n }\n\n // Find asset by path\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) {\n throw new Error(`Texture not found: ${assetPath}`);\n }\n\n // Verify it's a texture\n const info = this.reader.getAssetInfo(assetIndex);\n if (!info || info.type !== AssetType.TEXTURE_2D) {\n throw new Error(`Asset is not a texture: ${assetPath}`);\n }\n\n // Use the same logic as getPhaserTexture but with custom key\n const key = assetPath;\n const gl = scene.sys.game.renderer.gl;\n \n // Read and transcode\n const data = this.reader.readAssetData(assetIndex);\n if (!data) {\n throw new Error(`Failed to read texture data for ${assetPath}`);\n }\n\n const transcodeStart = performance.now();\n const transcoded = await this.transcoder.transcodeKTX2(data, gl);\n PerfLogger.log(`[Perf] Phaser Basis transcode: ${(performance.now() - transcodeStart).toFixed(2)}ms (${transcoded.width}x${transcoded.height})`);\n \n // Format like Phaser's KTX parser\n const compressedTextureData = {\n mipmaps: [{\n data: transcoded.data,\n width: transcoded.width,\n height: transcoded.height\n }],\n width: transcoded.width,\n height: transcoded.height,\n internalFormat: transcoded.internalFormat,\n compressed: transcoded.compressed,\n generateMipmap: false,\n format: transcoded.internalFormat\n };\n \n const phaserTexture = scene.textures.addCompressedTexture(key, compressedTextureData);\n\n // Apply nearest filtering if metadata specifies it\n const metadata = this.reader.parseTextureMetadata(assetIndex);\n if (metadata?.filtering === 1) {\n const glTexture = phaserTexture?.source?.[0]?.glTexture;\n if (glTexture) {\n gl.bindTexture(gl.TEXTURE_2D, glTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n gl.bindTexture(gl.TEXTURE_2D, null);\n }\n }\n\n this.textureCache.set(assetPath, phaserTexture);\n\n PerfLogger.log(`[Perf] ===== Total Phaser texture load: ${(performance.now() - totalStart).toFixed(2)}ms =====`);\n return phaserTexture;\n }\n\n /**\n * Get a Phaser texture by index (for previews/demos)\n * Creates compressed texture directly in Phaser's GL context\n */\n async getPhaserTexture(index: number, scene: any): Promise<any> {\n const key = `texture_${index}`;\n \n // Check if already exists in Phaser's texture manager\n if (scene.textures.exists(key)) {\n return scene.textures.get(key);\n }\n \n // Get Phaser's GL context\n const gl = scene.sys.game.renderer.gl;\n \n // Read and transcode the KTX2 data\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read texture data for index ${index}`);\n }\n\n // Transcode to compressed format (don't create the WebGL texture yet - let Phaser do it)\n const transcoded = await this.transcoder.transcodeKTX2(data, gl);\n \n // Format the data exactly like Phaser's KTX parser output\n const compressedTextureData = {\n mipmaps: [{\n data: transcoded.data,\n width: transcoded.width,\n height: transcoded.height\n }],\n width: transcoded.width,\n height: transcoded.height,\n internalFormat: transcoded.internalFormat,\n compressed: transcoded.compressed,\n generateMipmap: false,\n format: transcoded.internalFormat // Phaser uses this for compressionAlgorithm\n };\n \n // Add to Phaser's texture manager as a compressed texture\n const phaserTexture = scene.textures.addCompressedTexture(key, compressedTextureData);\n \n // Cache it\n this.textureCache.set(key, phaserTexture);\n \n return phaserTexture;\n }\n \n /**\n * Load texture by index into a specific GL context\n */\n private async loadTextureInContext(index: number, gl: WebGLRenderingContext | WebGL2RenderingContext): Promise<TextureData> {\n // Read texture data\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read texture data for index ${index}`);\n }\n\n // Get metadata - all textures in .stow files are KTX2 format\n const metadata = this.reader.parseTextureMetadata(index);\n const isKtx2 = metadata?.channelFormat !== undefined;\n\n if (isKtx2) {\n // Transcode KTX2 to WebGL texture using the provided context\n const transcoded = await this.transcoder.transcodeKTX2(data, gl);\n \n // Create WebGL texture in the provided context\n const texture = gl.createTexture();\n if (!texture) {\n throw new Error('Failed to create WebGL texture');\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n\n if (transcoded.compressed) {\n gl.compressedTexImage2D(\n gl.TEXTURE_2D,\n 0,\n transcoded.internalFormat!,\n transcoded.width,\n transcoded.height,\n 0,\n transcoded.data\n );\n } else {\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n transcoded.internalFormat!,\n transcoded.width,\n transcoded.height,\n 0,\n transcoded.format,\n gl.UNSIGNED_BYTE,\n transcoded.data\n );\n }\n\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n // Apply nearest filtering if metadata specifies it (filtering === 1)\n const useNearest = metadata?.filtering === 1;\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useNearest ? gl.NEAREST : gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, useNearest ? gl.NEAREST : gl.LINEAR);\n\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n return {\n texture,\n width: transcoded.width,\n height: transcoded.height\n };\n } else {\n // Handle uncompressed image data\n return await this.loadUncompressedTextureInContext(data, gl);\n }\n }\n\n /**\n * Load uncompressed image (PNG, JPEG) as WebGL texture in a specific context\n */\n private async loadUncompressedTextureInContext(data: Uint8Array, gl: WebGLRenderingContext | WebGL2RenderingContext): Promise<TextureData> {\n return new Promise((resolve, reject) => {\n const blob = new Blob([data.buffer as ArrayBuffer]);\n const url = URL.createObjectURL(blob);\n \n const img = new Image();\n img.onload = () => {\n const texture = gl.createTexture();\n if (!texture) {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to create WebGL texture'));\n return;\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n img\n );\n\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n URL.revokeObjectURL(url);\n\n resolve({\n texture,\n width: img.width,\n height: img.height\n });\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to load image'));\n };\n\n img.src = url;\n });\n }\n\n /**\n * Load audio by its canonical path/name\n * Returns an AudioBuffer\n */\n async loadAudio(assetPath: string, audioContext?: AudioContext): Promise<AudioBuffer> {\n // Find asset by path\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) {\n throw new Error(`Audio not found: ${assetPath}`);\n }\n\n // Verify it's audio\n const info = this.reader.getAssetInfo(assetIndex);\n if (!info || info.type !== AssetType.AUDIO) {\n throw new Error(`Asset is not audio: ${assetPath}`);\n }\n\n return await this.loadAudioByIndex(assetIndex, audioContext);\n }\n\n /**\n * Load audio by index\n */\n async loadAudioByIndex(index: number, audioContext?: AudioContext): Promise<AudioBuffer> {\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read audio data for index ${index}`);\n }\n\n // Use provided context or create a new one\n const ctx = audioContext || new AudioContext();\n\n // Decode audio data\n const arrayBuffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength) as ArrayBuffer;\n const audioBuffer = await ctx.decodeAudioData(arrayBuffer);\n\n return audioBuffer;\n }\n\n /**\n * Create an HTML audio element for preview\n */\n async createAudioPreview(index: number): Promise<HTMLAudioElement> {\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read audio for index ${index}`);\n }\n\n const blob = new Blob([data.buffer as ArrayBuffer], { type: 'audio/mp4' });\n const url = URL.createObjectURL(blob);\n\n const audio = document.createElement('audio');\n audio.controls = true;\n audio.src = url;\n\n audio.addEventListener('ended', () => URL.revokeObjectURL(url));\n audio.addEventListener('error', () => URL.revokeObjectURL(url));\n\n return audio;\n }\n\n\n /**\n * Load a spritesheet by its canonical path.\n * Loads the referenced texture, registers it as a Phaser spritesheet\n * with correct frame dimensions, and creates an animation.\n */\n async loadSpriteSheet(\n assetPath: string,\n scene: any,\n animKey?: string,\n ): Promise<{ texture: any; animationKey: string }> {\n // Find the spritesheet asset\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) {\n throw new Error(`SpriteSheet not found: ${assetPath}`);\n }\n\n const info = this.reader.getAssetInfo(assetIndex);\n if (!info || info.type !== 8) {\n throw new Error(`Asset is not a spritesheet: ${assetPath}`);\n }\n\n // Parse spritesheet metadata (method added in reader, cast for compat)\n const meta = (this.reader as any).parseSpriteSheetMetadata(assetIndex);\n if (!meta || !meta.textureId) {\n throw new Error(`SpriteSheet \"${assetPath}\" has no texture reference`);\n }\n\n // Load the referenced texture first\n const textureKey = meta.textureId;\n await this.loadTexture(textureKey, scene);\n\n // Get texture dimensions from Phaser\n const phaserTexture = scene.textures.get(textureKey);\n const source = phaserTexture.source[0];\n const texWidth = source.width;\n const texHeight = source.height;\n\n // Calculate frame dimensions\n const frameWidth = Math.floor(texWidth / meta.columns);\n const frameHeight = Math.floor(texHeight / meta.rows);\n\n // Add frames directly to the existing compressed texture.\n // We cannot use addSpriteSheet because it tries to create a new\n // texture from an image source, which fails for compressed GL textures.\n const ssKey = assetPath;\n if (!scene.textures.exists(ssKey)) {\n // Re-register the same GL source under the spritesheet key\n // so Phaser can look up frames by ssKey\n const ssTexture = scene.textures.addCompressedTexture(ssKey, {\n mipmaps: [],\n width: texWidth,\n height: texHeight,\n internalFormat: source.compressionAlgorithm,\n compressed: true,\n generateMipmap: false,\n format: source.compressionAlgorithm,\n });\n\n // Share the GL texture from the already-loaded base texture\n if (ssTexture?.source?.[0]) {\n const ssSource = ssTexture.source[0];\n ssSource.glTexture = source.glTexture;\n ssSource.width = texWidth;\n ssSource.height = texHeight;\n ssSource.isCompressedTexture = true;\n }\n\n // Add individual frames for each cell in the grid\n let frame = 0;\n for (let row = 0; row < meta.rows && frame < meta.frameCount; row++) {\n for (let col = 0; col < meta.columns && frame < meta.frameCount; col++) {\n ssTexture.add(\n frame, // frame name/index\n 0, // source index\n col * frameWidth,\n row * frameHeight,\n frameWidth,\n frameHeight,\n );\n frame++;\n }\n }\n }\n\n // Create animation\n const animationKey = animKey ?? `${assetPath}_anim`;\n if (!scene.anims.exists(animationKey)) {\n scene.anims.create({\n key: animationKey,\n frames: scene.anims.generateFrameNumbers(ssKey, {\n start: 0,\n end: meta.frameCount - 1,\n }),\n frameRate: meta.frameRate,\n repeat: -1,\n });\n }\n\n return { texture: phaserTexture, animationKey };\n }\n\n /**\n * Get spritesheet metadata by asset path\n */\n getSpriteSheetMetadata(assetPath: string) {\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) return null;\n return (this.reader as any).parseSpriteSheetMetadata(assetIndex);\n }\n\n /**\n * Get list of all assets in pack\n */\n listAssets() {\n return this.reader.listAssets();\n }\n\n /**\n * Get asset count\n */\n getAssetCount(): number {\n return this.reader.getAssetCount();\n }\n\n /**\n * Get asset info by index\n */\n getAssetInfo(index: number) {\n return this.reader.getAssetInfo(index);\n }\n\n /**\n * Get texture metadata\n */\n getTextureMetadata(index: number) {\n return this.reader.parseTextureMetadata(index);\n }\n\n /**\n * Get audio metadata\n */\n getAudioMetadata(index: number) {\n return this.reader.parseAudioMetadata(index);\n }\n\n /**\n * Close the pack and free resources\n */\n dispose(): void {\n // Clear texture cache (Phaser manages texture disposal)\n this.textureCache.clear();\n this.transcodedDataCache.clear();\n\n // Close reader\n this.reader.close();\n }\n}\n\n\n","import { StowKitReader } from '@series-inc/stowkit-reader';\nimport { BasisTranscoder } from './BasisTranscoder';\nimport { StowKitPhaserPack } from './StowKitPhaserPack';\n\nexport interface StowKitPhaserLoaderOptions {\n /**\n * Path to basis transcoder for KTX2 texture loading\n * @default '/basis/'\n */\n basisPath?: string;\n\n /**\n * Path to WASM reader module\n * @default '/stowkit/stowkit_reader.wasm'\n */\n wasmPath?: string;\n\n /**\n * WebGL context to use for texture loading\n * If not provided, a temporary canvas will be created\n */\n gl?: WebGLRenderingContext | WebGL2RenderingContext;\n}\n\n/**\n * Phaser loader for StowKit asset packs\n * Supports images and audio only (no 3D models)\n * \n * Usage:\n * ```typescript\n * const pack = await StowKitPhaserLoader.load('assets.stow');\n * const texture = await pack.loadTexture('textures/player');\n * const audio = await pack.loadAudio('sounds/bgm');\n * ```\n */\nexport class StowKitPhaserLoader {\n private static transcoder: BasisTranscoder | null = null;\n private static initialized = false;\n private static gl: WebGLRenderingContext | WebGL2RenderingContext | null = null;\n private static ownGl = false;\n private static wasmPath: string = '/stowkit/stowkit_reader.wasm';\n\n /**\n * Load a .stow pack file from a URL\n */\n static async load(url: string, options?: StowKitPhaserLoaderOptions): Promise<StowKitPhaserPack> {\n // Initialize loaders if needed\n if (!this.initialized) {\n await this.initialize(options);\n }\n\n // Fetch the pack file\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${url}: ${response.statusText}`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n\n // Create a new reader instance for this pack\n const reader = new StowKitReader(this.wasmPath);\n await reader.init();\n await reader.open(arrayBuffer);\n\n // Return pack wrapper with its own dedicated reader\n return new StowKitPhaserPack(reader, this.transcoder!, this.gl!);\n }\n\n /**\n * Load a .stow pack from memory (ArrayBuffer, Blob, or File)\n */\n static async loadFromMemory(\n data: ArrayBuffer | Blob | File,\n options?: StowKitPhaserLoaderOptions\n ): Promise<StowKitPhaserPack> {\n // Initialize loaders if needed\n if (!this.initialized) {\n await this.initialize(options);\n }\n\n // Convert to ArrayBuffer if needed\n let arrayBuffer: ArrayBuffer;\n if (data instanceof ArrayBuffer) {\n arrayBuffer = data;\n } else if (typeof Blob !== 'undefined' && data instanceof Blob) {\n arrayBuffer = await data.arrayBuffer();\n } else if ('arrayBuffer' in data && typeof (data as any).arrayBuffer === 'function') {\n arrayBuffer = await (data as any).arrayBuffer();\n } else {\n throw new Error('Data must be ArrayBuffer, Blob, or File');\n }\n\n // Create a new reader instance for this pack\n const reader = new StowKitReader(this.wasmPath);\n await reader.init();\n await reader.open(arrayBuffer);\n\n // Return pack wrapper with its own dedicated reader\n return new StowKitPhaserPack(reader, this.transcoder!, this.gl!);\n }\n\n /**\n * Initialize the loader (called automatically on first load)\n */\n private static async initialize(options?: StowKitPhaserLoaderOptions): Promise<void> {\n this.wasmPath = options?.wasmPath || '/stowkit/stowkit_reader.wasm';\n const basisPath = options?.basisPath || '/basis/';\n\n // Get or create WebGL context (shared across all packs)\n if (options?.gl) {\n this.gl = options.gl;\n this.ownGl = false;\n } else {\n // Create a temporary canvas for WebGL operations\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n canvas.style.display = 'none';\n document.body.appendChild(canvas);\n\n this.gl = canvas.getContext('webgl2') || canvas.getContext('webgl');\n if (!this.gl) {\n throw new Error('Failed to create WebGL context');\n }\n this.ownGl = true;\n }\n\n // Initialize basis transcoder (shared across all packs)\n this.transcoder = new BasisTranscoder(basisPath);\n await this.transcoder.init();\n\n this.initialized = true;\n }\n\n /**\n * Dispose of shared resources\n */\n static dispose(): void {\n if (this.transcoder) {\n this.transcoder.dispose();\n this.transcoder = null;\n }\n\n // Only dispose GL if we created it\n if (this.gl && this.ownGl) {\n const canvas = (this.gl as any).canvas;\n if (canvas && canvas.parentNode) {\n canvas.parentNode.removeChild(canvas);\n }\n this.gl = null;\n }\n\n this.initialized = false;\n }\n}\n\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stowkit-phaser-loader.esm.js","sources":["../src/BasisTranscoder.ts","../src/StowKitPhaserPack.ts","../src/StowKitPhaserLoader.ts"],"sourcesContent":["/**\n * BasisTranscoder - Manually decode KTX2 textures to WebGL textures\n * Used for Phaser which doesn't have built-in KTX2 support\n */\n\ninterface BasisModule {\n initializeBasis: () => void;\n BasisFile: new (data: Uint8Array) => BasisFile;\n KTX2File: new (data: Uint8Array) => KTX2File;\n}\n\ninterface BasisFile {\n getNumImages(): number;\n getNumLevels(imageIndex: number): number;\n getImageWidth(imageIndex: number, level: number): number;\n getImageHeight(imageIndex: number, level: number): number;\n startTranscoding(): boolean;\n getImageTranscodedSizeInBytes(imageIndex: number, level: number, format: number): number;\n transcodeImage(\n dst: Uint8Array,\n imageIndex: number,\n level: number,\n format: number,\n unused: number,\n getAlphaForOpaqueFormats: number\n ): number;\n close(): void;\n delete(): void;\n}\n\ninterface KTX2File {\n isValid(): boolean;\n isUASTC(): boolean;\n isETC1S(): boolean;\n isHDR(): boolean;\n getWidth(): number;\n getHeight(): number;\n getLayers(): number;\n getLevels(): number;\n getFaces(): number;\n getHasAlpha(): boolean;\n getDFDFlags(): number;\n startTranscoding(): boolean;\n getImageLevelInfo(mip: number, layer: number, face: number): any;\n getImageTranscodedSizeInBytes(mip: number, layer: number, face: number, format: number): number;\n transcodeImage(\n dst: Uint8Array,\n mip: number,\n layer: number,\n face: number,\n format: number,\n unused1: number,\n unused2: number,\n unused3: number\n ): number;\n close(): void;\n delete(): void;\n}\n\n// Basis transcoder formats (from Three.js KTX2Loader.TranscoderFormat)\nconst BASIS_FORMAT = {\n ETC1: 0,\n ETC2: 1,\n BC1: 2, // DXT1\n BC3: 3, // DXT5\n BC4: 4,\n BC5: 5,\n BC7_M6_OPAQUE_ONLY: 6,\n BC7_M5: 7, // BC7\n PVRTC1_4_RGB: 8,\n PVRTC1_4_RGBA: 9,\n ASTC_4x4: 10,\n ATC_RGB: 11,\n ATC_RGBA: 12,\n RGBA32: 13,\n RGB565: 14,\n BGR565: 15,\n RGBA4444: 16,\n BC6H: 22,\n RGB_HALF: 24,\n RGBA_HALF: 25,\n};\n\nexport interface TranscodedTexture {\n data: Uint8Array;\n width: number;\n height: number;\n format: number;\n internalFormat?: number;\n compressed: boolean;\n}\n\nexport class BasisTranscoder {\n private module: BasisModule | null = null;\n private initialized = false;\n private initPromise: Promise<void> | null = null;\n private basisPath: string;\n\n constructor(basisPath: string = '/basis/') {\n this.basisPath = basisPath;\n }\n\n /**\n * Initialize the Basis Universal transcoder\n */\n async init(): Promise<void> {\n if (this.initialized) return;\n if (this.initPromise) return this.initPromise;\n\n this.initPromise = (async () => {\n try {\n // Load the basis transcoder\n const scriptPath = `${this.basisPath}basis_transcoder.js`;\n \n // Import the basis module\n const BasisModule = await this.loadBasisModule(scriptPath);\n \n // Initialize\n BasisModule.initializeBasis();\n this.module = BasisModule;\n this.initialized = true;\n } catch (error) {\n console.error('[BasisTranscoder] Failed to initialize:', error);\n throw error;\n }\n })();\n\n return this.initPromise;\n }\n\n /**\n * Load the basis transcoder module\n */\n private async loadBasisModule(scriptPath: string): Promise<BasisModule> {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = scriptPath;\n script.async = true;\n \n script.onload = () => {\n // The basis transcoder exposes a global BASIS function\n if (typeof (window as any).BASIS === 'function') {\n (window as any).BASIS().then((module: BasisModule) => {\n resolve(module);\n }).catch(reject);\n } else {\n reject(new Error('BASIS module not found'));\n }\n };\n \n script.onerror = () => {\n reject(new Error(`Failed to load ${scriptPath}`));\n };\n \n document.head.appendChild(script);\n });\n }\n\n /**\n * Transcode KTX2 data to a WebGL-compatible format\n */\n async transcodeKTX2(data: Uint8Array, gl: WebGLRenderingContext | WebGL2RenderingContext): Promise<TranscodedTexture> {\n if (!this.initialized) {\n await this.init();\n }\n\n if (!this.module) {\n throw new Error('Basis module not initialized');\n }\n\n // Create KTX2File from data\n const ktx2File = new this.module.KTX2File(data);\n \n try {\n // Validate file\n if (!ktx2File.isValid()) {\n throw new Error('Invalid or unsupported KTX2 file');\n }\n\n // Get image dimensions\n const width = ktx2File.getWidth();\n const height = ktx2File.getHeight();\n \n // Check if the texture has alpha\n const hasAlpha = ktx2File.getHasAlpha();\n \n // Check format type (UASTC or ETC1S)\n const isUASTC = ktx2File.isUASTC();\n const isETC1S = ktx2File.isETC1S();\n\n // Start transcoding\n if (!ktx2File.startTranscoding()) {\n throw new Error('Failed to start KTX2 transcoding');\n }\n\n // Use first mip level, first layer, first face\n const mip = 0;\n const layer = 0;\n const face = 0;\n\n // Detect best format for this device and file type\n const targetFormat = this.detectBestFormat(gl, hasAlpha, isETC1S);\n \n // Get transcoded size\n const transcodedSize = ktx2File.getImageTranscodedSizeInBytes(\n mip,\n layer,\n face,\n targetFormat.basisFormat\n );\n\n // Allocate output buffer\n const transcodedData = new Uint8Array(transcodedSize);\n\n // Transcode (parameters: dst, mip, layer, face, format, unused1, unused2, unused3)\n const result = ktx2File.transcodeImage(\n transcodedData,\n mip,\n layer,\n face,\n targetFormat.basisFormat,\n 0,\n -1,\n -1\n );\n\n if (result === 0) {\n throw new Error('KTX2 transcoding failed');\n }\n\n return {\n data: transcodedData,\n width,\n height,\n format: targetFormat.glFormat,\n internalFormat: targetFormat.glInternalFormat,\n compressed: targetFormat.compressed\n };\n\n } finally {\n ktx2File.close();\n ktx2File.delete();\n }\n }\n\n /**\n * Detect the best compression format supported by the device\n */\n private detectBestFormat(gl: WebGLRenderingContext | WebGL2RenderingContext, hasAlpha: boolean = true, isETC1S: boolean = false): {\n basisFormat: number;\n glFormat: number;\n glInternalFormat: number;\n compressed: boolean;\n } {\n const isWebGL2 = gl instanceof WebGL2RenderingContext;\n\n // Check for extensions\n const s3tc = gl.getExtension('WEBGL_compressed_texture_s3tc') || \n gl.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc');\n const bptc = gl.getExtension('EXT_texture_compression_bptc');\n const etc1 = gl.getExtension('WEBGL_compressed_texture_etc1');\n const etc = gl.getExtension('WEBGL_compressed_texture_etc');\n const astc = gl.getExtension('WEBGL_compressed_texture_astc');\n const pvrtc = gl.getExtension('WEBGL_compressed_texture_pvrtc') ||\n gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc');\n\n // For ETC1S: Use BC1 (no alpha support in ETC1S)\n // For UASTC with alpha: Use BC3/BC7\n // For UASTC without alpha: Use BC1\n \n // BC7 on desktop with WebGL2 (requires separate BPTC extension)\n if (isWebGL2 && bptc && hasAlpha) {\n return {\n basisFormat: BASIS_FORMAT.BC7_M5,\n glFormat: gl.RGBA,\n glInternalFormat: (bptc as any).COMPRESSED_RGBA_BPTC_UNORM_EXT,\n compressed: true\n };\n }\n\n // BC3 (DXT5) on desktop - for textures with alpha\n // Basis handles ETC1S alpha via a separate slice transcoded into BC3's alpha block\n if (s3tc && hasAlpha) {\n return {\n basisFormat: BASIS_FORMAT.BC3,\n glFormat: gl.RGBA,\n glInternalFormat: (s3tc as any).COMPRESSED_RGBA_S3TC_DXT5_EXT,\n compressed: true\n };\n }\n\n // BC1 (DXT1) on desktop - for textures without alpha\n if (s3tc) {\n return {\n basisFormat: BASIS_FORMAT.BC1,\n glFormat: gl.RGB,\n glInternalFormat: (s3tc as any).COMPRESSED_RGB_S3TC_DXT1_EXT,\n compressed: true\n };\n }\n\n // ASTC on mobile (best quality)\n if (astc) {\n return {\n basisFormat: BASIS_FORMAT.ASTC_4x4,\n glFormat: gl.RGBA,\n glInternalFormat: (astc as any).COMPRESSED_RGBA_ASTC_4x4_KHR,\n compressed: true\n };\n }\n\n // ETC2 on mobile with WebGL2\n if (isWebGL2 && etc) {\n return {\n basisFormat: BASIS_FORMAT.ETC2,\n glFormat: gl.RGBA,\n glInternalFormat: (etc as any).COMPRESSED_RGBA8_ETC2_EAC || 0x9278,\n compressed: true\n };\n }\n\n // ETC1 on mobile\n if (etc1 || etc) {\n return {\n basisFormat: BASIS_FORMAT.ETC1,\n glFormat: gl.RGB,\n glInternalFormat: (etc1 as any)?.COMPRESSED_RGB_ETC1_WEBGL || 0x8D64,\n compressed: true\n };\n }\n\n // PVRTC on iOS (last resort for compressed)\n if (pvrtc) {\n return {\n basisFormat: hasAlpha ? BASIS_FORMAT.PVRTC1_4_RGBA : BASIS_FORMAT.PVRTC1_4_RGB,\n glFormat: gl.RGBA,\n glInternalFormat: (pvrtc as any).COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,\n compressed: true\n };\n }\n\n // Fallback to uncompressed RGBA\n return {\n basisFormat: BASIS_FORMAT.RGBA32,\n glFormat: gl.RGBA,\n glInternalFormat: gl.RGBA,\n compressed: false\n };\n }\n\n /**\n * Dispose resources\n */\n dispose(): void {\n this.module = null;\n this.initialized = false;\n this.initPromise = null;\n }\n}\n\n","import { StowKitReader, AssetType, PerfLogger } from '@series-inc/stowkit-reader';\nimport { BasisTranscoder } from './BasisTranscoder';\n\nexport interface TextureData {\n texture: WebGLTexture;\n width: number;\n height: number;\n}\n\n/**\n * Represents an opened StowKit pack for Phaser\n * Supports loading images and audio only (no 3D models)\n */\nexport class StowKitPhaserPack {\n public reader: StowKitReader;\n private transcoder: BasisTranscoder;\n private tempGl: WebGLRenderingContext | WebGL2RenderingContext;\n private textureCache: Map<string, any> = new Map();\n private transcodedDataCache: Map<number, { data: Uint8Array, width: number, height: number, compressed: boolean, format: number, internalFormat?: number }> = new Map();\n\n private blendModePatched = false;\n\n constructor(\n reader: StowKitReader,\n transcoder: BasisTranscoder,\n gl: WebGLRenderingContext | WebGL2RenderingContext\n ) {\n this.reader = reader;\n this.transcoder = transcoder;\n this.tempGl = gl;\n }\n\n /**\n * Patch Phaser's NORMAL blend mode (index 0) to use straight alpha.\n * Phaser defaults to gl.ONE, gl.ONE_MINUS_SRC_ALPHA (premultiplied),\n * but compressed textures always have straight alpha since\n * UNPACK_PREMULTIPLY_ALPHA_WEBGL is ignored for compressed uploads.\n */\n private ensureBlendMode(scene: any): void {\n if (this.blendModePatched) return;\n const renderer = scene.sys.game.renderer;\n const gl = renderer.gl;\n renderer.blendModes[0] = {\n func: [gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA],\n equation: gl.FUNC_ADD,\n };\n // Force Phaser to re-apply the blend state — it skips if it thinks\n // the current mode hasn't changed, so we pass force=true.\n renderer.setBlendMode(0, true);\n this.blendModePatched = true;\n }\n\n /**\n * Load a texture by its canonical path/name\n * Returns a Phaser texture\n */\n async loadTexture(assetPath: string, scene: any): Promise<any> {\n const totalStart = performance.now();\n \n // Check cache first\n if (this.textureCache.has(assetPath)) {\n PerfLogger.log(`[Perf] Texture cache hit: ${assetPath}`);\n return this.textureCache.get(assetPath)!;\n }\n\n // Find asset by path\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) {\n throw new Error(`Texture not found: ${assetPath}`);\n }\n\n // Verify it's a texture\n const info = this.reader.getAssetInfo(assetIndex);\n if (!info || info.type !== AssetType.TEXTURE_2D) {\n throw new Error(`Asset is not a texture: ${assetPath}`);\n }\n\n // Use the same logic as getPhaserTexture but with custom key\n const key = assetPath;\n const gl = scene.sys.game.renderer.gl;\n \n // Read and transcode\n const data = this.reader.readAssetData(assetIndex);\n if (!data) {\n throw new Error(`Failed to read texture data for ${assetPath}`);\n }\n\n const transcodeStart = performance.now();\n const transcoded = await this.transcoder.transcodeKTX2(data, gl);\n PerfLogger.log(`[Perf] Phaser Basis transcode: ${(performance.now() - transcodeStart).toFixed(2)}ms (${transcoded.width}x${transcoded.height})`);\n \n // Format like Phaser's KTX parser\n const compressedTextureData = {\n mipmaps: [{\n data: transcoded.data,\n width: transcoded.width,\n height: transcoded.height\n }],\n width: transcoded.width,\n height: transcoded.height,\n internalFormat: transcoded.internalFormat,\n compressed: transcoded.compressed,\n generateMipmap: false,\n format: transcoded.internalFormat\n };\n \n const phaserTexture = scene.textures.addCompressedTexture(key, compressedTextureData);\n\n // Register straight-alpha blend mode for compressed textures\n this.ensureBlendMode(scene);\n\n const source = phaserTexture?.source?.[0];\n\n // Apply nearest filtering if metadata specifies it\n const metadata = this.reader.parseTextureMetadata(assetIndex);\n if (metadata?.filtering === 1) {\n const glTexture = source?.glTexture;\n if (glTexture) {\n gl.bindTexture(gl.TEXTURE_2D, glTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n gl.bindTexture(gl.TEXTURE_2D, null);\n }\n }\n\n this.textureCache.set(assetPath, phaserTexture);\n\n PerfLogger.log(`[Perf] ===== Total Phaser texture load: ${(performance.now() - totalStart).toFixed(2)}ms =====`);\n return phaserTexture;\n }\n\n /**\n * Get a Phaser texture by index (for previews/demos)\n * Creates compressed texture directly in Phaser's GL context\n */\n async getPhaserTexture(index: number, scene: any): Promise<any> {\n const key = `texture_${index}`;\n \n // Check if already exists in Phaser's texture manager\n if (scene.textures.exists(key)) {\n return scene.textures.get(key);\n }\n \n // Get Phaser's GL context\n const gl = scene.sys.game.renderer.gl;\n \n // Read and transcode the KTX2 data\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read texture data for index ${index}`);\n }\n\n // Transcode to compressed format (don't create the WebGL texture yet - let Phaser do it)\n const transcoded = await this.transcoder.transcodeKTX2(data, gl);\n \n // Format the data exactly like Phaser's KTX parser output\n const compressedTextureData = {\n mipmaps: [{\n data: transcoded.data,\n width: transcoded.width,\n height: transcoded.height\n }],\n width: transcoded.width,\n height: transcoded.height,\n internalFormat: transcoded.internalFormat,\n compressed: transcoded.compressed,\n generateMipmap: false,\n format: transcoded.internalFormat // Phaser uses this for compressionAlgorithm\n };\n \n // Add to Phaser's texture manager as a compressed texture\n const phaserTexture = scene.textures.addCompressedTexture(key, compressedTextureData);\n \n // Cache it\n this.textureCache.set(key, phaserTexture);\n \n return phaserTexture;\n }\n \n /**\n * Load texture by index into a specific GL context\n */\n private async loadTextureInContext(index: number, gl: WebGLRenderingContext | WebGL2RenderingContext): Promise<TextureData> {\n // Read texture data\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read texture data for index ${index}`);\n }\n\n // Get metadata - all textures in .stow files are KTX2 format\n const metadata = this.reader.parseTextureMetadata(index);\n const isKtx2 = metadata?.channelFormat !== undefined;\n\n if (isKtx2) {\n // Transcode KTX2 to WebGL texture using the provided context\n const transcoded = await this.transcoder.transcodeKTX2(data, gl);\n \n // Create WebGL texture in the provided context\n const texture = gl.createTexture();\n if (!texture) {\n throw new Error('Failed to create WebGL texture');\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n\n if (transcoded.compressed) {\n gl.compressedTexImage2D(\n gl.TEXTURE_2D,\n 0,\n transcoded.internalFormat!,\n transcoded.width,\n transcoded.height,\n 0,\n transcoded.data\n );\n } else {\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n transcoded.internalFormat!,\n transcoded.width,\n transcoded.height,\n 0,\n transcoded.format,\n gl.UNSIGNED_BYTE,\n transcoded.data\n );\n }\n\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n // Apply nearest filtering if metadata specifies it (filtering === 1)\n const useNearest = metadata?.filtering === 1;\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useNearest ? gl.NEAREST : gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, useNearest ? gl.NEAREST : gl.LINEAR);\n\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n return {\n texture,\n width: transcoded.width,\n height: transcoded.height\n };\n } else {\n // Handle uncompressed image data\n return await this.loadUncompressedTextureInContext(data, gl);\n }\n }\n\n /**\n * Load uncompressed image (PNG, JPEG) as WebGL texture in a specific context\n */\n private async loadUncompressedTextureInContext(data: Uint8Array, gl: WebGLRenderingContext | WebGL2RenderingContext): Promise<TextureData> {\n return new Promise((resolve, reject) => {\n const blob = new Blob([data.buffer as ArrayBuffer]);\n const url = URL.createObjectURL(blob);\n \n const img = new Image();\n img.onload = () => {\n const texture = gl.createTexture();\n if (!texture) {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to create WebGL texture'));\n return;\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n img\n );\n\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n URL.revokeObjectURL(url);\n\n resolve({\n texture,\n width: img.width,\n height: img.height\n });\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to load image'));\n };\n\n img.src = url;\n });\n }\n\n /**\n * Load audio by its canonical path/name\n * Returns an AudioBuffer\n */\n async loadAudio(assetPath: string, audioContext?: AudioContext): Promise<AudioBuffer> {\n // Find asset by path\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) {\n throw new Error(`Audio not found: ${assetPath}`);\n }\n\n // Verify it's audio\n const info = this.reader.getAssetInfo(assetIndex);\n if (!info || info.type !== AssetType.AUDIO) {\n throw new Error(`Asset is not audio: ${assetPath}`);\n }\n\n return await this.loadAudioByIndex(assetIndex, audioContext);\n }\n\n /**\n * Load audio by index\n */\n async loadAudioByIndex(index: number, audioContext?: AudioContext): Promise<AudioBuffer> {\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read audio data for index ${index}`);\n }\n\n // Use provided context or create a new one\n const ctx = audioContext || new AudioContext();\n\n // Decode audio data\n const arrayBuffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength) as ArrayBuffer;\n const audioBuffer = await ctx.decodeAudioData(arrayBuffer);\n\n return audioBuffer;\n }\n\n /**\n * Create an HTML audio element for preview\n */\n async createAudioPreview(index: number): Promise<HTMLAudioElement> {\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read audio for index ${index}`);\n }\n\n const blob = new Blob([data.buffer as ArrayBuffer], { type: 'audio/mp4' });\n const url = URL.createObjectURL(blob);\n\n const audio = document.createElement('audio');\n audio.controls = true;\n audio.src = url;\n\n audio.addEventListener('ended', () => URL.revokeObjectURL(url));\n audio.addEventListener('error', () => URL.revokeObjectURL(url));\n\n return audio;\n }\n\n\n /**\n * Load a spritesheet by its canonical path.\n * Loads the referenced texture, registers it as a Phaser spritesheet\n * with correct frame dimensions, and creates an animation.\n */\n async loadSpriteSheet(\n assetPath: string,\n scene: any,\n animKey?: string,\n ): Promise<{ texture: any; animationKey: string }> {\n // Find the spritesheet asset\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) {\n throw new Error(`SpriteSheet not found: ${assetPath}`);\n }\n\n const info = this.reader.getAssetInfo(assetIndex);\n if (!info || info.type !== 8) {\n throw new Error(`Asset is not a spritesheet: ${assetPath}`);\n }\n\n // Parse spritesheet metadata (method added in reader, cast for compat)\n const meta = (this.reader as any).parseSpriteSheetMetadata(assetIndex);\n if (!meta || !meta.textureId) {\n throw new Error(`SpriteSheet \"${assetPath}\" has no texture reference`);\n }\n\n // Load the referenced texture first\n const textureKey = meta.textureId;\n await this.loadTexture(textureKey, scene);\n\n // Get texture dimensions from Phaser\n const phaserTexture = scene.textures.get(textureKey);\n const source = phaserTexture.source[0];\n const texWidth = source.width;\n const texHeight = source.height;\n\n // Calculate frame dimensions\n const frameWidth = Math.floor(texWidth / meta.columns);\n const frameHeight = Math.floor(texHeight / meta.rows);\n\n // Add numbered frames directly to the already-loaded compressed texture.\n // We cannot use addSpriteSheet — it calls texImage2D which fails for\n // compressed GL textures. Instead, add frames to the existing texture.\n const hasFrames = phaserTexture.has(0);\n if (!hasFrames) {\n let frame = 0;\n for (let row = 0; row < meta.rows && frame < meta.frameCount; row++) {\n for (let col = 0; col < meta.columns && frame < meta.frameCount; col++) {\n phaserTexture.add(\n frame,\n 0,\n col * frameWidth,\n row * frameHeight,\n frameWidth,\n frameHeight,\n );\n frame++;\n }\n }\n }\n\n // Create animation using the base texture key\n const animationKey = animKey ?? `${assetPath}_anim`;\n if (!scene.anims.exists(animationKey)) {\n scene.anims.create({\n key: animationKey,\n frames: scene.anims.generateFrameNumbers(textureKey, {\n start: 0,\n end: meta.frameCount - 1,\n }),\n frameRate: meta.frameRate,\n repeat: -1,\n });\n }\n\n return { texture: phaserTexture, textureKey, animationKey };\n }\n\n /**\n * Get spritesheet metadata by asset path\n */\n getSpriteSheetMetadata(assetPath: string) {\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) return null;\n return (this.reader as any).parseSpriteSheetMetadata(assetIndex);\n }\n\n /**\n * Get list of all assets in pack\n */\n listAssets() {\n return this.reader.listAssets();\n }\n\n /**\n * Get asset count\n */\n getAssetCount(): number {\n return this.reader.getAssetCount();\n }\n\n /**\n * Get asset info by index\n */\n getAssetInfo(index: number) {\n return this.reader.getAssetInfo(index);\n }\n\n /**\n * Get texture metadata\n */\n getTextureMetadata(index: number) {\n return this.reader.parseTextureMetadata(index);\n }\n\n /**\n * Get audio metadata\n */\n getAudioMetadata(index: number) {\n return this.reader.parseAudioMetadata(index);\n }\n\n /**\n * Close the pack and free resources\n */\n dispose(): void {\n // Clear texture cache (Phaser manages texture disposal)\n this.textureCache.clear();\n this.transcodedDataCache.clear();\n\n // Close reader\n this.reader.close();\n }\n}\n\n\n","import { StowKitReader } from '@series-inc/stowkit-reader';\nimport { BasisTranscoder } from './BasisTranscoder';\nimport { StowKitPhaserPack } from './StowKitPhaserPack';\n\nexport interface StowKitPhaserLoaderOptions {\n /**\n * Path to basis transcoder for KTX2 texture loading\n * @default '/basis/'\n */\n basisPath?: string;\n\n /**\n * Path to WASM reader module\n * @default '/stowkit/stowkit_reader.wasm'\n */\n wasmPath?: string;\n\n /**\n * WebGL context to use for texture loading\n * If not provided, a temporary canvas will be created\n */\n gl?: WebGLRenderingContext | WebGL2RenderingContext;\n}\n\n/**\n * Phaser loader for StowKit asset packs\n * Supports images and audio only (no 3D models)\n * \n * Usage:\n * ```typescript\n * const pack = await StowKitPhaserLoader.load('assets.stow');\n * const texture = await pack.loadTexture('textures/player');\n * const audio = await pack.loadAudio('sounds/bgm');\n * ```\n */\nexport class StowKitPhaserLoader {\n private static transcoder: BasisTranscoder | null = null;\n private static initialized = false;\n private static gl: WebGLRenderingContext | WebGL2RenderingContext | null = null;\n private static ownGl = false;\n private static wasmPath: string = '/stowkit/stowkit_reader.wasm';\n\n /**\n * Load a .stow pack file from a URL\n */\n static async load(url: string, options?: StowKitPhaserLoaderOptions): Promise<StowKitPhaserPack> {\n // Initialize loaders if needed\n if (!this.initialized) {\n await this.initialize(options);\n }\n\n // Fetch the pack file\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${url}: ${response.statusText}`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n\n // Create a new reader instance for this pack\n const reader = new StowKitReader(this.wasmPath);\n await reader.init();\n await reader.open(arrayBuffer);\n\n // Return pack wrapper with its own dedicated reader\n return new StowKitPhaserPack(reader, this.transcoder!, this.gl!);\n }\n\n /**\n * Load a .stow pack from memory (ArrayBuffer, Blob, or File)\n */\n static async loadFromMemory(\n data: ArrayBuffer | Blob | File,\n options?: StowKitPhaserLoaderOptions\n ): Promise<StowKitPhaserPack> {\n // Initialize loaders if needed\n if (!this.initialized) {\n await this.initialize(options);\n }\n\n // Convert to ArrayBuffer if needed\n let arrayBuffer: ArrayBuffer;\n if (data instanceof ArrayBuffer) {\n arrayBuffer = data;\n } else if (typeof Blob !== 'undefined' && data instanceof Blob) {\n arrayBuffer = await data.arrayBuffer();\n } else if ('arrayBuffer' in data && typeof (data as any).arrayBuffer === 'function') {\n arrayBuffer = await (data as any).arrayBuffer();\n } else {\n throw new Error('Data must be ArrayBuffer, Blob, or File');\n }\n\n // Create a new reader instance for this pack\n const reader = new StowKitReader(this.wasmPath);\n await reader.init();\n await reader.open(arrayBuffer);\n\n // Return pack wrapper with its own dedicated reader\n return new StowKitPhaserPack(reader, this.transcoder!, this.gl!);\n }\n\n /**\n * Initialize the loader (called automatically on first load)\n */\n private static async initialize(options?: StowKitPhaserLoaderOptions): Promise<void> {\n this.wasmPath = options?.wasmPath || '/stowkit/stowkit_reader.wasm';\n const basisPath = options?.basisPath || '/basis/';\n\n // Get or create WebGL context (shared across all packs)\n if (options?.gl) {\n this.gl = options.gl;\n this.ownGl = false;\n } else {\n // Create a temporary canvas for WebGL operations\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n canvas.style.display = 'none';\n document.body.appendChild(canvas);\n\n this.gl = canvas.getContext('webgl2') || canvas.getContext('webgl');\n if (!this.gl) {\n throw new Error('Failed to create WebGL context');\n }\n this.ownGl = true;\n }\n\n // Initialize basis transcoder (shared across all packs)\n this.transcoder = new BasisTranscoder(basisPath);\n await this.transcoder.init();\n\n this.initialized = true;\n }\n\n /**\n * Dispose of shared resources\n */\n static dispose(): void {\n if (this.transcoder) {\n this.transcoder.dispose();\n this.transcoder = null;\n }\n\n // Only dispose GL if we created it\n if (this.gl && this.ownGl) {\n const canvas = (this.gl as any).canvas;\n if (canvas && canvas.parentNode) {\n canvas.parentNode.removeChild(canvas);\n }\n this.gl = null;\n }\n\n this.initialized = false;\n }\n}\n\n"],"names":[],"mappings":"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"}
|
|
@@ -242,10 +242,31 @@
|
|
|
242
242
|
constructor(reader, transcoder, gl) {
|
|
243
243
|
this.textureCache = new Map();
|
|
244
244
|
this.transcodedDataCache = new Map();
|
|
245
|
+
this.blendModePatched = false;
|
|
245
246
|
this.reader = reader;
|
|
246
247
|
this.transcoder = transcoder;
|
|
247
248
|
this.tempGl = gl;
|
|
248
249
|
}
|
|
250
|
+
/**
|
|
251
|
+
* Patch Phaser's NORMAL blend mode (index 0) to use straight alpha.
|
|
252
|
+
* Phaser defaults to gl.ONE, gl.ONE_MINUS_SRC_ALPHA (premultiplied),
|
|
253
|
+
* but compressed textures always have straight alpha since
|
|
254
|
+
* UNPACK_PREMULTIPLY_ALPHA_WEBGL is ignored for compressed uploads.
|
|
255
|
+
*/
|
|
256
|
+
ensureBlendMode(scene) {
|
|
257
|
+
if (this.blendModePatched)
|
|
258
|
+
return;
|
|
259
|
+
const renderer = scene.sys.game.renderer;
|
|
260
|
+
const gl = renderer.gl;
|
|
261
|
+
renderer.blendModes[0] = {
|
|
262
|
+
func: [gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA],
|
|
263
|
+
equation: gl.FUNC_ADD,
|
|
264
|
+
};
|
|
265
|
+
// Force Phaser to re-apply the blend state — it skips if it thinks
|
|
266
|
+
// the current mode hasn't changed, so we pass force=true.
|
|
267
|
+
renderer.setBlendMode(0, true);
|
|
268
|
+
this.blendModePatched = true;
|
|
269
|
+
}
|
|
249
270
|
/**
|
|
250
271
|
* Load a texture by its canonical path/name
|
|
251
272
|
* Returns a Phaser texture
|
|
@@ -293,10 +314,13 @@
|
|
|
293
314
|
format: transcoded.internalFormat
|
|
294
315
|
};
|
|
295
316
|
const phaserTexture = scene.textures.addCompressedTexture(key, compressedTextureData);
|
|
317
|
+
// Register straight-alpha blend mode for compressed textures
|
|
318
|
+
this.ensureBlendMode(scene);
|
|
319
|
+
const source = phaserTexture?.source?.[0];
|
|
296
320
|
// Apply nearest filtering if metadata specifies it
|
|
297
321
|
const metadata = this.reader.parseTextureMetadata(assetIndex);
|
|
298
322
|
if (metadata?.filtering === 1) {
|
|
299
|
-
const glTexture =
|
|
323
|
+
const glTexture = source?.glTexture;
|
|
300
324
|
if (glTexture) {
|
|
301
325
|
gl.bindTexture(gl.TEXTURE_2D, glTexture);
|
|
302
326
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
@@ -508,47 +532,25 @@
|
|
|
508
532
|
// Calculate frame dimensions
|
|
509
533
|
const frameWidth = Math.floor(texWidth / meta.columns);
|
|
510
534
|
const frameHeight = Math.floor(texHeight / meta.rows);
|
|
511
|
-
// Add frames directly to the
|
|
512
|
-
// We cannot use addSpriteSheet
|
|
513
|
-
//
|
|
514
|
-
const
|
|
515
|
-
if (!
|
|
516
|
-
// Re-register the same GL source under the spritesheet key
|
|
517
|
-
// so Phaser can look up frames by ssKey
|
|
518
|
-
const ssTexture = scene.textures.addCompressedTexture(ssKey, {
|
|
519
|
-
mipmaps: [],
|
|
520
|
-
width: texWidth,
|
|
521
|
-
height: texHeight,
|
|
522
|
-
internalFormat: source.compressionAlgorithm,
|
|
523
|
-
compressed: true,
|
|
524
|
-
generateMipmap: false,
|
|
525
|
-
format: source.compressionAlgorithm,
|
|
526
|
-
});
|
|
527
|
-
// Share the GL texture from the already-loaded base texture
|
|
528
|
-
if (ssTexture?.source?.[0]) {
|
|
529
|
-
const ssSource = ssTexture.source[0];
|
|
530
|
-
ssSource.glTexture = source.glTexture;
|
|
531
|
-
ssSource.width = texWidth;
|
|
532
|
-
ssSource.height = texHeight;
|
|
533
|
-
ssSource.isCompressedTexture = true;
|
|
534
|
-
}
|
|
535
|
-
// Add individual frames for each cell in the grid
|
|
535
|
+
// Add numbered frames directly to the already-loaded compressed texture.
|
|
536
|
+
// We cannot use addSpriteSheet — it calls texImage2D which fails for
|
|
537
|
+
// compressed GL textures. Instead, add frames to the existing texture.
|
|
538
|
+
const hasFrames = phaserTexture.has(0);
|
|
539
|
+
if (!hasFrames) {
|
|
536
540
|
let frame = 0;
|
|
537
541
|
for (let row = 0; row < meta.rows && frame < meta.frameCount; row++) {
|
|
538
542
|
for (let col = 0; col < meta.columns && frame < meta.frameCount; col++) {
|
|
539
|
-
|
|
540
|
-
0, // source index
|
|
541
|
-
col * frameWidth, row * frameHeight, frameWidth, frameHeight);
|
|
543
|
+
phaserTexture.add(frame, 0, col * frameWidth, row * frameHeight, frameWidth, frameHeight);
|
|
542
544
|
frame++;
|
|
543
545
|
}
|
|
544
546
|
}
|
|
545
547
|
}
|
|
546
|
-
// Create animation
|
|
548
|
+
// Create animation using the base texture key
|
|
547
549
|
const animationKey = animKey ?? `${assetPath}_anim`;
|
|
548
550
|
if (!scene.anims.exists(animationKey)) {
|
|
549
551
|
scene.anims.create({
|
|
550
552
|
key: animationKey,
|
|
551
|
-
frames: scene.anims.generateFrameNumbers(
|
|
553
|
+
frames: scene.anims.generateFrameNumbers(textureKey, {
|
|
552
554
|
start: 0,
|
|
553
555
|
end: meta.frameCount - 1,
|
|
554
556
|
}),
|
|
@@ -556,7 +558,7 @@
|
|
|
556
558
|
repeat: -1,
|
|
557
559
|
});
|
|
558
560
|
}
|
|
559
|
-
return { texture: phaserTexture, animationKey };
|
|
561
|
+
return { texture: phaserTexture, textureKey, animationKey };
|
|
560
562
|
}
|
|
561
563
|
/**
|
|
562
564
|
* Get spritesheet metadata by asset path
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stowkit-phaser-loader.js","sources":["../src/BasisTranscoder.ts","../src/StowKitPhaserPack.ts","../src/StowKitPhaserLoader.ts"],"sourcesContent":["/**\n * BasisTranscoder - Manually decode KTX2 textures to WebGL textures\n * Used for Phaser which doesn't have built-in KTX2 support\n */\n\ninterface BasisModule {\n initializeBasis: () => void;\n BasisFile: new (data: Uint8Array) => BasisFile;\n KTX2File: new (data: Uint8Array) => KTX2File;\n}\n\ninterface BasisFile {\n getNumImages(): number;\n getNumLevels(imageIndex: number): number;\n getImageWidth(imageIndex: number, level: number): number;\n getImageHeight(imageIndex: number, level: number): number;\n startTranscoding(): boolean;\n getImageTranscodedSizeInBytes(imageIndex: number, level: number, format: number): number;\n transcodeImage(\n dst: Uint8Array,\n imageIndex: number,\n level: number,\n format: number,\n unused: number,\n getAlphaForOpaqueFormats: number\n ): number;\n close(): void;\n delete(): void;\n}\n\ninterface KTX2File {\n isValid(): boolean;\n isUASTC(): boolean;\n isETC1S(): boolean;\n isHDR(): boolean;\n getWidth(): number;\n getHeight(): number;\n getLayers(): number;\n getLevels(): number;\n getFaces(): number;\n getHasAlpha(): boolean;\n getDFDFlags(): number;\n startTranscoding(): boolean;\n getImageLevelInfo(mip: number, layer: number, face: number): any;\n getImageTranscodedSizeInBytes(mip: number, layer: number, face: number, format: number): number;\n transcodeImage(\n dst: Uint8Array,\n mip: number,\n layer: number,\n face: number,\n format: number,\n unused1: number,\n unused2: number,\n unused3: number\n ): number;\n close(): void;\n delete(): void;\n}\n\n// Basis transcoder formats (from Three.js KTX2Loader.TranscoderFormat)\nconst BASIS_FORMAT = {\n ETC1: 0,\n ETC2: 1,\n BC1: 2, // DXT1\n BC3: 3, // DXT5\n BC4: 4,\n BC5: 5,\n BC7_M6_OPAQUE_ONLY: 6,\n BC7_M5: 7, // BC7\n PVRTC1_4_RGB: 8,\n PVRTC1_4_RGBA: 9,\n ASTC_4x4: 10,\n ATC_RGB: 11,\n ATC_RGBA: 12,\n RGBA32: 13,\n RGB565: 14,\n BGR565: 15,\n RGBA4444: 16,\n BC6H: 22,\n RGB_HALF: 24,\n RGBA_HALF: 25,\n};\n\nexport interface TranscodedTexture {\n data: Uint8Array;\n width: number;\n height: number;\n format: number;\n internalFormat?: number;\n compressed: boolean;\n}\n\nexport class BasisTranscoder {\n private module: BasisModule | null = null;\n private initialized = false;\n private initPromise: Promise<void> | null = null;\n private basisPath: string;\n\n constructor(basisPath: string = '/basis/') {\n this.basisPath = basisPath;\n }\n\n /**\n * Initialize the Basis Universal transcoder\n */\n async init(): Promise<void> {\n if (this.initialized) return;\n if (this.initPromise) return this.initPromise;\n\n this.initPromise = (async () => {\n try {\n // Load the basis transcoder\n const scriptPath = `${this.basisPath}basis_transcoder.js`;\n \n // Import the basis module\n const BasisModule = await this.loadBasisModule(scriptPath);\n \n // Initialize\n BasisModule.initializeBasis();\n this.module = BasisModule;\n this.initialized = true;\n } catch (error) {\n console.error('[BasisTranscoder] Failed to initialize:', error);\n throw error;\n }\n })();\n\n return this.initPromise;\n }\n\n /**\n * Load the basis transcoder module\n */\n private async loadBasisModule(scriptPath: string): Promise<BasisModule> {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = scriptPath;\n script.async = true;\n \n script.onload = () => {\n // The basis transcoder exposes a global BASIS function\n if (typeof (window as any).BASIS === 'function') {\n (window as any).BASIS().then((module: BasisModule) => {\n resolve(module);\n }).catch(reject);\n } else {\n reject(new Error('BASIS module not found'));\n }\n };\n \n script.onerror = () => {\n reject(new Error(`Failed to load ${scriptPath}`));\n };\n \n document.head.appendChild(script);\n });\n }\n\n /**\n * Transcode KTX2 data to a WebGL-compatible format\n */\n async transcodeKTX2(data: Uint8Array, gl: WebGLRenderingContext | WebGL2RenderingContext): Promise<TranscodedTexture> {\n if (!this.initialized) {\n await this.init();\n }\n\n if (!this.module) {\n throw new Error('Basis module not initialized');\n }\n\n // Create KTX2File from data\n const ktx2File = new this.module.KTX2File(data);\n \n try {\n // Validate file\n if (!ktx2File.isValid()) {\n throw new Error('Invalid or unsupported KTX2 file');\n }\n\n // Get image dimensions\n const width = ktx2File.getWidth();\n const height = ktx2File.getHeight();\n \n // Check if the texture has alpha\n const hasAlpha = ktx2File.getHasAlpha();\n \n // Check format type (UASTC or ETC1S)\n const isUASTC = ktx2File.isUASTC();\n const isETC1S = ktx2File.isETC1S();\n\n // Start transcoding\n if (!ktx2File.startTranscoding()) {\n throw new Error('Failed to start KTX2 transcoding');\n }\n\n // Use first mip level, first layer, first face\n const mip = 0;\n const layer = 0;\n const face = 0;\n\n // Detect best format for this device and file type\n const targetFormat = this.detectBestFormat(gl, hasAlpha, isETC1S);\n \n // Get transcoded size\n const transcodedSize = ktx2File.getImageTranscodedSizeInBytes(\n mip,\n layer,\n face,\n targetFormat.basisFormat\n );\n\n // Allocate output buffer\n const transcodedData = new Uint8Array(transcodedSize);\n\n // Transcode (parameters: dst, mip, layer, face, format, unused1, unused2, unused3)\n const result = ktx2File.transcodeImage(\n transcodedData,\n mip,\n layer,\n face,\n targetFormat.basisFormat,\n 0,\n -1,\n -1\n );\n\n if (result === 0) {\n throw new Error('KTX2 transcoding failed');\n }\n\n return {\n data: transcodedData,\n width,\n height,\n format: targetFormat.glFormat,\n internalFormat: targetFormat.glInternalFormat,\n compressed: targetFormat.compressed\n };\n\n } finally {\n ktx2File.close();\n ktx2File.delete();\n }\n }\n\n /**\n * Detect the best compression format supported by the device\n */\n private detectBestFormat(gl: WebGLRenderingContext | WebGL2RenderingContext, hasAlpha: boolean = true, isETC1S: boolean = false): {\n basisFormat: number;\n glFormat: number;\n glInternalFormat: number;\n compressed: boolean;\n } {\n const isWebGL2 = gl instanceof WebGL2RenderingContext;\n\n // Check for extensions\n const s3tc = gl.getExtension('WEBGL_compressed_texture_s3tc') || \n gl.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc');\n const bptc = gl.getExtension('EXT_texture_compression_bptc');\n const etc1 = gl.getExtension('WEBGL_compressed_texture_etc1');\n const etc = gl.getExtension('WEBGL_compressed_texture_etc');\n const astc = gl.getExtension('WEBGL_compressed_texture_astc');\n const pvrtc = gl.getExtension('WEBGL_compressed_texture_pvrtc') ||\n gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc');\n\n // For ETC1S: Use BC1 (no alpha support in ETC1S)\n // For UASTC with alpha: Use BC3/BC7\n // For UASTC without alpha: Use BC1\n \n // BC7 on desktop with WebGL2 (requires separate BPTC extension)\n if (isWebGL2 && bptc && hasAlpha) {\n return {\n basisFormat: BASIS_FORMAT.BC7_M5,\n glFormat: gl.RGBA,\n glInternalFormat: (bptc as any).COMPRESSED_RGBA_BPTC_UNORM_EXT,\n compressed: true\n };\n }\n\n // BC3 (DXT5) on desktop - for textures with alpha\n // Basis handles ETC1S alpha via a separate slice transcoded into BC3's alpha block\n if (s3tc && hasAlpha) {\n return {\n basisFormat: BASIS_FORMAT.BC3,\n glFormat: gl.RGBA,\n glInternalFormat: (s3tc as any).COMPRESSED_RGBA_S3TC_DXT5_EXT,\n compressed: true\n };\n }\n\n // BC1 (DXT1) on desktop - for textures without alpha\n if (s3tc) {\n return {\n basisFormat: BASIS_FORMAT.BC1,\n glFormat: gl.RGB,\n glInternalFormat: (s3tc as any).COMPRESSED_RGB_S3TC_DXT1_EXT,\n compressed: true\n };\n }\n\n // ASTC on mobile (best quality)\n if (astc) {\n return {\n basisFormat: BASIS_FORMAT.ASTC_4x4,\n glFormat: gl.RGBA,\n glInternalFormat: (astc as any).COMPRESSED_RGBA_ASTC_4x4_KHR,\n compressed: true\n };\n }\n\n // ETC2 on mobile with WebGL2\n if (isWebGL2 && etc) {\n return {\n basisFormat: BASIS_FORMAT.ETC2,\n glFormat: gl.RGBA,\n glInternalFormat: (etc as any).COMPRESSED_RGBA8_ETC2_EAC || 0x9278,\n compressed: true\n };\n }\n\n // ETC1 on mobile\n if (etc1 || etc) {\n return {\n basisFormat: BASIS_FORMAT.ETC1,\n glFormat: gl.RGB,\n glInternalFormat: (etc1 as any)?.COMPRESSED_RGB_ETC1_WEBGL || 0x8D64,\n compressed: true\n };\n }\n\n // PVRTC on iOS (last resort for compressed)\n if (pvrtc) {\n return {\n basisFormat: hasAlpha ? BASIS_FORMAT.PVRTC1_4_RGBA : BASIS_FORMAT.PVRTC1_4_RGB,\n glFormat: gl.RGBA,\n glInternalFormat: (pvrtc as any).COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,\n compressed: true\n };\n }\n\n // Fallback to uncompressed RGBA\n return {\n basisFormat: BASIS_FORMAT.RGBA32,\n glFormat: gl.RGBA,\n glInternalFormat: gl.RGBA,\n compressed: false\n };\n }\n\n /**\n * Dispose resources\n */\n dispose(): void {\n this.module = null;\n this.initialized = false;\n this.initPromise = null;\n }\n}\n\n","import { StowKitReader, AssetType, PerfLogger } from '@series-inc/stowkit-reader';\nimport { BasisTranscoder } from './BasisTranscoder';\n\nexport interface TextureData {\n texture: WebGLTexture;\n width: number;\n height: number;\n}\n\n/**\n * Represents an opened StowKit pack for Phaser\n * Supports loading images and audio only (no 3D models)\n */\nexport class StowKitPhaserPack {\n public reader: StowKitReader;\n private transcoder: BasisTranscoder;\n private tempGl: WebGLRenderingContext | WebGL2RenderingContext;\n private textureCache: Map<string, any> = new Map();\n private transcodedDataCache: Map<number, { data: Uint8Array, width: number, height: number, compressed: boolean, format: number, internalFormat?: number }> = new Map();\n\n constructor(\n reader: StowKitReader,\n transcoder: BasisTranscoder,\n gl: WebGLRenderingContext | WebGL2RenderingContext\n ) {\n this.reader = reader;\n this.transcoder = transcoder;\n this.tempGl = gl;\n }\n\n /**\n * Load a texture by its canonical path/name\n * Returns a Phaser texture\n */\n async loadTexture(assetPath: string, scene: any): Promise<any> {\n const totalStart = performance.now();\n \n // Check cache first\n if (this.textureCache.has(assetPath)) {\n PerfLogger.log(`[Perf] Texture cache hit: ${assetPath}`);\n return this.textureCache.get(assetPath)!;\n }\n\n // Find asset by path\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) {\n throw new Error(`Texture not found: ${assetPath}`);\n }\n\n // Verify it's a texture\n const info = this.reader.getAssetInfo(assetIndex);\n if (!info || info.type !== AssetType.TEXTURE_2D) {\n throw new Error(`Asset is not a texture: ${assetPath}`);\n }\n\n // Use the same logic as getPhaserTexture but with custom key\n const key = assetPath;\n const gl = scene.sys.game.renderer.gl;\n \n // Read and transcode\n const data = this.reader.readAssetData(assetIndex);\n if (!data) {\n throw new Error(`Failed to read texture data for ${assetPath}`);\n }\n\n const transcodeStart = performance.now();\n const transcoded = await this.transcoder.transcodeKTX2(data, gl);\n PerfLogger.log(`[Perf] Phaser Basis transcode: ${(performance.now() - transcodeStart).toFixed(2)}ms (${transcoded.width}x${transcoded.height})`);\n \n // Format like Phaser's KTX parser\n const compressedTextureData = {\n mipmaps: [{\n data: transcoded.data,\n width: transcoded.width,\n height: transcoded.height\n }],\n width: transcoded.width,\n height: transcoded.height,\n internalFormat: transcoded.internalFormat,\n compressed: transcoded.compressed,\n generateMipmap: false,\n format: transcoded.internalFormat\n };\n \n const phaserTexture = scene.textures.addCompressedTexture(key, compressedTextureData);\n\n // Apply nearest filtering if metadata specifies it\n const metadata = this.reader.parseTextureMetadata(assetIndex);\n if (metadata?.filtering === 1) {\n const glTexture = phaserTexture?.source?.[0]?.glTexture;\n if (glTexture) {\n gl.bindTexture(gl.TEXTURE_2D, glTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n gl.bindTexture(gl.TEXTURE_2D, null);\n }\n }\n\n this.textureCache.set(assetPath, phaserTexture);\n\n PerfLogger.log(`[Perf] ===== Total Phaser texture load: ${(performance.now() - totalStart).toFixed(2)}ms =====`);\n return phaserTexture;\n }\n\n /**\n * Get a Phaser texture by index (for previews/demos)\n * Creates compressed texture directly in Phaser's GL context\n */\n async getPhaserTexture(index: number, scene: any): Promise<any> {\n const key = `texture_${index}`;\n \n // Check if already exists in Phaser's texture manager\n if (scene.textures.exists(key)) {\n return scene.textures.get(key);\n }\n \n // Get Phaser's GL context\n const gl = scene.sys.game.renderer.gl;\n \n // Read and transcode the KTX2 data\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read texture data for index ${index}`);\n }\n\n // Transcode to compressed format (don't create the WebGL texture yet - let Phaser do it)\n const transcoded = await this.transcoder.transcodeKTX2(data, gl);\n \n // Format the data exactly like Phaser's KTX parser output\n const compressedTextureData = {\n mipmaps: [{\n data: transcoded.data,\n width: transcoded.width,\n height: transcoded.height\n }],\n width: transcoded.width,\n height: transcoded.height,\n internalFormat: transcoded.internalFormat,\n compressed: transcoded.compressed,\n generateMipmap: false,\n format: transcoded.internalFormat // Phaser uses this for compressionAlgorithm\n };\n \n // Add to Phaser's texture manager as a compressed texture\n const phaserTexture = scene.textures.addCompressedTexture(key, compressedTextureData);\n \n // Cache it\n this.textureCache.set(key, phaserTexture);\n \n return phaserTexture;\n }\n \n /**\n * Load texture by index into a specific GL context\n */\n private async loadTextureInContext(index: number, gl: WebGLRenderingContext | WebGL2RenderingContext): Promise<TextureData> {\n // Read texture data\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read texture data for index ${index}`);\n }\n\n // Get metadata - all textures in .stow files are KTX2 format\n const metadata = this.reader.parseTextureMetadata(index);\n const isKtx2 = metadata?.channelFormat !== undefined;\n\n if (isKtx2) {\n // Transcode KTX2 to WebGL texture using the provided context\n const transcoded = await this.transcoder.transcodeKTX2(data, gl);\n \n // Create WebGL texture in the provided context\n const texture = gl.createTexture();\n if (!texture) {\n throw new Error('Failed to create WebGL texture');\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n\n if (transcoded.compressed) {\n gl.compressedTexImage2D(\n gl.TEXTURE_2D,\n 0,\n transcoded.internalFormat!,\n transcoded.width,\n transcoded.height,\n 0,\n transcoded.data\n );\n } else {\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n transcoded.internalFormat!,\n transcoded.width,\n transcoded.height,\n 0,\n transcoded.format,\n gl.UNSIGNED_BYTE,\n transcoded.data\n );\n }\n\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n // Apply nearest filtering if metadata specifies it (filtering === 1)\n const useNearest = metadata?.filtering === 1;\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useNearest ? gl.NEAREST : gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, useNearest ? gl.NEAREST : gl.LINEAR);\n\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n return {\n texture,\n width: transcoded.width,\n height: transcoded.height\n };\n } else {\n // Handle uncompressed image data\n return await this.loadUncompressedTextureInContext(data, gl);\n }\n }\n\n /**\n * Load uncompressed image (PNG, JPEG) as WebGL texture in a specific context\n */\n private async loadUncompressedTextureInContext(data: Uint8Array, gl: WebGLRenderingContext | WebGL2RenderingContext): Promise<TextureData> {\n return new Promise((resolve, reject) => {\n const blob = new Blob([data.buffer as ArrayBuffer]);\n const url = URL.createObjectURL(blob);\n \n const img = new Image();\n img.onload = () => {\n const texture = gl.createTexture();\n if (!texture) {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to create WebGL texture'));\n return;\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n img\n );\n\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n URL.revokeObjectURL(url);\n\n resolve({\n texture,\n width: img.width,\n height: img.height\n });\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to load image'));\n };\n\n img.src = url;\n });\n }\n\n /**\n * Load audio by its canonical path/name\n * Returns an AudioBuffer\n */\n async loadAudio(assetPath: string, audioContext?: AudioContext): Promise<AudioBuffer> {\n // Find asset by path\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) {\n throw new Error(`Audio not found: ${assetPath}`);\n }\n\n // Verify it's audio\n const info = this.reader.getAssetInfo(assetIndex);\n if (!info || info.type !== AssetType.AUDIO) {\n throw new Error(`Asset is not audio: ${assetPath}`);\n }\n\n return await this.loadAudioByIndex(assetIndex, audioContext);\n }\n\n /**\n * Load audio by index\n */\n async loadAudioByIndex(index: number, audioContext?: AudioContext): Promise<AudioBuffer> {\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read audio data for index ${index}`);\n }\n\n // Use provided context or create a new one\n const ctx = audioContext || new AudioContext();\n\n // Decode audio data\n const arrayBuffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength) as ArrayBuffer;\n const audioBuffer = await ctx.decodeAudioData(arrayBuffer);\n\n return audioBuffer;\n }\n\n /**\n * Create an HTML audio element for preview\n */\n async createAudioPreview(index: number): Promise<HTMLAudioElement> {\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read audio for index ${index}`);\n }\n\n const blob = new Blob([data.buffer as ArrayBuffer], { type: 'audio/mp4' });\n const url = URL.createObjectURL(blob);\n\n const audio = document.createElement('audio');\n audio.controls = true;\n audio.src = url;\n\n audio.addEventListener('ended', () => URL.revokeObjectURL(url));\n audio.addEventListener('error', () => URL.revokeObjectURL(url));\n\n return audio;\n }\n\n\n /**\n * Load a spritesheet by its canonical path.\n * Loads the referenced texture, registers it as a Phaser spritesheet\n * with correct frame dimensions, and creates an animation.\n */\n async loadSpriteSheet(\n assetPath: string,\n scene: any,\n animKey?: string,\n ): Promise<{ texture: any; animationKey: string }> {\n // Find the spritesheet asset\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) {\n throw new Error(`SpriteSheet not found: ${assetPath}`);\n }\n\n const info = this.reader.getAssetInfo(assetIndex);\n if (!info || info.type !== 8) {\n throw new Error(`Asset is not a spritesheet: ${assetPath}`);\n }\n\n // Parse spritesheet metadata (method added in reader, cast for compat)\n const meta = (this.reader as any).parseSpriteSheetMetadata(assetIndex);\n if (!meta || !meta.textureId) {\n throw new Error(`SpriteSheet \"${assetPath}\" has no texture reference`);\n }\n\n // Load the referenced texture first\n const textureKey = meta.textureId;\n await this.loadTexture(textureKey, scene);\n\n // Get texture dimensions from Phaser\n const phaserTexture = scene.textures.get(textureKey);\n const source = phaserTexture.source[0];\n const texWidth = source.width;\n const texHeight = source.height;\n\n // Calculate frame dimensions\n const frameWidth = Math.floor(texWidth / meta.columns);\n const frameHeight = Math.floor(texHeight / meta.rows);\n\n // Add frames directly to the existing compressed texture.\n // We cannot use addSpriteSheet because it tries to create a new\n // texture from an image source, which fails for compressed GL textures.\n const ssKey = assetPath;\n if (!scene.textures.exists(ssKey)) {\n // Re-register the same GL source under the spritesheet key\n // so Phaser can look up frames by ssKey\n const ssTexture = scene.textures.addCompressedTexture(ssKey, {\n mipmaps: [],\n width: texWidth,\n height: texHeight,\n internalFormat: source.compressionAlgorithm,\n compressed: true,\n generateMipmap: false,\n format: source.compressionAlgorithm,\n });\n\n // Share the GL texture from the already-loaded base texture\n if (ssTexture?.source?.[0]) {\n const ssSource = ssTexture.source[0];\n ssSource.glTexture = source.glTexture;\n ssSource.width = texWidth;\n ssSource.height = texHeight;\n ssSource.isCompressedTexture = true;\n }\n\n // Add individual frames for each cell in the grid\n let frame = 0;\n for (let row = 0; row < meta.rows && frame < meta.frameCount; row++) {\n for (let col = 0; col < meta.columns && frame < meta.frameCount; col++) {\n ssTexture.add(\n frame, // frame name/index\n 0, // source index\n col * frameWidth,\n row * frameHeight,\n frameWidth,\n frameHeight,\n );\n frame++;\n }\n }\n }\n\n // Create animation\n const animationKey = animKey ?? `${assetPath}_anim`;\n if (!scene.anims.exists(animationKey)) {\n scene.anims.create({\n key: animationKey,\n frames: scene.anims.generateFrameNumbers(ssKey, {\n start: 0,\n end: meta.frameCount - 1,\n }),\n frameRate: meta.frameRate,\n repeat: -1,\n });\n }\n\n return { texture: phaserTexture, animationKey };\n }\n\n /**\n * Get spritesheet metadata by asset path\n */\n getSpriteSheetMetadata(assetPath: string) {\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) return null;\n return (this.reader as any).parseSpriteSheetMetadata(assetIndex);\n }\n\n /**\n * Get list of all assets in pack\n */\n listAssets() {\n return this.reader.listAssets();\n }\n\n /**\n * Get asset count\n */\n getAssetCount(): number {\n return this.reader.getAssetCount();\n }\n\n /**\n * Get asset info by index\n */\n getAssetInfo(index: number) {\n return this.reader.getAssetInfo(index);\n }\n\n /**\n * Get texture metadata\n */\n getTextureMetadata(index: number) {\n return this.reader.parseTextureMetadata(index);\n }\n\n /**\n * Get audio metadata\n */\n getAudioMetadata(index: number) {\n return this.reader.parseAudioMetadata(index);\n }\n\n /**\n * Close the pack and free resources\n */\n dispose(): void {\n // Clear texture cache (Phaser manages texture disposal)\n this.textureCache.clear();\n this.transcodedDataCache.clear();\n\n // Close reader\n this.reader.close();\n }\n}\n\n\n","import { StowKitReader } from '@series-inc/stowkit-reader';\nimport { BasisTranscoder } from './BasisTranscoder';\nimport { StowKitPhaserPack } from './StowKitPhaserPack';\n\nexport interface StowKitPhaserLoaderOptions {\n /**\n * Path to basis transcoder for KTX2 texture loading\n * @default '/basis/'\n */\n basisPath?: string;\n\n /**\n * Path to WASM reader module\n * @default '/stowkit/stowkit_reader.wasm'\n */\n wasmPath?: string;\n\n /**\n * WebGL context to use for texture loading\n * If not provided, a temporary canvas will be created\n */\n gl?: WebGLRenderingContext | WebGL2RenderingContext;\n}\n\n/**\n * Phaser loader for StowKit asset packs\n * Supports images and audio only (no 3D models)\n * \n * Usage:\n * ```typescript\n * const pack = await StowKitPhaserLoader.load('assets.stow');\n * const texture = await pack.loadTexture('textures/player');\n * const audio = await pack.loadAudio('sounds/bgm');\n * ```\n */\nexport class StowKitPhaserLoader {\n private static transcoder: BasisTranscoder | null = null;\n private static initialized = false;\n private static gl: WebGLRenderingContext | WebGL2RenderingContext | null = null;\n private static ownGl = false;\n private static wasmPath: string = '/stowkit/stowkit_reader.wasm';\n\n /**\n * Load a .stow pack file from a URL\n */\n static async load(url: string, options?: StowKitPhaserLoaderOptions): Promise<StowKitPhaserPack> {\n // Initialize loaders if needed\n if (!this.initialized) {\n await this.initialize(options);\n }\n\n // Fetch the pack file\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${url}: ${response.statusText}`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n\n // Create a new reader instance for this pack\n const reader = new StowKitReader(this.wasmPath);\n await reader.init();\n await reader.open(arrayBuffer);\n\n // Return pack wrapper with its own dedicated reader\n return new StowKitPhaserPack(reader, this.transcoder!, this.gl!);\n }\n\n /**\n * Load a .stow pack from memory (ArrayBuffer, Blob, or File)\n */\n static async loadFromMemory(\n data: ArrayBuffer | Blob | File,\n options?: StowKitPhaserLoaderOptions\n ): Promise<StowKitPhaserPack> {\n // Initialize loaders if needed\n if (!this.initialized) {\n await this.initialize(options);\n }\n\n // Convert to ArrayBuffer if needed\n let arrayBuffer: ArrayBuffer;\n if (data instanceof ArrayBuffer) {\n arrayBuffer = data;\n } else if (typeof Blob !== 'undefined' && data instanceof Blob) {\n arrayBuffer = await data.arrayBuffer();\n } else if ('arrayBuffer' in data && typeof (data as any).arrayBuffer === 'function') {\n arrayBuffer = await (data as any).arrayBuffer();\n } else {\n throw new Error('Data must be ArrayBuffer, Blob, or File');\n }\n\n // Create a new reader instance for this pack\n const reader = new StowKitReader(this.wasmPath);\n await reader.init();\n await reader.open(arrayBuffer);\n\n // Return pack wrapper with its own dedicated reader\n return new StowKitPhaserPack(reader, this.transcoder!, this.gl!);\n }\n\n /**\n * Initialize the loader (called automatically on first load)\n */\n private static async initialize(options?: StowKitPhaserLoaderOptions): Promise<void> {\n this.wasmPath = options?.wasmPath || '/stowkit/stowkit_reader.wasm';\n const basisPath = options?.basisPath || '/basis/';\n\n // Get or create WebGL context (shared across all packs)\n if (options?.gl) {\n this.gl = options.gl;\n this.ownGl = false;\n } else {\n // Create a temporary canvas for WebGL operations\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n canvas.style.display = 'none';\n document.body.appendChild(canvas);\n\n this.gl = canvas.getContext('webgl2') || canvas.getContext('webgl');\n if (!this.gl) {\n throw new Error('Failed to create WebGL context');\n }\n this.ownGl = true;\n }\n\n // Initialize basis transcoder (shared across all packs)\n this.transcoder = new BasisTranscoder(basisPath);\n await this.transcoder.init();\n\n this.initialized = true;\n }\n\n /**\n * Dispose of shared resources\n */\n static dispose(): void {\n if (this.transcoder) {\n this.transcoder.dispose();\n this.transcoder = null;\n }\n\n // Only dispose GL if we created it\n if (this.gl && this.ownGl) {\n const canvas = (this.gl as any).canvas;\n if (canvas && canvas.parentNode) {\n canvas.parentNode.removeChild(canvas);\n }\n this.gl = null;\n }\n\n this.initialized = false;\n }\n}\n\n"],"names":["PerfLogger","AssetType","StowKitReader"],"mappings":";;;;;;IAAA;;;IAGG;IAwDH;IACA,MAAM,YAAY,GAAG;IACjB,IAAA,IAAI,EAAE,CAAC;IACP,IAAA,IAAI,EAAE,CAAC;QACP,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,CAAC;IACN,IAGA,MAAM,EAAE,CAAC;IACT,IAAA,YAAY,EAAE,CAAC;IACf,IAAA,aAAa,EAAE,CAAC;IAChB,IAAA,QAAQ,EAAE,EAAE;IACZ,IAEA,MAAM,EAAE,GAOX;UAWY,eAAe,CAAA;IAMxB,IAAA,WAAA,CAAY,YAAoB,SAAS,EAAA;YALjC,IAAA,CAAA,MAAM,GAAuB,IAAI;YACjC,IAAA,CAAA,WAAW,GAAG,KAAK;YACnB,IAAA,CAAA,WAAW,GAAyB,IAAI;IAI5C,QAAA,IAAI,CAAC,SAAS,GAAG,SAAS;QAC9B;IAEA;;IAEG;IACH,IAAA,MAAM,IAAI,GAAA;YACN,IAAI,IAAI,CAAC,WAAW;gBAAE;YACtB,IAAI,IAAI,CAAC,WAAW;gBAAE,OAAO,IAAI,CAAC,WAAW;IAE7C,QAAA,IAAI,CAAC,WAAW,GAAG,CAAC,YAAW;IAC3B,YAAA,IAAI;;IAEA,gBAAA,MAAM,UAAU,GAAG,CAAA,EAAG,IAAI,CAAC,SAAS,qBAAqB;;oBAGzD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC;;oBAG1D,WAAW,CAAC,eAAe,EAAE;IAC7B,gBAAA,IAAI,CAAC,MAAM,GAAG,WAAW;IACzB,gBAAA,IAAI,CAAC,WAAW,GAAG,IAAI;gBAC3B;gBAAE,OAAO,KAAK,EAAE;IACZ,gBAAA,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC;IAC/D,gBAAA,MAAM,KAAK;gBACf;YACJ,CAAC,GAAG;YAEJ,OAAO,IAAI,CAAC,WAAW;QAC3B;IAEA;;IAEG;QACK,MAAM,eAAe,CAAC,UAAkB,EAAA;YAC5C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAI;gBACnC,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;IAC/C,YAAA,MAAM,CAAC,GAAG,GAAG,UAAU;IACvB,YAAA,MAAM,CAAC,KAAK,GAAG,IAAI;IAEnB,YAAA,MAAM,CAAC,MAAM,GAAG,MAAK;;IAEjB,gBAAA,IAAI,OAAQ,MAAc,CAAC,KAAK,KAAK,UAAU,EAAE;wBAC5C,MAAc,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,MAAmB,KAAI;4BACjD,OAAO,CAAC,MAAM,CAAC;IACnB,oBAAA,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;oBACpB;yBAAO;IACH,oBAAA,MAAM,CAAC,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;oBAC/C;IACJ,YAAA,CAAC;IAED,YAAA,MAAM,CAAC,OAAO,GAAG,MAAK;oBAClB,MAAM,CAAC,IAAI,KAAK,CAAC,kBAAkB,UAAU,CAAA,CAAE,CAAC,CAAC;IACrD,YAAA,CAAC;IAED,YAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;IACrC,QAAA,CAAC,CAAC;QACN;IAEA;;IAEG;IACH,IAAA,MAAM,aAAa,CAAC,IAAgB,EAAE,EAAkD,EAAA;IACpF,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;IACnB,YAAA,MAAM,IAAI,CAAC,IAAI,EAAE;YACrB;IAEA,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;IACd,YAAA,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC;YACnD;;YAGA,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;IAE/C,QAAA,IAAI;;IAEA,YAAA,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE;IACrB,gBAAA,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC;gBACvD;;IAGA,YAAA,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE;IACjC,YAAA,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE;;IAGnC,YAAA,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE;;IAGvC,YAAA,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE;IAClC,YAAA,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE;;IAGlC,YAAA,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE,EAAE;IAC9B,gBAAA,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC;gBACvD;;gBAGA,MAAM,GAAG,GAAG,CAAC;gBACb,MAAM,KAAK,GAAG,CAAC;gBACf,MAAM,IAAI,GAAG,CAAC;;IAGd,YAAA,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC;;IAGjE,YAAA,MAAM,cAAc,GAAG,QAAQ,CAAC,6BAA6B,CACzD,GAAG,EACH,KAAK,EACL,IAAI,EACJ,YAAY,CAAC,WAAW,CAC3B;;IAGD,YAAA,MAAM,cAAc,GAAG,IAAI,UAAU,CAAC,cAAc,CAAC;;gBAGrD,MAAM,MAAM,GAAG,QAAQ,CAAC,cAAc,CAClC,cAAc,EACd,GAAG,EACH,KAAK,EACL,IAAI,EACJ,YAAY,CAAC,WAAW,EACxB,CAAC,EACD,CAAC,CAAC,EACF,CAAC,CAAC,CACL;IAED,YAAA,IAAI,MAAM,KAAK,CAAC,EAAE;IACd,gBAAA,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;gBAC9C;gBAEA,OAAO;IACH,gBAAA,IAAI,EAAE,cAAc;oBACpB,KAAK;oBACL,MAAM;oBACN,MAAM,EAAE,YAAY,CAAC,QAAQ;oBAC7B,cAAc,EAAE,YAAY,CAAC,gBAAgB;oBAC7C,UAAU,EAAE,YAAY,CAAC;iBAC5B;YAEL;oBAAU;gBACN,QAAQ,CAAC,KAAK,EAAE;gBAChB,QAAQ,CAAC,MAAM,EAAE;YACrB;QACJ;IAEA;;IAEG;IACK,IAAA,gBAAgB,CAAC,EAAkD,EAAE,WAAoB,IAAI,EAAE,UAAmB,KAAK,EAAA;IAM3H,QAAA,MAAM,QAAQ,GAAG,EAAE,YAAY,sBAAsB;;IAGrD,QAAA,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,+BAA+B,CAAC;IAChD,YAAA,EAAE,CAAC,YAAY,CAAC,sCAAsC,CAAC;YACpE,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,8BAA8B,CAAC;YAC5D,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,+BAA+B,CAAC;YAC7D,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,8BAA8B,CAAC;YAC3D,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,+BAA+B,CAAC;IAC7D,QAAA,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,gCAAgC,CAAC;IACjD,YAAA,EAAE,CAAC,YAAY,CAAC,uCAAuC,CAAC;;;;;IAOtE,QAAA,IAAI,QAAQ,IAAI,IAAI,IAAI,QAAQ,EAAE;gBAC9B,OAAO;oBACH,WAAW,EAAE,YAAY,CAAC,MAAM;oBAChC,QAAQ,EAAE,EAAE,CAAC,IAAI;oBACjB,gBAAgB,EAAG,IAAY,CAAC,8BAA8B;IAC9D,gBAAA,UAAU,EAAE;iBACf;YACL;;;IAIA,QAAA,IAAI,IAAI,IAAI,QAAQ,EAAE;gBAClB,OAAO;oBACH,WAAW,EAAE,YAAY,CAAC,GAAG;oBAC7B,QAAQ,EAAE,EAAE,CAAC,IAAI;oBACjB,gBAAgB,EAAG,IAAY,CAAC,6BAA6B;IAC7D,gBAAA,UAAU,EAAE;iBACf;YACL;;YAGA,IAAI,IAAI,EAAE;gBACN,OAAO;oBACH,WAAW,EAAE,YAAY,CAAC,GAAG;oBAC7B,QAAQ,EAAE,EAAE,CAAC,GAAG;oBAChB,gBAAgB,EAAG,IAAY,CAAC,4BAA4B;IAC5D,gBAAA,UAAU,EAAE;iBACf;YACL;;YAGA,IAAI,IAAI,EAAE;gBACN,OAAO;oBACH,WAAW,EAAE,YAAY,CAAC,QAAQ;oBAClC,QAAQ,EAAE,EAAE,CAAC,IAAI;oBACjB,gBAAgB,EAAG,IAAY,CAAC,4BAA4B;IAC5D,gBAAA,UAAU,EAAE;iBACf;YACL;;IAGA,QAAA,IAAI,QAAQ,IAAI,GAAG,EAAE;gBACjB,OAAO;oBACH,WAAW,EAAE,YAAY,CAAC,IAAI;oBAC9B,QAAQ,EAAE,EAAE,CAAC,IAAI;IACjB,gBAAA,gBAAgB,EAAG,GAAW,CAAC,yBAAyB,IAAI,MAAM;IAClE,gBAAA,UAAU,EAAE;iBACf;YACL;;IAGA,QAAA,IAAI,IAAI,IAAI,GAAG,EAAE;gBACb,OAAO;oBACH,WAAW,EAAE,YAAY,CAAC,IAAI;oBAC9B,QAAQ,EAAE,EAAE,CAAC,GAAG;IAChB,gBAAA,gBAAgB,EAAG,IAAY,EAAE,yBAAyB,IAAI,MAAM;IACpE,gBAAA,UAAU,EAAE;iBACf;YACL;;YAGA,IAAI,KAAK,EAAE;gBACP,OAAO;IACH,gBAAA,WAAW,EAAE,QAAQ,GAAG,YAAY,CAAC,aAAa,GAAG,YAAY,CAAC,YAAY;oBAC9E,QAAQ,EAAE,EAAE,CAAC,IAAI;oBACjB,gBAAgB,EAAG,KAAa,CAAC,gCAAgC;IACjE,gBAAA,UAAU,EAAE;iBACf;YACL;;YAGA,OAAO;gBACH,WAAW,EAAE,YAAY,CAAC,MAAM;gBAChC,QAAQ,EAAE,EAAE,CAAC,IAAI;gBACjB,gBAAgB,EAAE,EAAE,CAAC,IAAI;IACzB,YAAA,UAAU,EAAE;aACf;QACL;IAEA;;IAEG;QACH,OAAO,GAAA;IACH,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI;IAClB,QAAA,IAAI,CAAC,WAAW,GAAG,KAAK;IACxB,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI;QAC3B;IACH;;IC7VD;;;IAGG;UACU,iBAAiB,CAAA;IAO1B,IAAA,WAAA,CACI,MAAqB,EACrB,UAA2B,EAC3B,EAAkD,EAAA;IAN9C,QAAA,IAAA,CAAA,YAAY,GAAqB,IAAI,GAAG,EAAE;IAC1C,QAAA,IAAA,CAAA,mBAAmB,GAAmI,IAAI,GAAG,EAAE;IAOnK,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;IACpB,QAAA,IAAI,CAAC,UAAU,GAAG,UAAU;IAC5B,QAAA,IAAI,CAAC,MAAM,GAAG,EAAE;QACpB;IAEA;;;IAGG;IACH,IAAA,MAAM,WAAW,CAAC,SAAiB,EAAE,KAAU,EAAA;IAC3C,QAAA,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;;YAGpC,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;IAClC,YAAAA,wBAAU,CAAC,GAAG,CAAC,6BAA6B,SAAS,CAAA,CAAE,CAAC;gBACxD,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAE;YAC5C;;YAGA,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC;IACzD,QAAA,IAAI,UAAU,GAAG,CAAC,EAAE;IAChB,YAAA,MAAM,IAAI,KAAK,CAAC,sBAAsB,SAAS,CAAA,CAAE,CAAC;YACtD;;YAGA,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC;YACjD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAKC,uBAAS,CAAC,UAAU,EAAE;IAC7C,YAAA,MAAM,IAAI,KAAK,CAAC,2BAA2B,SAAS,CAAA,CAAE,CAAC;YAC3D;;YAGA,MAAM,GAAG,GAAG,SAAS;YACrB,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;;YAGrC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC;YAClD,IAAI,CAAC,IAAI,EAAE;IACP,YAAA,MAAM,IAAI,KAAK,CAAC,mCAAmC,SAAS,CAAA,CAAE,CAAC;YACnE;IAEA,QAAA,MAAM,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE;IACxC,QAAA,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC;YAChED,wBAAU,CAAC,GAAG,CAAC,CAAA,+BAAA,EAAkC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA,IAAA,EAAO,UAAU,CAAC,KAAK,CAAA,CAAA,EAAI,UAAU,CAAC,MAAM,CAAA,CAAA,CAAG,CAAC;;IAGhJ,QAAA,MAAM,qBAAqB,GAAG;IAC1B,YAAA,OAAO,EAAE,CAAC;wBACN,IAAI,EAAE,UAAU,CAAC,IAAI;wBACrB,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,MAAM,EAAE,UAAU,CAAC;qBACtB,CAAC;gBACF,KAAK,EAAE,UAAU,CAAC,KAAK;gBACvB,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,cAAc,EAAE,UAAU,CAAC,cAAc;gBACzC,UAAU,EAAE,UAAU,CAAC,UAAU;IACjC,YAAA,cAAc,EAAE,KAAK;gBACrB,MAAM,EAAE,UAAU,CAAC;aACtB;IAED,QAAA,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC,GAAG,EAAE,qBAAqB,CAAC;;YAGrF,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,UAAU,CAAC;IAC7D,QAAA,IAAI,QAAQ,EAAE,SAAS,KAAK,CAAC,EAAE;gBAC3B,MAAM,SAAS,GAAG,aAAa,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,SAAS;gBACvD,IAAI,SAAS,EAAE;oBACX,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC;IACxC,gBAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,OAAO,CAAC;IAClE,gBAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,OAAO,CAAC;oBAClE,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC;gBACvC;YACJ;YAEA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC;IAE/C,QAAAA,wBAAU,CAAC,GAAG,CAAC,2CAA2C,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA,QAAA,CAAU,CAAC;IAChH,QAAA,OAAO,aAAa;QACxB;IAEA;;;IAGG;IACH,IAAA,MAAM,gBAAgB,CAAC,KAAa,EAAE,KAAU,EAAA;IAC5C,QAAA,MAAM,GAAG,GAAG,CAAA,QAAA,EAAW,KAAK,EAAE;;YAG9B,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;gBAC5B,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;YAClC;;YAGA,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;;YAGrC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;YAC7C,IAAI,CAAC,IAAI,EAAE;IACP,YAAA,MAAM,IAAI,KAAK,CAAC,yCAAyC,KAAK,CAAA,CAAE,CAAC;YACrE;;IAGA,QAAA,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC;;IAGhE,QAAA,MAAM,qBAAqB,GAAG;IAC1B,YAAA,OAAO,EAAE,CAAC;wBACN,IAAI,EAAE,UAAU,CAAC,IAAI;wBACrB,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,MAAM,EAAE,UAAU,CAAC;qBACtB,CAAC;gBACF,KAAK,EAAE,UAAU,CAAC,KAAK;gBACvB,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,cAAc,EAAE,UAAU,CAAC,cAAc;gBACzC,UAAU,EAAE,UAAU,CAAC,UAAU;IACjC,YAAA,cAAc,EAAE,KAAK;IACrB,YAAA,MAAM,EAAE,UAAU,CAAC,cAAc;aACpC;;IAGD,QAAA,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC,GAAG,EAAE,qBAAqB,CAAC;;YAGrF,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,aAAa,CAAC;IAEzC,QAAA,OAAO,aAAa;QACxB;IAEA;;IAEG;IACK,IAAA,MAAM,oBAAoB,CAAC,KAAa,EAAE,EAAkD,EAAA;;YAEhG,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;YAC7C,IAAI,CAAC,IAAI,EAAE;IACP,YAAA,MAAM,IAAI,KAAK,CAAC,yCAAyC,KAAK,CAAA,CAAE,CAAC;YACrE;;YAGA,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC;IACxD,QAAA,MAAM,MAAM,GAAG,QAAQ,EAAE,aAAa,KAAK,SAAS;YAEpD,IAAI,MAAM,EAAE;;IAER,YAAA,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC;;IAGhE,YAAA,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,EAAE;gBAClC,IAAI,CAAC,OAAO,EAAE;IACV,gBAAA,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC;gBACrD;gBAEA,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC;IAEtC,YAAA,IAAI,UAAU,CAAC,UAAU,EAAE;oBACvB,EAAE,CAAC,oBAAoB,CACnB,EAAE,CAAC,UAAU,EACb,CAAC,EACD,UAAU,CAAC,cAAe,EAC1B,UAAU,CAAC,KAAK,EAChB,UAAU,CAAC,MAAM,EACjB,CAAC,EACD,UAAU,CAAC,IAAI,CAClB;gBACL;qBAAO;IACH,gBAAA,EAAE,CAAC,UAAU,CACT,EAAE,CAAC,UAAU,EACb,CAAC,EACD,UAAU,CAAC,cAAe,EAC1B,UAAU,CAAC,KAAK,EAChB,UAAU,CAAC,MAAM,EACjB,CAAC,EACD,UAAU,CAAC,MAAM,EACjB,EAAE,CAAC,aAAa,EAChB,UAAU,CAAC,IAAI,CAClB;gBACL;IAEA,YAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,aAAa,CAAC;IACpE,YAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,aAAa,CAAC;;IAEpE,YAAA,MAAM,UAAU,GAAG,QAAQ,EAAE,SAAS,KAAK,CAAC;gBAC5C,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,UAAU,GAAG,EAAE,CAAC,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC;gBAC3F,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,UAAU,GAAG,EAAE,CAAC,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC;gBAE3F,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC;gBAEnC,OAAO;oBACH,OAAO;oBACP,KAAK,EAAE,UAAU,CAAC,KAAK;oBACvB,MAAM,EAAE,UAAU,CAAC;iBACtB;YACL;iBAAO;;gBAEH,OAAO,MAAM,IAAI,CAAC,gCAAgC,CAAC,IAAI,EAAE,EAAE,CAAC;YAChE;QACJ;IAEA;;IAEG;IACK,IAAA,MAAM,gCAAgC,CAAC,IAAgB,EAAE,EAAkD,EAAA;YAC/G,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAI;gBACnC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,MAAqB,CAAC,CAAC;gBACnD,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC;IAErC,YAAA,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE;IACvB,YAAA,GAAG,CAAC,MAAM,GAAG,MAAK;IACd,gBAAA,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,EAAE;oBAClC,IAAI,CAAC,OAAO,EAAE;IACV,oBAAA,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC;IACxB,oBAAA,MAAM,CAAC,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;wBACnD;oBACJ;oBAEA,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC;oBACtC,EAAE,CAAC,UAAU,CACT,EAAE,CAAC,UAAU,EACb,CAAC,EACD,EAAE,CAAC,IAAI,EACP,EAAE,CAAC,IAAI,EACP,EAAE,CAAC,aAAa,EAChB,GAAG,CACN;IAED,gBAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,aAAa,CAAC;IACpE,gBAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,aAAa,CAAC;IACpE,gBAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,MAAM,CAAC;IACjE,gBAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,MAAM,CAAC;oBAEjE,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC;IAEnC,gBAAA,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC;IAExB,gBAAA,OAAO,CAAC;wBACJ,OAAO;wBACP,KAAK,EAAE,GAAG,CAAC,KAAK;wBAChB,MAAM,EAAE,GAAG,CAAC;IACf,iBAAA,CAAC;IACN,YAAA,CAAC;IAED,YAAA,GAAG,CAAC,OAAO,GAAG,MAAK;IACf,gBAAA,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC;IACxB,gBAAA,MAAM,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC7C,YAAA,CAAC;IAED,YAAA,GAAG,CAAC,GAAG,GAAG,GAAG;IACjB,QAAA,CAAC,CAAC;QACN;IAEA;;;IAGG;IACH,IAAA,MAAM,SAAS,CAAC,SAAiB,EAAE,YAA2B,EAAA;;YAE1D,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC;IACzD,QAAA,IAAI,UAAU,GAAG,CAAC,EAAE;IAChB,YAAA,MAAM,IAAI,KAAK,CAAC,oBAAoB,SAAS,CAAA,CAAE,CAAC;YACpD;;YAGA,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC;YACjD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAKC,uBAAS,CAAC,KAAK,EAAE;IACxC,YAAA,MAAM,IAAI,KAAK,CAAC,uBAAuB,SAAS,CAAA,CAAE,CAAC;YACvD;YAEA,OAAO,MAAM,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,YAAY,CAAC;QAChE;IAEA;;IAEG;IACH,IAAA,MAAM,gBAAgB,CAAC,KAAa,EAAE,YAA2B,EAAA;YAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;YAC7C,IAAI,CAAC,IAAI,EAAE;IACP,YAAA,MAAM,IAAI,KAAK,CAAC,uCAAuC,KAAK,CAAA,CAAE,CAAC;YACnE;;IAGA,QAAA,MAAM,GAAG,GAAG,YAAY,IAAI,IAAI,YAAY,EAAE;;YAG9C,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAgB;YACxG,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,WAAW,CAAC;IAE1D,QAAA,OAAO,WAAW;QACtB;IAEA;;IAEG;QACH,MAAM,kBAAkB,CAAC,KAAa,EAAA;YAClC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;YAC7C,IAAI,CAAC,IAAI,EAAE;IACP,YAAA,MAAM,IAAI,KAAK,CAAC,kCAAkC,KAAK,CAAA,CAAE,CAAC;YAC9D;IAEA,QAAA,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,MAAqB,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;YAC1E,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC;YAErC,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;IAC7C,QAAA,KAAK,CAAC,QAAQ,GAAG,IAAI;IACrB,QAAA,KAAK,CAAC,GAAG,GAAG,GAAG;IAEf,QAAA,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC/D,QAAA,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAE/D,QAAA,OAAO,KAAK;QAChB;IAGA;;;;IAIG;IACH,IAAA,MAAM,eAAe,CACjB,SAAiB,EACjB,KAAU,EACV,OAAgB,EAAA;;YAGhB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC;IACzD,QAAA,IAAI,UAAU,GAAG,CAAC,EAAE;IAChB,YAAA,MAAM,IAAI,KAAK,CAAC,0BAA0B,SAAS,CAAA,CAAE,CAAC;YAC1D;YAEA,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC;YACjD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE;IAC1B,YAAA,MAAM,IAAI,KAAK,CAAC,+BAA+B,SAAS,CAAA,CAAE,CAAC;YAC/D;;YAGA,MAAM,IAAI,GAAI,IAAI,CAAC,MAAc,CAAC,wBAAwB,CAAC,UAAU,CAAC;YACtE,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;IAC1B,YAAA,MAAM,IAAI,KAAK,CAAC,gBAAgB,SAAS,CAAA,0BAAA,CAA4B,CAAC;YAC1E;;IAGA,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS;YACjC,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,KAAK,CAAC;;YAGzC,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC;YACpD,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;IACtC,QAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK;IAC7B,QAAA,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM;;IAG/B,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;IACtD,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC;;;;YAKrD,MAAM,KAAK,GAAG,SAAS;YACvB,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;;;gBAG/B,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC,KAAK,EAAE;IACzD,gBAAA,OAAO,EAAE,EAAE;IACX,gBAAA,KAAK,EAAE,QAAQ;IACf,gBAAA,MAAM,EAAE,SAAS;oBACjB,cAAc,EAAE,MAAM,CAAC,oBAAoB;IAC3C,gBAAA,UAAU,EAAE,IAAI;IAChB,gBAAA,cAAc,EAAE,KAAK;oBACrB,MAAM,EAAE,MAAM,CAAC,oBAAoB;IACtC,aAAA,CAAC;;gBAGF,IAAI,SAAS,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE;oBACxB,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACpC,gBAAA,QAAQ,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS;IACrC,gBAAA,QAAQ,CAAC,KAAK,GAAG,QAAQ;IACzB,gBAAA,QAAQ,CAAC,MAAM,GAAG,SAAS;IAC3B,gBAAA,QAAQ,CAAC,mBAAmB,GAAG,IAAI;gBACvC;;gBAGA,IAAI,KAAK,GAAG,CAAC;gBACb,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,EAAE;oBACjE,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,OAAO,IAAI,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,EAAE;IACpE,oBAAA,SAAS,CAAC,GAAG,CACT,KAAK;IACL,oBAAA,CAAC;wBACD,GAAG,GAAG,UAAU,EAChB,GAAG,GAAG,WAAW,EACjB,UAAU,EACV,WAAW,CACd;IACD,oBAAA,KAAK,EAAE;oBACX;gBACJ;YACJ;;IAGA,QAAA,MAAM,YAAY,GAAG,OAAO,IAAI,CAAA,EAAG,SAAS,OAAO;YACnD,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE;IACnC,YAAA,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;IACf,gBAAA,GAAG,EAAE,YAAY;oBACjB,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,KAAK,EAAE;IAC5C,oBAAA,KAAK,EAAE,CAAC;IACR,oBAAA,GAAG,EAAE,IAAI,CAAC,UAAU,GAAG,CAAC;qBAC3B,CAAC;oBACF,SAAS,EAAE,IAAI,CAAC,SAAS;oBACzB,MAAM,EAAE,EAAE;IACb,aAAA,CAAC;YACN;IAEA,QAAA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE;QACnD;IAEA;;IAEG;IACH,IAAA,sBAAsB,CAAC,SAAiB,EAAA;YACpC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC;YACzD,IAAI,UAAU,GAAG,CAAC;IAAE,YAAA,OAAO,IAAI;YAC/B,OAAQ,IAAI,CAAC,MAAc,CAAC,wBAAwB,CAAC,UAAU,CAAC;QACpE;IAEA;;IAEG;QACH,UAAU,GAAA;IACN,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE;QACnC;IAEA;;IAEG;QACH,aAAa,GAAA;IACT,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE;QACtC;IAEA;;IAEG;IACH,IAAA,YAAY,CAAC,KAAa,EAAA;YACtB,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC;QAC1C;IAEA;;IAEG;IACH,IAAA,kBAAkB,CAAC,KAAa,EAAA;YAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC;QAClD;IAEA;;IAEG;IACH,IAAA,gBAAgB,CAAC,KAAa,EAAA;YAC1B,OAAO,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC;QAChD;IAEA;;IAEG;QACH,OAAO,GAAA;;IAEH,QAAA,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE;IACzB,QAAA,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE;;IAGhC,QAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;QACvB;IACH;;ICpdD;;;;;;;;;;IAUG;UACU,mBAAmB,CAAA;IAO5B;;IAEG;IACH,IAAA,aAAa,IAAI,CAAC,GAAW,EAAE,OAAoC,EAAA;;IAE/D,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;IACnB,YAAA,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAClC;;IAGA,QAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC;IACjC,QAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;gBACd,MAAM,IAAI,KAAK,CAAC,CAAA,gBAAA,EAAmB,GAAG,CAAA,EAAA,EAAK,QAAQ,CAAC,UAAU,CAAA,CAAE,CAAC;YACrE;IAEA,QAAA,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE;;YAGhD,MAAM,MAAM,GAAG,IAAIC,2BAAa,CAAC,IAAI,CAAC,QAAQ,CAAC;IAC/C,QAAA,MAAM,MAAM,CAAC,IAAI,EAAE;IACnB,QAAA,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;;IAG9B,QAAA,OAAO,IAAI,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,UAAW,EAAE,IAAI,CAAC,EAAG,CAAC;QACpE;IAEA;;IAEG;IACH,IAAA,aAAa,cAAc,CACvB,IAA+B,EAC/B,OAAoC,EAAA;;IAGpC,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;IACnB,YAAA,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAClC;;IAGA,QAAA,IAAI,WAAwB;IAC5B,QAAA,IAAI,IAAI,YAAY,WAAW,EAAE;gBAC7B,WAAW,GAAG,IAAI;YACtB;iBAAO,IAAI,OAAO,IAAI,KAAK,WAAW,IAAI,IAAI,YAAY,IAAI,EAAE;IAC5D,YAAA,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE;YAC1C;iBAAO,IAAI,aAAa,IAAI,IAAI,IAAI,OAAQ,IAAY,CAAC,WAAW,KAAK,UAAU,EAAE;IACjF,YAAA,WAAW,GAAG,MAAO,IAAY,CAAC,WAAW,EAAE;YACnD;iBAAO;IACH,YAAA,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC;YAC9D;;YAGA,MAAM,MAAM,GAAG,IAAIA,2BAAa,CAAC,IAAI,CAAC,QAAQ,CAAC;IAC/C,QAAA,MAAM,MAAM,CAAC,IAAI,EAAE;IACnB,QAAA,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;;IAG9B,QAAA,OAAO,IAAI,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,UAAW,EAAE,IAAI,CAAC,EAAG,CAAC;QACpE;IAEA;;IAEG;IACK,IAAA,aAAa,UAAU,CAAC,OAAoC,EAAA;YAChE,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,8BAA8B;IACnE,QAAA,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,SAAS;;IAGjD,QAAA,IAAI,OAAO,EAAE,EAAE,EAAE;IACb,YAAA,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC,EAAE;IACpB,YAAA,IAAI,CAAC,KAAK,GAAG,KAAK;YACtB;iBAAO;;gBAEH,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;IAC/C,YAAA,MAAM,CAAC,KAAK,GAAG,CAAC;IAChB,YAAA,MAAM,CAAC,MAAM,GAAG,CAAC;IACjB,YAAA,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM;IAC7B,YAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;IAEjC,YAAA,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;IACnE,YAAA,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;IACV,gBAAA,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC;gBACrD;IACA,YAAA,IAAI,CAAC,KAAK,GAAG,IAAI;YACrB;;YAGA,IAAI,CAAC,UAAU,GAAG,IAAI,eAAe,CAAC,SAAS,CAAC;IAChD,QAAA,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;IAE5B,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI;QAC3B;IAEA;;IAEG;IACH,IAAA,OAAO,OAAO,GAAA;IACV,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE;IACjB,YAAA,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE;IACzB,YAAA,IAAI,CAAC,UAAU,GAAG,IAAI;YAC1B;;YAGA,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,KAAK,EAAE;IACvB,YAAA,MAAM,MAAM,GAAI,IAAI,CAAC,EAAU,CAAC,MAAM;IACtC,YAAA,IAAI,MAAM,IAAI,MAAM,CAAC,UAAU,EAAE;IAC7B,gBAAA,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC;gBACzC;IACA,YAAA,IAAI,CAAC,EAAE,GAAG,IAAI;YAClB;IAEA,QAAA,IAAI,CAAC,WAAW,GAAG,KAAK;QAC5B;;IArHe,mBAAA,CAAA,UAAU,GAA2B,IAAI;IACzC,mBAAA,CAAA,WAAW,GAAG,KAAK;IACnB,mBAAA,CAAA,EAAE,GAA0D,IAAI;IAChE,mBAAA,CAAA,KAAK,GAAG,KAAK;IACb,mBAAA,CAAA,QAAQ,GAAW,8BAA8B;;;;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"stowkit-phaser-loader.js","sources":["../src/BasisTranscoder.ts","../src/StowKitPhaserPack.ts","../src/StowKitPhaserLoader.ts"],"sourcesContent":["/**\n * BasisTranscoder - Manually decode KTX2 textures to WebGL textures\n * Used for Phaser which doesn't have built-in KTX2 support\n */\n\ninterface BasisModule {\n initializeBasis: () => void;\n BasisFile: new (data: Uint8Array) => BasisFile;\n KTX2File: new (data: Uint8Array) => KTX2File;\n}\n\ninterface BasisFile {\n getNumImages(): number;\n getNumLevels(imageIndex: number): number;\n getImageWidth(imageIndex: number, level: number): number;\n getImageHeight(imageIndex: number, level: number): number;\n startTranscoding(): boolean;\n getImageTranscodedSizeInBytes(imageIndex: number, level: number, format: number): number;\n transcodeImage(\n dst: Uint8Array,\n imageIndex: number,\n level: number,\n format: number,\n unused: number,\n getAlphaForOpaqueFormats: number\n ): number;\n close(): void;\n delete(): void;\n}\n\ninterface KTX2File {\n isValid(): boolean;\n isUASTC(): boolean;\n isETC1S(): boolean;\n isHDR(): boolean;\n getWidth(): number;\n getHeight(): number;\n getLayers(): number;\n getLevels(): number;\n getFaces(): number;\n getHasAlpha(): boolean;\n getDFDFlags(): number;\n startTranscoding(): boolean;\n getImageLevelInfo(mip: number, layer: number, face: number): any;\n getImageTranscodedSizeInBytes(mip: number, layer: number, face: number, format: number): number;\n transcodeImage(\n dst: Uint8Array,\n mip: number,\n layer: number,\n face: number,\n format: number,\n unused1: number,\n unused2: number,\n unused3: number\n ): number;\n close(): void;\n delete(): void;\n}\n\n// Basis transcoder formats (from Three.js KTX2Loader.TranscoderFormat)\nconst BASIS_FORMAT = {\n ETC1: 0,\n ETC2: 1,\n BC1: 2, // DXT1\n BC3: 3, // DXT5\n BC4: 4,\n BC5: 5,\n BC7_M6_OPAQUE_ONLY: 6,\n BC7_M5: 7, // BC7\n PVRTC1_4_RGB: 8,\n PVRTC1_4_RGBA: 9,\n ASTC_4x4: 10,\n ATC_RGB: 11,\n ATC_RGBA: 12,\n RGBA32: 13,\n RGB565: 14,\n BGR565: 15,\n RGBA4444: 16,\n BC6H: 22,\n RGB_HALF: 24,\n RGBA_HALF: 25,\n};\n\nexport interface TranscodedTexture {\n data: Uint8Array;\n width: number;\n height: number;\n format: number;\n internalFormat?: number;\n compressed: boolean;\n}\n\nexport class BasisTranscoder {\n private module: BasisModule | null = null;\n private initialized = false;\n private initPromise: Promise<void> | null = null;\n private basisPath: string;\n\n constructor(basisPath: string = '/basis/') {\n this.basisPath = basisPath;\n }\n\n /**\n * Initialize the Basis Universal transcoder\n */\n async init(): Promise<void> {\n if (this.initialized) return;\n if (this.initPromise) return this.initPromise;\n\n this.initPromise = (async () => {\n try {\n // Load the basis transcoder\n const scriptPath = `${this.basisPath}basis_transcoder.js`;\n \n // Import the basis module\n const BasisModule = await this.loadBasisModule(scriptPath);\n \n // Initialize\n BasisModule.initializeBasis();\n this.module = BasisModule;\n this.initialized = true;\n } catch (error) {\n console.error('[BasisTranscoder] Failed to initialize:', error);\n throw error;\n }\n })();\n\n return this.initPromise;\n }\n\n /**\n * Load the basis transcoder module\n */\n private async loadBasisModule(scriptPath: string): Promise<BasisModule> {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = scriptPath;\n script.async = true;\n \n script.onload = () => {\n // The basis transcoder exposes a global BASIS function\n if (typeof (window as any).BASIS === 'function') {\n (window as any).BASIS().then((module: BasisModule) => {\n resolve(module);\n }).catch(reject);\n } else {\n reject(new Error('BASIS module not found'));\n }\n };\n \n script.onerror = () => {\n reject(new Error(`Failed to load ${scriptPath}`));\n };\n \n document.head.appendChild(script);\n });\n }\n\n /**\n * Transcode KTX2 data to a WebGL-compatible format\n */\n async transcodeKTX2(data: Uint8Array, gl: WebGLRenderingContext | WebGL2RenderingContext): Promise<TranscodedTexture> {\n if (!this.initialized) {\n await this.init();\n }\n\n if (!this.module) {\n throw new Error('Basis module not initialized');\n }\n\n // Create KTX2File from data\n const ktx2File = new this.module.KTX2File(data);\n \n try {\n // Validate file\n if (!ktx2File.isValid()) {\n throw new Error('Invalid or unsupported KTX2 file');\n }\n\n // Get image dimensions\n const width = ktx2File.getWidth();\n const height = ktx2File.getHeight();\n \n // Check if the texture has alpha\n const hasAlpha = ktx2File.getHasAlpha();\n \n // Check format type (UASTC or ETC1S)\n const isUASTC = ktx2File.isUASTC();\n const isETC1S = ktx2File.isETC1S();\n\n // Start transcoding\n if (!ktx2File.startTranscoding()) {\n throw new Error('Failed to start KTX2 transcoding');\n }\n\n // Use first mip level, first layer, first face\n const mip = 0;\n const layer = 0;\n const face = 0;\n\n // Detect best format for this device and file type\n const targetFormat = this.detectBestFormat(gl, hasAlpha, isETC1S);\n \n // Get transcoded size\n const transcodedSize = ktx2File.getImageTranscodedSizeInBytes(\n mip,\n layer,\n face,\n targetFormat.basisFormat\n );\n\n // Allocate output buffer\n const transcodedData = new Uint8Array(transcodedSize);\n\n // Transcode (parameters: dst, mip, layer, face, format, unused1, unused2, unused3)\n const result = ktx2File.transcodeImage(\n transcodedData,\n mip,\n layer,\n face,\n targetFormat.basisFormat,\n 0,\n -1,\n -1\n );\n\n if (result === 0) {\n throw new Error('KTX2 transcoding failed');\n }\n\n return {\n data: transcodedData,\n width,\n height,\n format: targetFormat.glFormat,\n internalFormat: targetFormat.glInternalFormat,\n compressed: targetFormat.compressed\n };\n\n } finally {\n ktx2File.close();\n ktx2File.delete();\n }\n }\n\n /**\n * Detect the best compression format supported by the device\n */\n private detectBestFormat(gl: WebGLRenderingContext | WebGL2RenderingContext, hasAlpha: boolean = true, isETC1S: boolean = false): {\n basisFormat: number;\n glFormat: number;\n glInternalFormat: number;\n compressed: boolean;\n } {\n const isWebGL2 = gl instanceof WebGL2RenderingContext;\n\n // Check for extensions\n const s3tc = gl.getExtension('WEBGL_compressed_texture_s3tc') || \n gl.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc');\n const bptc = gl.getExtension('EXT_texture_compression_bptc');\n const etc1 = gl.getExtension('WEBGL_compressed_texture_etc1');\n const etc = gl.getExtension('WEBGL_compressed_texture_etc');\n const astc = gl.getExtension('WEBGL_compressed_texture_astc');\n const pvrtc = gl.getExtension('WEBGL_compressed_texture_pvrtc') ||\n gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc');\n\n // For ETC1S: Use BC1 (no alpha support in ETC1S)\n // For UASTC with alpha: Use BC3/BC7\n // For UASTC without alpha: Use BC1\n \n // BC7 on desktop with WebGL2 (requires separate BPTC extension)\n if (isWebGL2 && bptc && hasAlpha) {\n return {\n basisFormat: BASIS_FORMAT.BC7_M5,\n glFormat: gl.RGBA,\n glInternalFormat: (bptc as any).COMPRESSED_RGBA_BPTC_UNORM_EXT,\n compressed: true\n };\n }\n\n // BC3 (DXT5) on desktop - for textures with alpha\n // Basis handles ETC1S alpha via a separate slice transcoded into BC3's alpha block\n if (s3tc && hasAlpha) {\n return {\n basisFormat: BASIS_FORMAT.BC3,\n glFormat: gl.RGBA,\n glInternalFormat: (s3tc as any).COMPRESSED_RGBA_S3TC_DXT5_EXT,\n compressed: true\n };\n }\n\n // BC1 (DXT1) on desktop - for textures without alpha\n if (s3tc) {\n return {\n basisFormat: BASIS_FORMAT.BC1,\n glFormat: gl.RGB,\n glInternalFormat: (s3tc as any).COMPRESSED_RGB_S3TC_DXT1_EXT,\n compressed: true\n };\n }\n\n // ASTC on mobile (best quality)\n if (astc) {\n return {\n basisFormat: BASIS_FORMAT.ASTC_4x4,\n glFormat: gl.RGBA,\n glInternalFormat: (astc as any).COMPRESSED_RGBA_ASTC_4x4_KHR,\n compressed: true\n };\n }\n\n // ETC2 on mobile with WebGL2\n if (isWebGL2 && etc) {\n return {\n basisFormat: BASIS_FORMAT.ETC2,\n glFormat: gl.RGBA,\n glInternalFormat: (etc as any).COMPRESSED_RGBA8_ETC2_EAC || 0x9278,\n compressed: true\n };\n }\n\n // ETC1 on mobile\n if (etc1 || etc) {\n return {\n basisFormat: BASIS_FORMAT.ETC1,\n glFormat: gl.RGB,\n glInternalFormat: (etc1 as any)?.COMPRESSED_RGB_ETC1_WEBGL || 0x8D64,\n compressed: true\n };\n }\n\n // PVRTC on iOS (last resort for compressed)\n if (pvrtc) {\n return {\n basisFormat: hasAlpha ? BASIS_FORMAT.PVRTC1_4_RGBA : BASIS_FORMAT.PVRTC1_4_RGB,\n glFormat: gl.RGBA,\n glInternalFormat: (pvrtc as any).COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,\n compressed: true\n };\n }\n\n // Fallback to uncompressed RGBA\n return {\n basisFormat: BASIS_FORMAT.RGBA32,\n glFormat: gl.RGBA,\n glInternalFormat: gl.RGBA,\n compressed: false\n };\n }\n\n /**\n * Dispose resources\n */\n dispose(): void {\n this.module = null;\n this.initialized = false;\n this.initPromise = null;\n }\n}\n\n","import { StowKitReader, AssetType, PerfLogger } from '@series-inc/stowkit-reader';\nimport { BasisTranscoder } from './BasisTranscoder';\n\nexport interface TextureData {\n texture: WebGLTexture;\n width: number;\n height: number;\n}\n\n/**\n * Represents an opened StowKit pack for Phaser\n * Supports loading images and audio only (no 3D models)\n */\nexport class StowKitPhaserPack {\n public reader: StowKitReader;\n private transcoder: BasisTranscoder;\n private tempGl: WebGLRenderingContext | WebGL2RenderingContext;\n private textureCache: Map<string, any> = new Map();\n private transcodedDataCache: Map<number, { data: Uint8Array, width: number, height: number, compressed: boolean, format: number, internalFormat?: number }> = new Map();\n\n private blendModePatched = false;\n\n constructor(\n reader: StowKitReader,\n transcoder: BasisTranscoder,\n gl: WebGLRenderingContext | WebGL2RenderingContext\n ) {\n this.reader = reader;\n this.transcoder = transcoder;\n this.tempGl = gl;\n }\n\n /**\n * Patch Phaser's NORMAL blend mode (index 0) to use straight alpha.\n * Phaser defaults to gl.ONE, gl.ONE_MINUS_SRC_ALPHA (premultiplied),\n * but compressed textures always have straight alpha since\n * UNPACK_PREMULTIPLY_ALPHA_WEBGL is ignored for compressed uploads.\n */\n private ensureBlendMode(scene: any): void {\n if (this.blendModePatched) return;\n const renderer = scene.sys.game.renderer;\n const gl = renderer.gl;\n renderer.blendModes[0] = {\n func: [gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA],\n equation: gl.FUNC_ADD,\n };\n // Force Phaser to re-apply the blend state — it skips if it thinks\n // the current mode hasn't changed, so we pass force=true.\n renderer.setBlendMode(0, true);\n this.blendModePatched = true;\n }\n\n /**\n * Load a texture by its canonical path/name\n * Returns a Phaser texture\n */\n async loadTexture(assetPath: string, scene: any): Promise<any> {\n const totalStart = performance.now();\n \n // Check cache first\n if (this.textureCache.has(assetPath)) {\n PerfLogger.log(`[Perf] Texture cache hit: ${assetPath}`);\n return this.textureCache.get(assetPath)!;\n }\n\n // Find asset by path\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) {\n throw new Error(`Texture not found: ${assetPath}`);\n }\n\n // Verify it's a texture\n const info = this.reader.getAssetInfo(assetIndex);\n if (!info || info.type !== AssetType.TEXTURE_2D) {\n throw new Error(`Asset is not a texture: ${assetPath}`);\n }\n\n // Use the same logic as getPhaserTexture but with custom key\n const key = assetPath;\n const gl = scene.sys.game.renderer.gl;\n \n // Read and transcode\n const data = this.reader.readAssetData(assetIndex);\n if (!data) {\n throw new Error(`Failed to read texture data for ${assetPath}`);\n }\n\n const transcodeStart = performance.now();\n const transcoded = await this.transcoder.transcodeKTX2(data, gl);\n PerfLogger.log(`[Perf] Phaser Basis transcode: ${(performance.now() - transcodeStart).toFixed(2)}ms (${transcoded.width}x${transcoded.height})`);\n \n // Format like Phaser's KTX parser\n const compressedTextureData = {\n mipmaps: [{\n data: transcoded.data,\n width: transcoded.width,\n height: transcoded.height\n }],\n width: transcoded.width,\n height: transcoded.height,\n internalFormat: transcoded.internalFormat,\n compressed: transcoded.compressed,\n generateMipmap: false,\n format: transcoded.internalFormat\n };\n \n const phaserTexture = scene.textures.addCompressedTexture(key, compressedTextureData);\n\n // Register straight-alpha blend mode for compressed textures\n this.ensureBlendMode(scene);\n\n const source = phaserTexture?.source?.[0];\n\n // Apply nearest filtering if metadata specifies it\n const metadata = this.reader.parseTextureMetadata(assetIndex);\n if (metadata?.filtering === 1) {\n const glTexture = source?.glTexture;\n if (glTexture) {\n gl.bindTexture(gl.TEXTURE_2D, glTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n gl.bindTexture(gl.TEXTURE_2D, null);\n }\n }\n\n this.textureCache.set(assetPath, phaserTexture);\n\n PerfLogger.log(`[Perf] ===== Total Phaser texture load: ${(performance.now() - totalStart).toFixed(2)}ms =====`);\n return phaserTexture;\n }\n\n /**\n * Get a Phaser texture by index (for previews/demos)\n * Creates compressed texture directly in Phaser's GL context\n */\n async getPhaserTexture(index: number, scene: any): Promise<any> {\n const key = `texture_${index}`;\n \n // Check if already exists in Phaser's texture manager\n if (scene.textures.exists(key)) {\n return scene.textures.get(key);\n }\n \n // Get Phaser's GL context\n const gl = scene.sys.game.renderer.gl;\n \n // Read and transcode the KTX2 data\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read texture data for index ${index}`);\n }\n\n // Transcode to compressed format (don't create the WebGL texture yet - let Phaser do it)\n const transcoded = await this.transcoder.transcodeKTX2(data, gl);\n \n // Format the data exactly like Phaser's KTX parser output\n const compressedTextureData = {\n mipmaps: [{\n data: transcoded.data,\n width: transcoded.width,\n height: transcoded.height\n }],\n width: transcoded.width,\n height: transcoded.height,\n internalFormat: transcoded.internalFormat,\n compressed: transcoded.compressed,\n generateMipmap: false,\n format: transcoded.internalFormat // Phaser uses this for compressionAlgorithm\n };\n \n // Add to Phaser's texture manager as a compressed texture\n const phaserTexture = scene.textures.addCompressedTexture(key, compressedTextureData);\n \n // Cache it\n this.textureCache.set(key, phaserTexture);\n \n return phaserTexture;\n }\n \n /**\n * Load texture by index into a specific GL context\n */\n private async loadTextureInContext(index: number, gl: WebGLRenderingContext | WebGL2RenderingContext): Promise<TextureData> {\n // Read texture data\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read texture data for index ${index}`);\n }\n\n // Get metadata - all textures in .stow files are KTX2 format\n const metadata = this.reader.parseTextureMetadata(index);\n const isKtx2 = metadata?.channelFormat !== undefined;\n\n if (isKtx2) {\n // Transcode KTX2 to WebGL texture using the provided context\n const transcoded = await this.transcoder.transcodeKTX2(data, gl);\n \n // Create WebGL texture in the provided context\n const texture = gl.createTexture();\n if (!texture) {\n throw new Error('Failed to create WebGL texture');\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n\n if (transcoded.compressed) {\n gl.compressedTexImage2D(\n gl.TEXTURE_2D,\n 0,\n transcoded.internalFormat!,\n transcoded.width,\n transcoded.height,\n 0,\n transcoded.data\n );\n } else {\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n transcoded.internalFormat!,\n transcoded.width,\n transcoded.height,\n 0,\n transcoded.format,\n gl.UNSIGNED_BYTE,\n transcoded.data\n );\n }\n\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n // Apply nearest filtering if metadata specifies it (filtering === 1)\n const useNearest = metadata?.filtering === 1;\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useNearest ? gl.NEAREST : gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, useNearest ? gl.NEAREST : gl.LINEAR);\n\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n return {\n texture,\n width: transcoded.width,\n height: transcoded.height\n };\n } else {\n // Handle uncompressed image data\n return await this.loadUncompressedTextureInContext(data, gl);\n }\n }\n\n /**\n * Load uncompressed image (PNG, JPEG) as WebGL texture in a specific context\n */\n private async loadUncompressedTextureInContext(data: Uint8Array, gl: WebGLRenderingContext | WebGL2RenderingContext): Promise<TextureData> {\n return new Promise((resolve, reject) => {\n const blob = new Blob([data.buffer as ArrayBuffer]);\n const url = URL.createObjectURL(blob);\n \n const img = new Image();\n img.onload = () => {\n const texture = gl.createTexture();\n if (!texture) {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to create WebGL texture'));\n return;\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n img\n );\n\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n URL.revokeObjectURL(url);\n\n resolve({\n texture,\n width: img.width,\n height: img.height\n });\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to load image'));\n };\n\n img.src = url;\n });\n }\n\n /**\n * Load audio by its canonical path/name\n * Returns an AudioBuffer\n */\n async loadAudio(assetPath: string, audioContext?: AudioContext): Promise<AudioBuffer> {\n // Find asset by path\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) {\n throw new Error(`Audio not found: ${assetPath}`);\n }\n\n // Verify it's audio\n const info = this.reader.getAssetInfo(assetIndex);\n if (!info || info.type !== AssetType.AUDIO) {\n throw new Error(`Asset is not audio: ${assetPath}`);\n }\n\n return await this.loadAudioByIndex(assetIndex, audioContext);\n }\n\n /**\n * Load audio by index\n */\n async loadAudioByIndex(index: number, audioContext?: AudioContext): Promise<AudioBuffer> {\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read audio data for index ${index}`);\n }\n\n // Use provided context or create a new one\n const ctx = audioContext || new AudioContext();\n\n // Decode audio data\n const arrayBuffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength) as ArrayBuffer;\n const audioBuffer = await ctx.decodeAudioData(arrayBuffer);\n\n return audioBuffer;\n }\n\n /**\n * Create an HTML audio element for preview\n */\n async createAudioPreview(index: number): Promise<HTMLAudioElement> {\n const data = this.reader.readAssetData(index);\n if (!data) {\n throw new Error(`Failed to read audio for index ${index}`);\n }\n\n const blob = new Blob([data.buffer as ArrayBuffer], { type: 'audio/mp4' });\n const url = URL.createObjectURL(blob);\n\n const audio = document.createElement('audio');\n audio.controls = true;\n audio.src = url;\n\n audio.addEventListener('ended', () => URL.revokeObjectURL(url));\n audio.addEventListener('error', () => URL.revokeObjectURL(url));\n\n return audio;\n }\n\n\n /**\n * Load a spritesheet by its canonical path.\n * Loads the referenced texture, registers it as a Phaser spritesheet\n * with correct frame dimensions, and creates an animation.\n */\n async loadSpriteSheet(\n assetPath: string,\n scene: any,\n animKey?: string,\n ): Promise<{ texture: any; animationKey: string }> {\n // Find the spritesheet asset\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) {\n throw new Error(`SpriteSheet not found: ${assetPath}`);\n }\n\n const info = this.reader.getAssetInfo(assetIndex);\n if (!info || info.type !== 8) {\n throw new Error(`Asset is not a spritesheet: ${assetPath}`);\n }\n\n // Parse spritesheet metadata (method added in reader, cast for compat)\n const meta = (this.reader as any).parseSpriteSheetMetadata(assetIndex);\n if (!meta || !meta.textureId) {\n throw new Error(`SpriteSheet \"${assetPath}\" has no texture reference`);\n }\n\n // Load the referenced texture first\n const textureKey = meta.textureId;\n await this.loadTexture(textureKey, scene);\n\n // Get texture dimensions from Phaser\n const phaserTexture = scene.textures.get(textureKey);\n const source = phaserTexture.source[0];\n const texWidth = source.width;\n const texHeight = source.height;\n\n // Calculate frame dimensions\n const frameWidth = Math.floor(texWidth / meta.columns);\n const frameHeight = Math.floor(texHeight / meta.rows);\n\n // Add numbered frames directly to the already-loaded compressed texture.\n // We cannot use addSpriteSheet — it calls texImage2D which fails for\n // compressed GL textures. Instead, add frames to the existing texture.\n const hasFrames = phaserTexture.has(0);\n if (!hasFrames) {\n let frame = 0;\n for (let row = 0; row < meta.rows && frame < meta.frameCount; row++) {\n for (let col = 0; col < meta.columns && frame < meta.frameCount; col++) {\n phaserTexture.add(\n frame,\n 0,\n col * frameWidth,\n row * frameHeight,\n frameWidth,\n frameHeight,\n );\n frame++;\n }\n }\n }\n\n // Create animation using the base texture key\n const animationKey = animKey ?? `${assetPath}_anim`;\n if (!scene.anims.exists(animationKey)) {\n scene.anims.create({\n key: animationKey,\n frames: scene.anims.generateFrameNumbers(textureKey, {\n start: 0,\n end: meta.frameCount - 1,\n }),\n frameRate: meta.frameRate,\n repeat: -1,\n });\n }\n\n return { texture: phaserTexture, textureKey, animationKey };\n }\n\n /**\n * Get spritesheet metadata by asset path\n */\n getSpriteSheetMetadata(assetPath: string) {\n const assetIndex = this.reader.findAssetByPath(assetPath);\n if (assetIndex < 0) return null;\n return (this.reader as any).parseSpriteSheetMetadata(assetIndex);\n }\n\n /**\n * Get list of all assets in pack\n */\n listAssets() {\n return this.reader.listAssets();\n }\n\n /**\n * Get asset count\n */\n getAssetCount(): number {\n return this.reader.getAssetCount();\n }\n\n /**\n * Get asset info by index\n */\n getAssetInfo(index: number) {\n return this.reader.getAssetInfo(index);\n }\n\n /**\n * Get texture metadata\n */\n getTextureMetadata(index: number) {\n return this.reader.parseTextureMetadata(index);\n }\n\n /**\n * Get audio metadata\n */\n getAudioMetadata(index: number) {\n return this.reader.parseAudioMetadata(index);\n }\n\n /**\n * Close the pack and free resources\n */\n dispose(): void {\n // Clear texture cache (Phaser manages texture disposal)\n this.textureCache.clear();\n this.transcodedDataCache.clear();\n\n // Close reader\n this.reader.close();\n }\n}\n\n\n","import { StowKitReader } from '@series-inc/stowkit-reader';\nimport { BasisTranscoder } from './BasisTranscoder';\nimport { StowKitPhaserPack } from './StowKitPhaserPack';\n\nexport interface StowKitPhaserLoaderOptions {\n /**\n * Path to basis transcoder for KTX2 texture loading\n * @default '/basis/'\n */\n basisPath?: string;\n\n /**\n * Path to WASM reader module\n * @default '/stowkit/stowkit_reader.wasm'\n */\n wasmPath?: string;\n\n /**\n * WebGL context to use for texture loading\n * If not provided, a temporary canvas will be created\n */\n gl?: WebGLRenderingContext | WebGL2RenderingContext;\n}\n\n/**\n * Phaser loader for StowKit asset packs\n * Supports images and audio only (no 3D models)\n * \n * Usage:\n * ```typescript\n * const pack = await StowKitPhaserLoader.load('assets.stow');\n * const texture = await pack.loadTexture('textures/player');\n * const audio = await pack.loadAudio('sounds/bgm');\n * ```\n */\nexport class StowKitPhaserLoader {\n private static transcoder: BasisTranscoder | null = null;\n private static initialized = false;\n private static gl: WebGLRenderingContext | WebGL2RenderingContext | null = null;\n private static ownGl = false;\n private static wasmPath: string = '/stowkit/stowkit_reader.wasm';\n\n /**\n * Load a .stow pack file from a URL\n */\n static async load(url: string, options?: StowKitPhaserLoaderOptions): Promise<StowKitPhaserPack> {\n // Initialize loaders if needed\n if (!this.initialized) {\n await this.initialize(options);\n }\n\n // Fetch the pack file\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${url}: ${response.statusText}`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n\n // Create a new reader instance for this pack\n const reader = new StowKitReader(this.wasmPath);\n await reader.init();\n await reader.open(arrayBuffer);\n\n // Return pack wrapper with its own dedicated reader\n return new StowKitPhaserPack(reader, this.transcoder!, this.gl!);\n }\n\n /**\n * Load a .stow pack from memory (ArrayBuffer, Blob, or File)\n */\n static async loadFromMemory(\n data: ArrayBuffer | Blob | File,\n options?: StowKitPhaserLoaderOptions\n ): Promise<StowKitPhaserPack> {\n // Initialize loaders if needed\n if (!this.initialized) {\n await this.initialize(options);\n }\n\n // Convert to ArrayBuffer if needed\n let arrayBuffer: ArrayBuffer;\n if (data instanceof ArrayBuffer) {\n arrayBuffer = data;\n } else if (typeof Blob !== 'undefined' && data instanceof Blob) {\n arrayBuffer = await data.arrayBuffer();\n } else if ('arrayBuffer' in data && typeof (data as any).arrayBuffer === 'function') {\n arrayBuffer = await (data as any).arrayBuffer();\n } else {\n throw new Error('Data must be ArrayBuffer, Blob, or File');\n }\n\n // Create a new reader instance for this pack\n const reader = new StowKitReader(this.wasmPath);\n await reader.init();\n await reader.open(arrayBuffer);\n\n // Return pack wrapper with its own dedicated reader\n return new StowKitPhaserPack(reader, this.transcoder!, this.gl!);\n }\n\n /**\n * Initialize the loader (called automatically on first load)\n */\n private static async initialize(options?: StowKitPhaserLoaderOptions): Promise<void> {\n this.wasmPath = options?.wasmPath || '/stowkit/stowkit_reader.wasm';\n const basisPath = options?.basisPath || '/basis/';\n\n // Get or create WebGL context (shared across all packs)\n if (options?.gl) {\n this.gl = options.gl;\n this.ownGl = false;\n } else {\n // Create a temporary canvas for WebGL operations\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n canvas.style.display = 'none';\n document.body.appendChild(canvas);\n\n this.gl = canvas.getContext('webgl2') || canvas.getContext('webgl');\n if (!this.gl) {\n throw new Error('Failed to create WebGL context');\n }\n this.ownGl = true;\n }\n\n // Initialize basis transcoder (shared across all packs)\n this.transcoder = new BasisTranscoder(basisPath);\n await this.transcoder.init();\n\n this.initialized = true;\n }\n\n /**\n * Dispose of shared resources\n */\n static dispose(): void {\n if (this.transcoder) {\n this.transcoder.dispose();\n this.transcoder = null;\n }\n\n // Only dispose GL if we created it\n if (this.gl && this.ownGl) {\n const canvas = (this.gl as any).canvas;\n if (canvas && canvas.parentNode) {\n canvas.parentNode.removeChild(canvas);\n }\n this.gl = null;\n }\n\n this.initialized = false;\n }\n}\n\n"],"names":["PerfLogger","AssetType","StowKitReader"],"mappings":";;;;;;IAAA;;;IAGG;IAwDH;IACA,MAAM,YAAY,GAAG;IACjB,IAAA,IAAI,EAAE,CAAC;IACP,IAAA,IAAI,EAAE,CAAC;QACP,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,CAAC;IACN,IAGA,MAAM,EAAE,CAAC;IACT,IAAA,YAAY,EAAE,CAAC;IACf,IAAA,aAAa,EAAE,CAAC;IAChB,IAAA,QAAQ,EAAE,EAAE;IACZ,IAEA,MAAM,EAAE,GAOX;UAWY,eAAe,CAAA;IAMxB,IAAA,WAAA,CAAY,YAAoB,SAAS,EAAA;YALjC,IAAA,CAAA,MAAM,GAAuB,IAAI;YACjC,IAAA,CAAA,WAAW,GAAG,KAAK;YACnB,IAAA,CAAA,WAAW,GAAyB,IAAI;IAI5C,QAAA,IAAI,CAAC,SAAS,GAAG,SAAS;QAC9B;IAEA;;IAEG;IACH,IAAA,MAAM,IAAI,GAAA;YACN,IAAI,IAAI,CAAC,WAAW;gBAAE;YACtB,IAAI,IAAI,CAAC,WAAW;gBAAE,OAAO,IAAI,CAAC,WAAW;IAE7C,QAAA,IAAI,CAAC,WAAW,GAAG,CAAC,YAAW;IAC3B,YAAA,IAAI;;IAEA,gBAAA,MAAM,UAAU,GAAG,CAAA,EAAG,IAAI,CAAC,SAAS,qBAAqB;;oBAGzD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC;;oBAG1D,WAAW,CAAC,eAAe,EAAE;IAC7B,gBAAA,IAAI,CAAC,MAAM,GAAG,WAAW;IACzB,gBAAA,IAAI,CAAC,WAAW,GAAG,IAAI;gBAC3B;gBAAE,OAAO,KAAK,EAAE;IACZ,gBAAA,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC;IAC/D,gBAAA,MAAM,KAAK;gBACf;YACJ,CAAC,GAAG;YAEJ,OAAO,IAAI,CAAC,WAAW;QAC3B;IAEA;;IAEG;QACK,MAAM,eAAe,CAAC,UAAkB,EAAA;YAC5C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAI;gBACnC,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;IAC/C,YAAA,MAAM,CAAC,GAAG,GAAG,UAAU;IACvB,YAAA,MAAM,CAAC,KAAK,GAAG,IAAI;IAEnB,YAAA,MAAM,CAAC,MAAM,GAAG,MAAK;;IAEjB,gBAAA,IAAI,OAAQ,MAAc,CAAC,KAAK,KAAK,UAAU,EAAE;wBAC5C,MAAc,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,MAAmB,KAAI;4BACjD,OAAO,CAAC,MAAM,CAAC;IACnB,oBAAA,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;oBACpB;yBAAO;IACH,oBAAA,MAAM,CAAC,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;oBAC/C;IACJ,YAAA,CAAC;IAED,YAAA,MAAM,CAAC,OAAO,GAAG,MAAK;oBAClB,MAAM,CAAC,IAAI,KAAK,CAAC,kBAAkB,UAAU,CAAA,CAAE,CAAC,CAAC;IACrD,YAAA,CAAC;IAED,YAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;IACrC,QAAA,CAAC,CAAC;QACN;IAEA;;IAEG;IACH,IAAA,MAAM,aAAa,CAAC,IAAgB,EAAE,EAAkD,EAAA;IACpF,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;IACnB,YAAA,MAAM,IAAI,CAAC,IAAI,EAAE;YACrB;IAEA,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;IACd,YAAA,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC;YACnD;;YAGA,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;IAE/C,QAAA,IAAI;;IAEA,YAAA,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE;IACrB,gBAAA,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC;gBACvD;;IAGA,YAAA,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE;IACjC,YAAA,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE;;IAGnC,YAAA,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE;;IAGvC,YAAA,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE;IAClC,YAAA,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE;;IAGlC,YAAA,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE,EAAE;IAC9B,gBAAA,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC;gBACvD;;gBAGA,MAAM,GAAG,GAAG,CAAC;gBACb,MAAM,KAAK,GAAG,CAAC;gBACf,MAAM,IAAI,GAAG,CAAC;;IAGd,YAAA,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC;;IAGjE,YAAA,MAAM,cAAc,GAAG,QAAQ,CAAC,6BAA6B,CACzD,GAAG,EACH,KAAK,EACL,IAAI,EACJ,YAAY,CAAC,WAAW,CAC3B;;IAGD,YAAA,MAAM,cAAc,GAAG,IAAI,UAAU,CAAC,cAAc,CAAC;;gBAGrD,MAAM,MAAM,GAAG,QAAQ,CAAC,cAAc,CAClC,cAAc,EACd,GAAG,EACH,KAAK,EACL,IAAI,EACJ,YAAY,CAAC,WAAW,EACxB,CAAC,EACD,CAAC,CAAC,EACF,CAAC,CAAC,CACL;IAED,YAAA,IAAI,MAAM,KAAK,CAAC,EAAE;IACd,gBAAA,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;gBAC9C;gBAEA,OAAO;IACH,gBAAA,IAAI,EAAE,cAAc;oBACpB,KAAK;oBACL,MAAM;oBACN,MAAM,EAAE,YAAY,CAAC,QAAQ;oBAC7B,cAAc,EAAE,YAAY,CAAC,gBAAgB;oBAC7C,UAAU,EAAE,YAAY,CAAC;iBAC5B;YAEL;oBAAU;gBACN,QAAQ,CAAC,KAAK,EAAE;gBAChB,QAAQ,CAAC,MAAM,EAAE;YACrB;QACJ;IAEA;;IAEG;IACK,IAAA,gBAAgB,CAAC,EAAkD,EAAE,WAAoB,IAAI,EAAE,UAAmB,KAAK,EAAA;IAM3H,QAAA,MAAM,QAAQ,GAAG,EAAE,YAAY,sBAAsB;;IAGrD,QAAA,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,+BAA+B,CAAC;IAChD,YAAA,EAAE,CAAC,YAAY,CAAC,sCAAsC,CAAC;YACpE,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,8BAA8B,CAAC;YAC5D,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,+BAA+B,CAAC;YAC7D,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,8BAA8B,CAAC;YAC3D,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,+BAA+B,CAAC;IAC7D,QAAA,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,gCAAgC,CAAC;IACjD,YAAA,EAAE,CAAC,YAAY,CAAC,uCAAuC,CAAC;;;;;IAOtE,QAAA,IAAI,QAAQ,IAAI,IAAI,IAAI,QAAQ,EAAE;gBAC9B,OAAO;oBACH,WAAW,EAAE,YAAY,CAAC,MAAM;oBAChC,QAAQ,EAAE,EAAE,CAAC,IAAI;oBACjB,gBAAgB,EAAG,IAAY,CAAC,8BAA8B;IAC9D,gBAAA,UAAU,EAAE;iBACf;YACL;;;IAIA,QAAA,IAAI,IAAI,IAAI,QAAQ,EAAE;gBAClB,OAAO;oBACH,WAAW,EAAE,YAAY,CAAC,GAAG;oBAC7B,QAAQ,EAAE,EAAE,CAAC,IAAI;oBACjB,gBAAgB,EAAG,IAAY,CAAC,6BAA6B;IAC7D,gBAAA,UAAU,EAAE;iBACf;YACL;;YAGA,IAAI,IAAI,EAAE;gBACN,OAAO;oBACH,WAAW,EAAE,YAAY,CAAC,GAAG;oBAC7B,QAAQ,EAAE,EAAE,CAAC,GAAG;oBAChB,gBAAgB,EAAG,IAAY,CAAC,4BAA4B;IAC5D,gBAAA,UAAU,EAAE;iBACf;YACL;;YAGA,IAAI,IAAI,EAAE;gBACN,OAAO;oBACH,WAAW,EAAE,YAAY,CAAC,QAAQ;oBAClC,QAAQ,EAAE,EAAE,CAAC,IAAI;oBACjB,gBAAgB,EAAG,IAAY,CAAC,4BAA4B;IAC5D,gBAAA,UAAU,EAAE;iBACf;YACL;;IAGA,QAAA,IAAI,QAAQ,IAAI,GAAG,EAAE;gBACjB,OAAO;oBACH,WAAW,EAAE,YAAY,CAAC,IAAI;oBAC9B,QAAQ,EAAE,EAAE,CAAC,IAAI;IACjB,gBAAA,gBAAgB,EAAG,GAAW,CAAC,yBAAyB,IAAI,MAAM;IAClE,gBAAA,UAAU,EAAE;iBACf;YACL;;IAGA,QAAA,IAAI,IAAI,IAAI,GAAG,EAAE;gBACb,OAAO;oBACH,WAAW,EAAE,YAAY,CAAC,IAAI;oBAC9B,QAAQ,EAAE,EAAE,CAAC,GAAG;IAChB,gBAAA,gBAAgB,EAAG,IAAY,EAAE,yBAAyB,IAAI,MAAM;IACpE,gBAAA,UAAU,EAAE;iBACf;YACL;;YAGA,IAAI,KAAK,EAAE;gBACP,OAAO;IACH,gBAAA,WAAW,EAAE,QAAQ,GAAG,YAAY,CAAC,aAAa,GAAG,YAAY,CAAC,YAAY;oBAC9E,QAAQ,EAAE,EAAE,CAAC,IAAI;oBACjB,gBAAgB,EAAG,KAAa,CAAC,gCAAgC;IACjE,gBAAA,UAAU,EAAE;iBACf;YACL;;YAGA,OAAO;gBACH,WAAW,EAAE,YAAY,CAAC,MAAM;gBAChC,QAAQ,EAAE,EAAE,CAAC,IAAI;gBACjB,gBAAgB,EAAE,EAAE,CAAC,IAAI;IACzB,YAAA,UAAU,EAAE;aACf;QACL;IAEA;;IAEG;QACH,OAAO,GAAA;IACH,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI;IAClB,QAAA,IAAI,CAAC,WAAW,GAAG,KAAK;IACxB,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI;QAC3B;IACH;;IC7VD;;;IAGG;UACU,iBAAiB,CAAA;IAS1B,IAAA,WAAA,CACI,MAAqB,EACrB,UAA2B,EAC3B,EAAkD,EAAA;IAR9C,QAAA,IAAA,CAAA,YAAY,GAAqB,IAAI,GAAG,EAAE;IAC1C,QAAA,IAAA,CAAA,mBAAmB,GAAmI,IAAI,GAAG,EAAE;YAE/J,IAAA,CAAA,gBAAgB,GAAG,KAAK;IAO5B,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;IACpB,QAAA,IAAI,CAAC,UAAU,GAAG,UAAU;IAC5B,QAAA,IAAI,CAAC,MAAM,GAAG,EAAE;QACpB;IAEA;;;;;IAKG;IACK,IAAA,eAAe,CAAC,KAAU,EAAA;YAC9B,IAAI,IAAI,CAAC,gBAAgB;gBAAE;YAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ;IACxC,QAAA,MAAM,EAAE,GAAG,QAAQ,CAAC,EAAE;IACtB,QAAA,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG;gBACrB,IAAI,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,mBAAmB,CAAC;gBAC5C,QAAQ,EAAE,EAAE,CAAC,QAAQ;aACxB;;;IAGD,QAAA,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC;IAC9B,QAAA,IAAI,CAAC,gBAAgB,GAAG,IAAI;QAChC;IAEA;;;IAGG;IACH,IAAA,MAAM,WAAW,CAAC,SAAiB,EAAE,KAAU,EAAA;IAC3C,QAAA,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;;YAGpC,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;IAClC,YAAAA,wBAAU,CAAC,GAAG,CAAC,6BAA6B,SAAS,CAAA,CAAE,CAAC;gBACxD,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAE;YAC5C;;YAGA,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC;IACzD,QAAA,IAAI,UAAU,GAAG,CAAC,EAAE;IAChB,YAAA,MAAM,IAAI,KAAK,CAAC,sBAAsB,SAAS,CAAA,CAAE,CAAC;YACtD;;YAGA,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC;YACjD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAKC,uBAAS,CAAC,UAAU,EAAE;IAC7C,YAAA,MAAM,IAAI,KAAK,CAAC,2BAA2B,SAAS,CAAA,CAAE,CAAC;YAC3D;;YAGA,MAAM,GAAG,GAAG,SAAS;YACrB,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;;YAGrC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC;YAClD,IAAI,CAAC,IAAI,EAAE;IACP,YAAA,MAAM,IAAI,KAAK,CAAC,mCAAmC,SAAS,CAAA,CAAE,CAAC;YACnE;IAEA,QAAA,MAAM,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE;IACxC,QAAA,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC;YAChED,wBAAU,CAAC,GAAG,CAAC,CAAA,+BAAA,EAAkC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA,IAAA,EAAO,UAAU,CAAC,KAAK,CAAA,CAAA,EAAI,UAAU,CAAC,MAAM,CAAA,CAAA,CAAG,CAAC;;IAGhJ,QAAA,MAAM,qBAAqB,GAAG;IAC1B,YAAA,OAAO,EAAE,CAAC;wBACN,IAAI,EAAE,UAAU,CAAC,IAAI;wBACrB,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,MAAM,EAAE,UAAU,CAAC;qBACtB,CAAC;gBACF,KAAK,EAAE,UAAU,CAAC,KAAK;gBACvB,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,cAAc,EAAE,UAAU,CAAC,cAAc;gBACzC,UAAU,EAAE,UAAU,CAAC,UAAU;IACjC,YAAA,cAAc,EAAE,KAAK;gBACrB,MAAM,EAAE,UAAU,CAAC;aACtB;IAED,QAAA,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC,GAAG,EAAE,qBAAqB,CAAC;;IAGrF,QAAA,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;YAE3B,MAAM,MAAM,GAAG,aAAa,EAAE,MAAM,GAAG,CAAC,CAAC;;YAGzC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,UAAU,CAAC;IAC7D,QAAA,IAAI,QAAQ,EAAE,SAAS,KAAK,CAAC,EAAE;IAC3B,YAAA,MAAM,SAAS,GAAG,MAAM,EAAE,SAAS;gBACnC,IAAI,SAAS,EAAE;oBACX,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC;IACxC,gBAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,OAAO,CAAC;IAClE,gBAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,OAAO,CAAC;oBAClE,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC;gBACvC;YACJ;YAEA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC;IAE/C,QAAAA,wBAAU,CAAC,GAAG,CAAC,2CAA2C,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA,QAAA,CAAU,CAAC;IAChH,QAAA,OAAO,aAAa;QACxB;IAEA;;;IAGG;IACH,IAAA,MAAM,gBAAgB,CAAC,KAAa,EAAE,KAAU,EAAA;IAC5C,QAAA,MAAM,GAAG,GAAG,CAAA,QAAA,EAAW,KAAK,EAAE;;YAG9B,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;gBAC5B,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;YAClC;;YAGA,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;;YAGrC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;YAC7C,IAAI,CAAC,IAAI,EAAE;IACP,YAAA,MAAM,IAAI,KAAK,CAAC,yCAAyC,KAAK,CAAA,CAAE,CAAC;YACrE;;IAGA,QAAA,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC;;IAGhE,QAAA,MAAM,qBAAqB,GAAG;IAC1B,YAAA,OAAO,EAAE,CAAC;wBACN,IAAI,EAAE,UAAU,CAAC,IAAI;wBACrB,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,MAAM,EAAE,UAAU,CAAC;qBACtB,CAAC;gBACF,KAAK,EAAE,UAAU,CAAC,KAAK;gBACvB,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,cAAc,EAAE,UAAU,CAAC,cAAc;gBACzC,UAAU,EAAE,UAAU,CAAC,UAAU;IACjC,YAAA,cAAc,EAAE,KAAK;IACrB,YAAA,MAAM,EAAE,UAAU,CAAC,cAAc;aACpC;;IAGD,QAAA,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC,GAAG,EAAE,qBAAqB,CAAC;;YAGrF,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,aAAa,CAAC;IAEzC,QAAA,OAAO,aAAa;QACxB;IAEA;;IAEG;IACK,IAAA,MAAM,oBAAoB,CAAC,KAAa,EAAE,EAAkD,EAAA;;YAEhG,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;YAC7C,IAAI,CAAC,IAAI,EAAE;IACP,YAAA,MAAM,IAAI,KAAK,CAAC,yCAAyC,KAAK,CAAA,CAAE,CAAC;YACrE;;YAGA,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC;IACxD,QAAA,MAAM,MAAM,GAAG,QAAQ,EAAE,aAAa,KAAK,SAAS;YAEpD,IAAI,MAAM,EAAE;;IAER,YAAA,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC;;IAGhE,YAAA,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,EAAE;gBAClC,IAAI,CAAC,OAAO,EAAE;IACV,gBAAA,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC;gBACrD;gBAEA,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC;IAEtC,YAAA,IAAI,UAAU,CAAC,UAAU,EAAE;oBACvB,EAAE,CAAC,oBAAoB,CACnB,EAAE,CAAC,UAAU,EACb,CAAC,EACD,UAAU,CAAC,cAAe,EAC1B,UAAU,CAAC,KAAK,EAChB,UAAU,CAAC,MAAM,EACjB,CAAC,EACD,UAAU,CAAC,IAAI,CAClB;gBACL;qBAAO;IACH,gBAAA,EAAE,CAAC,UAAU,CACT,EAAE,CAAC,UAAU,EACb,CAAC,EACD,UAAU,CAAC,cAAe,EAC1B,UAAU,CAAC,KAAK,EAChB,UAAU,CAAC,MAAM,EACjB,CAAC,EACD,UAAU,CAAC,MAAM,EACjB,EAAE,CAAC,aAAa,EAChB,UAAU,CAAC,IAAI,CAClB;gBACL;IAEA,YAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,aAAa,CAAC;IACpE,YAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,aAAa,CAAC;;IAEpE,YAAA,MAAM,UAAU,GAAG,QAAQ,EAAE,SAAS,KAAK,CAAC;gBAC5C,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,UAAU,GAAG,EAAE,CAAC,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC;gBAC3F,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,UAAU,GAAG,EAAE,CAAC,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC;gBAE3F,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC;gBAEnC,OAAO;oBACH,OAAO;oBACP,KAAK,EAAE,UAAU,CAAC,KAAK;oBACvB,MAAM,EAAE,UAAU,CAAC;iBACtB;YACL;iBAAO;;gBAEH,OAAO,MAAM,IAAI,CAAC,gCAAgC,CAAC,IAAI,EAAE,EAAE,CAAC;YAChE;QACJ;IAEA;;IAEG;IACK,IAAA,MAAM,gCAAgC,CAAC,IAAgB,EAAE,EAAkD,EAAA;YAC/G,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAI;gBACnC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,MAAqB,CAAC,CAAC;gBACnD,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC;IAErC,YAAA,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE;IACvB,YAAA,GAAG,CAAC,MAAM,GAAG,MAAK;IACd,gBAAA,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,EAAE;oBAClC,IAAI,CAAC,OAAO,EAAE;IACV,oBAAA,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC;IACxB,oBAAA,MAAM,CAAC,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;wBACnD;oBACJ;oBAEA,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC;oBACtC,EAAE,CAAC,UAAU,CACT,EAAE,CAAC,UAAU,EACb,CAAC,EACD,EAAE,CAAC,IAAI,EACP,EAAE,CAAC,IAAI,EACP,EAAE,CAAC,aAAa,EAChB,GAAG,CACN;IAED,gBAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,aAAa,CAAC;IACpE,gBAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,aAAa,CAAC;IACpE,gBAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,MAAM,CAAC;IACjE,gBAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,MAAM,CAAC;oBAEjE,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC;IAEnC,gBAAA,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC;IAExB,gBAAA,OAAO,CAAC;wBACJ,OAAO;wBACP,KAAK,EAAE,GAAG,CAAC,KAAK;wBAChB,MAAM,EAAE,GAAG,CAAC;IACf,iBAAA,CAAC;IACN,YAAA,CAAC;IAED,YAAA,GAAG,CAAC,OAAO,GAAG,MAAK;IACf,gBAAA,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC;IACxB,gBAAA,MAAM,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC7C,YAAA,CAAC;IAED,YAAA,GAAG,CAAC,GAAG,GAAG,GAAG;IACjB,QAAA,CAAC,CAAC;QACN;IAEA;;;IAGG;IACH,IAAA,MAAM,SAAS,CAAC,SAAiB,EAAE,YAA2B,EAAA;;YAE1D,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC;IACzD,QAAA,IAAI,UAAU,GAAG,CAAC,EAAE;IAChB,YAAA,MAAM,IAAI,KAAK,CAAC,oBAAoB,SAAS,CAAA,CAAE,CAAC;YACpD;;YAGA,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC;YACjD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAKC,uBAAS,CAAC,KAAK,EAAE;IACxC,YAAA,MAAM,IAAI,KAAK,CAAC,uBAAuB,SAAS,CAAA,CAAE,CAAC;YACvD;YAEA,OAAO,MAAM,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,YAAY,CAAC;QAChE;IAEA;;IAEG;IACH,IAAA,MAAM,gBAAgB,CAAC,KAAa,EAAE,YAA2B,EAAA;YAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;YAC7C,IAAI,CAAC,IAAI,EAAE;IACP,YAAA,MAAM,IAAI,KAAK,CAAC,uCAAuC,KAAK,CAAA,CAAE,CAAC;YACnE;;IAGA,QAAA,MAAM,GAAG,GAAG,YAAY,IAAI,IAAI,YAAY,EAAE;;YAG9C,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAgB;YACxG,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,WAAW,CAAC;IAE1D,QAAA,OAAO,WAAW;QACtB;IAEA;;IAEG;QACH,MAAM,kBAAkB,CAAC,KAAa,EAAA;YAClC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;YAC7C,IAAI,CAAC,IAAI,EAAE;IACP,YAAA,MAAM,IAAI,KAAK,CAAC,kCAAkC,KAAK,CAAA,CAAE,CAAC;YAC9D;IAEA,QAAA,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,MAAqB,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;YAC1E,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC;YAErC,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;IAC7C,QAAA,KAAK,CAAC,QAAQ,GAAG,IAAI;IACrB,QAAA,KAAK,CAAC,GAAG,GAAG,GAAG;IAEf,QAAA,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC/D,QAAA,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAE/D,QAAA,OAAO,KAAK;QAChB;IAGA;;;;IAIG;IACH,IAAA,MAAM,eAAe,CACjB,SAAiB,EACjB,KAAU,EACV,OAAgB,EAAA;;YAGhB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC;IACzD,QAAA,IAAI,UAAU,GAAG,CAAC,EAAE;IAChB,YAAA,MAAM,IAAI,KAAK,CAAC,0BAA0B,SAAS,CAAA,CAAE,CAAC;YAC1D;YAEA,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC;YACjD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE;IAC1B,YAAA,MAAM,IAAI,KAAK,CAAC,+BAA+B,SAAS,CAAA,CAAE,CAAC;YAC/D;;YAGA,MAAM,IAAI,GAAI,IAAI,CAAC,MAAc,CAAC,wBAAwB,CAAC,UAAU,CAAC;YACtE,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;IAC1B,YAAA,MAAM,IAAI,KAAK,CAAC,gBAAgB,SAAS,CAAA,0BAAA,CAA4B,CAAC;YAC1E;;IAGA,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS;YACjC,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,KAAK,CAAC;;YAGzC,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC;YACpD,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;IACtC,QAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK;IAC7B,QAAA,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM;;IAG/B,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;IACtD,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC;;;;YAKrD,MAAM,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;YACtC,IAAI,CAAC,SAAS,EAAE;gBACZ,IAAI,KAAK,GAAG,CAAC;gBACb,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,EAAE;oBACjE,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,OAAO,IAAI,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,EAAE;IACpE,oBAAA,aAAa,CAAC,GAAG,CACb,KAAK,EACL,CAAC,EACD,GAAG,GAAG,UAAU,EAChB,GAAG,GAAG,WAAW,EACjB,UAAU,EACV,WAAW,CACd;IACD,oBAAA,KAAK,EAAE;oBACX;gBACJ;YACJ;;IAGA,QAAA,MAAM,YAAY,GAAG,OAAO,IAAI,CAAA,EAAG,SAAS,OAAO;YACnD,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE;IACnC,YAAA,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;IACf,gBAAA,GAAG,EAAE,YAAY;oBACjB,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,UAAU,EAAE;IACjD,oBAAA,KAAK,EAAE,CAAC;IACR,oBAAA,GAAG,EAAE,IAAI,CAAC,UAAU,GAAG,CAAC;qBAC3B,CAAC;oBACF,SAAS,EAAE,IAAI,CAAC,SAAS;oBACzB,MAAM,EAAE,EAAE;IACb,aAAA,CAAC;YACN;YAEA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE;QAC/D;IAEA;;IAEG;IACH,IAAA,sBAAsB,CAAC,SAAiB,EAAA;YACpC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC;YACzD,IAAI,UAAU,GAAG,CAAC;IAAE,YAAA,OAAO,IAAI;YAC/B,OAAQ,IAAI,CAAC,MAAc,CAAC,wBAAwB,CAAC,UAAU,CAAC;QACpE;IAEA;;IAEG;QACH,UAAU,GAAA;IACN,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE;QACnC;IAEA;;IAEG;QACH,aAAa,GAAA;IACT,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE;QACtC;IAEA;;IAEG;IACH,IAAA,YAAY,CAAC,KAAa,EAAA;YACtB,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC;QAC1C;IAEA;;IAEG;IACH,IAAA,kBAAkB,CAAC,KAAa,EAAA;YAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC;QAClD;IAEA;;IAEG;IACH,IAAA,gBAAgB,CAAC,KAAa,EAAA;YAC1B,OAAO,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC;QAChD;IAEA;;IAEG;QACH,OAAO,GAAA;;IAEH,QAAA,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE;IACzB,QAAA,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE;;IAGhC,QAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;QACvB;IACH;;ICzdD;;;;;;;;;;IAUG;UACU,mBAAmB,CAAA;IAO5B;;IAEG;IACH,IAAA,aAAa,IAAI,CAAC,GAAW,EAAE,OAAoC,EAAA;;IAE/D,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;IACnB,YAAA,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAClC;;IAGA,QAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC;IACjC,QAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;gBACd,MAAM,IAAI,KAAK,CAAC,CAAA,gBAAA,EAAmB,GAAG,CAAA,EAAA,EAAK,QAAQ,CAAC,UAAU,CAAA,CAAE,CAAC;YACrE;IAEA,QAAA,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE;;YAGhD,MAAM,MAAM,GAAG,IAAIC,2BAAa,CAAC,IAAI,CAAC,QAAQ,CAAC;IAC/C,QAAA,MAAM,MAAM,CAAC,IAAI,EAAE;IACnB,QAAA,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;;IAG9B,QAAA,OAAO,IAAI,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,UAAW,EAAE,IAAI,CAAC,EAAG,CAAC;QACpE;IAEA;;IAEG;IACH,IAAA,aAAa,cAAc,CACvB,IAA+B,EAC/B,OAAoC,EAAA;;IAGpC,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;IACnB,YAAA,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAClC;;IAGA,QAAA,IAAI,WAAwB;IAC5B,QAAA,IAAI,IAAI,YAAY,WAAW,EAAE;gBAC7B,WAAW,GAAG,IAAI;YACtB;iBAAO,IAAI,OAAO,IAAI,KAAK,WAAW,IAAI,IAAI,YAAY,IAAI,EAAE;IAC5D,YAAA,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE;YAC1C;iBAAO,IAAI,aAAa,IAAI,IAAI,IAAI,OAAQ,IAAY,CAAC,WAAW,KAAK,UAAU,EAAE;IACjF,YAAA,WAAW,GAAG,MAAO,IAAY,CAAC,WAAW,EAAE;YACnD;iBAAO;IACH,YAAA,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC;YAC9D;;YAGA,MAAM,MAAM,GAAG,IAAIA,2BAAa,CAAC,IAAI,CAAC,QAAQ,CAAC;IAC/C,QAAA,MAAM,MAAM,CAAC,IAAI,EAAE;IACnB,QAAA,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;;IAG9B,QAAA,OAAO,IAAI,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,UAAW,EAAE,IAAI,CAAC,EAAG,CAAC;QACpE;IAEA;;IAEG;IACK,IAAA,aAAa,UAAU,CAAC,OAAoC,EAAA;YAChE,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,8BAA8B;IACnE,QAAA,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,SAAS;;IAGjD,QAAA,IAAI,OAAO,EAAE,EAAE,EAAE;IACb,YAAA,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC,EAAE;IACpB,YAAA,IAAI,CAAC,KAAK,GAAG,KAAK;YACtB;iBAAO;;gBAEH,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;IAC/C,YAAA,MAAM,CAAC,KAAK,GAAG,CAAC;IAChB,YAAA,MAAM,CAAC,MAAM,GAAG,CAAC;IACjB,YAAA,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM;IAC7B,YAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;IAEjC,YAAA,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;IACnE,YAAA,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;IACV,gBAAA,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC;gBACrD;IACA,YAAA,IAAI,CAAC,KAAK,GAAG,IAAI;YACrB;;YAGA,IAAI,CAAC,UAAU,GAAG,IAAI,eAAe,CAAC,SAAS,CAAC;IAChD,QAAA,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;IAE5B,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI;QAC3B;IAEA;;IAEG;IACH,IAAA,OAAO,OAAO,GAAA;IACV,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE;IACjB,YAAA,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE;IACzB,YAAA,IAAI,CAAC,UAAU,GAAG,IAAI;YAC1B;;YAGA,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,KAAK,EAAE;IACvB,YAAA,MAAM,MAAM,GAAI,IAAI,CAAC,EAAU,CAAC,MAAM;IACtC,YAAA,IAAI,MAAM,IAAI,MAAM,CAAC,UAAU,EAAE;IAC7B,gBAAA,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC;gBACzC;IACA,YAAA,IAAI,CAAC,EAAE,GAAG,IAAI;YAClB;IAEA,QAAA,IAAI,CAAC,WAAW,GAAG,KAAK;QAC5B;;IArHe,mBAAA,CAAA,UAAU,GAA2B,IAAI;IACzC,mBAAA,CAAA,WAAW,GAAG,KAAK;IACnB,mBAAA,CAAA,EAAE,GAA0D,IAAI;IAChE,mBAAA,CAAA,KAAK,GAAG,KAAK;IACb,mBAAA,CAAA,QAAQ,GAAW,8BAA8B;;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@series-inc/stowkit-phaser-loader",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.25",
|
|
4
4
|
"description": "Phaser loader for StowKit asset packs with KTX2/Basis Universal compressed texture support",
|
|
5
5
|
"main": "dist/stowkit-phaser-loader.js",
|
|
6
6
|
"module": "dist/stowkit-phaser-loader.esm.js",
|
package/skill.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# StowKit Phaser Loader
|
|
2
2
|
|
|
3
|
-
Use `@series-inc/stowkit-phaser-loader` to load `.stow` asset packs in Phaser applications. Supports 2D textures and audio
|
|
3
|
+
Use `@series-inc/stowkit-phaser-loader` to load `.stow` asset packs in Phaser applications. Supports 2D textures, spritesheets, and audio — for 3D models use `@series-inc/stowkit-three-loader`.
|
|
4
4
|
|
|
5
5
|
## How Assets Get Into the Game
|
|
6
6
|
|
|
@@ -16,28 +16,38 @@ If you need to add an asset to the game, the pipeline step (`stowkit build`) mus
|
|
|
16
16
|
|
|
17
17
|
| I need to... | Method |
|
|
18
18
|
|---|---|
|
|
19
|
-
| Load a pack | `await StowKitPhaserLoader.load('/assets/game.stow')` |
|
|
20
|
-
|
|
|
21
|
-
|
|
|
22
|
-
|
|
|
19
|
+
| Load a pack from URL | `await StowKitPhaserLoader.load('/assets/game.stow')` |
|
|
20
|
+
| Load a pack from CDN (RUN.game) | Fetch blob via `RundotGameAPI.cdn.fetchAsset('default.stow')`, then `StowKitPhaserLoader.loadFromMemory(await blob.arrayBuffer(), opts)` |
|
|
21
|
+
| Add a texture to a scene | `await pack.loadTexture('player', this)` |
|
|
22
|
+
| Use texture as a sprite | `this.add.sprite(x, y, 'player')` — key matches the stringId passed to `loadTexture` |
|
|
23
|
+
| Load a spritesheet with animation | `const { textureKey, animationKey } = await pack.loadSpriteSheet('walk_anim', this)` |
|
|
24
|
+
| Play a spritesheet animation | `const sprite = this.add.sprite(x, y, textureKey); sprite.play(animationKey)` |
|
|
25
|
+
| Load audio | `const buffer = await pack.loadAudio('bgm')` |
|
|
23
26
|
| Play audio with Phaser | Use `this.sound.context` — see Audio section below |
|
|
24
27
|
| See what's in a pack | `pack.listAssets()` — returns array of `{ index, name, id, type, dataSize }` |
|
|
25
28
|
| Clean up a pack | `pack.dispose()` |
|
|
26
29
|
| Clean up shared resources | `StowKitPhaserLoader.dispose()` |
|
|
27
30
|
|
|
31
|
+
## Critical Rules
|
|
32
|
+
|
|
33
|
+
1. **Game config must use `Phaser.WEBGL`** — compressed textures require WebGL, not `Phaser.AUTO` or `Phaser.CANVAS`.
|
|
34
|
+
2. **Load textures in `create()`, not `preload()`** — `loadTexture` needs the renderer's GL context which isn't available during preload.
|
|
35
|
+
3. **Spritesheet sprites use `textureKey`, not the spritesheet asset path** — `loadSpriteSheet` returns `{ textureKey, animationKey }`. Use `textureKey` for `this.add.sprite()`.
|
|
36
|
+
4. **Alpha blending is handled automatically** — no game-side blend mode setup needed.
|
|
37
|
+
|
|
28
38
|
## Common Mistakes
|
|
29
39
|
|
|
30
40
|
| Mistake | Fix |
|
|
31
41
|
|---|---|
|
|
32
42
|
| Using `this.load.image()` / `this.load.audio()` to load raw source files | StowKit projects load everything from `.stow` packs — use `pack.loadTexture()` and `pack.loadAudio()` |
|
|
33
|
-
| Calling `loadTexture` in `preload()` |
|
|
43
|
+
| Calling `loadTexture` in `preload()` | Must be called in or after `create()` — needs the renderer's GL context |
|
|
34
44
|
| Not awaiting `StowKitPhaserLoader.load()` | All load methods are async — always `await` them |
|
|
35
|
-
| Forgetting to pass `this` (the scene) to `loadTexture` | `loadTexture(path, scene)` requires the Phaser scene to register
|
|
36
|
-
|
|
|
37
|
-
| Using
|
|
38
|
-
| Trying to load meshes / skinned meshes | This loader is 2D only (textures
|
|
45
|
+
| Forgetting to pass `this` (the scene) to `loadTexture` | `loadTexture(path, scene)` requires the Phaser scene to register with the texture manager |
|
|
46
|
+
| Using `Phaser.AUTO` renderer type | Compressed textures require WebGL — use `Phaser.WEBGL` |
|
|
47
|
+
| Using spritesheet asset path as sprite texture key | `loadSpriteSheet` returns `textureKey` — use that for `this.add.sprite()`, not the spritesheet path |
|
|
48
|
+
| Trying to load meshes / skinned meshes | This loader is 2D only (textures, spritesheets, audio) — use `@series-inc/stowkit-three-loader` for 3D |
|
|
39
49
|
| Manually decoding KTX2 / Basis | The loader handles all transcoding internally — just call `loadTexture` |
|
|
40
|
-
|
|
|
50
|
+
| Setting blend mode for alpha transparency | Not needed — the loader handles this automatically |
|
|
41
51
|
|
|
42
52
|
## Installation
|
|
43
53
|
|
|
@@ -47,16 +57,32 @@ npm install @series-inc/stowkit-phaser-loader phaser
|
|
|
47
57
|
|
|
48
58
|
Requires Phaser 3.60+ for compressed texture support.
|
|
49
59
|
|
|
50
|
-
The postinstall script copies Basis Universal transcoder files
|
|
51
|
-
|
|
52
|
-
The `stowkit_reader.wasm` file is copied to `public/stowkit/` by the `@series-inc/stowkit-reader` package's own postinstall — the Phaser loader does not duplicate this.
|
|
60
|
+
The postinstall script copies Basis Universal transcoder files to `public/stowkit/basis/`. The `stowkit_reader.wasm` file is copied by the `@series-inc/stowkit-reader` dependency.
|
|
53
61
|
|
|
54
62
|
## Loading a Pack
|
|
55
63
|
|
|
64
|
+
### From URL (local dev)
|
|
65
|
+
|
|
56
66
|
```typescript
|
|
57
67
|
import { StowKitPhaserLoader } from '@series-inc/stowkit-phaser-loader';
|
|
58
68
|
|
|
59
|
-
const pack = await StowKitPhaserLoader.load('/assets/
|
|
69
|
+
const pack = await StowKitPhaserLoader.load('/cdn-assets/default.stow', {
|
|
70
|
+
basisPath: 'stowkit/basis/',
|
|
71
|
+
wasmPath: 'stowkit/stowkit_reader.wasm',
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### From CDN (RUN.game production)
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { StowKitPhaserLoader } from '@series-inc/stowkit-phaser-loader';
|
|
79
|
+
import RundotGameAPI from '@series-inc/rundot-game-sdk/api';
|
|
80
|
+
|
|
81
|
+
const blob = await RundotGameAPI.cdn.fetchAsset('default.stow');
|
|
82
|
+
const pack = await StowKitPhaserLoader.loadFromMemory(await blob.arrayBuffer(), {
|
|
83
|
+
basisPath: 'stowkit/basis/',
|
|
84
|
+
wasmPath: 'stowkit/stowkit_reader.wasm',
|
|
85
|
+
});
|
|
60
86
|
```
|
|
61
87
|
|
|
62
88
|
Options (all optional):
|
|
@@ -64,49 +90,102 @@ Options (all optional):
|
|
|
64
90
|
- `wasmPath` — path to `stowkit_reader.wasm` (default: `'/stowkit/stowkit_reader.wasm'`)
|
|
65
91
|
- `gl` — WebGL context to use (if not provided, a temporary canvas is created)
|
|
66
92
|
|
|
67
|
-
Load from memory (e.g. after a custom fetch):
|
|
68
|
-
```typescript
|
|
69
|
-
const buffer = await fetch(url).then(r => r.arrayBuffer());
|
|
70
|
-
const pack = await StowKitPhaserLoader.loadFromMemory(buffer);
|
|
71
|
-
```
|
|
72
|
-
|
|
73
93
|
## Asset Types
|
|
74
94
|
|
|
75
95
|
| Type | Enum | Load Method |
|
|
76
96
|
|------|------|-------------|
|
|
77
|
-
| Texture | `AssetType.TEXTURE_2D` (2) | `pack.loadTexture(
|
|
78
|
-
|
|
|
97
|
+
| Texture | `AssetType.TEXTURE_2D` (2) | `pack.loadTexture(stringId, scene)` |
|
|
98
|
+
| SpriteSheet | type `8` | `pack.loadSpriteSheet(stringId, scene, animKey?)` |
|
|
99
|
+
| Audio | `AssetType.AUDIO` (3) | `pack.loadAudio(stringId, audioContext?)` |
|
|
79
100
|
|
|
80
|
-
Assets are referenced by their `stringId` from `.stowmeta` files (e.g. `"
|
|
101
|
+
Assets are referenced by their `stringId` from `.stowmeta` files (e.g. `"player"`, `"background"`).
|
|
81
102
|
|
|
82
103
|
## Textures
|
|
83
104
|
|
|
84
105
|
```typescript
|
|
85
106
|
// In your scene's create() method:
|
|
86
|
-
await pack.loadTexture('
|
|
87
|
-
const player = this.add.sprite(400, 300, '
|
|
107
|
+
await pack.loadTexture('player', this);
|
|
108
|
+
const player = this.add.sprite(400, 300, 'player');
|
|
88
109
|
```
|
|
89
110
|
|
|
90
|
-
`loadTexture` registers the texture with Phaser's texture manager using the
|
|
111
|
+
`loadTexture` registers the texture with Phaser's texture manager using the stringId as the key. Must be called in or after `create()`.
|
|
91
112
|
|
|
92
113
|
KTX2 textures are automatically transcoded to the best GPU-compressed format:
|
|
93
|
-
- **Desktop:** BC7 (BPTC), BC3 (DXT5), BC1 (DXT1)
|
|
114
|
+
- **Desktop:** BC7 (BPTC) for alpha, BC3 (DXT5) for alpha, BC1 (DXT1) for opaque
|
|
94
115
|
- **Mobile:** ASTC 4x4, ETC2, ETC1, PVRTC
|
|
95
116
|
- **Fallback:** RGBA32 uncompressed
|
|
96
117
|
|
|
97
|
-
Textures are cached per-pack — loading the same
|
|
118
|
+
Textures are cached per-pack — loading the same stringId twice returns the same instance.
|
|
119
|
+
|
|
120
|
+
### Texture Filtering
|
|
121
|
+
|
|
122
|
+
Controlled by `.stowmeta` metadata. Set `"filtering": 1` for `NEAREST` (pixel art), otherwise `LINEAR` is used. Change this in the `.stowmeta` file and rebuild with `stowkit build`.
|
|
123
|
+
|
|
124
|
+
## Spritesheets
|
|
125
|
+
|
|
126
|
+
Spritesheets are defined as `.stowspritesheet` JSON files in the `srcArtDir` alongside their texture:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"version": 1,
|
|
131
|
+
"textureAsset": "ball_sheet.png",
|
|
132
|
+
"rows": 8,
|
|
133
|
+
"columns": 8,
|
|
134
|
+
"frameCount": 64,
|
|
135
|
+
"frameRate": 6
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The texture (`ball_sheet.png`) and spritesheet definition (`ball_animation.stowspritesheet`) are both placed in `srcArtDir`. Run `stowkit build` to pack them.
|
|
140
|
+
|
|
141
|
+
### Loading and Playing
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
// Load spritesheet — loads the texture, registers frames, and creates animation
|
|
145
|
+
const { textureKey, animationKey } = await pack.loadSpriteSheet('ball_animation', this);
|
|
146
|
+
|
|
147
|
+
// Create sprite using the BASE TEXTURE KEY (not the spritesheet path)
|
|
148
|
+
const sprite = this.add.sprite(400, 300, textureKey);
|
|
149
|
+
sprite.setDisplaySize(64, 64);
|
|
150
|
+
sprite.play(animationKey);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Important:** Use `textureKey` (returned by `loadSpriteSheet`) as the texture key for `this.add.sprite()`. The spritesheet's frames are added directly to the base texture — do NOT use the spritesheet asset path as the sprite key.
|
|
98
154
|
|
|
99
|
-
|
|
155
|
+
### Custom Animation Key
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
const { textureKey, animationKey } = await pack.loadSpriteSheet('walk_cycle', this, 'player_walk');
|
|
159
|
+
// animationKey === 'player_walk'
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
If no `animKey` is provided, it defaults to `${assetPath}_anim`.
|
|
163
|
+
|
|
164
|
+
### Spritesheet Metadata
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
const meta = pack.getSpriteSheetMetadata('ball_animation');
|
|
168
|
+
// { textureId, rows, columns, frameCount, frameRate }
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### How It Works Internally
|
|
172
|
+
|
|
173
|
+
1. Loads the referenced texture via `loadTexture` (KTX2 → GPU-compressed)
|
|
174
|
+
2. Calculates frame dimensions: `frameWidth = texWidth / columns`, `frameHeight = texHeight / rows`
|
|
175
|
+
3. Adds numbered frames (0, 1, 2, ...) directly to the compressed texture using `texture.add()`
|
|
176
|
+
4. Creates a Phaser animation with `generateFrameNumbers` and the specified frame rate
|
|
177
|
+
|
|
178
|
+
Frames are added to the base texture — NOT via `addSpriteSheet` (which fails for compressed textures because it tries to call `texImage2D` on a non-existent image source).
|
|
100
179
|
|
|
101
180
|
## Audio
|
|
102
181
|
|
|
103
182
|
```typescript
|
|
104
183
|
// Decode to AudioBuffer
|
|
105
|
-
const buffer = await pack.loadAudio('
|
|
184
|
+
const buffer = await pack.loadAudio('bgm');
|
|
106
185
|
|
|
107
186
|
// Or with a specific AudioContext
|
|
108
187
|
const ctx = new AudioContext();
|
|
109
|
-
const buffer = await pack.loadAudio('
|
|
188
|
+
const buffer = await pack.loadAudio('bgm', ctx);
|
|
110
189
|
```
|
|
111
190
|
|
|
112
191
|
Audio is AAC format (M4A container), decoded via Web Audio API.
|
|
@@ -114,8 +193,7 @@ Audio is AAC format (M4A container), decoded via Web Audio API.
|
|
|
114
193
|
### Playing audio with Phaser's sound system
|
|
115
194
|
|
|
116
195
|
```typescript
|
|
117
|
-
|
|
118
|
-
const buffer = await pack.loadAudio('sounds/bgm');
|
|
196
|
+
const buffer = await pack.loadAudio('bgm');
|
|
119
197
|
const source = this.sound.context.createBufferSource();
|
|
120
198
|
source.buffer = buffer;
|
|
121
199
|
source.connect(this.sound.context.destination);
|
|
@@ -145,6 +223,10 @@ const tex = pack.getTextureMetadata(index);
|
|
|
145
223
|
// Audio
|
|
146
224
|
const audio = pack.getAudioMetadata(index);
|
|
147
225
|
// { sampleRate, channels, durationMs }
|
|
226
|
+
|
|
227
|
+
// SpriteSheet
|
|
228
|
+
const ss = pack.getSpriteSheetMetadata('walk_cycle');
|
|
229
|
+
// { textureId, rows, columns, frameCount, frameRate }
|
|
148
230
|
```
|
|
149
231
|
|
|
150
232
|
## Multiple Packs
|
|
@@ -186,30 +268,36 @@ import type {
|
|
|
186
268
|
|
|
187
269
|
```typescript
|
|
188
270
|
import Phaser from 'phaser';
|
|
189
|
-
import
|
|
271
|
+
import RundotGameAPI from '@series-inc/rundot-game-sdk/api';
|
|
272
|
+
import { StowKitPhaserLoader, StowKitPhaserPack } from '@series-inc/stowkit-phaser-loader';
|
|
190
273
|
|
|
191
274
|
class GameScene extends Phaser.Scene {
|
|
192
|
-
private pack!:
|
|
275
|
+
private pack!: StowKitPhaserPack;
|
|
193
276
|
|
|
194
277
|
constructor() {
|
|
195
278
|
super('GameScene');
|
|
196
279
|
}
|
|
197
280
|
|
|
198
281
|
async create() {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
//
|
|
207
|
-
this.
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const
|
|
282
|
+
// Load pack from CDN
|
|
283
|
+
const blob = await RundotGameAPI.cdn.fetchAsset('default.stow');
|
|
284
|
+
this.pack = await StowKitPhaserLoader.loadFromMemory(await blob.arrayBuffer(), {
|
|
285
|
+
basisPath: 'stowkit/basis/',
|
|
286
|
+
wasmPath: 'stowkit/stowkit_reader.wasm',
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// Load a static texture
|
|
290
|
+
await this.pack.loadTexture('background', this);
|
|
291
|
+
this.add.image(400, 300, 'background');
|
|
292
|
+
|
|
293
|
+
// Load an animated spritesheet
|
|
294
|
+
const { textureKey, animationKey } = await this.pack.loadSpriteSheet('player_walk', this);
|
|
295
|
+
const player = this.add.sprite(400, 300, textureKey);
|
|
296
|
+
player.setDisplaySize(64, 64);
|
|
297
|
+
player.play(animationKey);
|
|
298
|
+
|
|
299
|
+
// Load and play audio
|
|
300
|
+
const bgm = await this.pack.loadAudio('bgm');
|
|
213
301
|
const source = this.sound.context.createBufferSource();
|
|
214
302
|
source.buffer = bgm;
|
|
215
303
|
source.connect(this.sound.context.destination);
|
|
@@ -222,19 +310,72 @@ const game = new Phaser.Game({
|
|
|
222
310
|
type: Phaser.WEBGL, // Required for compressed textures
|
|
223
311
|
width: 800,
|
|
224
312
|
height: 600,
|
|
225
|
-
scene: GameScene
|
|
313
|
+
scene: GameScene,
|
|
314
|
+
physics: {
|
|
315
|
+
default: 'arcade',
|
|
316
|
+
arcade: { gravity: { x: 0, y: 0 } },
|
|
317
|
+
},
|
|
318
|
+
scale: {
|
|
319
|
+
mode: Phaser.Scale.FIT,
|
|
320
|
+
autoCenter: Phaser.Scale.CENTER_BOTH,
|
|
321
|
+
},
|
|
226
322
|
});
|
|
227
323
|
```
|
|
228
324
|
|
|
325
|
+
## Complete Spritesheet Example
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
import Phaser from 'phaser';
|
|
329
|
+
import { StowKitPhaserLoader, StowKitPhaserPack } from '@series-inc/stowkit-phaser-loader';
|
|
330
|
+
|
|
331
|
+
class AnimatedScene extends Phaser.Scene {
|
|
332
|
+
private pack!: StowKitPhaserPack;
|
|
333
|
+
|
|
334
|
+
constructor() {
|
|
335
|
+
super('AnimatedScene');
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
async create() {
|
|
339
|
+
this.pack = await StowKitPhaserLoader.load('/cdn-assets/default.stow', {
|
|
340
|
+
basisPath: 'stowkit/basis/',
|
|
341
|
+
wasmPath: 'stowkit/stowkit_reader.wasm',
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// Load multiple spritesheets
|
|
345
|
+
const { textureKey: idleKey, animationKey: idleAnim } =
|
|
346
|
+
await this.pack.loadSpriteSheet('player_idle', this);
|
|
347
|
+
const { textureKey: walkKey, animationKey: walkAnim } =
|
|
348
|
+
await this.pack.loadSpriteSheet('player_walk', this);
|
|
349
|
+
|
|
350
|
+
// Create sprite with idle animation
|
|
351
|
+
const player = this.add.sprite(400, 300, idleKey);
|
|
352
|
+
player.play(idleAnim);
|
|
353
|
+
|
|
354
|
+
// Switch animation on click
|
|
355
|
+
this.input.on('pointerdown', () => {
|
|
356
|
+
if (player.anims.currentAnim?.key === idleAnim) {
|
|
357
|
+
player.setTexture(walkKey);
|
|
358
|
+
player.play(walkAnim);
|
|
359
|
+
} else {
|
|
360
|
+
player.setTexture(idleKey);
|
|
361
|
+
player.play(idleAnim);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
229
368
|
## Troubleshooting
|
|
230
369
|
|
|
231
370
|
| Symptom | Likely cause | Fix |
|
|
232
371
|
|---|---|---|
|
|
233
|
-
| Textures not loading / blank | Basis transcoder files missing | Verify `basis_transcoder.js` and `.wasm` are
|
|
372
|
+
| Textures not loading / blank | Basis transcoder files missing | Verify `basis_transcoder.js` and `.wasm` are at the `basisPath` URL. Re-run `npm install` to trigger postinstall copy |
|
|
234
373
|
| "Scene required" / texture errors | `loadTexture` called too early | Call `loadTexture` in or after `create()`, not in `preload()` |
|
|
235
|
-
| WASM file not found | Wrong `wasmPath` or file not copied | Check
|
|
236
|
-
|
|
|
237
|
-
|
|
|
238
|
-
| Pixel art looks blurry | Default linear filtering | Set `filtering: 1` in the asset's `.stowmeta`
|
|
239
|
-
|
|
|
240
|
-
|
|
|
374
|
+
| WASM file not found | Wrong `wasmPath` or file not copied | Check `stowkit_reader.wasm` exists at the expected URL |
|
|
375
|
+
| `texImage2D` error on spritesheet | Using Phaser's `addSpriteSheet` with compressed texture | Use `pack.loadSpriteSheet()` — it adds frames directly to the compressed texture |
|
|
376
|
+
| Dark fringe / halo around alpha edges | Outdated loader version | Update `@series-inc/stowkit-phaser-loader` to latest |
|
|
377
|
+
| Pixel art looks blurry | Default linear filtering | Set `"filtering": 1` in the asset's `.stowmeta` and rebuild |
|
|
378
|
+
| Spritesheet sprite is blank | Using spritesheet path as texture key | Use `textureKey` returned by `loadSpriteSheet`, not the asset path |
|
|
379
|
+
| No compressed format supported | WebGL unavailable | Use `Phaser.WEBGL` for game type. Falls back to RGBA32 if no GPU compression extensions |
|
|
380
|
+
| Audio not playing | AudioContext suspended | Browsers require user interaction before audio — start in response to click/tap |
|
|
381
|
+
| Need 3D models? | Wrong loader | Use `@series-inc/stowkit-three-loader` — this loader is 2D only |
|