Assets
AssetManager in @g2w/core is a minimal, renderer-agnostic asset cache. Keys are opaque strings; values are whatever the injected loader returns. The manager never interprets keys itself — everything format- and browser-specific lives in the loader you inject or the adapter you use.
Load and cache
import { AssetManager } from "@g2w/core";
const textures = new AssetManager<Texture>({
load: (url) => pixiAssetsLoad(url),
disposeAsset: (texture) => texture.destroy(true),
});
const logo = await textures.load("logo.png");The first load(key) invokes the loader; every later request for the same key returns the same promise — and therefore the same value. ThedisposeAsset option decides ownership (see below): with it, the manager owns its resources; without it, it merely caches caller-owned values.
Concurrent requests deduplicate
Requests made while a load is in flight share that one load. Failure is retryable: a rejected load removes its cache entry without poisoning it, so a later load(key) invokes the loader again — and loader errors are never wrapped:
const [a, b] = await Promise.all([
textures.load("logo.png"),
textures.load("logo.png"),
]);
// one load, one shared texture instanceTextures with @g2w/renderer-pixi
createTextureAssetManager wraps PixiJS's Assets.loadbehind the core contract. It is deliberately non-destructive: textures live in PixiJS's global shared cache, where any other manager,Sprite.from, or subsystem can reach the same instance — so the manager never destroys them. dispose() releases its cache entries and leaves texture lifetime to the session (the page unload reclaims GPU and CPU memory). When your application knows nothing else uses a texture, calling PixiJS's Assets.unload(url) explicitly is your decision, not the manager's:
import { createTextureAssetManager } from "@g2w/renderer-pixi";
const assets = createTextureAssetManager();
const logo = await assets.load("assets/logo.png");
// ...later, during teardown:
await assets.dispose(); // the texture is NOT destroyedWire disposal into the game
const assets = createTextureAssetManager();
// after game.init(): disposal joins the LIFO finalizer chain
game.addFinalizer(() => assets.dispose());Disposal is terminal and idempotent: new loads throwAssetError immediately, in-flight loads still settle for their callers, and once the disposal promise resolves every owned value has been cleaned up exactly once — shared resources are never destroyed twice.
Next steps
See Sprites & Transforms to render what you load, orarchitecture notes for the ownership policy in full.