Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
e24784c
refactor(examples)!: migrate batch A off Scene.load()/unload() to sea…
Jul 7, 2026
9a42eb9
refactor(examples)!: migrate batch B (audio) off Scene lifecycle hooks
Jul 7, 2026
cb7e44c
refactor(examples)!: migrate batch C (filters/rt/geometry) + drop unl…
Jul 7, 2026
18f0924
refactor(examples)!: migrate batch D (particles/perf/renderers) + dro…
Jul 7, 2026
efe8960
refactor(examples)!: migrate batch E (scene-graph/tweens/physics) off…
Jul 7, 2026
3fa0f6d
refactor(examples)!: migrate batch F (showcase) off Scene lifecycle h…
Jul 7, 2026
d5a9acb
refactor(examples)!: migrate batch G (input/debug/fonts) off Scene li…
Jul 7, 2026
3916143
fix(resources): explicit Sound token overloads for get()/load() — fix…
Jul 8, 2026
33b9697
feat(resources): assetMeta stamp for handle-hybrid catalog leaves
Jul 9, 2026
73d9371
refactor(resources): _-prefix assetMeta internals + real non-enumerab…
Jul 9, 2026
df8f3d4
feat(resources): module-level asset-kind registry + core kind registr…
Jul 9, 2026
31813f7
test(resources): cover asset-kind registry conflict/error paths + tig…
Jul 9, 2026
cd96c9b
feat(resources): Loader._adopt — fill externally-created catalog leav…
Jul 9, 2026
14ab3ee
fix(resources): _adopt fills already-stored handle in place + registe…
Jul 9, 2026
3ddf927
feat(resources): Assets.from handle-hybrid leaves + get/load(catalog)…
Jul 9, 2026
2a1fc18
feat(core): scene-scoped catalog adopt + auto-release on destroy
Jul 9, 2026
79d3f46
chore(resources): regen API docs for S1 catalog handle-hybrids
Jul 9, 2026
b60fa6c
fix(resources): sound value-leaf load overload + SceneLoader.load lea…
Jul 9, 2026
be3a88f
feat(resources): dev-warn on duplicate-source adopt instead of silent…
Jul 9, 2026
d8ac823
feat(resources): per-key multi-handle fill + per-handle texture samplers
Jul 9, 2026
3ffa55a
fix(resources): seamless get() bakes manifest samplerOptions into the…
Jul 9, 2026
1f0a070
feat(resources): shared AssetStatus projection of LoadState (§6)
Jul 9, 2026
e5fb7c1
test(core): update root-index type inventory snapshot for AssetStatus
Jul 9, 2026
f19580a
refactor(resources): AssetStatus interface-only; keep tests in test/ …
Jul 9, 2026
6e9d0c6
feat(resources,rendering,audio): state/ready/error status getters on …
Jul 9, 2026
5e06c02
feat(resources): extension→kind registry with loud bare-suffix collis…
Jul 9, 2026
cd29695
feat(resources): register core extension→kind mappings for bare-path …
Jul 9, 2026
25ff921
fix(resources): restrict bare-path ext→kind to leaf-capable kinds + lint
Jul 9, 2026
7e1d7d4
feat(resources): type-level ExtensionKindMap + KindByPath/LeafForPath…
Jul 9, 2026
91291f9
feat(resources): Assets.from() accepts bare paths + .of + configs (§4…
Jul 9, 2026
63b1bff
feat(resources): bare-path get()/load() infers value kinds → AssetRef…
Jul 9, 2026
55cdeca
feat(resources): _makeAsset descriptor factory for X.of() statics
Jul 9, 2026
b263ad8
feat(resources,rendering,audio): X.of() annotation statics on tokens …
Jul 9, 2026
097008b
fix(resources): brand dispatch tokens nominally + _valueTokenForKind …
Jul 9, 2026
f5ae6f0
test(resources): S2 asset-access end-to-end integration gate
Jul 9, 2026
a13d2f5
fix(resources): explicit resource-kind switch cases + default (lint e…
Jul 9, 2026
520b10e
refactor(resources): single-source value kind→token via Record (drops…
Jul 9, 2026
d66801a
fix(resources): guiding error points at real APIs (X.of/registerExten…
Jul 9, 2026
572472e
docs(resources): drop unused options? from bare-path load<S> overload…
Jul 9, 2026
06d0a79
style(resources): prettier formatting for S2 files
Jul 9, 2026
5e4526e
feat(resources): defineAsset descriptor + AssetBinding.kind
Jul 9, 2026
4492b28
refactor(resources): core bindings via defineAsset; drop hand-maintai…
Jul 9, 2026
0a78074
docs(test): fix stale seamless→coreAssetBindings comment (P1 review)
Jul 9, 2026
cd9fc86
feat(resources): add load(target, { background: true }) option (S3 P2)
Jul 9, 2026
bc41f68
feat(extensions): packages register via defineAsset + X.of() + intern…
Jul 9, 2026
bec5d23
refactor(examples)!: migrate showcase/filters/render-targets/custom-r…
Jul 9, 2026
8596722
refactor(examples)!: migrate tweens/sprites/scene-graph/geometry/text…
Jul 9, 2026
fe7a21b
refactor(examples)!: migrate particles/audio off token-form asset API…
Jul 9, 2026
90af8ac
refactor(examples)!: migrate input/debug/application-scenes/getting-s…
Jul 9, 2026
64d71d8
docs(guides): migrate guide snippets off token-form asset API (S3 P4 …
Jul 9, 2026
7ceab24
build(examples): regenerate .js from migrated .ts + drop unused init(…
Jul 9, 2026
071dbbc
fix(resources): Assets.from catalog inference robust under strict:false
Jul 9, 2026
e86b72a
feat(resources): get(asset) accepts X.of() descriptors (§4.2)
Jul 9, 2026
ee729c0
fix(resources): SvgAsset.of size options + Texture.of Partial sampler…
Jul 9, 2026
1fe703d
refactor(resources): internal bmFont sub-texture loads via Texture.of…
Jul 9, 2026
2ea58e0
test(resources): bmFontBinding asserts Texture.of() descriptor call s…
Jul 9, 2026
f4042a7
style(test): import type for type-only Texture in core-asset-bindings…
Jul 9, 2026
53f0613
@
Jul 9, 2026
d0bacfd
@
Jul 9, 2026
9be54c6
style(test): prettier-format bm-font-factory test (P5 leftover)
Jul 9, 2026
80d7175
feat(extensions): X.of() options params + migrate final token-form ca…
Jul 9, 2026
871ce67
test(resources): migrate batch-A loader tests off token get/load form…
Jul 9, 2026
2a1c526
test(resources): migrate batch-B loader tests off token get/load form…
Jul 9, 2026
10df5e8
test(resources): migrate bindAsset-handler tests to defineAsset+.of (…
Jul 9, 2026
c3b9d24
refactor(loader)!: remove token-class get/load fetch overloads (S3 P6…
Jul 9, 2026
ae71b16
docs: sweep remaining token-form asset API from prose docs (S3)
Jul 9, 2026
f72ff0c
docs(guide): rewrite stale asset-guide sections for the new API (S3)
Jul 9, 2026
1d1e3c1
fix(loader,tiled): final-review polish — drop dead ExtensionTokenType…
Jul 9, 2026
b3389ed
feat(resources): add typed Asset.kind() descriptor builder (delta A1)
Jul 9, 2026
4efd72e
refactor(resources)!: rename config discriminator type -> kind (delta…
Jul 9, 2026
b572ebc
feat(resources): add idle load state for unadopted catalog leaves (de…
Jul 9, 2026
96b2908
test(resources): lock resolved-value map from load(catalog) (delta D1)
Jul 9, 2026
4d8d354
refactor(loader)!: rename loadAll -> awaitBackground (delta E1)
Jul 9, 2026
2518df3
feat(resources): add Assets.one single-asset factory (delta F1)
Jul 9, 2026
4081e69
feat(resources): add Assets.group same-kind factory (spread form) (de…
Jul 9, 2026
9782141
fix(resources): brand value/ref descriptors so typed JSON is AssetRef…
Jul 9, 2026
ac2696f
feat(resources): add value-asset parse post-load transform (delta H1b)
Jul 9, 2026
ec6fc38
refactor: migrate engine + tests off .of onto Asset.kind (delta H2)
Jul 9, 2026
777b6fa
docs(examples): migrate 21 examples off .of onto Asset.kind (delta H3)
Jul 9, 2026
e3f4fe3
docs(guides): migrate guides to new asset API + regenerate api docs (…
Jul 9, 2026
6b4ccc3
Merge feat/v0.16-loader-lifecycle into access-redesign (delta H5)
Jul 10, 2026
413b619
refactor(resources)!: delete .of statics + internalize _makeAsset (de…
Jul 10, 2026
2d9bba5
refactor(resources)!: remove inline record-catalog load + internalize…
Jul 10, 2026
157e5da
style(resources): prettier + type-only imports after the delta cleanu…
Jul 10, 2026
bf3f1b7
fix(resources): address review — brand get(asset), guard parse, doc i…
Jul 10, 2026
dc9fec9
docs(resources): golden JSDoc/message polish (delta J review)
Jul 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 2 additions & 4 deletions examples/application-scenes/camera-basic.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Auto-generated from camera-basic.ts — edit the .ts source, not this file.
import { Application, Color, Graphics, Scene, Sprite, Texture } from '@codexo/exojs';
import { Application, Color, Graphics, Scene, Sprite } from '@codexo/exojs';
const app = new Application({
canvas: {
width: 1280,
Expand All @@ -17,11 +17,9 @@ class CameraBasicScene extends Scene {
grid;
uiBar;
zoom = 1;
async load(loader) {
this.bunny = new Sprite(await loader.load(Texture, 'image/ship-a.png'));
}
init() {
const { width, height } = this.app.canvas;
this.bunny = new Sprite(this.loader.get('image/ship-a.png'));
this.bunny.setAnchor(0.5).setPosition(width / 2, height / 2);
this.grid = new Graphics();
this.grid.lineWidth = 1;
Expand Down
7 changes: 2 additions & 5 deletions examples/application-scenes/camera-basic.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Application, Color, Graphics, Scene, Sprite, Texture } from '@codexo/exojs';
import { Application, Color, Graphics, Scene, Sprite } from '@codexo/exojs';

const app = new Application({
canvas: {
Expand All @@ -19,13 +19,10 @@ class CameraBasicScene extends Scene {
private uiBar!: Graphics;
private zoom = 1;

override async load(loader): Promise<void> {
this.bunny = new Sprite(await loader.load(Texture, 'image/ship-a.png'));
}

override init(): void {
const { width, height } = this.app.canvas;

this.bunny = new Sprite(this.loader.get('image/ship-a.png'));
this.bunny.setAnchor(0.5).setPosition(width / 2, height / 2);

this.grid = new Graphics();
Expand Down
6 changes: 2 additions & 4 deletions examples/application-scenes/multi-view-split-screen.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Auto-generated from multi-view-split-screen.ts — edit the .ts source, not this file.
import { Application, Color, Graphics, Keyboard, Scene, Sprite, Texture, View } from '@codexo/exojs';
import { Application, Color, Graphics, Keyboard, Scene, Sprite, View } from '@codexo/exojs';
const app = new Application({
canvas: {
width: 1280,
Expand Down Expand Up @@ -29,11 +29,9 @@ class SplitScreenScene extends Scene {
up: 0,
down: 0,
};
async load(loader) {
this.texture = await loader.load(Texture, 'image/ship-a.png');
}
init() {
const { width, height } = this.app.canvas;
this.texture = this.loader.get('image/ship-a.png');
this.leftView = new View(0, 0, width / 2, height).setViewport(0, 0, 0.5, 1);
this.rightView = new View(0, 0, width / 2, height).setViewport(0.5, 0, 0.5, 1);
this.divider = new Graphics();
Expand Down
6 changes: 2 additions & 4 deletions examples/application-scenes/multi-view-split-screen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,11 @@ class SplitScreenScene extends Scene {
down: 0,
};

override async load(loader): Promise<void> {
this.texture = await loader.load(Texture, 'image/ship-a.png');
}

override init(): void {
const { width, height } = this.app.canvas;

this.texture = this.loader.get('image/ship-a.png');

this.leftView = new View(0, 0, width / 2, height).setViewport(0, 0, 0.5, 1);
this.rightView = new View(0, 0, width / 2, height).setViewport(0.5, 0, 0.5, 1);

Expand Down
6 changes: 2 additions & 4 deletions examples/application-scenes/pause-and-resume.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Auto-generated from pause-and-resume.ts — edit the .ts source, not this file.
import { Application, Color, Keyboard, Scene, Sprite, Text, Texture } from '@codexo/exojs';
import { Application, Color, Keyboard, Scene, Sprite, Text } from '@codexo/exojs';
const app = new Application({
canvas: {
width: 1280,
Expand All @@ -15,11 +15,9 @@ const app = new Application({
class PauseResumeScene extends Scene {
sprite;
label;
async load(loader) {
this.sprite = new Sprite(await loader.load(Texture, 'image/ship-a.png'));
}
init() {
const { width, height } = this.app.canvas;
this.sprite = new Sprite(this.loader.get('image/ship-a.png'));
this.sprite.setAnchor(0.5);
this.sprite.setPosition(width / 2, height / 2);
this.label = new Text('Space or click: pause update', { fillColor: Color.white, fontSize: 16 });
Expand Down
7 changes: 2 additions & 5 deletions examples/application-scenes/pause-and-resume.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Application, Color, Keyboard, Scene, Sprite, Text, Texture } from '@codexo/exojs';
import { Application, Color, Keyboard, Scene, Sprite, Text } from '@codexo/exojs';

const app = new Application({
canvas: {
Expand All @@ -17,13 +17,10 @@ class PauseResumeScene extends Scene {
private sprite!: Sprite;
private label!: Text;

override async load(loader): Promise<void> {
this.sprite = new Sprite(await loader.load(Texture, 'image/ship-a.png'));
}

override init(): void {
const { width, height } = this.app.canvas;

this.sprite = new Sprite(this.loader.get('image/ship-a.png'));
this.sprite.setAnchor(0.5);
this.sprite.setPosition(width / 2, height / 2);

Expand Down
6 changes: 2 additions & 4 deletions examples/application-scenes/picture-in-picture.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Auto-generated from picture-in-picture.ts — edit the .ts source, not this file.
import { Application, Color, Graphics, Scene, Sprite, Texture, View } from '@codexo/exojs';
import { Application, Color, Graphics, Scene, Sprite, View } from '@codexo/exojs';
const app = new Application({
canvas: {
width: 1280,
Expand All @@ -18,11 +18,9 @@ class PictureInPictureScene extends Scene {
sprite;
velocity = 220;
frame;
async load(loader) {
this.sprite = new Sprite(await loader.load(Texture, 'image/ship-a.png'));
}
init() {
const { width, height } = this.app.canvas;
this.sprite = new Sprite(this.loader.get('image/ship-a.png'));
this.mainView = new View(0, 0, width, height);
this.pipView = new View(0, 0, width * 0.3, height * 0.3).setViewport(0.68, 0.04, 0.28, 0.28);
// Zoom < 1 zooms OUT (a larger visible world area maps into the same
Expand Down
8 changes: 3 additions & 5 deletions examples/application-scenes/picture-in-picture.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Application, Color, Graphics, Scene, Sprite, Texture, View } from '@codexo/exojs';
import { Application, Color, Graphics, Scene, Sprite, View } from '@codexo/exojs';

const app = new Application({
canvas: {
Expand All @@ -20,13 +20,11 @@ class PictureInPictureScene extends Scene {
private velocity = 220;
private frame!: Graphics;

override async load(loader): Promise<void> {
this.sprite = new Sprite(await loader.load(Texture, 'image/ship-a.png'));
}

override init(): void {
const { width, height } = this.app.canvas;

this.sprite = new Sprite(this.loader.get('image/ship-a.png'));

this.mainView = new View(0, 0, width, height);
this.pipView = new View(0, 0, width * 0.3, height * 0.3).setViewport(0.68, 0.04, 0.28, 0.28);
// Zoom < 1 zooms OUT (a larger visible world area maps into the same
Expand Down
31 changes: 26 additions & 5 deletions examples/application-scenes/scene-lifecycle.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,38 @@ const app = new Application({
basePath: 'assets/',
},
});
// The scene lifecycle has two hooks:
// - `init(loader)` — one-shot async setup, called once before the first frame.
// Fetch/await assets here (`this.loader.get(...)` for
// seamless resources, `await this.loader.load(...)` for
// value assets), then build the scene graph.
// - `destroy()` — one-shot teardown, called once when the scene is
// finally popped off the stack.
// `update`/`draw` run every frame in between. Two signals bracket the same
// span from the outside: `onLoad` fires right after `init()` resolves (the
// scene is about to become active) and `onUnload` fires right before
// `destroy()` runs (the scene is about to deactivate) — a hook point for
// cross-cutting concerns (audio cues, analytics, HUD toggles) that shouldn't
// live inside `init`/`destroy` themselves.
class LifecycleScene extends Scene {
events;
counter = 0;
drawCount = 0;
timer;
text;
async load() {
this.events = ['load'];
}
init() {
async init() {
const { width, height } = this.app.canvas;
this.events.push('init');
// This scene is procedural — nothing to fetch — but a real scene would
// resolve its assets here before touching the scene graph, e.g.:
// const texture = this.loader.get('ship.png');
// const data = (await this.loader.load(Asset.kind('json', 'level.json'))) as LevelData;
this.events = ['init'];
this.onLoad.add(() => {
this.events.push('onLoad');
});
this.onUnload.add(() => {
this.events.push('onUnload');
});
this.timer = new Timer(Time.fromSeconds(1), true);
this.text = new Text('', { fillColor: Color.white, fontSize: 18 });
this.text.setAnchor(0.5);
Expand All @@ -43,6 +63,7 @@ class LifecycleScene extends Scene {
context.render(this.text);
}
destroy() {
// destroy() is the single teardown hook — no separate unload() step.
this.events.push('destroy');
super.destroy();
}
Expand Down
36 changes: 29 additions & 7 deletions examples/application-scenes/scene-lifecycle.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Application, Color, Scene, Text, Time, Timer } from '@codexo/exojs';
import { Application, Asset, Color, Scene, Text, Time, Timer } from '@codexo/exojs';

const app = new Application({
canvas: {
Expand All @@ -13,21 +13,42 @@ const app = new Application({
},
});

// The scene lifecycle has two hooks:
// - `init(loader)` — one-shot async setup, called once before the first frame.
// Fetch/await assets here (`this.loader.get(...)` for
// seamless resources, `await this.loader.load(...)` for
// value assets), then build the scene graph.
// - `destroy()` — one-shot teardown, called once when the scene is
// finally popped off the stack.
// `update`/`draw` run every frame in between. Two signals bracket the same
// span from the outside: `onLoad` fires right after `init()` resolves (the
// scene is about to become active) and `onUnload` fires right before
// `destroy()` runs (the scene is about to deactivate) — a hook point for
// cross-cutting concerns (audio cues, analytics, HUD toggles) that shouldn't
// live inside `init`/`destroy` themselves.
class LifecycleScene extends Scene {
private events!: string[];
private counter = 0;
private drawCount = 0;
private timer!: Timer;
private text!: Text;

override async load(): Promise<void> {
this.events = ['load'];
}

override init(): void {
override async init(): Promise<void> {
const { width, height } = this.app.canvas;

this.events.push('init');
// This scene is procedural — nothing to fetch — but a real scene would
// resolve its assets here before touching the scene graph, e.g.:
// const texture = this.loader.get('ship.png');
// const data = (await this.loader.load(Asset.kind('json', 'level.json'))) as LevelData;
this.events = ['init'];

this.onLoad.add(() => {
this.events.push('onLoad');
});

this.onUnload.add(() => {
this.events.push('onUnload');
});

this.timer = new Timer(Time.fromSeconds(1), true);

Expand All @@ -52,6 +73,7 @@ class LifecycleScene extends Scene {
}

override destroy(): void {
// destroy() is the single teardown hook — no separate unload() step.
this.events.push('destroy');
super.destroy();
}
Expand Down
18 changes: 10 additions & 8 deletions examples/audio-basics/audio-buses.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Auto-generated from audio-buses.ts — edit the .ts source, not this file.
import { Application, AudioStream, Color, Graphics, Scene, Sound, Text } from '@codexo/exojs';
import { Application, Asset, Assets, Color, Graphics, Scene, Text } from '@codexo/exojs';
import { mountControls } from '@examples/runtime';
const app = new Application({
canvas: {
Expand Down Expand Up @@ -32,20 +32,22 @@ class AudioBusesScene extends Scene {
rowY = [];
sfxButton = { x: 0, y: 0, w: 0, h: 0 };
hud;
async load(loader) {
await loader.load(AudioStream, { music: assets.demo.audio.musicLoop });
await loader.load(Sound, { sfx: assets.demo.audio.uiClick });
}
init(loader) {
async init() {
const { width, height } = this.app.canvas;
// Centre the bus mixer horizontally and spread the bars across the wide
// 16:9 canvas.
this.trackW = width * 0.5;
this.trackX = (width - this.trackW) / 2;
this.rowY = rows.map((_, i) => height * 0.34 + i * 90);
this.sfxButton = { x: width / 2 - 150, y: height * 0.74, w: 300, h: 36 };
this.music = loader.get(AudioStream, 'music');
this.sfx = loader.get(Sound, 'sfx');
// AudioStream has no seamless adapter — await it explicitly.
const { music } = await this.loader.load(Assets.from({ music: Asset.kind('music', assets.demo.audio.musicLoop) }));
this.music = music;
// Path-only get() infers Sound from the .ogg extension — sidesteps a
// compile-time overload ambiguity between Sound and the Json token form
// (both have zero-arg-constructible instance types) when passing the
// Sound token explicitly.
this.sfx = this.loader.get(assets.demo.audio.uiClick);
this.graphics = new Graphics();
this.labels = rows.map((_, i) => new Text('', { fillColor: Color.white, fontSize: 18 }).setPosition(this.trackX - 50, this.rowY[i] - 34));
this.sfxLabel = new Text('Play SFX ▶', { fillColor: new Color(20, 20, 20), fontSize: 20 }).setPosition(this.sfxButton.x + 92, this.sfxButton.y + 7);
Expand Down
19 changes: 10 additions & 9 deletions examples/audio-basics/audio-buses.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Application, AudioStream, Color, Graphics, Scene, Sound, Text } from '@codexo/exojs';
import { Application, Asset, Assets, AudioStream, Color, Graphics, Scene, Sound, Text } from '@codexo/exojs';
import { mountControls } from '@examples/runtime';

const app = new Application({
Expand Down Expand Up @@ -35,12 +35,7 @@ class AudioBusesScene extends Scene {
private sfxButton = { x: 0, y: 0, w: 0, h: 0 };
private hud!: ReturnType<typeof mountControls>;

override async load(loader): Promise<void> {
await loader.load(AudioStream, { music: assets.demo.audio.musicLoop });
await loader.load(Sound, { sfx: assets.demo.audio.uiClick });
}

override init(loader): void {
override async init(): Promise<void> {
const { width, height } = this.app.canvas;

// Centre the bus mixer horizontally and spread the bars across the wide
Expand All @@ -50,8 +45,14 @@ class AudioBusesScene extends Scene {
this.rowY = rows.map((_, i) => height * 0.34 + i * 90);
this.sfxButton = { x: width / 2 - 150, y: height * 0.74, w: 300, h: 36 };

this.music = loader.get(AudioStream, 'music');
this.sfx = loader.get(Sound, 'sfx');
// AudioStream has no seamless adapter — await it explicitly.
const { music } = await this.loader.load(Assets.from({ music: Asset.kind('music', assets.demo.audio.musicLoop) }));
this.music = music;
// Path-only get() infers Sound from the .ogg extension — sidesteps a
// compile-time overload ambiguity between Sound and the Json token form
// (both have zero-arg-constructible instance types) when passing the
// Sound token explicitly.
this.sfx = this.loader.get(assets.demo.audio.uiClick);

this.graphics = new Graphics();
this.labels = rows.map((_, i) => new Text('', { fillColor: Color.white, fontSize: 18 }).setPosition(this.trackX - 50, this.rowY[i] - 34));
Expand Down
15 changes: 7 additions & 8 deletions examples/audio-basics/crossfade-tracks.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Auto-generated from crossfade-tracks.ts — edit the .ts source, not this file.
import { Application, AudioStream, Color, crossFade, Graphics, Scene, Text } from '@codexo/exojs';
import { Application, Asset, Assets, Color, crossFade, Graphics, Scene, Text } from '@codexo/exojs';
import { mountControls } from '@examples/runtime';
const app = new Application({
canvas: {
Expand Down Expand Up @@ -34,19 +34,18 @@ class CrossfadeTracksScene extends Scene {
meterBX = 0;
meterBaseY = 0;
hud;
async load(loader) {
await loader.load(AudioStream, { a: assets.demo.audio.musicA, b: assets.demo.audio.musicB });
}
init(loader) {
async init() {
const { width, height } = this.app.canvas;
// Spread the two meters across the wide canvas: each sits a third of the
// way in from its side, centred on the meter width.
this.meterAX = width * 0.33 - METER_W / 2;
this.meterBX = width * 0.67 - METER_W / 2;
this.meterBaseY = height * 0.82;
// Both tracks loop; the crossfade only swaps which one is audible.
this.trackA = loader.get(AudioStream, 'a');
this.trackB = loader.get(AudioStream, 'b');
// AudioStream has no seamless adapter — await it explicitly. Both tracks
// loop; the crossfade only swaps which one is audible.
const tracks = await this.loader.load(Assets.from({ a: Asset.kind('music', assets.demo.audio.musicA), b: Asset.kind('music', assets.demo.audio.musicB) }));
this.trackA = tracks.a;
this.trackB = tracks.b;
this.graphics = new Graphics();
this.labelA = new Text('Track A', { fillColor: Color.white, fontSize: 22, align: 'center' })
.setAnchor(0.5, 0.5)
Expand Down
Loading
Loading