@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.
@@ -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;gBAGpK,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,eAAe,EAC3B,EAAE,EAAE,qBAAqB,GAAG,sBAAsB;IAOtD;;;OAGG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAsE9D;;;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;IA4FlD;;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"}
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 = phaserTexture?.source?.[0]?.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 existing compressed texture.
509
- // We cannot use addSpriteSheet because it tries to create a new
510
- // texture from an image source, which fails for compressed GL textures.
511
- const ssKey = assetPath;
512
- if (!scene.textures.exists(ssKey)) {
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
- ssTexture.add(frame, // frame name/index
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(ssKey, {
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 = phaserTexture?.source?.[0]?.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 existing compressed texture.
512
- // We cannot use addSpriteSheet because it tries to create a new
513
- // texture from an image source, which fails for compressed GL textures.
514
- const ssKey = assetPath;
515
- if (!scene.textures.exists(ssKey)) {
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
- ssTexture.add(frame, // frame name/index
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(ssKey, {
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":"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"}
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":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@series-inc/stowkit-phaser-loader",
3
- "version": "0.1.24",
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 only — for 3D models use `@series-inc/stowkit-three-loader`.
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
- | Add a texture to a scene | `await pack.loadTexture('characters/player', this)` |
21
- | Use texture as a sprite | `this.add.sprite(x, y, 'characters/player')` — key matches the path passed to `loadTexture` |
22
- | Load audio | `const buffer = await pack.loadAudio('sounds/bgm')` |
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()` | `loadTexture` must be called in or after `create()`, not in `preload()`it needs the renderer's GL context |
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 the texture with the texture manager |
36
- | Texture key mismatch | The texture key in Phaser's texture manager is the exact `assetPath` you pass to `loadTexture` — use the same string in `this.add.sprite()` |
37
- | Using `Phaser.AUTO` renderer type | Compressed textures require WebGL — use `Phaser.WEBGL` for the game config `type` |
38
- | Trying to load meshes / skinned meshes | This loader is 2D only (textures + audio) — use `@series-inc/stowkit-three-loader` for 3D |
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
- | Basis transcoder files not accessible | Ensure `basis_transcoder.js` and `.wasm` are served at the `basisPath` URL (default: `/basis/`) |
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 (`basis_transcoder.js` and `basis_transcoder.wasm`) to `public/stowkit/basis/`.
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/game.stow');
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(path, scene)` / `pack.getPhaserTexture(index, scene)` |
78
- | Audio | `AssetType.AUDIO` (3) | `pack.loadAudio(path, ctx?)` / `pack.loadAudioByIndex(index, ctx?)` |
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. `"characters/player"`, `"ui/button"`).
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('characters/player', this);
87
- const player = this.add.sprite(400, 300, 'characters/player');
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 asset path as the key. Must be called in or after `create()`.
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 path twice returns the same instance.
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
- Texture filtering is controlled by `.stowmeta` metadata: `filtering: 1` applies `NEAREST` filtering (pixel art), otherwise `LINEAR` is used.
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('sounds/bgm');
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('sounds/bgm', ctx);
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
- // Using Web Audio API through Phaser's context:
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 { StowKitPhaserLoader } from '@series-inc/stowkit-phaser-loader';
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!: Awaited<ReturnType<typeof StowKitPhaserLoader.load>>;
275
+ private pack!: StowKitPhaserPack;
193
276
 
194
277
  constructor() {
195
278
  super('GameScene');
196
279
  }
197
280
 
198
281
  async create() {
199
- this.pack = await StowKitPhaserLoader.load('/assets/game.stow');
200
-
201
- // Load textures (registers them with Phaser's texture manager)
202
- await this.pack.loadTexture('backgrounds/sky', this);
203
- await this.pack.loadTexture('characters/player', this);
204
- await this.pack.loadTexture('ui/button', this);
205
-
206
- // Use textures keys match the paths above
207
- this.add.image(400, 300, 'backgrounds/sky');
208
- const player = this.add.sprite(400, 300, 'characters/player');
209
- this.add.image(100, 50, 'ui/button');
210
-
211
- // Load and play audio via Web Audio API
212
- const bgm = await this.pack.loadAudio('sounds/bgm');
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 accessible at the `basisPath` URL. If using stowkit-three-loader, they're in `public/stowkit/basis/` set `basisPath: '/stowkit/basis/'` |
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 that `stowkit_reader.wasm` exists at the expected URL. Pass custom `wasmPath` if serving from a different location |
236
- | No compressed format supported | WebGL context unavailable | Use `Phaser.WEBGL` for game type, not `Phaser.CANVAS`. Falls back to RGBA32 if no GPU compression extensions found |
237
- | Texture key not found in sprite | Key mismatch between `loadTexture` and `this.add.sprite` | The texture key is the exact `assetPath` string passed to `loadTexture` — use the same string |
238
- | Pixel art looks blurry | Default linear filtering | Set `filtering: 1` in the asset's `.stowmeta` file and rebuild with `stowkit build` |
239
- | Need 3D models? | Wrong loader | Use `@series-inc/stowkit-three-loader` instead this loader is 2D only |
240
- | Audio not playing | AudioContext suspended | Browsers require user interaction before audio plays start audio in response to a click/tap event |
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 |