@yagejs/core 0.1.0 → 0.3.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.cjs +764 -87
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +440 -23
- package/dist/index.d.ts +440 -23
- package/dist/index.js +759 -87
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -209,6 +209,25 @@ 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
|
+
* @deprecated Prefer Entity subclasses with `setup()` for entity types.
|
|
217
|
+
* Blueprints still work for parametric factories but are no longer the
|
|
218
|
+
* recommended pattern for new code.
|
|
219
|
+
*/
|
|
220
|
+
interface Blueprint<P = void> {
|
|
221
|
+
readonly name: string;
|
|
222
|
+
build(entity: Entity, params: P): void;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Create a blueprint from a name and a build function.
|
|
226
|
+
*
|
|
227
|
+
* @deprecated Prefer Entity subclasses with `setup()` for entity types.
|
|
228
|
+
*/
|
|
229
|
+
declare function defineBlueprint<P = void>(name: string, build: (entity: Entity, params: P) => void): Blueprint<P>;
|
|
230
|
+
|
|
212
231
|
/**
|
|
213
232
|
* Passed to `afterRestore` hooks so user code can resolve entity references
|
|
214
233
|
* that were captured as IDs at save time.
|
|
@@ -330,8 +349,20 @@ declare class Entity {
|
|
|
330
349
|
private _parent;
|
|
331
350
|
private _children;
|
|
332
351
|
constructor(name?: string, tags?: Iterable<string>);
|
|
333
|
-
/**
|
|
334
|
-
|
|
352
|
+
/**
|
|
353
|
+
* The scene this entity belongs to. Throws if the entity is not attached
|
|
354
|
+
* to a scene — which in practice only happens before `scene.spawn` /
|
|
355
|
+
* `addChild` wires it up, or after `destroy()` tears it down. Inside
|
|
356
|
+
* lifecycle methods (`setup`, component `onAdd`, `update`, etc.) this is
|
|
357
|
+
* always safe to access.
|
|
358
|
+
*
|
|
359
|
+
* For the rare case where you genuinely need to inspect whether an
|
|
360
|
+
* entity has a scene (e.g. defensive code in systems iterating a query
|
|
361
|
+
* result), use `tryScene` instead.
|
|
362
|
+
*/
|
|
363
|
+
get scene(): Scene;
|
|
364
|
+
/** The scene this entity belongs to, or `null` if detached. */
|
|
365
|
+
get tryScene(): Scene | null;
|
|
335
366
|
/** True if destroy() has been called. */
|
|
336
367
|
get isDestroyed(): boolean;
|
|
337
368
|
/** The parent entity, or null if this is a root entity. */
|
|
@@ -340,6 +371,28 @@ declare class Entity {
|
|
|
340
371
|
get children(): ReadonlyMap<string, Entity>;
|
|
341
372
|
/** Add a named child entity. Auto-adds to parent's scene if not already in one. */
|
|
342
373
|
addChild(name: string, child: Entity): void;
|
|
374
|
+
/**
|
|
375
|
+
* Spawn a new entity in this entity's scene and add it as a named child.
|
|
376
|
+
* Combines `scene.spawn(...)` + `this.addChild(name, ...)` in one call —
|
|
377
|
+
* the idiomatic way to compose entity trees (logical root + visual body
|
|
378
|
+
* + UI sibling + ...).
|
|
379
|
+
*
|
|
380
|
+
* Mirrors the overload shape of `Scene.spawn`: pass an Entity subclass
|
|
381
|
+
* (with optional setup params), a `Blueprint`, or omit for an anonymous
|
|
382
|
+
* base Entity.
|
|
383
|
+
*
|
|
384
|
+
* ```ts
|
|
385
|
+
* this.spawnChild("body", EnemyBody, { color: 0xff6b6b });
|
|
386
|
+
* this.spawnChild("hp", EnemyHealthBar);
|
|
387
|
+
* ```
|
|
388
|
+
*/
|
|
389
|
+
spawnChild(name: string): Entity;
|
|
390
|
+
spawnChild<E extends Entity>(name: string, Class: new () => E): E;
|
|
391
|
+
spawnChild<E extends Entity, P>(name: string, Class: new () => E & {
|
|
392
|
+
setup(params: P): void;
|
|
393
|
+
}, params: P): E;
|
|
394
|
+
spawnChild<P>(name: string, blueprint: Blueprint<P>, params: P): Entity;
|
|
395
|
+
spawnChild(name: string, blueprint: Blueprint<void>): Entity;
|
|
343
396
|
/** Remove a named child. Returns the detached entity. */
|
|
344
397
|
removeChild(name: string): Entity;
|
|
345
398
|
/** Get a child by name. Throws if not found. */
|
|
@@ -390,16 +443,45 @@ declare class Entity {
|
|
|
390
443
|
_setScene(scene: Scene | null, callbacks: EntityCallbacks | null): void;
|
|
391
444
|
}
|
|
392
445
|
|
|
446
|
+
/** Which scene op triggered this transition. */
|
|
447
|
+
type SceneTransitionKind = "push" | "pop" | "replace";
|
|
448
|
+
/** Context passed to a transition each frame. */
|
|
449
|
+
interface SceneTransitionContext {
|
|
450
|
+
/** Wall-clock ms elapsed since begin(). */
|
|
451
|
+
readonly elapsed: number;
|
|
452
|
+
readonly kind: SceneTransitionKind;
|
|
453
|
+
readonly engineContext: EngineContext;
|
|
454
|
+
/** The scene being left or removed (undefined on first push). */
|
|
455
|
+
readonly fromScene: Scene | undefined;
|
|
456
|
+
/** The scene being entered or revealed (undefined on last pop). */
|
|
457
|
+
readonly toScene: Scene | undefined;
|
|
458
|
+
}
|
|
393
459
|
/**
|
|
394
|
-
* A
|
|
395
|
-
*
|
|
460
|
+
* A scene transition animates the handoff between scene stack states.
|
|
461
|
+
*
|
|
462
|
+
* `SceneManager` keeps both the outgoing and incoming scenes on the stack
|
|
463
|
+
* for the transition's duration, then removes the outgoing scene afterward.
|
|
464
|
+
* Transitions use raw wall-clock dt and ignore engine + scene `timeScale`.
|
|
396
465
|
*/
|
|
397
|
-
interface
|
|
398
|
-
|
|
399
|
-
|
|
466
|
+
interface SceneTransition {
|
|
467
|
+
/** Total duration in wall-clock ms. */
|
|
468
|
+
readonly duration: number;
|
|
469
|
+
/** Called once when the transition starts. Set up resources here. */
|
|
470
|
+
begin?(ctx: SceneTransitionContext): void;
|
|
471
|
+
/** Called each frame with frame dt in ms. `ctx.elapsed` is clamped to `duration`. */
|
|
472
|
+
tick(dt: number, ctx: SceneTransitionContext): void;
|
|
473
|
+
/** Called when the transition ends. Tear down resources here. */
|
|
474
|
+
end?(ctx: SceneTransitionContext): void;
|
|
400
475
|
}
|
|
401
|
-
/**
|
|
402
|
-
|
|
476
|
+
/** Options accepted by `SceneManager.push/pop/replace`. */
|
|
477
|
+
interface SceneTransitionOptions {
|
|
478
|
+
transition?: SceneTransition;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Resolve the effective transition for a scene op.
|
|
482
|
+
* Precedence: call-site option → destination's `defaultTransition` → undefined.
|
|
483
|
+
*/
|
|
484
|
+
declare function resolveTransition(callSite: SceneTransition | undefined, destination: Scene | undefined): SceneTransition | undefined;
|
|
403
485
|
|
|
404
486
|
/** Filter criteria for entity queries. All fields are AND'd together. */
|
|
405
487
|
interface EntityFilter {
|
|
@@ -428,6 +510,8 @@ declare abstract class Scene {
|
|
|
428
510
|
readonly transparentBelow: boolean;
|
|
429
511
|
/** Asset handles to load before onEnter(). Override in subclasses. */
|
|
430
512
|
readonly preload?: readonly AssetHandle<unknown>[];
|
|
513
|
+
/** Default transition used when this scene is the destination of a push/pop/replace. */
|
|
514
|
+
readonly defaultTransition?: SceneTransition;
|
|
431
515
|
/** Manual pause flag. Set by game code to pause this scene regardless of stack position. */
|
|
432
516
|
paused: boolean;
|
|
433
517
|
/** Time scale multiplier for this scene. 1.0 = normal, 0.5 = half speed. Default: 1. */
|
|
@@ -439,10 +523,13 @@ declare abstract class Scene {
|
|
|
439
523
|
private queryCache;
|
|
440
524
|
private bus;
|
|
441
525
|
private _entityEventHandlers?;
|
|
526
|
+
private _scopedServices?;
|
|
442
527
|
/** Access the EngineContext. */
|
|
443
528
|
get context(): EngineContext;
|
|
444
529
|
/** Whether this scene is effectively paused (manual pause or paused by stack). */
|
|
445
530
|
get isPaused(): boolean;
|
|
531
|
+
/** Whether a scene transition is currently running. */
|
|
532
|
+
get isTransitioning(): boolean;
|
|
446
533
|
/** Convenience accessor for the AssetManager. */
|
|
447
534
|
get assets(): AssetManager;
|
|
448
535
|
/**
|
|
@@ -507,6 +594,24 @@ declare abstract class Scene {
|
|
|
507
594
|
serialize?(): unknown;
|
|
508
595
|
/** Called after entities are restored during save/load. Rebuild non-serializable state here. */
|
|
509
596
|
afterRestore?(data: unknown, resolve: SnapshotResolver): void;
|
|
597
|
+
/**
|
|
598
|
+
* Register a scene-scoped service. Called from a plugin's `beforeEnter`
|
|
599
|
+
* hook to make per-scene state (render tree, physics world) resolvable via
|
|
600
|
+
* `Component.use(key)`.
|
|
601
|
+
* @internal
|
|
602
|
+
*/
|
|
603
|
+
_registerScoped<T>(key: ServiceKey<T>, value: T): void;
|
|
604
|
+
/**
|
|
605
|
+
* Resolve a scene-scoped service, or `undefined` if none was registered.
|
|
606
|
+
* @internal
|
|
607
|
+
*/
|
|
608
|
+
_resolveScoped<T>(key: ServiceKey<T>): T | undefined;
|
|
609
|
+
/**
|
|
610
|
+
* Clear all scene-scoped services. Called by the SceneManager after
|
|
611
|
+
* `afterExit` hooks run, so plugin cleanup code still sees scoped state.
|
|
612
|
+
* @internal
|
|
613
|
+
*/
|
|
614
|
+
_clearScopedServices(): void;
|
|
510
615
|
/**
|
|
511
616
|
* Set the engine context. Called by SceneManager when the scene is pushed.
|
|
512
617
|
* @internal
|
|
@@ -544,7 +649,8 @@ declare abstract class Component {
|
|
|
544
649
|
private _cleanups?;
|
|
545
650
|
/**
|
|
546
651
|
* Access the entity's scene. Throws if the entity is not in a scene.
|
|
547
|
-
* Prefer this over `this.entity.scene
|
|
652
|
+
* Prefer this over threading through `this.entity.scene` in component
|
|
653
|
+
* code.
|
|
548
654
|
*/
|
|
549
655
|
get scene(): Scene;
|
|
550
656
|
/**
|
|
@@ -552,12 +658,19 @@ declare abstract class Component {
|
|
|
552
658
|
* Throws if the entity is not in a scene.
|
|
553
659
|
*/
|
|
554
660
|
get context(): EngineContext;
|
|
555
|
-
/**
|
|
661
|
+
/**
|
|
662
|
+
* Resolve a service by key, cached after first lookup. Scene-scoped values
|
|
663
|
+
* (registered via `scene._registerScoped`) take precedence over engine
|
|
664
|
+
* scope. A key declared with `scope: "scene"` that falls back to engine
|
|
665
|
+
* scope emits a one-shot dev warning — almost always signals a missed
|
|
666
|
+
* `beforeEnter` hook.
|
|
667
|
+
*/
|
|
556
668
|
protected use<T>(key: ServiceKey<T>): T;
|
|
669
|
+
private _warnScopedFallback;
|
|
557
670
|
/**
|
|
558
671
|
* Lazy proxy-based service resolution. Can be used at field-declaration time:
|
|
559
672
|
* ```ts
|
|
560
|
-
* readonly
|
|
673
|
+
* readonly input = this.service(InputManagerKey);
|
|
561
674
|
* ```
|
|
562
675
|
* The actual resolution is deferred until first property access.
|
|
563
676
|
*/
|
|
@@ -727,38 +840,114 @@ declare class SceneManager {
|
|
|
727
840
|
private _context;
|
|
728
841
|
private bus;
|
|
729
842
|
private assetManager;
|
|
843
|
+
private hookRegistry;
|
|
844
|
+
private logger;
|
|
845
|
+
private _currentRun;
|
|
846
|
+
private _pendingChain;
|
|
847
|
+
private _mutationDepth;
|
|
848
|
+
private _destroyed;
|
|
849
|
+
private _autoPauseOnBlur;
|
|
850
|
+
private _isBlurred;
|
|
851
|
+
private readonly _visibilityPausedScenes;
|
|
852
|
+
private _visibilityListenerCleanup;
|
|
853
|
+
/**
|
|
854
|
+
* Pause all non-paused scenes when `document.hidden` becomes `true`; restore
|
|
855
|
+
* them on focus. Default: `false`. Only scenes paused by this mechanism are
|
|
856
|
+
* restored — user-paused scenes (manual `scene.paused = true` or `pauseBelow`
|
|
857
|
+
* cascade) are never touched.
|
|
858
|
+
*/
|
|
859
|
+
get autoPauseOnBlur(): boolean;
|
|
860
|
+
set autoPauseOnBlur(value: boolean);
|
|
730
861
|
/**
|
|
731
862
|
* Set the engine context.
|
|
732
863
|
* @internal
|
|
733
864
|
*/
|
|
734
865
|
_setContext(context: EngineContext): void;
|
|
866
|
+
/**
|
|
867
|
+
* React to a visibility change. Parameterised on `hidden` so unit tests can
|
|
868
|
+
* drive it without a real `document`.
|
|
869
|
+
* @internal
|
|
870
|
+
*/
|
|
871
|
+
_handleVisibilityChange(hidden: boolean): void;
|
|
872
|
+
private _applyBlurPause;
|
|
873
|
+
private _restoreBlurPause;
|
|
735
874
|
/** The topmost (active) scene. */
|
|
736
875
|
get active(): Scene | undefined;
|
|
737
876
|
/** All scenes in the stack, bottom to top. */
|
|
738
877
|
get all(): readonly Scene[];
|
|
739
878
|
/** All non-paused scenes in the stack, bottom to top. */
|
|
740
879
|
get activeScenes(): readonly Scene[];
|
|
880
|
+
/** Whether a scene transition is currently running. */
|
|
881
|
+
get isTransitioning(): boolean;
|
|
741
882
|
/**
|
|
742
883
|
* Push a scene onto the stack. Scenes below may receive onPause().
|
|
743
884
|
* If the scene declares a `preload` array, assets are loaded before onEnter().
|
|
744
|
-
* Await the returned promise when using preloaded scenes.
|
|
745
885
|
*/
|
|
746
|
-
push(scene: Scene): Promise<void>;
|
|
886
|
+
push(scene: Scene, opts?: SceneTransitionOptions): Promise<void>;
|
|
747
887
|
/** Pop the top scene. Scenes below may receive onResume(). */
|
|
748
|
-
pop(): Scene | undefined
|
|
888
|
+
pop(opts?: SceneTransitionOptions): Promise<Scene | undefined>;
|
|
749
889
|
/**
|
|
750
|
-
* Replace the top scene.
|
|
751
|
-
*
|
|
890
|
+
* Replace the top scene. Without a transition the old scene exits first,
|
|
891
|
+
* then the new scene enters. With a transition the new scene is pushed
|
|
892
|
+
* first, both scenes coexist for the transition duration, then the old
|
|
893
|
+
* scene is removed at the end.
|
|
752
894
|
*/
|
|
753
|
-
replace(scene: Scene): Promise<void>;
|
|
754
|
-
/**
|
|
755
|
-
|
|
895
|
+
replace(scene: Scene, opts?: SceneTransitionOptions): Promise<void>;
|
|
896
|
+
/**
|
|
897
|
+
* Pop every scene on the stack, top to bottom. Each receives onExit().
|
|
898
|
+
* Queued like push/pop/replace — runs after any in-flight transition.
|
|
899
|
+
* Use for "restart from menu"-style flows. Does not run transitions.
|
|
900
|
+
*/
|
|
901
|
+
popAll(): Promise<void>;
|
|
902
|
+
/**
|
|
903
|
+
* Run the full scene-enter lifecycle (beforeEnter hooks, preload, onEnter)
|
|
904
|
+
* for a scene that is NOT placed on the stack. Used by infrastructure
|
|
905
|
+
* plugins like DebugPlugin that render a scene off-stack.
|
|
906
|
+
* @internal
|
|
907
|
+
*/
|
|
908
|
+
_mountDetached(scene: Scene): Promise<void>;
|
|
909
|
+
/**
|
|
910
|
+
* Run the scene-exit lifecycle (onExit, entity destruction, afterExit
|
|
911
|
+
* hooks, scoped-service clear) for a detached scene.
|
|
912
|
+
* @internal
|
|
913
|
+
*/
|
|
914
|
+
_unmountDetached(scene: Scene): void;
|
|
915
|
+
/**
|
|
916
|
+
* Mark the manager destroyed and synchronously tear down every scene.
|
|
917
|
+
* Called by Engine.destroy(). Any queued async work short-circuits on
|
|
918
|
+
* resume; in-flight transitions' pending promises are resolved via
|
|
919
|
+
* _cleanupRun so they don't leak.
|
|
920
|
+
* @internal
|
|
921
|
+
*/
|
|
922
|
+
_destroy(): void;
|
|
756
923
|
/**
|
|
757
924
|
* Flush destroy queues for all active scenes.
|
|
758
925
|
* Called by the engine during endOfFrame.
|
|
759
926
|
* @internal
|
|
760
927
|
*/
|
|
761
928
|
_flushDestroyQueues(): void;
|
|
929
|
+
/**
|
|
930
|
+
* Advance the active transition by `dt` ms. Called by Engine's earlyUpdate
|
|
931
|
+
* callback with raw (unscaled) wall-clock dt.
|
|
932
|
+
* @internal
|
|
933
|
+
*/
|
|
934
|
+
_tickTransition(dt: number): void;
|
|
935
|
+
private _enqueue;
|
|
936
|
+
private _pushScene;
|
|
937
|
+
private _popScene;
|
|
938
|
+
private _replaceScene;
|
|
939
|
+
private _removeScene;
|
|
940
|
+
private _preloadScene;
|
|
941
|
+
private _teardownScene;
|
|
942
|
+
private _runTransition;
|
|
943
|
+
private _cleanupRun;
|
|
944
|
+
private _safeTick;
|
|
945
|
+
private _safeCall;
|
|
946
|
+
private _makeContext;
|
|
947
|
+
private _snapshotPauseStates;
|
|
948
|
+
private _assertNotMutating;
|
|
949
|
+
private _withMutation;
|
|
950
|
+
private _withMutationSync;
|
|
762
951
|
/** Fire onPause() for scenes that transitioned from not-paused to paused. */
|
|
763
952
|
private _firePauseTransitions;
|
|
764
953
|
/** Fire onResume() for scenes that transitioned from paused to not-paused. */
|
|
@@ -883,6 +1072,23 @@ interface EngineEvents {
|
|
|
883
1072
|
oldScene: SceneRef;
|
|
884
1073
|
newScene: SceneRef;
|
|
885
1074
|
};
|
|
1075
|
+
"scene:transition:started": {
|
|
1076
|
+
kind: SceneTransitionKind;
|
|
1077
|
+
fromScene: SceneRef | undefined;
|
|
1078
|
+
toScene: SceneRef | undefined;
|
|
1079
|
+
};
|
|
1080
|
+
"scene:transition:ended": {
|
|
1081
|
+
kind: SceneTransitionKind;
|
|
1082
|
+
fromScene: SceneRef | undefined;
|
|
1083
|
+
toScene: SceneRef | undefined;
|
|
1084
|
+
};
|
|
1085
|
+
"scene:loading:progress": {
|
|
1086
|
+
scene: Scene;
|
|
1087
|
+
ratio: number;
|
|
1088
|
+
};
|
|
1089
|
+
"scene:loading:done": {
|
|
1090
|
+
scene: Scene;
|
|
1091
|
+
};
|
|
886
1092
|
"engine:started": undefined;
|
|
887
1093
|
"engine:stopped": undefined;
|
|
888
1094
|
}
|
|
@@ -899,6 +1105,39 @@ declare class EventBus<E = EventMap> {
|
|
|
899
1105
|
clear(event?: keyof E): void;
|
|
900
1106
|
}
|
|
901
1107
|
|
|
1108
|
+
/**
|
|
1109
|
+
* Plugin hooks invoked by the SceneManager at scene lifecycle points.
|
|
1110
|
+
* Plugins register hooks via `engine.registerSceneHooks(hooks)` to set up or
|
|
1111
|
+
* tear down per-scene state (e.g. render containers, physics worlds).
|
|
1112
|
+
*/
|
|
1113
|
+
interface SceneHooks {
|
|
1114
|
+
/**
|
|
1115
|
+
* Runs after the scene's context is bound but before preload / `onEnter`.
|
|
1116
|
+
* Awaited serially so scoped services registered here are ready when the
|
|
1117
|
+
* scene's own code runs. Fires on `push`, `replace`, and `_mountDetached`.
|
|
1118
|
+
*/
|
|
1119
|
+
beforeEnter?(scene: Scene): void | Promise<void>;
|
|
1120
|
+
/**
|
|
1121
|
+
* Runs after `onExit` + `_destroyAllEntities` and before the scene's
|
|
1122
|
+
* scoped-service map is cleared. Fires on `pop`, `replace`, `clear`, and
|
|
1123
|
+
* `_unmountDetached`.
|
|
1124
|
+
*/
|
|
1125
|
+
afterExit?(scene: Scene): void;
|
|
1126
|
+
}
|
|
1127
|
+
/**
|
|
1128
|
+
* Registry of scene hooks. Held by the engine, consumed by the SceneManager.
|
|
1129
|
+
* @internal
|
|
1130
|
+
*/
|
|
1131
|
+
declare class SceneHookRegistry {
|
|
1132
|
+
private readonly hooks;
|
|
1133
|
+
register(hooks: SceneHooks): () => void;
|
|
1134
|
+
/** Run all `beforeEnter` hooks serially. */
|
|
1135
|
+
runBeforeEnter(scene: Scene): Promise<void>;
|
|
1136
|
+
runAfterExit(scene: Scene): void;
|
|
1137
|
+
}
|
|
1138
|
+
/** DI key for the scene-hook registry. @internal */
|
|
1139
|
+
declare const SceneHookRegistryKey: ServiceKey<SceneHookRegistry>;
|
|
1140
|
+
|
|
902
1141
|
/** Engine configuration. */
|
|
903
1142
|
interface EngineConfig {
|
|
904
1143
|
/** Enable debug mode (Inspector API, debug logging). */
|
|
@@ -930,6 +1169,7 @@ declare class Engine {
|
|
|
930
1169
|
private readonly scheduler;
|
|
931
1170
|
private readonly errorBoundary;
|
|
932
1171
|
private readonly queryCache;
|
|
1172
|
+
private readonly sceneHooks;
|
|
933
1173
|
/** The asset manager. */
|
|
934
1174
|
readonly assets: AssetManager;
|
|
935
1175
|
private readonly plugins;
|
|
@@ -937,6 +1177,12 @@ declare class Engine {
|
|
|
937
1177
|
private started;
|
|
938
1178
|
private readonly debug;
|
|
939
1179
|
constructor(config?: EngineConfig);
|
|
1180
|
+
/**
|
|
1181
|
+
* Register scene lifecycle hooks. The returned function unregisters the
|
|
1182
|
+
* hooks. Infrastructure plugins (renderer, physics, debug) register hooks
|
|
1183
|
+
* in their `install` or `onStart` to set up and tear down per-scene state.
|
|
1184
|
+
*/
|
|
1185
|
+
registerSceneHooks(hooks: SceneHooks): () => void;
|
|
940
1186
|
/** Register a plugin. Must be called before start(). */
|
|
941
1187
|
use(plugin: Plugin): this;
|
|
942
1188
|
/** Start the engine. Installs plugins in topological order, starts the game loop. */
|
|
@@ -951,13 +1197,27 @@ declare class Engine {
|
|
|
951
1197
|
private topologicalSort;
|
|
952
1198
|
}
|
|
953
1199
|
|
|
1200
|
+
/** The resolution scope for a service. */
|
|
1201
|
+
type ServiceScope = "engine" | "scene";
|
|
1202
|
+
/** Options passed to `new ServiceKey(id, options)`. */
|
|
1203
|
+
interface ServiceKeyOptions {
|
|
1204
|
+
/**
|
|
1205
|
+
* Declared scope. `"scene"` keys are expected to be registered per-scene
|
|
1206
|
+
* via a `beforeEnter` hook; `Component.use` will check scene scope first
|
|
1207
|
+
* and warn if it falls back to engine scope.
|
|
1208
|
+
* Default: `"engine"`.
|
|
1209
|
+
*/
|
|
1210
|
+
scope?: ServiceScope;
|
|
1211
|
+
}
|
|
954
1212
|
/** A typed key for service registration and resolution. */
|
|
955
1213
|
declare class ServiceKey<T> {
|
|
956
1214
|
/** Unique string identifier for this service. */
|
|
957
1215
|
readonly id: string;
|
|
1216
|
+
/** Declared scope (engine or scene). Defaults to `"engine"`. */
|
|
1217
|
+
readonly scope: ServiceScope;
|
|
958
1218
|
constructor(
|
|
959
1219
|
/** Unique string identifier for this service. */
|
|
960
|
-
id: string);
|
|
1220
|
+
id: string, options?: ServiceKeyOptions);
|
|
961
1221
|
/** Phantom field to preserve the generic type. */
|
|
962
1222
|
readonly _type: T;
|
|
963
1223
|
}
|
|
@@ -1072,7 +1332,7 @@ interface Plugin {
|
|
|
1072
1332
|
/** Register systems with the scheduler. Called after install. */
|
|
1073
1333
|
registerSystems?(scheduler: SystemScheduler): void;
|
|
1074
1334
|
/** Called after all plugins are installed and the engine has started. */
|
|
1075
|
-
onStart?(): void
|
|
1335
|
+
onStart?(): void | Promise<void>;
|
|
1076
1336
|
/** Called when the engine is destroyed. */
|
|
1077
1337
|
onDestroy?(): void;
|
|
1078
1338
|
}
|
|
@@ -1145,16 +1405,32 @@ declare class Vec2 implements Vec2Like {
|
|
|
1145
1405
|
static distance(a: Vec2Like, b: Vec2Like): number;
|
|
1146
1406
|
/** Linear interpolation between two vectors. */
|
|
1147
1407
|
static lerp(a: Vec2Like, b: Vec2Like, t: number): Vec2;
|
|
1408
|
+
/** Move current toward target by at most maxDelta without overshooting. */
|
|
1409
|
+
static moveTowards(current: Vec2Like, target: Vec2Like, maxDelta: number): Vec2;
|
|
1148
1410
|
}
|
|
1149
1411
|
|
|
1412
|
+
interface SmoothDampResult {
|
|
1413
|
+
/** Smoothed value after this step. */
|
|
1414
|
+
readonly value: number;
|
|
1415
|
+
/** Velocity to pass into the next smoothDamp step. */
|
|
1416
|
+
readonly velocity: number;
|
|
1417
|
+
}
|
|
1150
1418
|
/** Common math utility functions. */
|
|
1151
1419
|
declare const MathUtils: {
|
|
1152
1420
|
/** Linear interpolation between a and b. */
|
|
1153
1421
|
readonly lerp: (a: number, b: number, t: number) => number;
|
|
1422
|
+
/** Return the clamped interpolation factor that produces v between a and b. */
|
|
1423
|
+
readonly inverseLerp: (a: number, b: number, v: number) => number;
|
|
1424
|
+
/** Interpolate between angles in radians along the shortest path. */
|
|
1425
|
+
readonly lerpAngle: (a: number, b: number, t: number) => number;
|
|
1426
|
+
/** Signed shortest angular delta from a to b, in radians. */
|
|
1427
|
+
readonly shortestAngleBetween: (a: number, b: number) => number;
|
|
1154
1428
|
/** Clamp a value between min and max. */
|
|
1155
1429
|
readonly clamp: (value: number, min: number, max: number) => number;
|
|
1156
1430
|
/** Remap a value from one range to another. */
|
|
1157
1431
|
readonly remap: (value: number, inMin: number, inMax: number, outMin: number, outMax: number) => number;
|
|
1432
|
+
/** Bounce t between 0 and length. */
|
|
1433
|
+
readonly pingPong: (t: number, length: number) => number;
|
|
1158
1434
|
/** Random float in [min, max). */
|
|
1159
1435
|
readonly randomRange: (min: number, max: number) => number;
|
|
1160
1436
|
/** Random integer in [min, max] (inclusive). */
|
|
@@ -1165,6 +1441,11 @@ declare const MathUtils: {
|
|
|
1165
1441
|
readonly radToDeg: (radians: number) => number;
|
|
1166
1442
|
/** Move current toward target by at most step. */
|
|
1167
1443
|
readonly approach: (current: number, target: number, step: number) => number;
|
|
1444
|
+
/**
|
|
1445
|
+
* Smoothly damp current toward target without overshooting.
|
|
1446
|
+
* Pass the returned velocity back into the next call.
|
|
1447
|
+
*/
|
|
1448
|
+
readonly smoothDamp: (current: number, target: number, velocity: number, smoothTime: number, deltaTime: number, maxSpeed?: number) => SmoothDampResult;
|
|
1168
1449
|
/** Wrap value into the range [min, max). */
|
|
1169
1450
|
readonly wrap: (value: number, min: number, max: number) => number;
|
|
1170
1451
|
};
|
|
@@ -1265,6 +1546,112 @@ declare class ComponentUpdateSystem extends BaseComponentUpdateSystem {
|
|
|
1265
1546
|
update(dt: number): void;
|
|
1266
1547
|
}
|
|
1267
1548
|
|
|
1549
|
+
/**
|
|
1550
|
+
* Base class for a progress-bar style loading screen.
|
|
1551
|
+
*
|
|
1552
|
+
* Preloads the target scene's assets through the `AssetManager`, exposes
|
|
1553
|
+
* `progress` and emits `scene:loading:progress` / `scene:loading:done` on
|
|
1554
|
+
* the engine event bus, enforces `minDuration` to prevent flicker on cached
|
|
1555
|
+
* loads, then replaces itself with `target` — optionally through a
|
|
1556
|
+
* transition.
|
|
1557
|
+
*
|
|
1558
|
+
* LoadingScene owns orchestration only. It does not render anything. To show
|
|
1559
|
+
* a progress UI, spawn an entity that subscribes to the loading events (the
|
|
1560
|
+
* canonical default is `LoadingSceneProgressBar` in `@yagejs/ui`, or any
|
|
1561
|
+
* custom component). The loading scene is a normal Scene, so you can use
|
|
1562
|
+
* `onEnter` to spawn whatever you want.
|
|
1563
|
+
*
|
|
1564
|
+
* ```ts
|
|
1565
|
+
* class Boot extends LoadingScene {
|
|
1566
|
+
* readonly target = new GameScene();
|
|
1567
|
+
* readonly minDuration = 500;
|
|
1568
|
+
* readonly transition = fade({ duration: 300 });
|
|
1569
|
+
* override onEnter() {
|
|
1570
|
+
* this.spawn(LoadingSceneProgressBar);
|
|
1571
|
+
* this.startLoading();
|
|
1572
|
+
* }
|
|
1573
|
+
* }
|
|
1574
|
+
*
|
|
1575
|
+
* await engine.scenes.replace(new Boot());
|
|
1576
|
+
* ```
|
|
1577
|
+
*
|
|
1578
|
+
* Set `autoContinue = false` to gate the handoff behind a `continue()` call
|
|
1579
|
+
* — useful for "press any key to continue" flows. `scene:loading:done`
|
|
1580
|
+
* still fires so UI can react (show a prompt), and whoever eventually
|
|
1581
|
+
* calls `this.continue()` triggers the transition.
|
|
1582
|
+
*/
|
|
1583
|
+
declare abstract class LoadingScene extends Scene {
|
|
1584
|
+
readonly name: string;
|
|
1585
|
+
/**
|
|
1586
|
+
* Scene to load and transition to. Accepts an instance or a factory —
|
|
1587
|
+
* use a factory when target construction should be deferred until
|
|
1588
|
+
* loading starts (heavy constructors, side effects). The factory runs
|
|
1589
|
+
* before `assets.loadAll` so `target.preload` can be inspected.
|
|
1590
|
+
*/
|
|
1591
|
+
abstract readonly target: Scene | (() => Scene);
|
|
1592
|
+
/**
|
|
1593
|
+
* Minimum wall-clock ms the scene stays visible before handing off.
|
|
1594
|
+
* Prevents flicker on cached loads. Default 0.
|
|
1595
|
+
*/
|
|
1596
|
+
readonly minDuration: number;
|
|
1597
|
+
/** Transition used for the loading → target handoff. */
|
|
1598
|
+
readonly transition?: SceneTransition;
|
|
1599
|
+
/**
|
|
1600
|
+
* When true (default), the handoff fires automatically after loading and
|
|
1601
|
+
* `minDuration`. Set false to gate it behind `continue()` — useful when
|
|
1602
|
+
* the loading scene also asks the player to press a key or click.
|
|
1603
|
+
*/
|
|
1604
|
+
readonly autoContinue: boolean;
|
|
1605
|
+
/**
|
|
1606
|
+
* Optional hook; fires if asset loading rejects. The scene stays mounted
|
|
1607
|
+
* whether or not this is set. When set, the hook is the recovery channel:
|
|
1608
|
+
* draw a retry UI, push an error scene, or call `this.startLoading()`
|
|
1609
|
+
* again to retry the load. When unset, the error is logged via the engine
|
|
1610
|
+
* logger and the scene remains mounted in a failed state with no
|
|
1611
|
+
* automatic recovery.
|
|
1612
|
+
*
|
|
1613
|
+
* The hook may still be running when the scene is replaced externally —
|
|
1614
|
+
* don't assume the scene is live (check `this.context.tryResolve` rather
|
|
1615
|
+
* than `this.service` before touching engine services, and avoid spawning
|
|
1616
|
+
* new entities after an `await`).
|
|
1617
|
+
*/
|
|
1618
|
+
onLoadError?(error: Error): void | Promise<void>;
|
|
1619
|
+
private _progress;
|
|
1620
|
+
private _started;
|
|
1621
|
+
private _active;
|
|
1622
|
+
private _continueRequested;
|
|
1623
|
+
private _continueGate?;
|
|
1624
|
+
private _attempt;
|
|
1625
|
+
/** Current load progress, 0 → 1. Updated as the AssetManager reports progress. */
|
|
1626
|
+
get progress(): number;
|
|
1627
|
+
/**
|
|
1628
|
+
* Kick off asset loading. While a load is in flight, subsequent calls
|
|
1629
|
+
* are no-ops. After a load failure the guard is released, so calling
|
|
1630
|
+
* `startLoading()` from `onLoadError` (or from a retry button) kicks off
|
|
1631
|
+
* a fresh load against the same target.
|
|
1632
|
+
*
|
|
1633
|
+
* Usually called once from `onEnter` after spawning the loading UI:
|
|
1634
|
+
* ```ts
|
|
1635
|
+
* override onEnter() {
|
|
1636
|
+
* this.spawn(LoadingSceneProgressBar);
|
|
1637
|
+
* this.startLoading();
|
|
1638
|
+
* }
|
|
1639
|
+
* ```
|
|
1640
|
+
*
|
|
1641
|
+
* Deferring the call lets you gate the start of the load behind a
|
|
1642
|
+
* title screen, "press any key" prompt, intro animation, etc.
|
|
1643
|
+
*/
|
|
1644
|
+
startLoading(): void;
|
|
1645
|
+
/**
|
|
1646
|
+
* Trigger the handoff to `target`. No-op if already called or if
|
|
1647
|
+
* `autoContinue` already fired it. If called before loading finishes,
|
|
1648
|
+
* the handoff runs as soon as loading + `minDuration` complete.
|
|
1649
|
+
*/
|
|
1650
|
+
continue(): void;
|
|
1651
|
+
onExit(): void;
|
|
1652
|
+
private _run;
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1268
1655
|
/** Static factory for creating tween Processes. */
|
|
1269
1656
|
declare const Tween: {
|
|
1270
1657
|
/** Tween a numeric property on a target object. */
|
|
@@ -1491,6 +1878,36 @@ declare class TimerEntity extends Entity {
|
|
|
1491
1878
|
cancel(tag?: string): void;
|
|
1492
1879
|
}
|
|
1493
1880
|
|
|
1881
|
+
/**
|
|
1882
|
+
* Cross-package contract for "something that owns a canvas and can map
|
|
1883
|
+
* canvas-relative CSS pixels into virtual-space pixels".
|
|
1884
|
+
*
|
|
1885
|
+
* Implemented by `@yagejs/renderer`'s `RendererPlugin` and consumed by
|
|
1886
|
+
* `@yagejs/input` for pointer-event targeting and coordinate mapping under
|
|
1887
|
+
* responsive fit. Foreign renderers can implement this interface and register
|
|
1888
|
+
* under `RendererAdapterKey` to integrate with the input plugin without
|
|
1889
|
+
* importing `@yagejs/renderer`.
|
|
1890
|
+
*/
|
|
1891
|
+
interface RendererAdapter {
|
|
1892
|
+
readonly canvas: HTMLCanvasElement;
|
|
1893
|
+
/**
|
|
1894
|
+
* Convert CSS pixels relative to the canvas into virtual-space pixels.
|
|
1895
|
+
* Optional — when absent, consumers fall back to raw CSS pixels (correct
|
|
1896
|
+
* only when canvas CSS size equals virtual size).
|
|
1897
|
+
*/
|
|
1898
|
+
canvasToVirtual?(x: number, y: number): {
|
|
1899
|
+
x: number;
|
|
1900
|
+
y: number;
|
|
1901
|
+
};
|
|
1902
|
+
}
|
|
1903
|
+
/**
|
|
1904
|
+
* Well-known service key for the current renderer's pointer-input adapter.
|
|
1905
|
+
* The canonical `@yagejs/renderer` plugin registers itself here; consumers
|
|
1906
|
+
* (notably `@yagejs/input`) resolve this key to auto-wire canvas targeting
|
|
1907
|
+
* and coordinate mapping.
|
|
1908
|
+
*/
|
|
1909
|
+
declare const RendererAdapterKey: ServiceKey<RendererAdapter>;
|
|
1910
|
+
|
|
1494
1911
|
/** Create a fully wired Engine for integration tests. */
|
|
1495
1912
|
declare function createTestEngine(config?: EngineConfig): Promise<Engine>;
|
|
1496
1913
|
/** Create a lightweight mock scene with EngineContext for unit tests. */
|
|
@@ -1509,4 +1926,4 @@ declare function advanceFrames(engine: Engine, n: number, dtMs?: number): void;
|
|
|
1509
1926
|
|
|
1510
1927
|
declare const VERSION = "0.0.0";
|
|
1511
1928
|
|
|
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 };
|
|
1929
|
+
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, type RendererAdapter, RendererAdapterKey, 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 SmoothDampResult, 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 };
|