@yagejs/core 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -209,6 +209,17 @@ declare class EventToken<T = void> {
209
209
  /** Create a typed event token. */
210
210
  declare function defineEvent<T = void>(name: string): EventToken<T>;
211
211
 
212
+ /**
213
+ * A reusable entity template. Blueprints define how to assemble
214
+ * an entity from components, given optional parameters.
215
+ */
216
+ interface Blueprint<P = void> {
217
+ readonly name: string;
218
+ build(entity: Entity, params: P): void;
219
+ }
220
+ /** Create a blueprint from a name and a build function. */
221
+ declare function defineBlueprint<P = void>(name: string, build: (entity: Entity, params: P) => void): Blueprint<P>;
222
+
212
223
  /**
213
224
  * Passed to `afterRestore` hooks so user code can resolve entity references
214
225
  * that were captured as IDs at save time.
@@ -330,8 +341,20 @@ declare class Entity {
330
341
  private _parent;
331
342
  private _children;
332
343
  constructor(name?: string, tags?: Iterable<string>);
333
- /** The scene this entity belongs to, or null. */
334
- get scene(): Scene | null;
344
+ /**
345
+ * The scene this entity belongs to. Throws if the entity is not attached
346
+ * to a scene — which in practice only happens before `scene.spawn` /
347
+ * `addChild` wires it up, or after `destroy()` tears it down. Inside
348
+ * lifecycle methods (`setup`, component `onAdd`, `update`, etc.) this is
349
+ * always safe to access.
350
+ *
351
+ * For the rare case where you genuinely need to inspect whether an
352
+ * entity has a scene (e.g. defensive code in systems iterating a query
353
+ * result), use `tryScene` instead.
354
+ */
355
+ get scene(): Scene;
356
+ /** The scene this entity belongs to, or `null` if detached. */
357
+ get tryScene(): Scene | null;
335
358
  /** True if destroy() has been called. */
336
359
  get isDestroyed(): boolean;
337
360
  /** The parent entity, or null if this is a root entity. */
@@ -340,6 +363,28 @@ declare class Entity {
340
363
  get children(): ReadonlyMap<string, Entity>;
341
364
  /** Add a named child entity. Auto-adds to parent's scene if not already in one. */
342
365
  addChild(name: string, child: Entity): void;
366
+ /**
367
+ * Spawn a new entity in this entity's scene and add it as a named child.
368
+ * Combines `scene.spawn(...)` + `this.addChild(name, ...)` in one call —
369
+ * the idiomatic way to compose entity trees (logical root + visual body
370
+ * + UI sibling + ...).
371
+ *
372
+ * Mirrors the overload shape of `Scene.spawn`: pass an Entity subclass
373
+ * (with optional setup params), a `Blueprint`, or omit for an anonymous
374
+ * base Entity.
375
+ *
376
+ * ```ts
377
+ * this.spawnChild("body", EnemyBody, { color: 0xff6b6b });
378
+ * this.spawnChild("hp", EnemyHealthBar);
379
+ * ```
380
+ */
381
+ spawnChild(name: string): Entity;
382
+ spawnChild<E extends Entity>(name: string, Class: new () => E): E;
383
+ spawnChild<E extends Entity, P>(name: string, Class: new () => E & {
384
+ setup(params: P): void;
385
+ }, params: P): E;
386
+ spawnChild<P>(name: string, blueprint: Blueprint<P>, params: P): Entity;
387
+ spawnChild(name: string, blueprint: Blueprint<void>): Entity;
343
388
  /** Remove a named child. Returns the detached entity. */
344
389
  removeChild(name: string): Entity;
345
390
  /** Get a child by name. Throws if not found. */
@@ -390,16 +435,45 @@ declare class Entity {
390
435
  _setScene(scene: Scene | null, callbacks: EntityCallbacks | null): void;
391
436
  }
392
437
 
438
+ /** Which scene op triggered this transition. */
439
+ type SceneTransitionKind = "push" | "pop" | "replace";
440
+ /** Context passed to a transition each frame. */
441
+ interface SceneTransitionContext {
442
+ /** Wall-clock ms elapsed since begin(). */
443
+ readonly elapsed: number;
444
+ readonly kind: SceneTransitionKind;
445
+ readonly engineContext: EngineContext;
446
+ /** The scene being left or removed (undefined on first push). */
447
+ readonly fromScene: Scene | undefined;
448
+ /** The scene being entered or revealed (undefined on last pop). */
449
+ readonly toScene: Scene | undefined;
450
+ }
393
451
  /**
394
- * A reusable entity template. Blueprints define how to assemble
395
- * an entity from components, given optional parameters.
452
+ * A scene transition animates the handoff between scene stack states.
453
+ *
454
+ * `SceneManager` keeps both the outgoing and incoming scenes on the stack
455
+ * for the transition's duration, then removes the outgoing scene afterward.
456
+ * Transitions use raw wall-clock dt and ignore engine + scene `timeScale`.
396
457
  */
397
- interface Blueprint<P = void> {
398
- readonly name: string;
399
- build(entity: Entity, params: P): void;
458
+ interface SceneTransition {
459
+ /** Total duration in wall-clock ms. */
460
+ readonly duration: number;
461
+ /** Called once when the transition starts. Set up resources here. */
462
+ begin?(ctx: SceneTransitionContext): void;
463
+ /** Called each frame with frame dt in ms. `ctx.elapsed` is clamped to `duration`. */
464
+ tick(dt: number, ctx: SceneTransitionContext): void;
465
+ /** Called when the transition ends. Tear down resources here. */
466
+ end?(ctx: SceneTransitionContext): void;
400
467
  }
401
- /** Create a blueprint from a name and a build function. */
402
- declare function defineBlueprint<P = void>(name: string, build: (entity: Entity, params: P) => void): Blueprint<P>;
468
+ /** Options accepted by `SceneManager.push/pop/replace`. */
469
+ interface SceneTransitionOptions {
470
+ transition?: SceneTransition;
471
+ }
472
+ /**
473
+ * Resolve the effective transition for a scene op.
474
+ * Precedence: call-site option → destination's `defaultTransition` → undefined.
475
+ */
476
+ declare function resolveTransition(callSite: SceneTransition | undefined, destination: Scene | undefined): SceneTransition | undefined;
403
477
 
404
478
  /** Filter criteria for entity queries. All fields are AND'd together. */
405
479
  interface EntityFilter {
@@ -428,6 +502,8 @@ declare abstract class Scene {
428
502
  readonly transparentBelow: boolean;
429
503
  /** Asset handles to load before onEnter(). Override in subclasses. */
430
504
  readonly preload?: readonly AssetHandle<unknown>[];
505
+ /** Default transition used when this scene is the destination of a push/pop/replace. */
506
+ readonly defaultTransition?: SceneTransition;
431
507
  /** Manual pause flag. Set by game code to pause this scene regardless of stack position. */
432
508
  paused: boolean;
433
509
  /** Time scale multiplier for this scene. 1.0 = normal, 0.5 = half speed. Default: 1. */
@@ -439,10 +515,13 @@ declare abstract class Scene {
439
515
  private queryCache;
440
516
  private bus;
441
517
  private _entityEventHandlers?;
518
+ private _scopedServices?;
442
519
  /** Access the EngineContext. */
443
520
  get context(): EngineContext;
444
521
  /** Whether this scene is effectively paused (manual pause or paused by stack). */
445
522
  get isPaused(): boolean;
523
+ /** Whether a scene transition is currently running. */
524
+ get isTransitioning(): boolean;
446
525
  /** Convenience accessor for the AssetManager. */
447
526
  get assets(): AssetManager;
448
527
  /**
@@ -507,6 +586,24 @@ declare abstract class Scene {
507
586
  serialize?(): unknown;
508
587
  /** Called after entities are restored during save/load. Rebuild non-serializable state here. */
509
588
  afterRestore?(data: unknown, resolve: SnapshotResolver): void;
589
+ /**
590
+ * Register a scene-scoped service. Called from a plugin's `beforeEnter`
591
+ * hook to make per-scene state (render tree, physics world) resolvable via
592
+ * `Component.use(key)`.
593
+ * @internal
594
+ */
595
+ _registerScoped<T>(key: ServiceKey<T>, value: T): void;
596
+ /**
597
+ * Resolve a scene-scoped service, or `undefined` if none was registered.
598
+ * @internal
599
+ */
600
+ _resolveScoped<T>(key: ServiceKey<T>): T | undefined;
601
+ /**
602
+ * Clear all scene-scoped services. Called by the SceneManager after
603
+ * `afterExit` hooks run, so plugin cleanup code still sees scoped state.
604
+ * @internal
605
+ */
606
+ _clearScopedServices(): void;
510
607
  /**
511
608
  * Set the engine context. Called by SceneManager when the scene is pushed.
512
609
  * @internal
@@ -544,7 +641,8 @@ declare abstract class Component {
544
641
  private _cleanups?;
545
642
  /**
546
643
  * Access the entity's scene. Throws if the entity is not in a scene.
547
- * Prefer this over `this.entity.scene!` in component methods.
644
+ * Prefer this over threading through `this.entity.scene` in component
645
+ * code.
548
646
  */
549
647
  get scene(): Scene;
550
648
  /**
@@ -552,12 +650,19 @@ declare abstract class Component {
552
650
  * Throws if the entity is not in a scene.
553
651
  */
554
652
  get context(): EngineContext;
555
- /** Resolve a service by key, cached after first lookup. */
653
+ /**
654
+ * Resolve a service by key, cached after first lookup. Scene-scoped values
655
+ * (registered via `scene._registerScoped`) take precedence over engine
656
+ * scope. A key declared with `scope: "scene"` that falls back to engine
657
+ * scope emits a one-shot dev warning — almost always signals a missed
658
+ * `beforeEnter` hook.
659
+ */
556
660
  protected use<T>(key: ServiceKey<T>): T;
661
+ private _warnScopedFallback;
557
662
  /**
558
663
  * Lazy proxy-based service resolution. Can be used at field-declaration time:
559
664
  * ```ts
560
- * readonly camera = this.service(CameraKey);
665
+ * readonly input = this.service(InputManagerKey);
561
666
  * ```
562
667
  * The actual resolution is deferred until first property access.
563
668
  */
@@ -727,6 +832,12 @@ declare class SceneManager {
727
832
  private _context;
728
833
  private bus;
729
834
  private assetManager;
835
+ private hookRegistry;
836
+ private logger;
837
+ private _currentRun;
838
+ private _pendingChain;
839
+ private _mutationDepth;
840
+ private _destroyed;
730
841
  /**
731
842
  * Set the engine context.
732
843
  * @internal
@@ -738,27 +849,77 @@ declare class SceneManager {
738
849
  get all(): readonly Scene[];
739
850
  /** All non-paused scenes in the stack, bottom to top. */
740
851
  get activeScenes(): readonly Scene[];
852
+ /** Whether a scene transition is currently running. */
853
+ get isTransitioning(): boolean;
741
854
  /**
742
855
  * Push a scene onto the stack. Scenes below may receive onPause().
743
856
  * If the scene declares a `preload` array, assets are loaded before onEnter().
744
- * Await the returned promise when using preloaded scenes.
745
857
  */
746
- push(scene: Scene): Promise<void>;
858
+ push(scene: Scene, opts?: SceneTransitionOptions): Promise<void>;
747
859
  /** Pop the top scene. Scenes below may receive onResume(). */
748
- pop(): Scene | undefined;
860
+ pop(opts?: SceneTransitionOptions): Promise<Scene | undefined>;
749
861
  /**
750
- * Replace the top scene. Old scene receives onExit().
751
- * New scene receives onEnter() (after preload, if declared).
862
+ * Replace the top scene. Without a transition the old scene exits first,
863
+ * then the new scene enters. With a transition the new scene is pushed
864
+ * first, both scenes coexist for the transition duration, then the old
865
+ * scene is removed at the end.
752
866
  */
753
- replace(scene: Scene): Promise<void>;
754
- /** Clear all scenes. Each receives onExit() from top to bottom. */
755
- clear(): void;
867
+ replace(scene: Scene, opts?: SceneTransitionOptions): Promise<void>;
868
+ /**
869
+ * Pop every scene on the stack, top to bottom. Each receives onExit().
870
+ * Queued like push/pop/replace — runs after any in-flight transition.
871
+ * Use for "restart from menu"-style flows. Does not run transitions.
872
+ */
873
+ popAll(): Promise<void>;
874
+ /**
875
+ * Run the full scene-enter lifecycle (beforeEnter hooks, preload, onEnter)
876
+ * for a scene that is NOT placed on the stack. Used by infrastructure
877
+ * plugins like DebugPlugin that render a scene off-stack.
878
+ * @internal
879
+ */
880
+ _mountDetached(scene: Scene): Promise<void>;
881
+ /**
882
+ * Run the scene-exit lifecycle (onExit, entity destruction, afterExit
883
+ * hooks, scoped-service clear) for a detached scene.
884
+ * @internal
885
+ */
886
+ _unmountDetached(scene: Scene): void;
887
+ /**
888
+ * Mark the manager destroyed and synchronously tear down every scene.
889
+ * Called by Engine.destroy(). Any queued async work short-circuits on
890
+ * resume; in-flight transitions' pending promises are resolved via
891
+ * _cleanupRun so they don't leak.
892
+ * @internal
893
+ */
894
+ _destroy(): void;
756
895
  /**
757
896
  * Flush destroy queues for all active scenes.
758
897
  * Called by the engine during endOfFrame.
759
898
  * @internal
760
899
  */
761
900
  _flushDestroyQueues(): void;
901
+ /**
902
+ * Advance the active transition by `dt` ms. Called by Engine's earlyUpdate
903
+ * callback with raw (unscaled) wall-clock dt.
904
+ * @internal
905
+ */
906
+ _tickTransition(dt: number): void;
907
+ private _enqueue;
908
+ private _pushScene;
909
+ private _popScene;
910
+ private _replaceScene;
911
+ private _removeScene;
912
+ private _preloadScene;
913
+ private _teardownScene;
914
+ private _runTransition;
915
+ private _cleanupRun;
916
+ private _safeTick;
917
+ private _safeCall;
918
+ private _makeContext;
919
+ private _snapshotPauseStates;
920
+ private _assertNotMutating;
921
+ private _withMutation;
922
+ private _withMutationSync;
762
923
  /** Fire onPause() for scenes that transitioned from not-paused to paused. */
763
924
  private _firePauseTransitions;
764
925
  /** Fire onResume() for scenes that transitioned from paused to not-paused. */
@@ -883,6 +1044,23 @@ interface EngineEvents {
883
1044
  oldScene: SceneRef;
884
1045
  newScene: SceneRef;
885
1046
  };
1047
+ "scene:transition:started": {
1048
+ kind: SceneTransitionKind;
1049
+ fromScene: SceneRef | undefined;
1050
+ toScene: SceneRef | undefined;
1051
+ };
1052
+ "scene:transition:ended": {
1053
+ kind: SceneTransitionKind;
1054
+ fromScene: SceneRef | undefined;
1055
+ toScene: SceneRef | undefined;
1056
+ };
1057
+ "scene:loading:progress": {
1058
+ scene: Scene;
1059
+ ratio: number;
1060
+ };
1061
+ "scene:loading:done": {
1062
+ scene: Scene;
1063
+ };
886
1064
  "engine:started": undefined;
887
1065
  "engine:stopped": undefined;
888
1066
  }
@@ -899,6 +1077,39 @@ declare class EventBus<E = EventMap> {
899
1077
  clear(event?: keyof E): void;
900
1078
  }
901
1079
 
1080
+ /**
1081
+ * Plugin hooks invoked by the SceneManager at scene lifecycle points.
1082
+ * Plugins register hooks via `engine.registerSceneHooks(hooks)` to set up or
1083
+ * tear down per-scene state (e.g. render containers, physics worlds).
1084
+ */
1085
+ interface SceneHooks {
1086
+ /**
1087
+ * Runs after the scene's context is bound but before preload / `onEnter`.
1088
+ * Awaited serially so scoped services registered here are ready when the
1089
+ * scene's own code runs. Fires on `push`, `replace`, and `_mountDetached`.
1090
+ */
1091
+ beforeEnter?(scene: Scene): void | Promise<void>;
1092
+ /**
1093
+ * Runs after `onExit` + `_destroyAllEntities` and before the scene's
1094
+ * scoped-service map is cleared. Fires on `pop`, `replace`, `clear`, and
1095
+ * `_unmountDetached`.
1096
+ */
1097
+ afterExit?(scene: Scene): void;
1098
+ }
1099
+ /**
1100
+ * Registry of scene hooks. Held by the engine, consumed by the SceneManager.
1101
+ * @internal
1102
+ */
1103
+ declare class SceneHookRegistry {
1104
+ private readonly hooks;
1105
+ register(hooks: SceneHooks): () => void;
1106
+ /** Run all `beforeEnter` hooks serially. */
1107
+ runBeforeEnter(scene: Scene): Promise<void>;
1108
+ runAfterExit(scene: Scene): void;
1109
+ }
1110
+ /** DI key for the scene-hook registry. @internal */
1111
+ declare const SceneHookRegistryKey: ServiceKey<SceneHookRegistry>;
1112
+
902
1113
  /** Engine configuration. */
903
1114
  interface EngineConfig {
904
1115
  /** Enable debug mode (Inspector API, debug logging). */
@@ -930,6 +1141,7 @@ declare class Engine {
930
1141
  private readonly scheduler;
931
1142
  private readonly errorBoundary;
932
1143
  private readonly queryCache;
1144
+ private readonly sceneHooks;
933
1145
  /** The asset manager. */
934
1146
  readonly assets: AssetManager;
935
1147
  private readonly plugins;
@@ -937,6 +1149,12 @@ declare class Engine {
937
1149
  private started;
938
1150
  private readonly debug;
939
1151
  constructor(config?: EngineConfig);
1152
+ /**
1153
+ * Register scene lifecycle hooks. The returned function unregisters the
1154
+ * hooks. Infrastructure plugins (renderer, physics, debug) register hooks
1155
+ * in their `install` or `onStart` to set up and tear down per-scene state.
1156
+ */
1157
+ registerSceneHooks(hooks: SceneHooks): () => void;
940
1158
  /** Register a plugin. Must be called before start(). */
941
1159
  use(plugin: Plugin): this;
942
1160
  /** Start the engine. Installs plugins in topological order, starts the game loop. */
@@ -951,13 +1169,27 @@ declare class Engine {
951
1169
  private topologicalSort;
952
1170
  }
953
1171
 
1172
+ /** The resolution scope for a service. */
1173
+ type ServiceScope = "engine" | "scene";
1174
+ /** Options passed to `new ServiceKey(id, options)`. */
1175
+ interface ServiceKeyOptions {
1176
+ /**
1177
+ * Declared scope. `"scene"` keys are expected to be registered per-scene
1178
+ * via a `beforeEnter` hook; `Component.use` will check scene scope first
1179
+ * and warn if it falls back to engine scope.
1180
+ * Default: `"engine"`.
1181
+ */
1182
+ scope?: ServiceScope;
1183
+ }
954
1184
  /** A typed key for service registration and resolution. */
955
1185
  declare class ServiceKey<T> {
956
1186
  /** Unique string identifier for this service. */
957
1187
  readonly id: string;
1188
+ /** Declared scope (engine or scene). Defaults to `"engine"`. */
1189
+ readonly scope: ServiceScope;
958
1190
  constructor(
959
1191
  /** Unique string identifier for this service. */
960
- id: string);
1192
+ id: string, options?: ServiceKeyOptions);
961
1193
  /** Phantom field to preserve the generic type. */
962
1194
  readonly _type: T;
963
1195
  }
@@ -1072,7 +1304,7 @@ interface Plugin {
1072
1304
  /** Register systems with the scheduler. Called after install. */
1073
1305
  registerSystems?(scheduler: SystemScheduler): void;
1074
1306
  /** Called after all plugins are installed and the engine has started. */
1075
- onStart?(): void;
1307
+ onStart?(): void | Promise<void>;
1076
1308
  /** Called when the engine is destroyed. */
1077
1309
  onDestroy?(): void;
1078
1310
  }
@@ -1265,6 +1497,112 @@ declare class ComponentUpdateSystem extends BaseComponentUpdateSystem {
1265
1497
  update(dt: number): void;
1266
1498
  }
1267
1499
 
1500
+ /**
1501
+ * Base class for a progress-bar style loading screen.
1502
+ *
1503
+ * Preloads the target scene's assets through the `AssetManager`, exposes
1504
+ * `progress` and emits `scene:loading:progress` / `scene:loading:done` on
1505
+ * the engine event bus, enforces `minDuration` to prevent flicker on cached
1506
+ * loads, then replaces itself with `target` — optionally through a
1507
+ * transition.
1508
+ *
1509
+ * LoadingScene owns orchestration only. It does not render anything. To show
1510
+ * a progress UI, spawn an entity that subscribes to the loading events (the
1511
+ * canonical default is `LoadingSceneProgressBar` in `@yagejs/ui`, or any
1512
+ * custom component). The loading scene is a normal Scene, so you can use
1513
+ * `onEnter` to spawn whatever you want.
1514
+ *
1515
+ * ```ts
1516
+ * class Boot extends LoadingScene {
1517
+ * readonly target = new GameScene();
1518
+ * readonly minDuration = 500;
1519
+ * readonly transition = fade({ duration: 300 });
1520
+ * override onEnter() {
1521
+ * this.spawn(LoadingSceneProgressBar);
1522
+ * this.startLoading();
1523
+ * }
1524
+ * }
1525
+ *
1526
+ * await engine.scenes.replace(new Boot());
1527
+ * ```
1528
+ *
1529
+ * Set `autoContinue = false` to gate the handoff behind a `continue()` call
1530
+ * — useful for "press any key to continue" flows. `scene:loading:done`
1531
+ * still fires so UI can react (show a prompt), and whoever eventually
1532
+ * calls `this.continue()` triggers the transition.
1533
+ */
1534
+ declare abstract class LoadingScene extends Scene {
1535
+ readonly name: string;
1536
+ /**
1537
+ * Scene to load and transition to. Accepts an instance or a factory —
1538
+ * use a factory when target construction should be deferred until
1539
+ * loading starts (heavy constructors, side effects). The factory runs
1540
+ * before `assets.loadAll` so `target.preload` can be inspected.
1541
+ */
1542
+ abstract readonly target: Scene | (() => Scene);
1543
+ /**
1544
+ * Minimum wall-clock ms the scene stays visible before handing off.
1545
+ * Prevents flicker on cached loads. Default 0.
1546
+ */
1547
+ readonly minDuration: number;
1548
+ /** Transition used for the loading → target handoff. */
1549
+ readonly transition?: SceneTransition;
1550
+ /**
1551
+ * When true (default), the handoff fires automatically after loading and
1552
+ * `minDuration`. Set false to gate it behind `continue()` — useful when
1553
+ * the loading scene also asks the player to press a key or click.
1554
+ */
1555
+ readonly autoContinue: boolean;
1556
+ /**
1557
+ * Optional hook; fires if asset loading rejects. The scene stays mounted
1558
+ * whether or not this is set. When set, the hook is the recovery channel:
1559
+ * draw a retry UI, push an error scene, or call `this.startLoading()`
1560
+ * again to retry the load. When unset, the error is logged via the engine
1561
+ * logger and the scene remains mounted in a failed state with no
1562
+ * automatic recovery.
1563
+ *
1564
+ * The hook may still be running when the scene is replaced externally —
1565
+ * don't assume the scene is live (check `this.context.tryResolve` rather
1566
+ * than `this.service` before touching engine services, and avoid spawning
1567
+ * new entities after an `await`).
1568
+ */
1569
+ onLoadError?(error: Error): void | Promise<void>;
1570
+ private _progress;
1571
+ private _started;
1572
+ private _active;
1573
+ private _continueRequested;
1574
+ private _continueGate?;
1575
+ private _attempt;
1576
+ /** Current load progress, 0 → 1. Updated as the AssetManager reports progress. */
1577
+ get progress(): number;
1578
+ /**
1579
+ * Kick off asset loading. While a load is in flight, subsequent calls
1580
+ * are no-ops. After a load failure the guard is released, so calling
1581
+ * `startLoading()` from `onLoadError` (or from a retry button) kicks off
1582
+ * a fresh load against the same target.
1583
+ *
1584
+ * Usually called once from `onEnter` after spawning the loading UI:
1585
+ * ```ts
1586
+ * override onEnter() {
1587
+ * this.spawn(LoadingSceneProgressBar);
1588
+ * this.startLoading();
1589
+ * }
1590
+ * ```
1591
+ *
1592
+ * Deferring the call lets you gate the start of the load behind a
1593
+ * title screen, "press any key" prompt, intro animation, etc.
1594
+ */
1595
+ startLoading(): void;
1596
+ /**
1597
+ * Trigger the handoff to `target`. No-op if already called or if
1598
+ * `autoContinue` already fired it. If called before loading finishes,
1599
+ * the handoff runs as soon as loading + `minDuration` complete.
1600
+ */
1601
+ continue(): void;
1602
+ onExit(): void;
1603
+ private _run;
1604
+ }
1605
+
1268
1606
  /** Static factory for creating tween Processes. */
1269
1607
  declare const Tween: {
1270
1608
  /** Tween a numeric property on a target object. */
@@ -1509,4 +1847,4 @@ declare function advanceFrames(engine: Engine, n: number, dtMs?: number): void;
1509
1847
 
1510
1848
  declare const VERSION = "0.0.0";
1511
1849
 
1512
- export { AssetHandle, type AssetLoader, AssetManager, AssetManagerKey, type Blueprint, Component, type ComponentClass, ComponentFixedUpdateSystem, ComponentUpdateSystem, type EasingFunction, Engine, type EngineConfig, EngineContext, type EngineEvents, EngineKey, type EngineSnapshot, Entity, type EntityCallbacks, type EntityFilter, type EntitySnapshot, ErrorBoundary, ErrorBoundaryKey, type ErrorSnapshot, EventBus, EventBusKey, type EventMap, EventToken, GameLoop, type GameLoopCallbacks, type GameLoopConfig, GameLoopKey, Inspector, InspectorKey, type Interpolatable, type Keyframe, type KeyframeAnimationDef, KeyframeAnimator, type KeyframeTrackOptions, type LogEntry, LogLevel, Logger, type LoggerConfig, LoggerKey, MathUtils, Phase, type Plugin, Process, ProcessComponent, type ProcessOptions, ProcessSlot, type ProcessSlotConfig, ProcessSystem, ProcessSystemKey, QueryCache, QueryCacheKey, QueryResult, SERIALIZABLE_KEY, Scene, SceneManager, SceneManagerKey, type SceneSnapshot, Sequence, SerializableRegistry, ServiceKey, type SnapshotResolver, System, SystemScheduler, SystemSchedulerKey, type SystemSnapshot, TimerEntity, TraitToken, Transform, type TransformData, Tween, VERSION, Vec2, type Vec2Like, _resetEntityIdCounter, advanceFrames, createKeyframeTrack, createMockEntity, createMockScene, createTestEngine, defineBlueprint, defineEvent, defineTrait, easeInOutQuad, easeInQuad, easeLinear, easeOutBounce, easeOutQuad, filterEntities, getSerializableType, interpolate, isSerializable, serializable, trait };
1850
+ export { AssetHandle, type AssetLoader, AssetManager, AssetManagerKey, type Blueprint, Component, type ComponentClass, ComponentFixedUpdateSystem, ComponentUpdateSystem, type EasingFunction, Engine, type EngineConfig, EngineContext, type EngineEvents, EngineKey, type EngineSnapshot, Entity, type EntityCallbacks, type EntityFilter, type EntitySnapshot, ErrorBoundary, ErrorBoundaryKey, type ErrorSnapshot, EventBus, EventBusKey, type EventMap, EventToken, GameLoop, type GameLoopCallbacks, type GameLoopConfig, GameLoopKey, Inspector, InspectorKey, type Interpolatable, type Keyframe, type KeyframeAnimationDef, KeyframeAnimator, type KeyframeTrackOptions, LoadingScene, type LogEntry, LogLevel, Logger, type LoggerConfig, LoggerKey, MathUtils, Phase, type Plugin, Process, ProcessComponent, type ProcessOptions, ProcessSlot, type ProcessSlotConfig, ProcessSystem, ProcessSystemKey, QueryCache, QueryCacheKey, QueryResult, SERIALIZABLE_KEY, Scene, SceneHookRegistry, SceneHookRegistryKey, type SceneHooks, SceneManager, SceneManagerKey, type SceneSnapshot, type SceneTransition, type SceneTransitionContext, type SceneTransitionKind, type SceneTransitionOptions, Sequence, SerializableRegistry, ServiceKey, type ServiceKeyOptions, type ServiceScope, type SnapshotResolver, System, SystemScheduler, SystemSchedulerKey, type SystemSnapshot, TimerEntity, TraitToken, Transform, type TransformData, Tween, VERSION, Vec2, type Vec2Like, _resetEntityIdCounter, advanceFrames, createKeyframeTrack, createMockEntity, createMockScene, createTestEngine, defineBlueprint, defineEvent, defineTrait, easeInOutQuad, easeInQuad, easeLinear, easeOutBounce, easeOutQuad, filterEntities, getSerializableType, interpolate, isSerializable, resolveTransition, serializable, trait };