ecspresso 0.10.2 → 0.11.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/README.md +73 -17
- package/dist/asset-manager.d.ts +15 -15
- package/dist/asset-types.d.ts +16 -14
- package/dist/bundle.d.ts +66 -16
- package/dist/bundles/audio.d.ts +293 -0
- package/dist/bundles/{utils/bounds.d.ts → bounds.d.ts} +9 -7
- package/dist/bundles/camera.d.ts +89 -0
- package/dist/bundles/collision.d.ts +289 -0
- package/dist/bundles/diagnostics.d.ts +48 -0
- package/dist/bundles/{utils/input.d.ts → input.d.ts} +16 -17
- package/dist/bundles/physics2D.d.ts +159 -0
- package/dist/bundles/renderers/renderer2D.d.ts +65 -24
- package/dist/bundles/spatial-index.d.ts +57 -0
- package/dist/bundles/state-machine.d.ts +298 -0
- package/dist/bundles/{utils/timers.d.ts → timers.d.ts} +9 -8
- package/dist/bundles/{utils/transform.d.ts → transform.d.ts} +10 -10
- package/dist/bundles/tween.d.ts +197 -0
- package/dist/command-buffer.d.ts +20 -20
- package/dist/ecspresso-builder.d.ts +165 -0
- package/dist/ecspresso.d.ts +157 -178
- package/dist/entity-manager.d.ts +76 -40
- package/dist/event-bus.d.ts +6 -1
- package/dist/index.d.ts +1 -9
- package/dist/reactive-query-manager.d.ts +14 -3
- package/dist/resource-manager.d.ts +35 -19
- package/dist/screen-manager.d.ts +4 -4
- package/dist/screen-types.d.ts +12 -11
- package/dist/src/bundles/audio.js +4 -0
- package/dist/src/bundles/audio.js.map +10 -0
- package/dist/src/bundles/bounds.js +4 -0
- package/dist/src/bundles/bounds.js.map +10 -0
- package/dist/src/bundles/camera.js +4 -0
- package/dist/src/bundles/camera.js.map +10 -0
- package/dist/src/bundles/collision.js +4 -0
- package/dist/src/bundles/collision.js.map +11 -0
- package/dist/src/bundles/diagnostics.js +5 -0
- package/dist/src/bundles/diagnostics.js.map +10 -0
- package/dist/src/bundles/input.js +4 -0
- package/dist/src/bundles/input.js.map +10 -0
- package/dist/src/bundles/physics2D.js +4 -0
- package/dist/src/bundles/physics2D.js.map +11 -0
- package/dist/src/bundles/renderers/renderer2D.js +4 -0
- package/dist/src/bundles/renderers/renderer2D.js.map +10 -0
- package/dist/src/bundles/spatial-index.js +4 -0
- package/dist/src/bundles/spatial-index.js.map +11 -0
- package/dist/src/bundles/state-machine.js +4 -0
- package/dist/src/bundles/state-machine.js.map +10 -0
- package/dist/src/bundles/timers.js +4 -0
- package/dist/src/bundles/timers.js.map +10 -0
- package/dist/src/bundles/transform.js +4 -0
- package/dist/src/bundles/transform.js.map +10 -0
- package/dist/src/bundles/tween.js +4 -0
- package/dist/src/bundles/tween.js.map +11 -0
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +25 -0
- package/dist/system-builder.d.ts +36 -42
- package/dist/type-utils.d.ts +52 -3
- package/dist/types.d.ts +10 -19
- package/dist/utils/check-required-cycle.d.ts +12 -0
- package/dist/utils/easing.d.ts +71 -0
- package/dist/utils/math.d.ts +67 -0
- package/dist/utils/narrowphase.d.ts +63 -0
- package/dist/utils/spatial-hash.d.ts +53 -0
- package/package.json +50 -20
- package/dist/bundles/renderers/renderer2D.js +0 -4
- package/dist/bundles/renderers/renderer2D.js.map +0 -10
- package/dist/bundles/utils/bounds.js +0 -4
- package/dist/bundles/utils/bounds.js.map +0 -10
- package/dist/bundles/utils/collision.d.ts +0 -204
- package/dist/bundles/utils/collision.js +0 -4
- package/dist/bundles/utils/collision.js.map +0 -10
- package/dist/bundles/utils/input.js +0 -4
- package/dist/bundles/utils/input.js.map +0 -10
- package/dist/bundles/utils/movement.d.ts +0 -86
- package/dist/bundles/utils/movement.js +0 -4
- package/dist/bundles/utils/movement.js.map +0 -10
- package/dist/bundles/utils/timers.js +0 -4
- package/dist/bundles/utils/timers.js.map +0 -10
- package/dist/bundles/utils/transform.js +0 -4
- package/dist/bundles/utils/transform.js.map +0 -10
- package/dist/index.js +0 -4
- package/dist/index.js.map +0 -22
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tween Bundle for ECSpresso
|
|
3
|
+
*
|
|
4
|
+
* Declarative property animation within the ECS. Tween any numeric component
|
|
5
|
+
* field over time with standard easing functions, sequences, and completion events.
|
|
6
|
+
*/
|
|
7
|
+
import { Bundle } from 'ecspresso';
|
|
8
|
+
import type { SystemPhase, ComponentsOfWorld, EventsOfWorld } from 'ecspresso';
|
|
9
|
+
import { type EasingFn } from '../utils/easing';
|
|
10
|
+
/**
|
|
11
|
+
* Data structure published when a tween completes.
|
|
12
|
+
* Use this type when defining tween completion events in your EventTypes interface.
|
|
13
|
+
*/
|
|
14
|
+
export interface TweenEventData {
|
|
15
|
+
/** The entity ID the tween belongs to */
|
|
16
|
+
entityId: number;
|
|
17
|
+
/** Number of steps in the tween */
|
|
18
|
+
stepCount: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Extracts event names from EventTypes that have TweenEventData as their payload.
|
|
22
|
+
* This ensures only compatible events can be used with tween.onComplete.
|
|
23
|
+
* Uses `keyof EventTypes & string` to exclude number/symbol keys, ensuring the
|
|
24
|
+
* result is always a string subtype and Tween<E> is assignable to Tween<Record<string, any>>.
|
|
25
|
+
*/
|
|
26
|
+
export type TweenEventName<EventTypes extends Record<string, any>> = {
|
|
27
|
+
[K in keyof EventTypes & string]: EventTypes[K] extends TweenEventData ? K : never;
|
|
28
|
+
}[keyof EventTypes & string];
|
|
29
|
+
export interface TweenTarget {
|
|
30
|
+
/** Component name on the entity */
|
|
31
|
+
component: string;
|
|
32
|
+
/** Pre-split field path (e.g., ['position', 'x']) */
|
|
33
|
+
path: readonly string[];
|
|
34
|
+
/** Starting value. null = resolve from current value on first tick */
|
|
35
|
+
from: number | null;
|
|
36
|
+
/** Target value */
|
|
37
|
+
to: number;
|
|
38
|
+
}
|
|
39
|
+
export interface TweenStep {
|
|
40
|
+
targets: TweenTarget[];
|
|
41
|
+
duration: number;
|
|
42
|
+
easing: EasingFn;
|
|
43
|
+
}
|
|
44
|
+
export interface Tween<EventTypes extends Record<string, any> = Record<string, any>> {
|
|
45
|
+
steps: TweenStep[];
|
|
46
|
+
currentStep: number;
|
|
47
|
+
elapsed: number;
|
|
48
|
+
loop: LoopMode;
|
|
49
|
+
totalLoops: number;
|
|
50
|
+
completedLoops: number;
|
|
51
|
+
direction: 1 | -1;
|
|
52
|
+
state: 'pending' | 'active' | 'complete';
|
|
53
|
+
onComplete?: TweenEventName<EventTypes>;
|
|
54
|
+
justFinished: boolean;
|
|
55
|
+
}
|
|
56
|
+
export type LoopMode = 'once' | 'loop' | 'yoyo';
|
|
57
|
+
/**
|
|
58
|
+
* Component types provided by the tween bundle.
|
|
59
|
+
*/
|
|
60
|
+
export interface TweenComponentTypes<EventTypes extends Record<string, any> = Record<string, any>> {
|
|
61
|
+
tween: Tween<EventTypes>;
|
|
62
|
+
}
|
|
63
|
+
export interface TweenBundleOptions<G extends string = 'tweens'> {
|
|
64
|
+
/** System group name (default: 'tweens') */
|
|
65
|
+
systemGroup?: G;
|
|
66
|
+
/** Priority for tween update system (default: 0) */
|
|
67
|
+
priority?: number;
|
|
68
|
+
/** Execution phase (default: 'update') */
|
|
69
|
+
phase?: SystemPhase;
|
|
70
|
+
}
|
|
71
|
+
export interface TweenOptions<EventTypes extends Record<string, any> = Record<string, any>> {
|
|
72
|
+
/** Explicit starting value (default: captures current value on first tick) */
|
|
73
|
+
from?: number;
|
|
74
|
+
/** Easing function (default: linear) */
|
|
75
|
+
easing?: EasingFn;
|
|
76
|
+
/** Loop mode (default: 'once') */
|
|
77
|
+
loop?: LoopMode;
|
|
78
|
+
/** Number of loops. -1 = infinite (default: 1) */
|
|
79
|
+
loops?: number;
|
|
80
|
+
/** Event name to publish when tween completes */
|
|
81
|
+
onComplete?: TweenEventName<EventTypes>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Create a single-target tween component.
|
|
85
|
+
*
|
|
86
|
+
* @param component Component name on the entity
|
|
87
|
+
* @param field Field path (dot-separated for nested, e.g. 'position.x')
|
|
88
|
+
* @param to Target value
|
|
89
|
+
* @param duration Duration in seconds
|
|
90
|
+
* @param options Optional configuration
|
|
91
|
+
* @returns Component object suitable for spreading into spawn()
|
|
92
|
+
*/
|
|
93
|
+
export declare function createTween<EventTypes extends Record<string, any> = Record<string, any>>(component: string, field: string, to: number, duration: number, options?: TweenOptions<EventTypes>): Pick<TweenComponentTypes<EventTypes>, 'tween'>;
|
|
94
|
+
export interface TweenSequenceStepInput {
|
|
95
|
+
targets: ReadonlyArray<{
|
|
96
|
+
component: string;
|
|
97
|
+
field: string;
|
|
98
|
+
to: number;
|
|
99
|
+
from?: number;
|
|
100
|
+
}>;
|
|
101
|
+
duration: number;
|
|
102
|
+
easing?: EasingFn;
|
|
103
|
+
}
|
|
104
|
+
export interface TweenSequenceOptions<EventTypes extends Record<string, any> = Record<string, any>> {
|
|
105
|
+
/** Loop mode (default: 'once') */
|
|
106
|
+
loop?: LoopMode;
|
|
107
|
+
/** Number of loops. -1 = infinite (default: 1) */
|
|
108
|
+
loops?: number;
|
|
109
|
+
/** Event name to publish when tween completes */
|
|
110
|
+
onComplete?: TweenEventName<EventTypes>;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Create a multi-step tween sequence. Each step can have parallel targets.
|
|
114
|
+
*
|
|
115
|
+
* @param steps Array of step definitions
|
|
116
|
+
* @param options Optional configuration
|
|
117
|
+
* @returns Component object suitable for spreading into spawn()
|
|
118
|
+
*/
|
|
119
|
+
export declare function createTweenSequence<EventTypes extends Record<string, any> = Record<string, any>>(steps: ReadonlyArray<TweenSequenceStepInput>, options?: TweenSequenceOptions<EventTypes>): Pick<TweenComponentTypes<EventTypes>, 'tween'>;
|
|
120
|
+
type AnyECSpresso = import('ecspresso').default<any, any, any, any, any, any, any>;
|
|
121
|
+
/**
|
|
122
|
+
* Recursively produce a union of dot-separated paths that resolve to `number`
|
|
123
|
+
* within type T. Depth-limited to 4 levels to prevent TS recursion errors.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* NumericPaths<{ x: number; y: number }> // 'x' | 'y'
|
|
127
|
+
* NumericPaths<{ position: { x: number }; rotation: number }> // 'position.x' | 'rotation'
|
|
128
|
+
*/
|
|
129
|
+
export type NumericPaths<T, Depth extends readonly unknown[] = []> = Depth['length'] extends 4 ? never : T extends readonly unknown[] ? never : T extends Record<string, unknown> ? {
|
|
130
|
+
[K in keyof T & string]: NonNullable<T[K]> extends number ? K : NonNullable<T[K]> extends readonly unknown[] ? never : NonNullable<T[K]> extends Record<string, unknown> ? `${K}.${NumericPaths<NonNullable<T[K]>, [...Depth, unknown]>}` : never;
|
|
131
|
+
}[keyof T & string] : never;
|
|
132
|
+
/**
|
|
133
|
+
* Discriminated union over component names: each variant constrains `field`
|
|
134
|
+
* to the numeric paths of that component. TS narrows inline object literals
|
|
135
|
+
* by `component` discriminant — zero runtime overhead.
|
|
136
|
+
*/
|
|
137
|
+
export type TypedTweenTargetInput<C extends Record<string, any>> = {
|
|
138
|
+
[K in keyof C & string]: {
|
|
139
|
+
component: K;
|
|
140
|
+
field: NumericPaths<C[K]>;
|
|
141
|
+
to: number;
|
|
142
|
+
from?: number;
|
|
143
|
+
};
|
|
144
|
+
}[keyof C & string];
|
|
145
|
+
export interface TypedTweenSequenceStepInput<C extends Record<string, any>> {
|
|
146
|
+
targets: ReadonlyArray<TypedTweenTargetInput<C>>;
|
|
147
|
+
duration: number;
|
|
148
|
+
easing?: EasingFn;
|
|
149
|
+
}
|
|
150
|
+
export interface TweenKit<W extends AnyECSpresso, G extends string = 'tweens'> {
|
|
151
|
+
bundle: Bundle<TweenComponentTypes<EventsOfWorld<W>>, EventsOfWorld<W>, {}, {}, {}, 'tween-update', G>;
|
|
152
|
+
createTween: <K extends keyof ComponentsOfWorld<W> & string>(component: K, field: NumericPaths<ComponentsOfWorld<W>[K]>, to: number, duration: number, options?: TweenOptions<EventsOfWorld<W>>) => Pick<TweenComponentTypes<EventsOfWorld<W>>, 'tween'>;
|
|
153
|
+
createTweenSequence: (steps: ReadonlyArray<TypedTweenSequenceStepInput<ComponentsOfWorld<W>>>, options?: TweenSequenceOptions<EventsOfWorld<W>>) => Pick<TweenComponentTypes<EventsOfWorld<W>>, 'tween'>;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Create a typed tween kit that captures the world type W.
|
|
157
|
+
*
|
|
158
|
+
* The returned `createTween` and `createTweenSequence` validate component names
|
|
159
|
+
* and field paths at compile time. Runtime behavior is identical to the standalone
|
|
160
|
+
* functions — all validation is type-level only.
|
|
161
|
+
*
|
|
162
|
+
* @template W - Concrete ECS world type (e.g. `typeof ecs`)
|
|
163
|
+
* @template G - System group name (default: 'tweens')
|
|
164
|
+
* @param options - Optional bundle configuration (same as createTweenBundle)
|
|
165
|
+
* @returns A kit object with bundle, createTween, createTweenSequence
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* const kit = createTweenKit<typeof ecs>();
|
|
170
|
+
* // or: const kit = createTweenKit<ECS>();
|
|
171
|
+
*
|
|
172
|
+
* const ecs = ECSpresso.create()
|
|
173
|
+
* .withBundle(kit.bundle)
|
|
174
|
+
* .build();
|
|
175
|
+
*
|
|
176
|
+
* // Type-safe: 'position' must be a component, 'x' must be a numeric field
|
|
177
|
+
* kit.createTween('position', 'x', 100, 1);
|
|
178
|
+
*
|
|
179
|
+
* // Type error: 'z' is not a field of position
|
|
180
|
+
* kit.createTween('position', 'z', 100, 1);
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export declare function createTweenKit<W extends AnyECSpresso, G extends string = 'tweens'>(options?: TweenBundleOptions<G>): TweenKit<W, G>;
|
|
184
|
+
/**
|
|
185
|
+
* Create a tween bundle for ECSpresso.
|
|
186
|
+
*
|
|
187
|
+
* This bundle provides:
|
|
188
|
+
* - Tween system that processes all tween components each frame
|
|
189
|
+
* - Support for single-field, multi-target, and multi-step sequences
|
|
190
|
+
* - 31 standard easing functions
|
|
191
|
+
* - Loop modes: once, loop, yoyo
|
|
192
|
+
* - `justFinished` flag for one-frame completion detection
|
|
193
|
+
* - `onComplete` event publishing
|
|
194
|
+
* - Change detection via markChanged
|
|
195
|
+
*/
|
|
196
|
+
export declare function createTweenBundle<EventTypes extends Record<string, any> = Record<string, any>, G extends string = 'tweens'>(options?: TweenBundleOptions<G>): Bundle<TweenComponentTypes<EventTypes>, EventTypes, {}, {}, {}, 'tween-update', G>;
|
|
197
|
+
export {};
|
package/dist/command-buffer.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type ECSpresso from './ecspresso';
|
|
2
|
-
import type { RemoveEntityOptions } from './types';
|
|
2
|
+
import type { Entity, RemoveEntityOptions } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* CommandBuffer queues structural changes to be executed later.
|
|
5
5
|
* This prevents ordering issues when modifying entities during system execution.
|
|
@@ -16,27 +16,27 @@ import type { RemoveEntityOptions } from './types';
|
|
|
16
16
|
* ecs.commands.playback(ecs);
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
|
-
export default class CommandBuffer<ComponentTypes extends Record<string, any> = {}, EventTypes extends Record<string, any> = {}, ResourceTypes extends Record<string, any> = {}> {
|
|
19
|
+
export default class CommandBuffer<ComponentTypes extends Record<string, any> = {}, EventTypes extends Record<string, any> = {}, ResourceTypes extends Record<string, any> = {}, AssetTypes extends Record<string, unknown> = {}, ScreenStates extends Record<string, any> = {}> {
|
|
20
20
|
private commands;
|
|
21
21
|
/**
|
|
22
22
|
* Queue an entity removal command
|
|
23
|
-
* @param
|
|
23
|
+
* @param entityOrId The entity or entity ID to remove
|
|
24
24
|
* @param options Optional removal options (cascade, etc.)
|
|
25
25
|
*/
|
|
26
|
-
removeEntity(
|
|
26
|
+
removeEntity(entityOrId: number | Entity<ComponentTypes>, options?: RemoveEntityOptions): void;
|
|
27
27
|
/**
|
|
28
28
|
* Queue a component addition command
|
|
29
|
-
* @param
|
|
29
|
+
* @param entityOrId The entity or entity ID
|
|
30
30
|
* @param componentName The name of the component to add
|
|
31
31
|
* @param componentValue The component data
|
|
32
32
|
*/
|
|
33
|
-
addComponent<K extends keyof ComponentTypes>(
|
|
33
|
+
addComponent<K extends keyof ComponentTypes>(entityOrId: number | Entity<ComponentTypes>, componentName: K, componentValue: ComponentTypes[K]): void;
|
|
34
34
|
/**
|
|
35
35
|
* Queue a component removal command
|
|
36
|
-
* @param
|
|
36
|
+
* @param entityOrId The entity or entity ID
|
|
37
37
|
* @param componentName The name of the component to remove
|
|
38
38
|
*/
|
|
39
|
-
removeComponent<K extends keyof ComponentTypes>(
|
|
39
|
+
removeComponent<K extends keyof ComponentTypes>(entityOrId: number | Entity<ComponentTypes>, componentName: K): void;
|
|
40
40
|
/**
|
|
41
41
|
* Queue an entity spawn command
|
|
42
42
|
* @param components The initial components for the new entity
|
|
@@ -47,43 +47,43 @@ export default class CommandBuffer<ComponentTypes extends Record<string, any> =
|
|
|
47
47
|
}>(components: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>): void;
|
|
48
48
|
/**
|
|
49
49
|
* Queue a child entity spawn command
|
|
50
|
-
* @param
|
|
50
|
+
* @param parentOrId The parent entity or entity ID
|
|
51
51
|
* @param components The initial components for the new child entity
|
|
52
52
|
*/
|
|
53
53
|
spawnChild<T extends {
|
|
54
54
|
[K in keyof ComponentTypes]?: ComponentTypes[K];
|
|
55
|
-
}>(
|
|
55
|
+
}>(parentOrId: number | Entity<ComponentTypes>, components: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>): void;
|
|
56
56
|
/**
|
|
57
57
|
* Queue multiple component additions
|
|
58
|
-
* @param
|
|
58
|
+
* @param entityOrId The entity or entity ID
|
|
59
59
|
* @param components Object with component names as keys and component data as values
|
|
60
60
|
*/
|
|
61
61
|
addComponents<T extends {
|
|
62
62
|
[K in keyof ComponentTypes]?: ComponentTypes[K];
|
|
63
|
-
}>(
|
|
63
|
+
}>(entityOrId: number | Entity<ComponentTypes>, components: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>): void;
|
|
64
64
|
/**
|
|
65
65
|
* Queue a parent assignment command
|
|
66
|
-
* @param
|
|
67
|
-
* @param
|
|
66
|
+
* @param childOrId The child entity or entity ID
|
|
67
|
+
* @param parentOrId The parent entity or entity ID
|
|
68
68
|
*/
|
|
69
|
-
setParent(
|
|
69
|
+
setParent(childOrId: number | Entity<ComponentTypes>, parentOrId: number | Entity<ComponentTypes>): void;
|
|
70
70
|
/**
|
|
71
71
|
* Queue a markChanged command
|
|
72
|
-
* @param
|
|
72
|
+
* @param entityOrId The entity or entity ID
|
|
73
73
|
* @param componentName The component to mark as changed
|
|
74
74
|
*/
|
|
75
|
-
markChanged<K extends keyof ComponentTypes>(
|
|
75
|
+
markChanged<K extends keyof ComponentTypes>(entityOrId: number | Entity<ComponentTypes>, componentName: K): void;
|
|
76
76
|
/**
|
|
77
77
|
* Queue a parent removal command
|
|
78
|
-
* @param
|
|
78
|
+
* @param childOrId The child entity or entity ID
|
|
79
79
|
*/
|
|
80
|
-
removeParent(
|
|
80
|
+
removeParent(childOrId: number | Entity<ComponentTypes>): void;
|
|
81
81
|
/**
|
|
82
82
|
* Execute all queued commands in FIFO order.
|
|
83
83
|
* Errors from individual commands are caught and logged, but do not stop playback.
|
|
84
84
|
* @param ecs The ECSpresso instance to execute commands on
|
|
85
85
|
*/
|
|
86
|
-
playback
|
|
86
|
+
playback(ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): void;
|
|
87
87
|
/**
|
|
88
88
|
* Clear all queued commands without executing them
|
|
89
89
|
*/
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import type ECSpresso from "./ecspresso";
|
|
2
|
+
import type { ResourceFactoryWithDeps } from "./resource-manager";
|
|
3
|
+
import type Bundle from "./bundle";
|
|
4
|
+
import type { BundlesAreCompatible, TypesAreCompatible } from "./type-utils";
|
|
5
|
+
import type { AssetConfigurator, AssetsResource } from "./asset-types";
|
|
6
|
+
import type { ScreenDefinition, ScreenConfigurator, ScreenResource } from "./screen-types";
|
|
7
|
+
/**
|
|
8
|
+
* Helper type: finalize built-in resources ($assets, $screen) in the resource map.
|
|
9
|
+
* Auto-injects $assets/$screen when bundles contribute asset/screen types even without
|
|
10
|
+
* explicit withAssets()/withScreens(). Also narrows the AssetGroupNames on $assets.
|
|
11
|
+
*/
|
|
12
|
+
type FinalizeBuiltinResources<R, A extends Record<string, unknown>, S extends Record<string, ScreenDefinition<any, any>>, AG extends string> = Omit<R, '$assets' | '$screen'> & ([keyof A] extends [never] ? {} : {
|
|
13
|
+
$assets: AssetsResource<A, AG>;
|
|
14
|
+
}) & ([keyof S] extends [never] ? {} : {
|
|
15
|
+
$screen: ScreenResource<S>;
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Builder class for ECSpresso that provides fluent type-safe bundle installation.
|
|
19
|
+
* Handles type checking during build process to ensure type safety.
|
|
20
|
+
*/
|
|
21
|
+
export declare class ECSpressoBuilder<C extends Record<string, any> = {}, E extends Record<string, any> = {}, R extends Record<string, any> = {}, A extends Record<string, unknown> = {}, S extends Record<string, ScreenDefinition<any, any>> = {}, Labels extends string = never, Groups extends string = never, AssetGroupNames extends string = never, ReactiveQueryNames extends string = never> {
|
|
22
|
+
/** The ECSpresso instance being built*/
|
|
23
|
+
private ecspresso;
|
|
24
|
+
/** Asset configurator for collecting asset definitions */
|
|
25
|
+
private assetConfigurator;
|
|
26
|
+
/** Screen configurator for collecting screen definitions */
|
|
27
|
+
private screenConfigurator;
|
|
28
|
+
/** Pending resources to add during build */
|
|
29
|
+
private pendingResources;
|
|
30
|
+
/** Pending dispose callbacks to register during build */
|
|
31
|
+
private pendingDisposeCallbacks;
|
|
32
|
+
/** Pending required component registrations to apply during build */
|
|
33
|
+
private pendingRequiredComponents;
|
|
34
|
+
/** Fixed timestep interval (null means use default 1/60) */
|
|
35
|
+
private _fixedDt;
|
|
36
|
+
constructor();
|
|
37
|
+
/**
|
|
38
|
+
* Add the first bundle when starting with empty types.
|
|
39
|
+
* This overload allows any bundle to be added to an empty ECSpresso instance.
|
|
40
|
+
*/
|
|
41
|
+
withBundle<BC extends Record<string, any>, BE extends Record<string, any>, BR extends Record<string, any>, BA extends Record<string, unknown> = {}, BS extends Record<string, ScreenDefinition<any, any>> = {}, BL extends string = never, BG extends string = never, BAG extends string = never, BRQ extends string = never>(this: ECSpressoBuilder<{}, {}, {}, A, S, Labels, Groups, AssetGroupNames, ReactiveQueryNames>, bundle: Bundle<BC, BE, BR, BA, BS, BL, BG, BAG, BRQ>): ECSpressoBuilder<BC, BE, BR, A & BA, S & BS, Labels | BL, Groups | BG, AssetGroupNames | BAG, ReactiveQueryNames | BRQ>;
|
|
42
|
+
/**
|
|
43
|
+
* Add a subsequent bundle with type checking.
|
|
44
|
+
* This overload enforces bundle type compatibility.
|
|
45
|
+
*/
|
|
46
|
+
withBundle<BC extends Record<string, any>, BE extends Record<string, any>, BR extends Record<string, any>, BA extends Record<string, unknown> = {}, BS extends Record<string, ScreenDefinition<any, any>> = {}, BL extends string = never, BG extends string = never, BAG extends string = never, BRQ extends string = never>(bundle: BundlesAreCompatible<C, BC, E, BE, R, BR, A, BA, S, BS> extends true ? Bundle<BC, BE, BR, BA, BS, BL, BG, BAG, BRQ> : never): ECSpressoBuilder<C & BC, E & BE, R & BR, A & BA, S & BS, Labels | BL, Groups | BG, AssetGroupNames | BAG, ReactiveQueryNames | BRQ>;
|
|
47
|
+
/**
|
|
48
|
+
* Add application-specific component types to the builder chain.
|
|
49
|
+
* This is a pure type-level operation with no runtime cost.
|
|
50
|
+
* Conflicts with existing component types (same key, different type) produce a `never` return.
|
|
51
|
+
*/
|
|
52
|
+
withComponentTypes<T extends Record<string, any>>(): TypesAreCompatible<C, T> extends true ? ECSpressoBuilder<C & T, E, R, A, S, Labels, Groups, AssetGroupNames, ReactiveQueryNames> : never;
|
|
53
|
+
/**
|
|
54
|
+
* Add application-specific event types to the builder chain.
|
|
55
|
+
* This is a pure type-level operation with no runtime cost.
|
|
56
|
+
* Conflicts with existing event types (same key, different type) produce a `never` return.
|
|
57
|
+
*/
|
|
58
|
+
withEventTypes<T extends Record<string, any>>(): TypesAreCompatible<E, T> extends true ? ECSpressoBuilder<C, E & T, R, A, S, Labels, Groups, AssetGroupNames, ReactiveQueryNames> : never;
|
|
59
|
+
/**
|
|
60
|
+
* Add a resource during ECSpresso construction
|
|
61
|
+
* @param key The resource key
|
|
62
|
+
* @param resource The resource value, factory function, or factory with dependencies/disposal
|
|
63
|
+
* @returns This builder with updated resource types
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* ECSpresso.create<Components, Events, Resources>()
|
|
68
|
+
* .withResource('config', { debug: true })
|
|
69
|
+
* .withResource('counter', () => 42)
|
|
70
|
+
* .withResource('derived', {
|
|
71
|
+
* dependsOn: ['base'],
|
|
72
|
+
* factory: (ecs) => ecs.getResource('base') * 2,
|
|
73
|
+
* onDispose: (value) => console.log('Disposed:', value)
|
|
74
|
+
* })
|
|
75
|
+
* .build();
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
withResource<K extends string, V>(key: K, resource: V | ((context: ECSpresso<C, E, R & Record<K, V>, A, S>) => V | Promise<V>) | ResourceFactoryWithDeps<V, ECSpresso<C, E, R & Record<K, V>, A, S>, keyof (R & Record<K, V>) & string>): ECSpressoBuilder<C, E, R & Record<K, V>, A, S, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;
|
|
79
|
+
/**
|
|
80
|
+
* Register a dispose callback for a component type during build.
|
|
81
|
+
* Called when a component is removed (explicit removal, entity destruction, or replacement).
|
|
82
|
+
* @param componentName The component type to register disposal for
|
|
83
|
+
* @param callback Function receiving the component value being disposed
|
|
84
|
+
* @returns This builder for method chaining
|
|
85
|
+
*/
|
|
86
|
+
withDispose<K extends keyof C & string>(componentName: K, callback: (value: C[K]) => void): this;
|
|
87
|
+
/**
|
|
88
|
+
* Register a required component relationship during build.
|
|
89
|
+
* When an entity gains `trigger`, the `required` component is auto-added
|
|
90
|
+
* (using `factory` for the default value) if not already present.
|
|
91
|
+
* @param trigger The component whose presence triggers auto-addition
|
|
92
|
+
* @param required The component to auto-add
|
|
93
|
+
* @param factory Function that creates the default value for the required component
|
|
94
|
+
* @returns This builder for method chaining
|
|
95
|
+
*/
|
|
96
|
+
withRequired<Trigger extends keyof C & string, Required extends keyof C & string>(trigger: Trigger, required: Required, factory: (triggerValue: C[Trigger]) => C[Required]): this;
|
|
97
|
+
/**
|
|
98
|
+
* Configure assets for this ECSpresso instance
|
|
99
|
+
* @param configurator Function that receives an AssetConfigurator and returns it after adding assets
|
|
100
|
+
* @returns This builder with updated asset types
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* ECSpresso.create<Components, Events, Resources>()
|
|
105
|
+
* .withAssets(assets => assets
|
|
106
|
+
* .add('playerSprite', () => loadTexture('player.png'))
|
|
107
|
+
* .addGroup('level1', {
|
|
108
|
+
* background: () => loadTexture('level1-bg.png'),
|
|
109
|
+
* music: () => loadAudio('level1.mp3'),
|
|
110
|
+
* })
|
|
111
|
+
* )
|
|
112
|
+
* .build();
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
withAssets<NewA extends Record<string, unknown>, NewG extends string = never>(configurator: (assets: AssetConfigurator<{}, never>) => AssetConfigurator<NewA, NewG>): ECSpressoBuilder<C, E, R & {
|
|
116
|
+
$assets: AssetsResource<A & NewA, string>;
|
|
117
|
+
}, A & NewA, S, Labels, Groups, AssetGroupNames | NewG, ReactiveQueryNames>;
|
|
118
|
+
/**
|
|
119
|
+
* Configure screens for this ECSpresso instance
|
|
120
|
+
* @param configurator Function that receives a ScreenConfigurator and returns it after adding screens
|
|
121
|
+
* @returns This builder with updated screen types
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```typescript
|
|
125
|
+
* ECSpresso.create<Components, Events, Resources>()
|
|
126
|
+
* .withScreens(screens => screens
|
|
127
|
+
* .add('loading', {
|
|
128
|
+
* initialState: () => ({ progress: 0 }),
|
|
129
|
+
* })
|
|
130
|
+
* .add('gameplay', {
|
|
131
|
+
* initialState: ({ level }) => ({ score: 0, level }),
|
|
132
|
+
* requiredAssetGroups: ['level1'],
|
|
133
|
+
* })
|
|
134
|
+
* )
|
|
135
|
+
* .build();
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
withScreens<NewS extends Record<string, ScreenDefinition<any, any>>>(configurator: (screens: ScreenConfigurator<{}, ECSpresso<C, E, R, A, Record<string, ScreenDefinition>>>) => ScreenConfigurator<NewS, ECSpresso<C, E, R, A, Record<string, ScreenDefinition>>>): ECSpressoBuilder<C, E, R & {
|
|
139
|
+
$screen: ScreenResource<S & NewS>;
|
|
140
|
+
}, A, S & NewS, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;
|
|
141
|
+
/**
|
|
142
|
+
* Configure the fixed timestep interval for the fixedUpdate phase.
|
|
143
|
+
* @param dt The fixed timestep in seconds (e.g., 1/60 for 60Hz physics)
|
|
144
|
+
* @returns This builder for method chaining
|
|
145
|
+
*/
|
|
146
|
+
withFixedTimestep(dt: number): this;
|
|
147
|
+
/**
|
|
148
|
+
* Declare reactive query names that will be registered at runtime.
|
|
149
|
+
* This is a pure type-level operation with no runtime cost.
|
|
150
|
+
*/
|
|
151
|
+
withReactiveQueryNames<N extends string>(): ECSpressoBuilder<C, E, R, A, S, Labels, Groups, AssetGroupNames, ReactiveQueryNames | N>;
|
|
152
|
+
/**
|
|
153
|
+
* Complete the build process and return the built ECSpresso instance
|
|
154
|
+
*/
|
|
155
|
+
build(): ECSpresso<C, E, FinalizeBuiltinResources<R, A, S, [AssetGroupNames] extends [never] ? string : AssetGroupNames>, A, S, [
|
|
156
|
+
Labels
|
|
157
|
+
] extends [never] ? string : Labels, [
|
|
158
|
+
Groups
|
|
159
|
+
] extends [never] ? string : Groups, [
|
|
160
|
+
AssetGroupNames
|
|
161
|
+
] extends [never] ? string : AssetGroupNames, [
|
|
162
|
+
ReactiveQueryNames
|
|
163
|
+
] extends [never] ? string : ReactiveQueryNames>;
|
|
164
|
+
}
|
|
165
|
+
export {};
|