npm package: @series-inc/stowkit-phaser-loader
Description: Phaser loader for StowKit asset packs with KTX2/Basis Universal compressed texture support
Latest version: 0.1.25

# @series-inc/stowkit-phaser-loader

Phaser.js loader for StowKit asset packs. Supports loading compressed textures (KTX2/Basis Universal) and audio from `.stow` files.

## Features

- **Compressed Texture Support** - Automatically decodes KTX2 textures to GPU-compressed formats (BC3/DXT5, BC1/DXT1, ASTC, ETC2, etc.)
- **Audio Loading** - Loads audio assets as Web Audio buffers or HTML5 audio elements
- **Multiple Packs** - Load multiple .stow files simultaneously with isolated state
- **Phaser Integration** - Textures are registered with Phaser's texture manager and work with all Phaser game objects
- **Efficient** - Textures remain compressed on the GPU, reducing memory usage

## Installation

```bash
npm install @series-inc/stowkit-phaser-loader phaser
```

## Quick Start

```typescript
import Phaser from 'phaser';
import { StowKitPhaserLoader } from '@series-inc/stowkit-phaser-loader';

class GameScene extends Phaser.Scene {
    constructor() {
        super('GameScene');
    }

    async create() {
        const pack = await StowKitPhaserLoader.load('/assets/game.stow', {
            basisPath: '/basis/',
            wasmPath: '/stowkit/stowkit_reader.wasm'
        });

        await pack.loadTexture('characters/player', this);
        await pack.loadTexture('ui/button', this);

        const player = this.add.sprite(400, 300, 'characters/player');
        const button = this.add.image(100, 50, 'ui/button');

        const bgmBuffer = await pack.loadAudio('sounds/bgm');
    }
}

const config = {
    type: Phaser.WEBGL,
    width: 800,
    height: 600,
    scene: GameScene
};

const game = new Phaser.Game(config);
```

## API Reference

### Exports

```typescript
export { StowKitPhaserLoader } from '@series-inc/stowkit-phaser-loader';
export { StowKitPhaserPack } from '@series-inc/stowkit-phaser-loader';
export { BasisTranscoder } from '@series-inc/stowkit-phaser-loader';
export { AssetType, PerfLogger } from '@series-inc/stowkit-phaser-loader';

export type { StowKitPhaserLoaderOptions } from '@series-inc/stowkit-phaser-loader';
export type { TextureData } from '@series-inc/stowkit-phaser-loader';
```

### StowKitPhaserLoader

Static loader class for opening `.stow` pack files.

#### `StowKitPhaserLoader.load(url, options?)`

Loads a `.stow` pack from a URL.

```typescript
const pack = await StowKitPhaserLoader.load('/assets/game.stow', {
    basisPath: '/basis/',
    wasmPath: '/stowkit/stowkit_reader.wasm'
});
```

**Options:**
- `basisPath` (string) - Path to Basis Universal transcoder files (default: `'/basis/'`)
- `wasmPath` (string) - Path to StowKit WASM module (default: `'/stowkit/stowkit_reader.wasm'`)
- `gl` (WebGLRenderingContext | WebGL2RenderingContext) - WebGL context to use. If not provided, a temporary canvas is created.

**Returns:** `Promise<StowKitPhaserPack>`

#### `StowKitPhaserLoader.loadFromMemory(data, options?)`

Loads a `.stow` pack from memory.

```typescript
const response = await fetch('/assets/game.stow');
const buffer = await response.arrayBuffer();
const pack = await StowKitPhaserLoader.loadFromMemory(buffer);
```

**Parameters:**
- `data` (ArrayBuffer | Blob | File) - The `.stow` file data
- `options` (StowKitPhaserLoaderOptions, optional) - Loader options

**Returns:** `Promise<StowKitPhaserPack>`

#### `StowKitPhaserLoader.dispose()`

Dispose of shared resources (Basis transcoder and temporary WebGL context if one was created).

```typescript
StowKitPhaserLoader.dispose();
```

### StowKitPhaserPack

Represents an opened `.stow` pack file.

#### `pack.loadTexture(assetPath, scene)`

Loads a texture by its canonical path and registers it with Phaser's texture manager.

**Parameters:**
- `assetPath` (string) - The canonical path of the texture (e.g., `"characters/player"`)
- `scene` (Phaser.Scene) - The Phaser scene instance

**Returns:** `Promise<Phaser.Textures.Texture>`

Must be called after the Phaser scene is initialized (in or after `create()`).

```typescript
await pack.loadTexture('textures/player', this);
this.add.sprite(100, 100, 'textures/player');
```

#### `pack.getPhaserTexture(index, scene)`

Loads a texture by index (useful for asset browsing/previews).

**Parameters:**
- `index` (number) - Asset index
- `scene` (Phaser.Scene) - The Phaser scene instance

**Returns:** `Promise<Phaser.Textures.Texture>`

#### `pack.loadAudio(assetPath, audioContext?)`

Loads audio by path as an AudioBuffer.

**Parameters:**
- `assetPath` (string) - The canonical path of the audio asset
- `audioContext` (AudioContext, optional) - Web Audio context to use

**Returns:** `Promise<AudioBuffer>`

#### `pack.loadAudioByIndex(index, audioContext?)`

Loads audio by index as an AudioBuffer.

**Parameters:**
- `index` (number) - Asset index
- `audioContext` (AudioContext, optional) - Web Audio context to use

**Returns:** `Promise<AudioBuffer>`

#### `pack.createAudioPreview(index)`

Creates an HTML5 audio element for preview.

**Returns:** `Promise<HTMLAudioElement>`

#### `pack.listAssets()`

Returns array of all assets in the pack.

#### `pack.getAssetCount(): number`

Returns total number of assets.

#### `pack.getAssetInfo(index)`

Get asset info by index.

#### `pack.getTextureMetadata(index)`

Get texture metadata (dimensions, format, tags, etc.) using WASM parsing.

```typescript
const texData = pack.getTextureMetadata(index);
console.log(`${texData.width}x${texData.height}, ${texData.channels} channels`);
```

#### `pack.getAudioMetadata(index)`

Get audio metadata using WASM parsing.

```typescript
const audioData = pack.getAudioMetadata(index);
console.log(`${audioData.sampleRate}Hz, ${audioData.durationMs}ms`);
```

#### `pack.dispose()`

Closes the pack and frees resources.

```typescript
pack.dispose();
```

## Loading Multiple Packs

Each pack is fully isolated with its own WASM reader instance. You can load multiple packs simultaneously:

```typescript
class GameScene extends Phaser.Scene {
    async create() {
        const [uiPack, levelPack, characterPack] = await Promise.all([
            StowKitPhaserLoader.load('/assets/ui.stow'),
            StowKitPhaserLoader.load('/assets/level1.stow'),
            StowKitPhaserLoader.load('/assets/characters.stow')
        ]);

        await uiPack.loadTexture('button', this);
        await levelPack.loadTexture('background', this);
        await characterPack.loadTexture('player', this);

        this.add.image(100, 50, 'button');
        this.add.image(0, 0, 'background');
        this.add.sprite(400, 300, 'player');

        console.log(`UI Pack: ${uiPack.getAssetCount()} assets`);
        console.log(`Level Pack: ${levelPack.getAssetCount()} assets`);
        console.log(`Character Pack: ${characterPack.getAssetCount()} assets`);
    }
}
```

Dispose packs when no longer needed:

```typescript
uiPack.dispose();
```

## Compressed Texture Formats

The loader automatically transcodes KTX2 textures to the best format supported by the device:

**Desktop (DXT/BC formats):**
- BC7 (BPTC) - Highest quality for UASTC textures with alpha (requires WebGL2 + `EXT_texture_compression_bptc`)
- BC3 (DXT5) - High quality for textures with alpha
- BC1 (DXT1) - For textures without alpha or ETC1S encoded textures

**Mobile:**
- ASTC 4x4 - Highest quality (iOS, Android with GPU support)
- ETC2 - Good quality (WebGL2 required)
- ETC1 - Legacy Android support
- PVRTC - iOS fallback

**Fallback:**
- RGBA32 - Uncompressed fallback if no compressed formats are supported

## Limitations

- **No 3D Model Support** - This loader only handles 2D textures and audio. For 3D models, use `@series-inc/stowkit-three-loader`.
- **Phaser 3.60+** - Compressed texture support requires Phaser 3.60 or later.
- **Scene Required** - Textures must be loaded within or after a Phaser scene is initialized.