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
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Movement Bundle for ECSpresso
|
|
3
|
-
*
|
|
4
|
-
* Provides velocity → localTransform integration for entities.
|
|
5
|
-
* Works with the transform bundle's localTransform/worldTransform system.
|
|
6
|
-
*/
|
|
7
|
-
import { Bundle } from 'ecspresso';
|
|
8
|
-
import type { SystemPhase } from 'ecspresso';
|
|
9
|
-
import type { TransformComponentTypes } from './transform';
|
|
10
|
-
/**
|
|
11
|
-
* Velocity component data structure.
|
|
12
|
-
*/
|
|
13
|
-
export interface Velocity {
|
|
14
|
-
x: number;
|
|
15
|
-
y: number;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Component types provided by the movement bundle.
|
|
19
|
-
* Extend your component types with this interface.
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```typescript
|
|
23
|
-
* interface GameComponents extends TransformComponentTypes, MovementComponentTypes {
|
|
24
|
-
* sprite: Sprite;
|
|
25
|
-
* player: boolean;
|
|
26
|
-
* }
|
|
27
|
-
* ```
|
|
28
|
-
*/
|
|
29
|
-
export interface MovementComponentTypes extends TransformComponentTypes {
|
|
30
|
-
velocity: Velocity;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Configuration options for the movement bundle.
|
|
34
|
-
*/
|
|
35
|
-
export interface MovementBundleOptions {
|
|
36
|
-
/** System group name (default: 'physics') */
|
|
37
|
-
systemGroup?: string;
|
|
38
|
-
/** Priority for movement update system (default: 1000, runs early before transform propagation) */
|
|
39
|
-
priority?: number;
|
|
40
|
-
/** Execution phase (default: 'fixedUpdate') */
|
|
41
|
-
phase?: SystemPhase;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Create a velocity component.
|
|
45
|
-
*
|
|
46
|
-
* @param x The x velocity
|
|
47
|
-
* @param y The y velocity
|
|
48
|
-
* @returns Component object suitable for spreading into spawn()
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* ```typescript
|
|
52
|
-
* ecs.spawn({
|
|
53
|
-
* ...createTransform(100, 200),
|
|
54
|
-
* ...createVelocity(50, -25),
|
|
55
|
-
* projectile: true,
|
|
56
|
-
* });
|
|
57
|
-
* ```
|
|
58
|
-
*/
|
|
59
|
-
export declare function createVelocity(x: number, y: number): Pick<MovementComponentTypes, 'velocity'>;
|
|
60
|
-
/**
|
|
61
|
-
* Create a movement bundle for ECSpresso.
|
|
62
|
-
*
|
|
63
|
-
* This bundle provides:
|
|
64
|
-
* - Movement update system that integrates velocity into localTransform
|
|
65
|
-
* - Processes all entities with both localTransform and velocity components
|
|
66
|
-
*
|
|
67
|
-
* Note: This bundle modifies localTransform. The transform bundle's propagation
|
|
68
|
-
* system will then compute worldTransform for use by other systems.
|
|
69
|
-
*
|
|
70
|
-
* @example
|
|
71
|
-
* ```typescript
|
|
72
|
-
* const ecs = ECSpresso
|
|
73
|
-
* .create<Components, Events, Resources>()
|
|
74
|
-
* .withBundle(createTransformBundle())
|
|
75
|
-
* .withBundle(createMovementBundle())
|
|
76
|
-
* .build();
|
|
77
|
-
*
|
|
78
|
-
* // Spawn entity with movement
|
|
79
|
-
* ecs.spawn({
|
|
80
|
-
* ...createTransform(100, 200),
|
|
81
|
-
* ...createVelocity(50, -25),
|
|
82
|
-
* sprite,
|
|
83
|
-
* });
|
|
84
|
-
* ```
|
|
85
|
-
*/
|
|
86
|
-
export declare function createMovementBundle(options?: MovementBundleOptions): Bundle<MovementComponentTypes, {}, {}>;
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
var Q=((j)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(j,{get:(k,z)=>(typeof require<"u"?require:k)[z]}):j)(function(j){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+j+'" is not supported')});import{Bundle as O}from"ecspresso";function X(j,k){return{velocity:{x:j,y:k}}}function Y(j){let{systemGroup:k="physics",priority:z=1000,phase:J="fixedUpdate"}=j??{},A=new O("movement");return A.addSystem("movement").setPriority(z).inPhase(J).inGroup(k).addQuery("movingEntities",{with:["localTransform","velocity"]}).setProcess((K,D,L)=>{for(let F of K.movingEntities){let{localTransform:H,velocity:I}=F.components;H.x+=I.x*D,H.y+=I.y*D,L.markChanged(F.id,"localTransform")}}).and(),A}export{X as createVelocity,Y as createMovementBundle};
|
|
2
|
-
|
|
3
|
-
//# debugId=3E601B940224B76564756E2164756E21
|
|
4
|
-
//# sourceMappingURL=movement.js.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/bundles/utils/movement.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * Movement Bundle for ECSpresso\n *\n * Provides velocity → localTransform integration for entities.\n * Works with the transform bundle's localTransform/worldTransform system.\n */\n\nimport { Bundle } from 'ecspresso';\nimport type { SystemPhase } from 'ecspresso';\nimport type { TransformComponentTypes } from './transform';\n\n// ==================== Component Types ====================\n\n/**\n * Velocity component data structure.\n */\nexport interface Velocity {\n\tx: number;\n\ty: number;\n}\n\n/**\n * Component types provided by the movement bundle.\n * Extend your component types with this interface.\n *\n * @example\n * ```typescript\n * interface GameComponents extends TransformComponentTypes, MovementComponentTypes {\n * sprite: Sprite;\n * player: boolean;\n * }\n * ```\n */\nexport interface MovementComponentTypes extends TransformComponentTypes {\n\tvelocity: Velocity;\n}\n\n// ==================== Bundle Options ====================\n\n/**\n * Configuration options for the movement bundle.\n */\nexport interface MovementBundleOptions {\n\t/** System group name (default: 'physics') */\n\tsystemGroup?: string;\n\t/** Priority for movement update system (default: 1000, runs early before transform propagation) */\n\tpriority?: number;\n\t/** Execution phase (default: 'fixedUpdate') */\n\tphase?: SystemPhase;\n}\n\n// ==================== Helper Functions ====================\n\n/**\n * Create a velocity component.\n *\n * @param x The x velocity\n * @param y The y velocity\n * @returns Component object suitable for spreading into spawn()\n *\n * @example\n * ```typescript\n * ecs.spawn({\n * ...createTransform(100, 200),\n * ...createVelocity(50, -25),\n * projectile: true,\n * });\n * ```\n */\nexport function createVelocity(x: number, y: number): Pick<MovementComponentTypes, 'velocity'> {\n\treturn {\n\t\tvelocity: { x, y },\n\t};\n}\n\n// ==================== Bundle Factory ====================\n\n/**\n * Create a movement bundle for ECSpresso.\n *\n * This bundle provides:\n * - Movement update system that integrates velocity into localTransform\n * - Processes all entities with both localTransform and velocity components\n *\n * Note: This bundle modifies localTransform. The transform bundle's propagation\n * system will then compute worldTransform for use by other systems.\n *\n * @example\n * ```typescript\n * const ecs = ECSpresso\n * .create<Components, Events, Resources>()\n * .withBundle(createTransformBundle())\n * .withBundle(createMovementBundle())\n * .build();\n *\n * // Spawn entity with movement\n * ecs.spawn({\n * ...createTransform(100, 200),\n * ...createVelocity(50, -25),\n * sprite,\n * });\n * ```\n */\nexport function createMovementBundle(\n\toptions?: MovementBundleOptions\n): Bundle<MovementComponentTypes, {}, {}> {\n\tconst {\n\t\tsystemGroup = 'physics',\n\t\tpriority = 1000,\n\t\tphase = 'fixedUpdate',\n\t} = options ?? {};\n\n\tconst bundle = new Bundle<MovementComponentTypes, {}, {}>('movement');\n\n\tbundle\n\t\t.addSystem('movement')\n\t\t.setPriority(priority)\n\t\t.inPhase(phase)\n\t\t.inGroup(systemGroup)\n\t\t.addQuery('movingEntities', {\n\t\t\twith: ['localTransform', 'velocity'],\n\t\t})\n\t\t.setProcess((queries, deltaTime, ecs) => {\n\t\t\tfor (const entity of queries.movingEntities) {\n\t\t\t\tconst { localTransform, velocity } = entity.components;\n\t\t\t\tlocalTransform.x += velocity.x * deltaTime;\n\t\t\t\tlocalTransform.y += velocity.y * deltaTime;\n\t\t\t\tecs.markChanged(entity.id, 'localTransform');\n\t\t\t}\n\t\t})\n\t\t.and();\n\n\treturn bundle;\n}\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": "2PAOA,iBAAS,kBA8DF,SAAS,CAAc,CAAC,EAAW,EAAqD,CAC9F,MAAO,CACN,SAAU,CAAE,IAAG,GAAE,CAClB,EA+BM,SAAS,CAAoB,CACnC,EACyC,CACzC,IACC,cAAc,UACd,WAAW,KACX,QAAQ,eACL,GAAW,CAAC,EAEV,EAAS,IAAI,EAAuC,UAAU,EAoBpE,OAlBA,EACE,UAAU,UAAU,EACpB,YAAY,CAAQ,EACpB,QAAQ,CAAK,EACb,QAAQ,CAAW,EACnB,SAAS,iBAAkB,CAC3B,KAAM,CAAC,iBAAkB,UAAU,CACpC,CAAC,EACA,WAAW,CAAC,EAAS,EAAW,IAAQ,CACxC,QAAW,KAAU,EAAQ,eAAgB,CAC5C,IAAQ,iBAAgB,YAAa,EAAO,WAC5C,EAAe,GAAK,EAAS,EAAI,EACjC,EAAe,GAAK,EAAS,EAAI,EACjC,EAAI,YAAY,EAAO,GAAI,gBAAgB,GAE5C,EACA,IAAI,EAEC",
|
|
8
|
-
"debugId": "3E601B940224B76564756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
var Q=((k)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(k,{get:(z,F)=>(typeof require<"u"?require:z)[F]}):k)(function(k){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+k+'" is not supported')});import{Bundle as O}from"ecspresso";function V(k,z){return{timer:{elapsed:0,duration:k,repeat:!1,active:!0,justFinished:!1,onComplete:z?.onComplete}}}function W(k,z){return{timer:{elapsed:0,duration:k,repeat:!0,active:!0,justFinished:!1,onComplete:z?.onComplete}}}function X(k){let{systemGroup:z="timers",priority:F=0,phase:M="preUpdate"}=k??{},K=new O("timers");K.addSystem("timer-update").setPriority(F).inPhase(M).inGroup(z).addQuery("timers",{with:["timer"]}).setProcess((H,J,x)=>{for(let A of H.timers){let{timer:j}=A.components;if(j.justFinished=!1,!j.active)continue;if(j.elapsed+=J,j.elapsed<j.duration)continue;if(j.repeat)while(j.elapsed>=j.duration)j.justFinished=!0,L(x,A.id,j),j.elapsed-=j.duration;else j.justFinished=!0,L(x,A.id,j),j.active=!1,x.commands.removeEntity(A.id)}}).and();function L(H,J,x){if(!x.onComplete)return;let A={entityId:J,duration:x.duration,elapsed:x.elapsed};H.eventBus.publish(x.onComplete,A)}return K}export{X as createTimerBundle,V as createTimer,W as createRepeatingTimer};
|
|
2
|
-
|
|
3
|
-
//# debugId=3CE4B9B931E088F464756E2164756E21
|
|
4
|
-
//# sourceMappingURL=timers.js.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/bundles/utils/timers.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * Timer Bundle for ECSpresso\n *\n * Provides ECS-native timers following the \"data, not callbacks\" philosophy.\n * Timers are components processed each frame, automatically cleaned up when entities are removed.\n */\n\nimport { Bundle } from 'ecspresso';\nimport type { SystemPhase } from 'ecspresso';\n\n// ==================== Event Types ====================\n\n/**\n * Data structure published when a timer completes.\n * Use this type when defining timer completion events in your EventTypes interface.\n *\n * @example\n * ```typescript\n * interface Events {\n * hideMessage: TimerEventData;\n * spawnWave: TimerEventData;\n * }\n * ```\n */\nexport interface TimerEventData {\n\t/** The entity ID that the timer belongs to */\n\tentityId: number;\n\t/** The timer's configured duration in seconds */\n\tduration: number;\n\t/** The actual elapsed time (may exceed duration slightly) */\n\telapsed: number;\n}\n\n// ==================== Component Types ====================\n\n/**\n * Extracts event names from EventTypes that have TimerEventData as their payload.\n * This ensures only compatible events can be used with timer.onComplete.\n */\nexport type TimerEventName<EventTypes extends Record<string, any>> = {\n\t[K in keyof EventTypes]: EventTypes[K] extends TimerEventData ? K : never\n}[keyof EventTypes];\n\n/**\n * Timer component data structure.\n * Use `justFinished` to detect timer completion in your systems.\n *\n * @template EventTypes The event types from your ECS\n */\nexport interface Timer<EventTypes extends Record<string, any>> {\n\t/** Time accumulated so far (seconds) */\n\telapsed: number;\n\t/** Target duration (seconds) */\n\tduration: number;\n\t/** Whether timer repeats after completion */\n\trepeat: boolean;\n\t/** Whether timer is currently running */\n\tactive: boolean;\n\t/** True for one frame after timer completes */\n\tjustFinished: boolean;\n\t/** Optional event name to publish when timer completes. Must be an event with TimerEventData payload. */\n\tonComplete?: TimerEventName<EventTypes>;\n}\n\n/**\n * Component types provided by the timer bundle.\n * Extend your component types with this interface.\n *\n * @template EventTypes The event types from your ECS\n *\n * @example\n * ```typescript\n * interface GameComponents extends TimerComponentTypes<GameEvents> {\n * velocity: { x: number; y: number };\n * player: true;\n * }\n * ```\n */\nexport interface TimerComponentTypes<EventTypes extends Record<string, any>> {\n\ttimer: Timer<EventTypes>;\n}\n\n// ==================== Bundle Options ====================\n\n/**\n * Configuration options for the timer bundle.\n */\nexport interface TimerBundleOptions {\n\t/** System group name (default: 'timers') */\n\tsystemGroup?: string;\n\t/** Priority for timer update system (default: 0) */\n\tpriority?: number;\n\t/** Execution phase (default: 'preUpdate') */\n\tphase?: SystemPhase;\n}\n\n// ==================== Helper Functions ====================\n\n/**\n * Options for timer creation\n *\n * @template EventTypes The event types from your ECS\n */\nexport interface TimerOptions<EventTypes extends Record<string, any>> {\n\t/** Event name to publish when timer completes. Must be an event with TimerEventData payload. */\n\tonComplete?: TimerEventName<EventTypes>;\n}\n\n/**\n * Create a one-shot timer that fires once after the specified duration.\n *\n * @template EventTypes The event types from your ECS (must be explicitly provided)\n * @param duration Duration in seconds until the timer completes\n * @param options Optional configuration including event name\n * @returns Component object suitable for spreading into spawn()\n *\n * @example\n * ```typescript\n * // Timer without event\n * ecs.spawn({\n * ...createTimer<GameEvents>(2),\n * explosion: true,\n * });\n *\n * // Timer that publishes an event on completion\n * ecs.spawn({\n * ...createTimer<GameEvents>(1.5, { onComplete: 'hideMessage' }),\n * });\n * ```\n */\nexport function createTimer<EventTypes extends Record<string, any>>(\n\tduration: number,\n\toptions?: TimerOptions<EventTypes>\n): Pick<TimerComponentTypes<EventTypes>, 'timer'> {\n\treturn {\n\t\ttimer: {\n\t\t\telapsed: 0,\n\t\t\tduration,\n\t\t\trepeat: false,\n\t\t\tactive: true,\n\t\t\tjustFinished: false,\n\t\t\tonComplete: options?.onComplete,\n\t\t},\n\t};\n}\n\n/**\n * Create a repeating timer that fires every `duration` seconds.\n *\n * @template EventTypes The event types from your ECS (must be explicitly provided)\n * @param duration Duration in seconds between each timer completion\n * @param options Optional configuration including event name\n * @returns Component object suitable for spreading into spawn()\n *\n * @example\n * ```typescript\n * // Timer without event\n * ecs.spawn({\n * ...createRepeatingTimer<GameEvents>(5),\n * spawner: true,\n * });\n *\n * // Repeating timer that publishes an event each cycle\n * ecs.spawn({\n * ...createRepeatingTimer<GameEvents>(3, { onComplete: 'spawnWave' }),\n * });\n * ```\n */\nexport function createRepeatingTimer<EventTypes extends Record<string, any>>(\n\tduration: number,\n\toptions?: TimerOptions<EventTypes>\n): Pick<TimerComponentTypes<EventTypes>, 'timer'> {\n\treturn {\n\t\ttimer: {\n\t\t\telapsed: 0,\n\t\t\tduration,\n\t\t\trepeat: true,\n\t\t\tactive: true,\n\t\t\tjustFinished: false,\n\t\t\tonComplete: options?.onComplete,\n\t\t},\n\t};\n}\n\n// ==================== Bundle Factory ====================\n\n/**\n * Create a timer bundle for ECSpresso.\n *\n * This bundle provides:\n * - Timer update system that processes all timer components each frame\n * - `justFinished` flag pattern for one-frame completion detection\n * - Automatic cleanup when entities are removed\n *\n * @example\n * ```typescript\n * const ecs = ECSpresso\n * .create<Components, Events, Resources>()\n * .withBundle(createTimerBundle())\n * .build();\n *\n * // Spawn entity with timer\n * ecs.spawn({\n * ...createRepeatingTimer(5),\n * spawner: true,\n * });\n *\n * // React to timer completion in a system\n * ecs.addSystem('spawn-on-timer')\n * .addQuery('spawners', { with: ['timer', 'spawner'] })\n * .setProcess((queries, _dt, ecs) => {\n * for (const { components } of queries.spawners) {\n * if (components.timer.justFinished) {\n * ecs.spawn({ enemy: true });\n * }\n * }\n * });\n * ```\n */\nexport function createTimerBundle<EventTypes extends Record<string, any>>(\n\toptions?: TimerBundleOptions\n): Bundle<TimerComponentTypes<EventTypes>, EventTypes, {}> {\n\tconst {\n\t\tsystemGroup = 'timers',\n\t\tpriority = 0,\n\t\tphase = 'preUpdate',\n\t} = options ?? {};\n\n\tconst bundle = new Bundle<TimerComponentTypes<EventTypes>, EventTypes, {}>('timers');\n\n\tbundle\n\t\t.addSystem('timer-update')\n\t\t.setPriority(priority)\n\t\t.inPhase(phase)\n\t\t.inGroup(systemGroup)\n\t\t.addQuery('timers', {\n\t\t\twith: ['timer'],\n\t\t})\n\t\t.setProcess((queries, deltaTime, ecs) => {\n\t\t\tfor (const entity of queries.timers) {\n\t\t\t\tconst { timer } = entity.components;\n\n\t\t\t\t// Reset justFinished flag from previous frame\n\t\t\t\ttimer.justFinished = false;\n\n\t\t\t\t// Skip inactive timers\n\t\t\t\tif (!timer.active) continue;\n\n\t\t\t\t// Accumulate time\n\t\t\t\ttimer.elapsed += deltaTime;\n\n\t\t\t\t// Check if timer completed\n\t\t\t\tif (timer.elapsed < timer.duration) continue;\n\n\t\t\t\t// Timer completed - handle based on repeat mode\n\t\t\t\tif (timer.repeat) {\n\t\t\t\t\t// Handle multiple cycles in one frame\n\t\t\t\t\twhile (timer.elapsed >= timer.duration) {\n\t\t\t\t\t\ttimer.justFinished = true;\n\t\t\t\t\t\tpublishTimerEvent(ecs, entity.id, timer);\n\t\t\t\t\t\ttimer.elapsed -= timer.duration;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// One-shot timer\n\t\t\t\t\ttimer.justFinished = true;\n\t\t\t\t\tpublishTimerEvent(ecs, entity.id, timer);\n\t\t\t\t\ttimer.active = false;\n\t\t\t\t\t// Auto-remove one-shot timer entities after completion.\n\t\t\t\t\t// If configurability is needed in the future, add an autoRemove option to TimerOptions.\n\t\t\t\t\tecs.commands.removeEntity(entity.id);\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t\t.and();\n\n\t/**\n\t * Publishes timer completion event if onComplete is specified.\n\t * Type assertion needed: TypeScript can't infer that TimerEventName<EventTypes>\n\t * maps to events with TimerEventData payloads, even though that's what the type enforces.\n\t */\n\tfunction publishTimerEvent(\n\t\tecs: { eventBus: { publish: (event: any, data: any) => void } },\n\t\tentityId: number,\n\t\ttimer: Timer<EventTypes>\n\t): void {\n\t\tif (!timer.onComplete) return;\n\t\tconst eventData: TimerEventData = {\n\t\t\tentityId,\n\t\t\tduration: timer.duration,\n\t\t\telapsed: timer.elapsed,\n\t\t};\n\t\tecs.eventBus.publish(timer.onComplete, eventData);\n\t}\n\n\treturn bundle;\n}\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": "2PAOA,iBAAS,kBA2HF,SAAS,CAAmD,CAClE,EACA,EACiD,CACjD,MAAO,CACN,MAAO,CACN,QAAS,EACT,WACA,OAAQ,GACR,OAAQ,GACR,aAAc,GACd,WAAY,GAAS,UACtB,CACD,EAyBM,SAAS,CAA4D,CAC3E,EACA,EACiD,CACjD,MAAO,CACN,MAAO,CACN,QAAS,EACT,WACA,OAAQ,GACR,OAAQ,GACR,aAAc,GACd,WAAY,GAAS,UACtB,CACD,EAsCM,SAAS,CAAyD,CACxE,EAC0D,CAC1D,IACC,cAAc,SACd,WAAW,EACX,QAAQ,aACL,GAAW,CAAC,EAEV,EAAS,IAAI,EAAwD,QAAQ,EAEnF,EACE,UAAU,cAAc,EACxB,YAAY,CAAQ,EACpB,QAAQ,CAAK,EACb,QAAQ,CAAW,EACnB,SAAS,SAAU,CACnB,KAAM,CAAC,OAAO,CACf,CAAC,EACA,WAAW,CAAC,EAAS,EAAW,IAAQ,CACxC,QAAW,KAAU,EAAQ,OAAQ,CACpC,IAAQ,SAAU,EAAO,WAMzB,GAHA,EAAM,aAAe,GAGjB,CAAC,EAAM,OAAQ,SAMnB,GAHA,EAAM,SAAW,EAGb,EAAM,QAAU,EAAM,SAAU,SAGpC,GAAI,EAAM,OAET,MAAO,EAAM,SAAW,EAAM,SAC7B,EAAM,aAAe,GACrB,EAAkB,EAAK,EAAO,GAAI,CAAK,EACvC,EAAM,SAAW,EAAM,SAIxB,OAAM,aAAe,GACrB,EAAkB,EAAK,EAAO,GAAI,CAAK,EACvC,EAAM,OAAS,GAGf,EAAI,SAAS,aAAa,EAAO,EAAE,GAGrC,EACA,IAAI,EAON,SAAS,CAAiB,CACzB,EACA,EACA,EACO,CACP,GAAI,CAAC,EAAM,WAAY,OACvB,IAAM,EAA4B,CACjC,WACA,SAAU,EAAM,SAChB,QAAS,EAAM,OAChB,EACA,EAAI,SAAS,QAAQ,EAAM,WAAY,CAAS,EAGjD,OAAO",
|
|
8
|
-
"debugId": "3CE4B9B931E088F464756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
var S=((j)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(j,{get:(k,q)=>(typeof require<"u"?require:k)[q]}):j)(function(j){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+j+'" is not supported')});import{Bundle as O}from"ecspresso";var Z={x:0,y:0,rotation:0,scaleX:1,scaleY:1},_={x:0,y:0,rotation:0,scaleX:1,scaleY:1};function $(j,k){return{localTransform:{x:j,y:k,rotation:0,scaleX:1,scaleY:1}}}function A(j,k){return{worldTransform:{x:j,y:k,rotation:0,scaleX:1,scaleY:1}}}function B(j,k,q){let H=q?.scale??q?.scaleX??1,v=q?.scale??q?.scaleY??1,D=q?.rotation??0,z={x:j,y:k,rotation:D,scaleX:H,scaleY:v};return{localTransform:{...z},worldTransform:{...z}}}function E(j){let{systemGroup:k="transform",priority:q=500,phase:H="postUpdate"}=j??{},v=new O("transform");return v.addSystem("transform-propagation").setPriority(q).inPhase(H).inGroup(k).setProcess((D,z,F)=>{P(F)}).and(),v}function P(j){let{changeThreshold:k,entityManager:q}=j;j.forEachInHierarchy((v,D)=>{let z=q.getComponent(v,"localTransform"),F=q.getComponent(v,"worldTransform");if(!z||!F)return;let J=q.getChangeSeq(v,"localTransform")>k,N=D!==null&&q.getChangeSeq(D,"worldTransform")>k;if(!J&&!N)return;if(D===null)K(z,F);else{let M=q.getComponent(D,"worldTransform");if(M)Q(M,z,F);else K(z,F)}j.markChanged(v,"worldTransform")});let H=j.getEntitiesWithQuery(["localTransform","worldTransform"]);for(let v of H)if(j.getParent(v.id)===null&&j.getChildren(v.id).length===0){if(!(q.getChangeSeq(v.id,"localTransform")>k))continue;let{localTransform:F,worldTransform:J}=v.components;K(F,J),j.markChanged(v.id,"worldTransform")}}function K(j,k){k.x=j.x,k.y=j.y,k.rotation=j.rotation,k.scaleX=j.scaleX,k.scaleY=j.scaleY}function Q(j,k,q){let H=k.x*j.scaleX,v=k.y*j.scaleY,D=Math.cos(j.rotation),z=Math.sin(j.rotation),F=H*D-v*z,J=H*z+v*D;q.x=j.x+F,q.y=j.y+J,q.rotation=j.rotation+k.rotation,q.scaleX=j.scaleX*k.scaleX,q.scaleY=j.scaleY*k.scaleY}export{A as createWorldTransform,E as createTransformBundle,B as createTransform,$ as createLocalTransform,_ as DEFAULT_WORLD_TRANSFORM,Z as DEFAULT_LOCAL_TRANSFORM};
|
|
2
|
-
|
|
3
|
-
//# debugId=2B678F92021E438E64756E2164756E21
|
|
4
|
-
//# sourceMappingURL=transform.js.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/bundles/utils/transform.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * Transform Bundle for ECSpresso\n *\n * Provides hierarchical transform propagation following Bevy's Transform/GlobalTransform pattern.\n * LocalTransform is modified by user code; WorldTransform is computed automatically.\n *\n * @see https://docs.rs/bevy/latest/bevy/transform/components/struct.GlobalTransform.html\n */\n\nimport { Bundle } from 'ecspresso';\nimport type { SystemPhase } from 'ecspresso';\nimport type ECSpresso from 'ecspresso';\n\n// ==================== Component Types ====================\n\n/**\n * Local transform relative to parent (or world if no parent).\n * This is the transform you modify directly.\n */\nexport interface LocalTransform {\n\tx: number;\n\ty: number;\n\trotation: number;\n\tscaleX: number;\n\tscaleY: number;\n}\n\n/**\n * Computed world transform (accumulated from parent chain).\n * Read-only - managed by the transform propagation system.\n */\nexport interface WorldTransform {\n\tx: number;\n\ty: number;\n\trotation: number;\n\tscaleX: number;\n\tscaleY: number;\n}\n\n/**\n * Component types provided by the transform bundle.\n * Extend your component types with this interface.\n *\n * @example\n * ```typescript\n * interface GameComponents extends TransformComponentTypes {\n * sprite: Sprite;\n * velocity: { x: number; y: number };\n * }\n * ```\n */\nexport interface TransformComponentTypes {\n\tlocalTransform: LocalTransform;\n\tworldTransform: WorldTransform;\n}\n\n// ==================== Bundle Options ====================\n\n/**\n * Configuration options for the transform bundle.\n */\nexport interface TransformBundleOptions {\n\t/** System group name (default: 'transform') */\n\tsystemGroup?: string;\n\t/** Priority for transform propagation (default: 500, runs after physics/movement) */\n\tpriority?: number;\n\t/** Execution phase (default: 'postUpdate') */\n\tphase?: SystemPhase;\n}\n\n// ==================== Default Values ====================\n\n/**\n * Default local transform values.\n */\nexport const DEFAULT_LOCAL_TRANSFORM: Readonly<LocalTransform> = {\n\tx: 0,\n\ty: 0,\n\trotation: 0,\n\tscaleX: 1,\n\tscaleY: 1,\n};\n\n/**\n * Default world transform values.\n */\nexport const DEFAULT_WORLD_TRANSFORM: Readonly<WorldTransform> = {\n\tx: 0,\n\ty: 0,\n\trotation: 0,\n\tscaleX: 1,\n\tscaleY: 1,\n};\n\n// ==================== Helper Functions ====================\n\n/**\n * Create a local transform component with position only.\n * Uses default rotation (0) and scale (1, 1).\n *\n * @param x The x coordinate\n * @param y The y coordinate\n * @returns Component object suitable for spreading into spawn()\n *\n * @example\n * ```typescript\n * ecs.spawn({\n * ...createLocalTransform(100, 200),\n * sprite,\n * });\n * ```\n */\nexport function createLocalTransform(x: number, y: number): Pick<TransformComponentTypes, 'localTransform'> {\n\treturn {\n\t\tlocalTransform: {\n\t\t\tx,\n\t\t\ty,\n\t\t\trotation: 0,\n\t\t\tscaleX: 1,\n\t\t\tscaleY: 1,\n\t\t},\n\t};\n}\n\n/**\n * Create a world transform component with position only.\n * Typically used alongside createLocalTransform for initial state.\n *\n * @param x The x coordinate\n * @param y The y coordinate\n * @returns Component object suitable for spreading into spawn()\n */\nexport function createWorldTransform(x: number, y: number): Pick<TransformComponentTypes, 'worldTransform'> {\n\treturn {\n\t\tworldTransform: {\n\t\t\tx,\n\t\t\ty,\n\t\t\trotation: 0,\n\t\t\tscaleX: 1,\n\t\t\tscaleY: 1,\n\t\t},\n\t};\n}\n\n/**\n * Options for creating a full transform.\n */\nexport interface TransformOptions {\n\trotation?: number;\n\tscaleX?: number;\n\tscaleY?: number;\n\t/** Uniform scale (overrides scaleX/scaleY if provided) */\n\tscale?: number;\n}\n\n/**\n * Create both local and world transform components.\n * World transform is initialized to match local transform.\n *\n * @param x The x coordinate\n * @param y The y coordinate\n * @param options Optional rotation and scale\n * @returns Component object suitable for spreading into spawn()\n *\n * @example\n * ```typescript\n * ecs.spawn({\n * ...createTransform(100, 200),\n * sprite,\n * });\n *\n * // With rotation and scale\n * ecs.spawn({\n * ...createTransform(100, 200, { rotation: Math.PI / 4, scale: 2 }),\n * sprite,\n * });\n * ```\n */\nexport function createTransform(\n\tx: number,\n\ty: number,\n\toptions?: TransformOptions\n): TransformComponentTypes {\n\tconst scaleX = options?.scale ?? options?.scaleX ?? 1;\n\tconst scaleY = options?.scale ?? options?.scaleY ?? 1;\n\tconst rotation = options?.rotation ?? 0;\n\n\tconst transform = {\n\t\tx,\n\t\ty,\n\t\trotation,\n\t\tscaleX,\n\t\tscaleY,\n\t};\n\n\treturn {\n\t\tlocalTransform: { ...transform },\n\t\tworldTransform: { ...transform },\n\t};\n}\n\n// ==================== Bundle Factory ====================\n\n/**\n * Create a transform bundle for ECSpresso.\n *\n * This bundle provides:\n * - Transform propagation system that computes world transforms from local transforms\n * - Parent-first traversal ensures parents are processed before children\n * - Supports full transform hierarchy (position, rotation, scale)\n *\n * @example\n * ```typescript\n * const ecs = ECSpresso\n * .create<Components, Events, Resources>()\n * .withBundle(createTransformBundle())\n * .withBundle(createMovementBundle())\n * .build();\n *\n * // Spawn entity with transform\n * ecs.spawn({\n * ...createTransform(100, 200),\n * velocity: { x: 50, y: 0 },\n * });\n * ```\n */\nexport function createTransformBundle(\n\toptions?: TransformBundleOptions\n): Bundle<TransformComponentTypes, {}, {}> {\n\tconst {\n\t\tsystemGroup = 'transform',\n\t\tpriority = 500,\n\t\tphase = 'postUpdate',\n\t} = options ?? {};\n\n\tconst bundle = new Bundle<TransformComponentTypes, {}, {}>('transform');\n\n\tbundle\n\t\t.addSystem('transform-propagation')\n\t\t.setPriority(priority)\n\t\t.inPhase(phase)\n\t\t.inGroup(systemGroup)\n\t\t.setProcess((_queries, _deltaTime, ecs) => {\n\t\t\tpropagateTransforms(ecs as ECSpresso<TransformComponentTypes, {}, {}>);\n\t\t})\n\t\t.and();\n\n\treturn bundle;\n}\n\n/**\n * Propagate transforms through the hierarchy.\n * Parent-first traversal ensures parents are computed before children.\n *\n * Only recomputes entities whose localTransform changed since this system\n * last ran, or whose parent's worldTransform changed (cascade).\n * Uses per-system monotonic sequence threshold for change detection.\n */\nfunction propagateTransforms(ecs: ECSpresso<TransformComponentTypes, {}, {}>): void {\n\tconst threshold = ecs.changeThreshold;\n\tconst em = ecs.entityManager;\n\n\t// Use parent-first traversal for entities in hierarchy\n\tecs.forEachInHierarchy((entityId, parentId) => {\n\t\tconst localTransform = em.getComponent(entityId, 'localTransform');\n\t\tconst worldTransform = em.getComponent(entityId, 'worldTransform');\n\n\t\tif (!localTransform || !worldTransform) return;\n\n\t\tconst localChanged = em.getChangeSeq(entityId, 'localTransform') > threshold;\n\t\tconst parentWorldChanged = parentId !== null\n\t\t\t&& em.getChangeSeq(parentId, 'worldTransform') > threshold;\n\n\t\tif (!localChanged && !parentWorldChanged) return;\n\n\t\tif (parentId === null) {\n\t\t\t// Root entity: world transform equals local transform\n\t\t\tcopyTransform(localTransform, worldTransform);\n\t\t} else {\n\t\t\t// Child entity: combine with parent's world transform\n\t\t\tconst parentWorld = em.getComponent(parentId, 'worldTransform');\n\t\t\tif (parentWorld) {\n\t\t\t\tcombineTransforms(parentWorld, localTransform, worldTransform);\n\t\t\t} else {\n\t\t\t\t// Parent has no world transform, treat as root\n\t\t\t\tcopyTransform(localTransform, worldTransform);\n\t\t\t}\n\t\t}\n\n\t\tecs.markChanged(entityId, 'worldTransform');\n\t});\n\n\t// Process orphaned entities (not in hierarchy but have transforms)\n\tconst orphanedEntities = ecs.getEntitiesWithQuery(['localTransform', 'worldTransform']);\n\tfor (const entity of orphanedEntities) {\n\t\tconst parentId = ecs.getParent(entity.id);\n\t\t// Only process if truly orphaned (no parent and not a root with children)\n\t\tif (parentId === null && ecs.getChildren(entity.id).length === 0) {\n\t\t\tconst localChanged = em.getChangeSeq(entity.id, 'localTransform') > threshold;\n\t\t\tif (!localChanged) continue;\n\n\t\t\tconst { localTransform, worldTransform } = entity.components;\n\t\t\tcopyTransform(localTransform, worldTransform);\n\t\t\tecs.markChanged(entity.id, 'worldTransform');\n\t\t}\n\t}\n}\n\n/**\n * Copy transform values from source to destination.\n */\nfunction copyTransform(src: LocalTransform, dest: WorldTransform): void {\n\tdest.x = src.x;\n\tdest.y = src.y;\n\tdest.rotation = src.rotation;\n\tdest.scaleX = src.scaleX;\n\tdest.scaleY = src.scaleY;\n}\n\n/**\n * Combine parent world transform with child local transform into child world transform.\n */\nfunction combineTransforms(\n\tparent: WorldTransform,\n\tlocal: LocalTransform,\n\tworld: WorldTransform\n): void {\n\t// Apply parent's scale to local position\n\tconst scaledLocalX = local.x * parent.scaleX;\n\tconst scaledLocalY = local.y * parent.scaleY;\n\n\t// Rotate local position by parent's rotation\n\tconst cos = Math.cos(parent.rotation);\n\tconst sin = Math.sin(parent.rotation);\n\tconst rotatedX = scaledLocalX * cos - scaledLocalY * sin;\n\tconst rotatedY = scaledLocalX * sin + scaledLocalY * cos;\n\n\t// Add to parent's position\n\tworld.x = parent.x + rotatedX;\n\tworld.y = parent.y + rotatedY;\n\tworld.rotation = parent.rotation + local.rotation;\n\tworld.scaleX = parent.scaleX * local.scaleX;\n\tworld.scaleY = parent.scaleY * local.scaleY;\n}\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": "2PASA,iBAAS,kBAkEF,IAAM,EAAoD,CAChE,EAAG,EACH,EAAG,EACH,SAAU,EACV,OAAQ,EACR,OAAQ,CACT,EAKa,EAAoD,CAChE,EAAG,EACH,EAAG,EACH,SAAU,EACV,OAAQ,EACR,OAAQ,CACT,EAoBO,SAAS,CAAoB,CAAC,EAAW,EAA4D,CAC3G,MAAO,CACN,eAAgB,CACf,IACA,IACA,SAAU,EACV,OAAQ,EACR,OAAQ,CACT,CACD,EAWM,SAAS,CAAoB,CAAC,EAAW,EAA4D,CAC3G,MAAO,CACN,eAAgB,CACf,IACA,IACA,SAAU,EACV,OAAQ,EACR,OAAQ,CACT,CACD,EAqCM,SAAS,CAAe,CAC9B,EACA,EACA,EAC0B,CAC1B,IAAM,EAAS,GAAS,OAAS,GAAS,QAAU,EAC9C,EAAS,GAAS,OAAS,GAAS,QAAU,EAC9C,EAAW,GAAS,UAAY,EAEhC,EAAY,CACjB,IACA,IACA,WACA,SACA,QACD,EAEA,MAAO,CACN,eAAgB,IAAK,CAAU,EAC/B,eAAgB,IAAK,CAAU,CAChC,EA4BM,SAAS,CAAqB,CACpC,EAC0C,CAC1C,IACC,cAAc,YACd,WAAW,IACX,QAAQ,cACL,GAAW,CAAC,EAEV,EAAS,IAAI,EAAwC,WAAW,EAYtE,OAVA,EACE,UAAU,uBAAuB,EACjC,YAAY,CAAQ,EACpB,QAAQ,CAAK,EACb,QAAQ,CAAW,EACnB,WAAW,CAAC,EAAU,EAAY,IAAQ,CAC1C,EAAoB,CAAiD,EACrE,EACA,IAAI,EAEC,EAWR,SAAS,CAAmB,CAAC,EAAuD,CACnF,IAAsB,gBAAhB,EACS,cAAT,GAAK,EAGX,EAAI,mBAAmB,CAAC,EAAU,IAAa,CAC9C,IAAM,EAAiB,EAAG,aAAa,EAAU,gBAAgB,EAC3D,EAAiB,EAAG,aAAa,EAAU,gBAAgB,EAEjE,GAAI,CAAC,GAAkB,CAAC,EAAgB,OAExC,IAAM,EAAe,EAAG,aAAa,EAAU,gBAAgB,EAAI,EAC7D,EAAqB,IAAa,MACpC,EAAG,aAAa,EAAU,gBAAgB,EAAI,EAElD,GAAI,CAAC,GAAgB,CAAC,EAAoB,OAE1C,GAAI,IAAa,KAEhB,EAAc,EAAgB,CAAc,EACtC,KAEN,IAAM,EAAc,EAAG,aAAa,EAAU,gBAAgB,EAC9D,GAAI,EACH,EAAkB,EAAa,EAAgB,CAAc,EAG7D,OAAc,EAAgB,CAAc,EAI9C,EAAI,YAAY,EAAU,gBAAgB,EAC1C,EAGD,IAAM,EAAmB,EAAI,qBAAqB,CAAC,iBAAkB,gBAAgB,CAAC,EACtF,QAAW,KAAU,EAGpB,GAFiB,EAAI,UAAU,EAAO,EAAE,IAEvB,MAAQ,EAAI,YAAY,EAAO,EAAE,EAAE,SAAW,EAAG,CAEjE,GAAI,EADiB,EAAG,aAAa,EAAO,GAAI,gBAAgB,EAAI,GACjD,SAEnB,IAAQ,iBAAgB,kBAAmB,EAAO,WAClD,EAAc,EAAgB,CAAc,EAC5C,EAAI,YAAY,EAAO,GAAI,gBAAgB,GAQ9C,SAAS,CAAa,CAAC,EAAqB,EAA4B,CACvE,EAAK,EAAI,EAAI,EACb,EAAK,EAAI,EAAI,EACb,EAAK,SAAW,EAAI,SACpB,EAAK,OAAS,EAAI,OAClB,EAAK,OAAS,EAAI,OAMnB,SAAS,CAAiB,CACzB,EACA,EACA,EACO,CAEP,IAAM,EAAe,EAAM,EAAI,EAAO,OAChC,EAAe,EAAM,EAAI,EAAO,OAGhC,EAAM,KAAK,IAAI,EAAO,QAAQ,EAC9B,EAAM,KAAK,IAAI,EAAO,QAAQ,EAC9B,EAAW,EAAe,EAAM,EAAe,EAC/C,EAAW,EAAe,EAAM,EAAe,EAGrD,EAAM,EAAI,EAAO,EAAI,EACrB,EAAM,EAAI,EAAO,EAAI,EACrB,EAAM,SAAW,EAAO,SAAW,EAAM,SACzC,EAAM,OAAS,EAAO,OAAS,EAAM,OACrC,EAAM,OAAS,EAAO,OAAS,EAAM",
|
|
8
|
-
"debugId": "2B678F92021E438E64756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
package/dist/index.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
var c=((j)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(j,{get:(J,X)=>(typeof require<"u"?require:J)[X]}):j)(function(j){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+j+'" is not supported')});class z{parentMap=new Map;childrenMap=new Map;setParent(j,J){if(j===J)throw Error(`Cannot set entity ${j} as its own parent`);if(this.wouldCreateCycle(j,J))throw Error("Cannot set parent: would create circular reference");let X=this.parentMap.get(j);if(X!==void 0){let Z=this.childrenMap.get(X);if(Z){let $=Z.indexOf(j);if($!==-1)Z.splice($,1)}}this.parentMap.set(j,J);let Y=this.childrenMap.get(J);if(Y)Y.push(j);else this.childrenMap.set(J,[j]);return this}removeParent(j){let J=this.parentMap.get(j);if(J===void 0)return!1;let X=this.childrenMap.get(J);if(X){let Y=X.indexOf(j);if(Y!==-1)X.splice(Y,1)}return this.parentMap.delete(j),!0}getParent(j){return this.parentMap.get(j)??null}getChildren(j){let J=this.childrenMap.get(j);return J?[...J]:[]}getChildAt(j,J){if(J<0)return null;let X=this.childrenMap.get(j);if(!X||J>=X.length)return null;return X[J]??null}getChildIndex(j,J){let X=this.childrenMap.get(j);if(!X)return-1;return X.indexOf(J)}removeEntity(j){let J=this.parentMap.get(j)??null;if(J!==null){let Z=this.childrenMap.get(J);if(Z){let $=Z.indexOf(j);if($!==-1)Z.splice($,1)}}this.parentMap.delete(j);let X=this.childrenMap.get(j)??[],Y=[...X];for(let Z of X)this.parentMap.delete(Z);return this.childrenMap.delete(j),{oldParent:J,orphanedChildren:Y}}getAncestors(j){let J=[],X=this.parentMap.get(j);while(X!==void 0)J.push(X),X=this.parentMap.get(X);return J}getDescendants(j){let J=[],X=[...this.childrenMap.get(j)??[]];while(X.length>0){let Y=X.shift();if(Y===void 0)continue;J.push(Y);let Z=this.childrenMap.get(Y);if(Z)X.unshift(...Z)}return J}getRoot(j){let J=j,X=this.parentMap.get(J);while(X!==void 0)J=X,X=this.parentMap.get(J);return J}getSiblings(j){let J=this.parentMap.get(j);if(J===void 0)return[];let X=this.childrenMap.get(J);if(!X)return[];return X.filter((Y)=>Y!==j)}isDescendantOf(j,J){if(j===J)return!1;let X=this.parentMap.get(j);while(X!==void 0){if(X===J)return!0;X=this.parentMap.get(X)}return!1}isAncestorOf(j,J){return this.isDescendantOf(J,j)}getRootEntities(){let j=[];for(let J of this.childrenMap.keys())if(!this.parentMap.has(J))j.push(J);return j}wouldCreateCycle(j,J){let X=J;while(X!==void 0){if(X===j)return!0;X=this.parentMap.get(X)}return!1}forEachInHierarchy(j,J){let X=J?.roots??this.getRootEntities(),Y=[];for(let Z of X)Y.push({entityId:Z,parentId:null,depth:0});while(Y.length>0){let Z=Y.shift();if(!Z)break;j(Z.entityId,Z.parentId,Z.depth);let $=this.childrenMap.get(Z.entityId);if($)for(let G of $)Y.push({entityId:G,parentId:Z.entityId,depth:Z.depth+1})}}*hierarchyIterator(j){let J=j?.roots??this.getRootEntities(),X=[];for(let Y of J)X.push({entityId:Y,parentId:null,depth:0});while(X.length>0){let Y=X.shift();if(!Y)break;yield Y;let Z=this.childrenMap.get(Y.entityId);if(Z)for(let $ of Z)X.push({entityId:$,parentId:Y.entityId,depth:Y.depth+1})}}}class A{nextId=1;entities=new Map;componentIndices=new Map;addedCallbacks=new Map;removedCallbacks=new Map;hierarchyManager=new z;changeSeqs=new Map;_changeSeq=0;createEntity(){let j=this.nextId++,J={id:j,components:{}};return this.entities.set(j,J),J}addComponent(j,J,X){let Y=typeof j==="number"?this.entities.get(j):j;if(!Y){let $=typeof j==="number"?j:j.id;throw Error(`Cannot add component '${String(J)}': Entity with ID ${$} does not exist`)}if(Y.components[J]=X,!this.componentIndices.has(J))this.componentIndices.set(J,new Set);this.componentIndices.get(J)?.add(Y.id);let Z=this.addedCallbacks.get(J);if(Z)for(let $ of[...Z])$(X,Y);return this}addComponents(j,J){let X=typeof j==="number"?this.entities.get(j):j;if(!X){let Y=typeof j==="number"?j:j.id;throw Error(`Cannot add components: Entity with ID ${Y} does not exist`)}for(let Y in J)this.addComponent(X,Y,J[Y]);return this}removeComponent(j,J){let X=typeof j==="number"?this.entities.get(j):j;if(!X){let $=typeof j==="number"?j:j.id;throw Error(`Cannot remove component '${String(J)}': Entity with ID ${$} does not exist`)}let Y=X.components[J];delete X.components[J];let Z=this.removedCallbacks.get(J);if(Z&&Y!==void 0)for(let $ of[...Z])$(Y,X);return this.componentIndices.get(J)?.delete(X.id),this}getComponent(j,J){let X=this.entities.get(j);if(!X)throw Error(`Cannot get component '${String(J)}': Entity with ID ${j} does not exist`);return X.components[J]||null}getEntitiesWithQuery(j=[],J=[],X,Y,Z){let $=X!==void 0&&X.length>0&&Y!==void 0,G=Z!==void 0&&Z.length>0;if(j.length===0){if(J.length===0&&!$&&!G)return Array.from(this.entities.values());return Array.from(this.entities.values()).filter((_)=>{if(J.length>0&&!J.every((W)=>!(W in _.components)))return!1;if($){let W=this.changeSeqs.get(_.id);if(!W)return!1;if(!X.some((L)=>(W.get(L)??-1)>Y))return!1}if(G&&!this.parentHasComponents(_.id,Z))return!1;return!0})}let Q=j.reduce((_,W)=>{let L=this.componentIndices.get(W)?.size??0,D=this.componentIndices.get(_)?.size??1/0;return L<D?W:_},j[0]),F=this.componentIndices.get(Q);if(!F||F.size===0)return[];let U=[],V=J.length>0;for(let _ of F){let W=this.entities.get(_);if(W&&j.every((L)=>(L in W.components))&&(!V||J.every((L)=>!(L in W.components)))){if($){let L=this.changeSeqs.get(_);if(!L||!X.some((D)=>(L.get(D)??-1)>Y))continue}if(G&&!this.parentHasComponents(_,Z))continue;U.push(W)}}return U}parentHasComponents(j,J){let X=this.hierarchyManager.getParent(j);if(X===null)return!1;let Y=this.entities.get(X);if(!Y)return!1;for(let Z of J)if(!(Z in Y.components))return!1;return!0}removeEntity(j,J){let X=typeof j==="number"?this.entities.get(j):j;if(!X)return!1;if(J?.cascade??!0){let Z=this.hierarchyManager.getDescendants(X.id);for(let $ of[...Z].reverse())this.removeEntityInternal($)}return this.removeEntityInternal(X.id)}removeEntityInternal(j){let J=this.entities.get(j);if(!J)return!1;this.hierarchyManager.removeEntity(j);for(let X of Object.keys(J.components)){let Y=J.components[X];if(Y!==void 0){let Z=this.removedCallbacks.get(X);if(Z)for(let $ of[...Z])$(Y,J)}this.componentIndices.get(X)?.delete(J.id)}return this.changeSeqs.delete(J.id),this.entities.delete(J.id)}getEntity(j){return this.entities.get(j)}onComponentAdded(j,J){if(!this.addedCallbacks.has(j))this.addedCallbacks.set(j,new Set);return this.addedCallbacks.get(j).add(J),()=>{this.addedCallbacks.get(j)?.delete(J)}}onComponentRemoved(j,J){if(!this.removedCallbacks.has(j))this.removedCallbacks.set(j,new Set);return this.removedCallbacks.get(j).add(J),()=>{this.removedCallbacks.get(j)?.delete(J)}}get changeSeq(){return this._changeSeq}markChanged(j,J){let X=++this._changeSeq,Y=this.changeSeqs.get(j);if(!Y)Y=new Map,this.changeSeqs.set(j,Y);Y.set(J,X)}getChangeSeq(j,J){return this.changeSeqs.get(j)?.get(J)??-1}clearChangeSeqs(j){this.changeSeqs.delete(j)}spawnChild(j,J){let X=this.createEntity();return this.addComponents(X,J),this.setParent(X.id,j),X}setParent(j,J){return this.hierarchyManager.setParent(j,J),this}removeParent(j){return this.hierarchyManager.removeParent(j)}getParent(j){return this.hierarchyManager.getParent(j)}getChildren(j){return this.hierarchyManager.getChildren(j)}getChildAt(j,J){return this.hierarchyManager.getChildAt(j,J)}getChildIndex(j,J){return this.hierarchyManager.getChildIndex(j,J)}getAncestors(j){return this.hierarchyManager.getAncestors(j)}getDescendants(j){return this.hierarchyManager.getDescendants(j)}getRoot(j){return this.hierarchyManager.getRoot(j)}getSiblings(j){return this.hierarchyManager.getSiblings(j)}isDescendantOf(j,J){return this.hierarchyManager.isDescendantOf(j,J)}isAncestorOf(j,J){return this.hierarchyManager.isAncestorOf(j,J)}getRootEntities(){return this.hierarchyManager.getRootEntities()}forEachInHierarchy(j,J){this.hierarchyManager.forEachInHierarchy(j,J)}hierarchyIterator(j){return this.hierarchyManager.hierarchyIterator(j)}}class H{handlers=new Map;subscribe(j,J){return this.addHandler(j,J,!1)}once(j,J){return this.addHandler(j,J,!0)}unsubscribe(j,J){let X=this.handlers.get(j);if(!X)return!1;let Y=X.findIndex((Z)=>Z.callback===J);if(Y===-1)return!1;return X.splice(Y,1),!0}addHandler(j,J,X){if(!this.handlers.has(j))this.handlers.set(j,[]);let Y={callback:J,once:X};return this.handlers.get(j).push(Y),()=>{let Z=this.handlers.get(j);if(Z){let $=Z.indexOf(Y);if($!==-1)Z.splice($,1)}}}publish(j,J){let X=this.handlers.get(j);if(!X)return;let Y=[...X],Z=[];for(let $ of Y)if($.callback(J),$.once)Z.push($);if(Z.length>0)for(let $ of Z){let G=X.indexOf($);if(G!==-1)X.splice(G,1)}}clear(){this.handlers.clear()}clearEvent(j){this.handlers.delete(j)}}function I(j){return typeof j==="object"&&j!==null&&"factory"in j&&typeof j.factory==="function"}function v(j,J){let X=[],Y=new Set,Z=new Set;function $(G,Q=[]){if(Y.has(G))return;if(Z.has(G))throw Error(`Circular resource dependency: ${[...Q,G].join(" -> ")}`);Z.add(G);for(let F of J(G))if(j.includes(F))$(F,[...Q,G]);Z.delete(G),Y.add(G),X.push(G)}for(let G of j)$(G);return X}class P{resources=new Map;resourceFactories=new Map;resourceDependencies=new Map;resourceDisposers=new Map;initializedResourceKeys=new Set;add(j,J){if(I(J)){if(this.resourceFactories.set(j,J.factory),this.resourceDependencies.set(j,J.dependsOn??[]),J.onDispose)this.resourceDisposers.set(j,J.onDispose)}else if(this._isFactoryFunction(J))this.resourceFactories.set(j,J),this.resourceDependencies.set(j,[]);else this.resources.set(j,J),this.initializedResourceKeys.add(j),this.resourceDependencies.set(j,[]);return this}_isFactoryFunction(j){if(typeof j!=="function")return!1;let J=j.toString();if(J.startsWith("class "))return!1;if(J.includes("[native code]"))return!1;if(j.prototype){let X=Object.getOwnPropertyNames(j.prototype);if(X.length>1||X.length===1&&X[0]!=="constructor")return!1}if(j.name&&j.name[0]===j.name[0].toUpperCase()&&j.name.length>1){if(J.includes("this.")||J.includes("new "))return!1}return!0}get(j,J){let X=this.resources.get(j);if(X!==void 0)return X;let Y=this.resourceFactories.get(j);if(Y===void 0)throw Error(`Resource ${String(j)} not found`);let Z=Y(J);if(!(Z instanceof Promise))this.resources.set(j,Z),this.initializedResourceKeys.add(j);return Z}has(j){return this.resources.has(j)||this.resourceFactories.has(j)}remove(j){let J=this.resources.delete(j),X=this.resourceFactories.delete(j);return this.resourceDependencies.delete(j),this.resourceDisposers.delete(j),this.initializedResourceKeys.delete(j),J||X}getKeys(){let j=new Set([...this.resources.keys(),...this.resourceFactories.keys()]);return Array.from(j)}needsInitialization(j){return this.resourceFactories.has(j)&&!this.initializedResourceKeys.has(j)}getPendingInitializationKeys(){return Array.from(this.resourceFactories.keys()).filter((j)=>!this.initializedResourceKeys.has(j))}async initializeResource(j,J){if(!this.resourceFactories.has(j)||this.initializedResourceKeys.has(j))return;let Y=await this.resourceFactories.get(j)(J);this.resources.set(j,Y),this.initializedResourceKeys.add(j),this.resourceFactories.delete(j)}async initializeResources(j,...J){let X=J.length===0?this.getPendingInitializationKeys():J.map((Z)=>Z);if(X.length===0)return;let Y=v(X,(Z)=>this.resourceDependencies.get(Z)??[]);for(let Z of Y)await this.initializeResource(Z,j)}getDependencies(j){return this.resourceDependencies.get(j)??[]}async disposeResource(j,J){let X=j;if(!this.resources.has(X)&&!this.resourceFactories.has(X))return!1;if(this.initializedResourceKeys.has(X)){let Y=this.resourceDisposers.get(X),Z=this.resources.get(X);if(Y&&Z!==void 0)await Y(Z,J)}return this.resources.delete(X),this.resourceFactories.delete(X),this.resourceDependencies.delete(X),this.resourceDisposers.delete(X),this.initializedResourceKeys.delete(X),!0}async disposeResources(j){let J=Array.from(this.initializedResourceKeys);if(J.length===0)return;let X=v(J,(Y)=>this.resourceDependencies.get(Y)??[]).reverse();for(let Y of X)await this.disposeResource(Y,j)}}class E{assets=new Map;groups=new Map;eventBus=null;setEventBus(j){this.eventBus=j}register(j,J){if(this.assets.set(j,{definition:J,status:"pending"}),J.group){let X=this.groups.get(J.group)??new Set;X.add(j),this.groups.set(J.group,X)}}async loadEagerAssets(){let j=[];for(let[J,X]of this.assets)if(X.definition.eager&&X.status==="pending")j.push(J);await Promise.all(j.map((J)=>this.loadAsset(J)))}async loadAsset(j){let J=j,X=this.assets.get(J);if(!X)throw Error(`Asset '${J}' not found`);if(X.status==="loaded"&&X.value!==void 0)return X.value;if(X.status==="loading"&&X.loadPromise)return X.loadPromise;if(X.status==="failed")X.status="pending";X.status="loading",X.loadPromise=X.definition.loader();try{let Y=await X.loadPromise;return X.value=Y,X.status="loaded",X.loadPromise=void 0,this.eventBus?.publish("assetLoaded",{key:J}),this.checkGroupProgress(X.definition.group),Y}catch(Y){let Z=Y instanceof Error?Y:Error(String(Y));throw X.status="failed",X.error=Z,X.loadPromise=void 0,this.eventBus?.publish("assetFailed",{key:J,error:Z}),Z}}async loadAssetGroup(j){let J=this.groups.get(j);if(!J||J.size===0)throw Error(`Asset group '${j}' not found or empty`);await Promise.all(Array.from(J).map((X)=>this.loadAsset(X)))}get(j){let J=j,X=this.assets.get(J);if(!X)throw Error(`Asset '${J}' not found`);if(X.status!=="loaded"||X.value===void 0)throw Error(`Asset '${J}' is not loaded (status: ${X.status})`);return X.value}getOrUndefined(j){let J=j,X=this.assets.get(J);if(!X||X.status!=="loaded")return;return X.value}getHandle(j){let J=j,X=this.assets.get(J);if(!X)throw Error(`Asset '${J}' not found`);let Y=this;return{get status(){return X.status},get isLoaded(){return X.status==="loaded"},get(){return Y.get(j)},getOrUndefined(){return Y.getOrUndefined(j)}}}getStatus(j){let J=j,X=this.assets.get(J);if(!X)throw Error(`Asset '${J}' not found`);return X.status}isLoaded(j){let J=j;return this.assets.get(J)?.status==="loaded"}isGroupLoaded(j){let J=this.groups.get(j);if(!J||J.size===0)return!1;for(let X of J){let Y=this.assets.get(X);if(!Y||Y.status!=="loaded")return!1}return!0}getGroupProgress(j){let J=this.groups.get(j);if(!J||J.size===0)return 0;let X=0;for(let Y of J)if(this.assets.get(Y)?.status==="loaded")X++;return X/J.size}getGroupProgressDetails(j){let J=this.groups.get(j);if(!J||J.size===0)return{loaded:0,total:0,progress:0};let X=0;for(let Z of J)if(this.assets.get(Z)?.status==="loaded")X++;let Y=J.size;return{loaded:X,total:Y,progress:X/Y}}checkGroupProgress(j){if(!j||!this.eventBus)return;let J=this.getGroupProgressDetails(j);if(this.eventBus.publish("assetGroupProgress",{group:j,...J}),J.loaded===J.total)this.eventBus.publish("assetGroupLoaded",{group:j})}createResource(){let j=this;return{getStatus(J){return j.getStatus(J)},isLoaded(J){return j.isLoaded(J)},isGroupLoaded(J){return j.isGroupLoaded(J)},getGroupProgress(J){return j.getGroupProgress(J)},get(J){return j.get(J)},getOrUndefined(J){return j.getOrUndefined(J)},getHandle(J){return j.getHandle(J)}}}getKeys(){return Array.from(this.assets.keys())}getGroupNames(){return Array.from(this.groups.keys())}getGroupKeys(j){let J=this.groups.get(j);return J?Array.from(J):[]}}class O{manager;constructor(j){this.manager=j}add(j,J){return this.manager.register(j,{loader:J,eager:!0}),this}addWithConfig(j,J){return this.manager.register(j,J),this}addGroup(j,J){for(let[X,Y]of Object.entries(J))this.manager.register(X,{loader:Y,eager:!1,group:j});return this}getManager(){return this.manager}}function T(j){return new O(j??new E)}class R{screens=new Map;currentScreen=null;screenStack=[];eventBus=null;assetManager=null;ecs=null;setDependencies(j,J,X){this.eventBus=j,this.assetManager=J,this.ecs=X}register(j,J){this.screens.set(j,{definition:J})}async setScreen(j,J){let X=j,Y=this.screens.get(X);if(!Y)throw Error(`Screen '${X}' not found`);await this.verifyRequiredAssets(Y.definition);while(this.screenStack.length>0){let $=this.screenStack.pop();if($)await this.exitScreen($.name)}if(this.currentScreen)await this.exitScreen(this.currentScreen.name);let Z=Y.definition.initialState(J);this.currentScreen={name:j,config:J,state:Z},await Y.definition.onEnter?.(J,this.ecs),this.eventBus?.publish("screenEnter",{screen:X,config:J})}async pushScreen(j,J){let X=j,Y=this.screens.get(X);if(!Y)throw Error(`Screen '${X}' not found`);if(await this.verifyRequiredAssets(Y.definition),this.currentScreen)this.screenStack.push(this.currentScreen);let Z=Y.definition.initialState(J);this.currentScreen={name:j,config:J,state:Z},await Y.definition.onEnter?.(J,this.ecs),this.eventBus?.publish("screenPush",{screen:X,config:J})}async popScreen(){if(this.screenStack.length===0)throw Error("Cannot pop screen: stack is empty");if(this.currentScreen){let j=this.currentScreen.name;await this.exitScreen(j),this.eventBus?.publish("screenPop",{screen:j})}this.currentScreen=this.screenStack.pop()??null}async exitScreen(j){let J=this.screens.get(j);if(J?.definition.onExit)await J.definition.onExit(this.ecs);this.eventBus?.publish("screenExit",{screen:j})}async verifyRequiredAssets(j){if(!this.assetManager)return;if(j.requiredAssets){for(let J of j.requiredAssets)if(!this.assetManager.isLoaded(J))await this.assetManager.loadAsset(J)}if(j.requiredAssetGroups){for(let J of j.requiredAssetGroups)if(!this.assetManager.isGroupLoaded(J))await this.assetManager.loadAssetGroup(J)}}getCurrentScreen(){return this.currentScreen?.name??null}getConfig(){if(!this.currentScreen)throw Error("No current screen");return this.currentScreen.config}getConfigOrNull(){return this.currentScreen?.config??null}getState(){if(!this.currentScreen)throw Error("No current screen");return this.currentScreen.state}getStateOrNull(){return this.currentScreen?.state??null}updateState(j){if(!this.currentScreen)throw Error("No current screen");let J=typeof j==="function"?j(this.currentScreen.state):j;this.currentScreen.state={...this.currentScreen.state,...J}}getStackDepth(){return this.screenStack.length}isOverlay(){return this.screenStack.length>0}isActive(j){if(this.currentScreen?.name===j)return!0;return this.screenStack.some((J)=>J.name===j)}isCurrent(j){return this.currentScreen?.name===j}createResource(){let j=this;return{get current(){return j.getCurrentScreen()},get config(){return j.getConfigOrNull()},get state(){return j.getStateOrNull()},set state(J){if(j.currentScreen)j.currentScreen.state=J},get stack(){return j.screenStack},get isOverlay(){return j.isOverlay()},get stackDepth(){return j.getStackDepth()},isActive(J){return j.isActive(J)},isCurrent(J){return j.isCurrent(J)}}}getScreenNames(){return Array.from(this.screens.keys())}hasScreen(j){return this.screens.has(j)}}class S{manager;constructor(j){this.manager=j}add(j,J){return this.manager.register(j,J),this}getManager(){return this.manager}}function q(j){return new S(j??new R)}class x{queries=new Map;entityManager;_hasParentHasQueries=!1;constructor(j){this.entityManager=j}get hasParentHasQueries(){return this._hasParentHasQueries}addQuery(j,J){let X={definition:J,matchingEntities:new Set};if(this.queries.set(j,X),J.parentHas?.length)this._hasParentHasQueries=!0;let Y=this.entityManager.getEntitiesWithQuery(J.with,J.without??[]);for(let Z of Y)if(this.entityMatchesQuery(Z,X.definition))X.matchingEntities.add(Z.id),X.definition.onEnter?.(Z)}removeQuery(j){let J=this.queries.delete(j);if(J)this._recalcParentHasFlag();return J}entityMatchesQuery(j,J){for(let X of J.with)if(!(X in j.components))return!1;if(J.without){for(let X of J.without)if(X in j.components)return!1}if(J.parentHas?.length){let X=this.entityManager.getParent(j.id);if(X===null)return!1;let Y=this.entityManager.getEntity(X);if(!Y)return!1;for(let Z of J.parentHas)if(!(Z in Y.components))return!1}return!0}onComponentAdded(j,J){for(let[X,Y]of this.queries){let Z=Y.matchingEntities.has(j.id),$=this.entityMatchesQuery(j,Y.definition);if(!Z&&$)Y.matchingEntities.add(j.id),Y.definition.onEnter?.(j);else if(Z&&!$)Y.matchingEntities.delete(j.id),Y.definition.onExit?.(j.id)}if(this._hasParentHasQueries)this._recheckChildren(j.id)}onComponentRemoved(j,J){for(let[X,Y]of this.queries){let Z=Y.matchingEntities.has(j.id),$=this.entityMatchesQuery(j,Y.definition);if(Z&&!$)Y.matchingEntities.delete(j.id),Y.definition.onExit?.(j.id);else if(!Z&&$)Y.matchingEntities.add(j.id),Y.definition.onEnter?.(j)}if(this._hasParentHasQueries)this._recheckChildren(j.id)}onEntityRemoved(j){for(let[J,X]of this.queries)if(X.matchingEntities.has(j))X.matchingEntities.delete(j),X.definition.onExit?.(j)}recheckEntity(j){for(let[J,X]of this.queries){let Y=X.matchingEntities.has(j.id),Z=this.entityMatchesQuery(j,X.definition);if(!Y&&Z)X.matchingEntities.add(j.id),X.definition.onEnter?.(j);else if(Y&&!Z)X.matchingEntities.delete(j.id),X.definition.onExit?.(j.id)}}_recheckChildren(j){let J=this.entityManager.getChildren(j);for(let X of J){let Y=this.entityManager.getEntity(X);if(Y)this.recheckEntity(Y)}}_recalcParentHasFlag(){this._hasParentHasQueries=!1;for(let[,j]of this.queries)if(j.definition.parentHas?.length){this._hasParentHasQueries=!0;return}}}class M{commands=[];removeEntity(j,J){this.commands.push((X)=>{X.removeEntity(j,J)})}addComponent(j,J,X){this.commands.push((Y)=>{Y.entityManager.addComponent(j,J,X)})}removeComponent(j,J){this.commands.push((X)=>{X.entityManager.removeComponent(j,J)})}spawn(j){this.commands.push((J)=>{J.spawn(j)})}spawnChild(j,J){this.commands.push((X)=>{X.spawnChild(j,J)})}addComponents(j,J){this.commands.push((X)=>{X.entityManager.addComponents(j,J)})}setParent(j,J){this.commands.push((X)=>{X.setParent(j,J)})}markChanged(j,J){this.commands.push((X)=>{X.markChanged(j,J)})}removeParent(j){this.commands.push((J)=>{J.removeParent(j)})}playback(j){for(let J of this.commands)try{J(j)}catch(X){console.warn("CommandBuffer: Command failed during playback:",X)}this.commands=[]}clear(){this.commands=[]}get length(){return this.commands.length}}class w{_label;_ecspresso;_bundle;queries={};processFunction;detachFunction;initializeFunction;eventHandlers;_priority=0;_phase="update";_isRegistered=!1;_groups=[];_inScreens;_excludeScreens;_requiredAssets;constructor(j,J=null,X=null){this._label=j;this._ecspresso=J;this._bundle=X}get label(){return this._label}get bundle(){return this._bundle}get ecspresso(){return this._ecspresso}_autoRegister(){if(this._isRegistered||!this._ecspresso)return;let j=this._buildSystemObject();C(j,this._ecspresso),this._isRegistered=!0}_buildSystemObject(){return this._createSystemObject()}_createSystemObject(){let j={label:this._label,entityQueries:this.queries,priority:this._priority,phase:this._phase};if(this.processFunction)j.process=this.processFunction;if(this.detachFunction)j.onDetach=this.detachFunction;if(this.initializeFunction)j.onInitialize=this.initializeFunction;if(this.eventHandlers)j.eventHandlers=this.eventHandlers;if(this._groups.length>0)j.groups=[...this._groups];if(this._inScreens)j.inScreens=this._inScreens;if(this._excludeScreens)j.excludeScreens=this._excludeScreens;if(this._requiredAssets)j.requiredAssets=this._requiredAssets;return j}setPriority(j){return this._priority=j,this}inPhase(j){return this._phase=j,this}inGroup(j){if(!this._groups.includes(j))this._groups.push(j);return this}inScreens(j){return this._inScreens=[...j],this}excludeScreens(j){return this._excludeScreens=[...j],this}requiresAssets(j){return this._requiredAssets=[...j],this}addQuery(j,J){let X=this;return X.queries={...this.queries,[j]:J},X}setProcess(j){return this.processFunction=j,this}registerAndContinue(){if(!this._ecspresso)throw Error(`Cannot register system '${this._label}': SystemBuilder is not attached to an ECSpresso instance. Use Bundle.addSystem() or ECSpresso.addSystem() instead.`);return this._autoRegister(),this._ecspresso}and(){if(this._ecspresso)return this._autoRegister(),this._ecspresso;if(this._bundle)return this._bundle;throw Error(`Cannot use and() on system '${this._label}': not attached to ECSpresso or Bundle.`)}setOnDetach(j){return this.detachFunction=j,this}setOnInitialize(j){return this.initializeFunction=j,this}setEventHandlers(j){return this.eventHandlers=j,this}build(j){let J=this._createSystemObject();if(this._ecspresso)C(J,this._ecspresso);if(j)C(J,j);return this}}function C(j,J){J._registerSystem(j)}function f(j,J){return new w(j,J)}function b(j,J){return new w(j,null,J)}var N="0.10.2";var k=["preUpdate","fixedUpdate","update","postUpdate","render"],p={};class K{static VERSION=N;_entityManager;_eventBus;_resourceManager;_commandBuffer;_systems=[];_phaseSystems={preUpdate:[],fixedUpdate:[],update:[],postUpdate:[],render:[]};_installedBundles=new Set;_disabledGroups=new Set;_assetManager=null;_screenManager=null;_reactiveQueryManager;_postUpdateHooks=[];_currentTick=0;_systemLastSeqs=new Map;_changeThreshold=0;_fixedDt=0.016666666666666666;_fixedAccumulator=0;_interpolationAlpha=0;_maxFixedSteps=8;constructor(){this._entityManager=new A,this._eventBus=new H,this._resourceManager=new P,this._reactiveQueryManager=new x(this._entityManager),this._commandBuffer=new M,this._setupReactiveQueryHooks()}_setupReactiveQueryHooks(){let j=0,J=new Set,X=()=>{for(let U of J){let V=this._entityManager.getEntity(U);if(V)this._reactiveQueryManager.recheckEntity(V)}J.clear()},Y=this._entityManager.addComponent.bind(this._entityManager);this._entityManager.addComponent=(U,V,_)=>{let W=Y(U,V,_),L=typeof U==="number"?U:U.id;if(this._entityManager.markChanged(L,V),j>0)J.add(L);else{let D=this._entityManager.getEntity(L);if(D)this._reactiveQueryManager.onComponentAdded(D,V)}return W};let Z=this._entityManager.addComponents.bind(this._entityManager);this._entityManager.addComponents=(U,V)=>{j++;let _=Z(U,V);if(j--,j===0)X();return _};let $=this._entityManager.removeComponent.bind(this._entityManager);this._entityManager.removeComponent=(U,V)=>{let _=typeof U==="number"?U:U.id,W=this._entityManager.getEntity(_),L=$(U,V);if(W)this._reactiveQueryManager.onComponentRemoved(W,V);return L};let G=this._entityManager.setParent.bind(this._entityManager);this._entityManager.setParent=(U,V)=>{let _=G(U,V);if(this._reactiveQueryManager.hasParentHasQueries){let W=this._entityManager.getEntity(U);if(W)this._reactiveQueryManager.recheckEntity(W)}return _};let Q=this._entityManager.removeParent.bind(this._entityManager);this._entityManager.removeParent=(U)=>{let V=Q(U);if(this._reactiveQueryManager.hasParentHasQueries){let _=this._entityManager.getEntity(U);if(_)this._reactiveQueryManager.recheckEntity(_)}return V};let F=this._entityManager.removeEntity.bind(this._entityManager);this._entityManager.removeEntity=(U,V)=>{let _=typeof U==="number"?U:U.id;if(this._entityManager.getEntity(_)){if(V?.cascade??!0){let D=this._entityManager.getDescendants(_);for(let h of D)this._reactiveQueryManager.onEntityRemoved(h)}this._reactiveQueryManager.onEntityRemoved(_)}return F(U,V)}}static create(){return new g}addSystem(j){return f(j,this)}update(j){let J=this._screenManager?.getCurrentScreen()??null;this._executePhase(this._phaseSystems.preUpdate,j,J),this._commandBuffer.playback(this),this._fixedAccumulator+=j;let X=0;while(this._fixedAccumulator>=this._fixedDt&&X<this._maxFixedSteps)this._executePhase(this._phaseSystems.fixedUpdate,this._fixedDt,J),this._commandBuffer.playback(this),this._fixedAccumulator-=this._fixedDt,X++;if(this._fixedAccumulator>=this._fixedDt)this._fixedAccumulator=0;this._interpolationAlpha=this._fixedAccumulator/this._fixedDt,this._executePhase(this._phaseSystems.update,j,J),this._commandBuffer.playback(this),this._executePhase(this._phaseSystems.postUpdate,j,J),this._commandBuffer.playback(this);for(let Y of this._postUpdateHooks)Y(this,j);this._executePhase(this._phaseSystems.render,j,J),this._commandBuffer.playback(this),this._changeThreshold=this._entityManager.changeSeq,this._currentTick++}_executePhase(j,J,X){for(let Y of j){if(!Y.process)continue;if(Y.groups?.length){let F=!1;for(let U of Y.groups)if(this._disabledGroups.has(U)){F=!0;break}if(F)continue}if(Y.inScreens?.length){if(X===null||!Y.inScreens.includes(X))continue}if(Y.excludeScreens?.length){if(X!==null&&Y.excludeScreens.includes(X))continue}if(Y.requiredAssets?.length&&this._assetManager){let F=!0;for(let U of Y.requiredAssets)if(!this._assetManager.isLoaded(U)){F=!1;break}if(!F)continue}let Z=this._systemLastSeqs.get(Y)??0;this._changeThreshold=Z;let $={},G=!1,Q=!1;if(Y.entityQueries)for(let F in Y.entityQueries){Q=!0;let U=Y.entityQueries[F];if(U){if($[F]=this._entityManager.getEntitiesWithQuery(U.with,U.without||[],U.changed,U.changed?this._changeThreshold:void 0,U.parentHas),$[F].length)G=!0}}if(G)Y.process($,J,this);else if(!Q)Y.process(p,J,this);this._systemLastSeqs.set(Y,this._entityManager.changeSeq)}}async initialize(){if(await this.initializeResources(),this._assetManager)this._assetManager.setEventBus(this._eventBus),await this._assetManager.loadEagerAssets(),this._resourceManager.add("$assets",this._assetManager.createResource());if(this._screenManager)this._screenManager.setDependencies(this._eventBus,this._assetManager,this),this._resourceManager.add("$screen",this._screenManager.createResource());for(let j of this._systems)await j.onInitialize?.(this)}async initializeResources(...j){await this._resourceManager.initializeResources(this,...j)}_rebuildPhaseSystems(){for(let j of k)this._phaseSystems[j]=[];for(let j of this._systems){let J=j.phase??"update";this._phaseSystems[J].push(j)}for(let j of k)this._phaseSystems[j].sort((J,X)=>{let Y=J.priority??0;return(X.priority??0)-Y})}updateSystemPriority(j,J){let X=this._systems.find((Y)=>Y.label===j);if(!X)return!1;return X.priority=J,this._rebuildPhaseSystems(),!0}updateSystemPhase(j,J){let X=this._systems.find((Y)=>Y.label===j);if(!X)return!1;return X.phase=J,this._rebuildPhaseSystems(),!0}get interpolationAlpha(){return this._interpolationAlpha}get fixedDt(){return this._fixedDt}disableSystemGroup(j){this._disabledGroups.add(j)}enableSystemGroup(j){this._disabledGroups.delete(j)}isSystemGroupEnabled(j){return!this._disabledGroups.has(j)}getSystemsInGroup(j){return this._systems.filter((J)=>J.groups?.includes(j)).map((J)=>J.label)}removeSystem(j){let J=this._systems.findIndex((Y)=>Y.label===j);if(J===-1)return!1;let X=this._systems[J];if(!X)return!1;if(X.onDetach)X.onDetach(this);return this._systems.splice(J,1),this._systemLastSeqs.delete(X),this._rebuildPhaseSystems(),!0}_registerSystem(j){if(this._systems.push(j),this._systemLastSeqs.set(j,this._changeThreshold),this._rebuildPhaseSystems(),!j.eventHandlers)return;for(let J in j.eventHandlers){let X=j.eventHandlers[J]?.handler;if(X)this._eventBus.subscribe(J,(Y)=>{X(Y,this)})}}hasResource(j){return this._resourceManager.has(j)}getResource(j){let J=this._resourceManager.get(j,this);if(!J)throw Error(`Resource '${String(j)}' not found. Available resources: [${this.getResourceKeys().map((X)=>String(X)).join(", ")}]`);return J}addResource(j,J){return this._resourceManager.add(j,J),this}removeResource(j){return this._resourceManager.remove(j)}async disposeResource(j){return this._resourceManager.disposeResource(j,this)}async disposeResources(){return this._resourceManager.disposeResources(this)}updateResource(j,J){let X=this.getResource(j),Y=J(X);return this._resourceManager.add(j,Y),this}getResourceKeys(){return this._resourceManager.getKeys()}resourceNeedsInitialization(j){return this._resourceManager.needsInitialization(j)}hasComponent(j,J){return this._entityManager.getComponent(j,J)!==null}spawn(j){let J=this._entityManager.createEntity();return this._entityManager.addComponents(J,j),J}getEntitiesWithQuery(j,J=[],X,Y){return this._entityManager.getEntitiesWithQuery(j,J,X,X?this._changeThreshold:void 0,Y)}getSingleton(j,J=[]){let X=this._entityManager.getEntitiesWithQuery(j,J);if(X.length===0)throw Error(`getSingleton: no entity matches query with=[${String(j)}] without=[${String(J)}]`);if(X.length>1)throw Error(`getSingleton: expected 1 entity but found ${X.length} matching query with=[${String(j)}] without=[${String(J)}]`);return X[0]}tryGetSingleton(j,J=[]){let X=this._entityManager.getEntitiesWithQuery(j,J);if(X.length===0)return;if(X.length>1)throw Error(`tryGetSingleton: expected 0 or 1 entity but found ${X.length} matching query with=[${String(j)}] without=[${String(J)}]`);return X[0]}removeEntity(j,J){return this._entityManager.removeEntity(j,J)}spawnChild(j,J){let X=this._entityManager.spawnChild(j,J);return this._emitHierarchyChanged(X.id,null,j),X}setParent(j,J){let X=this._entityManager.getParent(j);return this._entityManager.setParent(j,J),this._emitHierarchyChanged(j,X,J),this}removeParent(j){let J=this._entityManager.getParent(j),X=this._entityManager.removeParent(j);if(X)this._emitHierarchyChanged(j,J,null);return X}getParent(j){return this._entityManager.getParent(j)}getChildren(j){return this._entityManager.getChildren(j)}getChildAt(j,J){return this._entityManager.getChildAt(j,J)}getChildIndex(j,J){return this._entityManager.getChildIndex(j,J)}getAncestors(j){return this._entityManager.getAncestors(j)}getDescendants(j){return this._entityManager.getDescendants(j)}getRoot(j){return this._entityManager.getRoot(j)}getSiblings(j){return this._entityManager.getSiblings(j)}isDescendantOf(j,J){return this._entityManager.isDescendantOf(j,J)}isAncestorOf(j,J){return this._entityManager.isAncestorOf(j,J)}getRootEntities(){return this._entityManager.getRootEntities()}forEachInHierarchy(j,J){this._entityManager.forEachInHierarchy(j,J)}hierarchyIterator(j){return this._entityManager.hierarchyIterator(j)}_emitHierarchyChanged(j,J,X){this._eventBus.publish("hierarchyChanged",{entityId:j,oldParent:J,newParent:X})}get installedBundles(){return Array.from(this._installedBundles)}get entityManager(){return this._entityManager}get eventBus(){return this._eventBus}get commands(){return this._commandBuffer}get currentTick(){return this._currentTick}get changeThreshold(){return this._changeThreshold}markChanged(j,J){this._entityManager.markChanged(j,J)}onComponentAdded(j,J){return this._entityManager.onComponentAdded(j,J)}onComponentRemoved(j,J){return this._entityManager.onComponentRemoved(j,J)}addReactiveQuery(j,J){this._reactiveQueryManager.addQuery(j,J)}removeReactiveQuery(j){return this._reactiveQueryManager.removeQuery(j)}on(j,J){return this._eventBus.subscribe(j,J)}off(j,J){return this._eventBus.unsubscribe(j,J)}onPostUpdate(j){return this._postUpdateHooks.push(j),()=>{let J=this._postUpdateHooks.indexOf(j);if(J!==-1)this._postUpdateHooks.splice(J,1)}}getAsset(j){if(!this._assetManager)throw Error("Asset manager not configured. Use withAssets() in builder.");return this._assetManager.get(j)}getAssetOrUndefined(j){return this._assetManager?.getOrUndefined(j)}getAssetHandle(j){if(!this._assetManager)throw Error("Asset manager not configured. Use withAssets() in builder.");return this._assetManager.getHandle(j)}isAssetLoaded(j){return this._assetManager?.isLoaded(j)??!1}async loadAsset(j){if(!this._assetManager)throw Error("Asset manager not configured. Use withAssets() in builder.");return this._assetManager.loadAsset(j)}async loadAssetGroup(j){if(!this._assetManager)throw Error("Asset manager not configured. Use withAssets() in builder.");return this._assetManager.loadAssetGroup(j)}isAssetGroupLoaded(j){return this._assetManager?.isGroupLoaded(j)??!1}getAssetGroupProgress(j){return this._assetManager?.getGroupProgress(j)??0}async setScreen(j,J){if(!this._screenManager)throw Error("Screen manager not configured. Use withScreens() in builder.");return this._screenManager.setScreen(j,J)}async pushScreen(j,J){if(!this._screenManager)throw Error("Screen manager not configured. Use withScreens() in builder.");return this._screenManager.pushScreen(j,J)}async popScreen(){if(!this._screenManager)throw Error("Screen manager not configured. Use withScreens() in builder.");return this._screenManager.popScreen()}getCurrentScreen(){return this._screenManager?.getCurrentScreen()??null}getScreenConfig(){if(!this._screenManager)throw Error("Screen manager not configured. Use withScreens() in builder.");return this._screenManager.getConfig()}getScreenConfigOrNull(){return this._screenManager?.getConfigOrNull()??null}getScreenState(){if(!this._screenManager)throw Error("Screen manager not configured. Use withScreens() in builder.");return this._screenManager.getState()}getScreenStateOrNull(){return this._screenManager?.getStateOrNull()??null}updateScreenState(j){if(!this._screenManager)throw Error("Screen manager not configured. Use withScreens() in builder.");this._screenManager.updateState(j)}isCurrentScreen(j){return this._screenManager?.isCurrent(j)??!1}isScreenActive(j){return this._screenManager?.isActive(j)??!1}getScreenStackDepth(){return this._screenManager?.getStackDepth()??0}_setAssetManager(j){this._assetManager=j}_setScreenManager(j){this._screenManager=j}_setFixedDt(j){this._fixedDt=j}_installBundle(j){if(this._installedBundles.has(j.id))return this;this._installedBundles.add(j.id),j.registerSystemsWithEcspresso(this);let J=j.getResources();for(let[X,Y]of J.entries())this._resourceManager.add(X,Y);if(this._assetManager){let X=j.getAssets();for(let[Y,Z]of X.entries())this._assetManager.register(Y,Z)}if(this._screenManager){let X=j.getScreens();for(let[Y,Z]of X.entries())this._screenManager.register(Y,Z)}return this}}class g{ecspresso;assetConfigurator=null;screenConfigurator=null;pendingResources=[];_fixedDt=null;constructor(){this.ecspresso=new K}withBundle(j){return this.ecspresso._installBundle(j),this}withResource(j,J){return this.pendingResources.push({key:j,value:J}),this}withAssets(j){let J=T();return j(J),this.assetConfigurator=J,this}withScreens(j){let J=q();return j(J),this.screenConfigurator=J,this}withFixedTimestep(j){return this._fixedDt=j,this}build(){for(let{key:j,value:J}of this.pendingResources)this.ecspresso.addResource(j,J);if(this.assetConfigurator)this.ecspresso._setAssetManager(this.assetConfigurator.getManager());if(this.screenConfigurator)this.ecspresso._setScreenManager(this.screenConfigurator.getManager());if(this._fixedDt!==null)this.ecspresso._setFixedDt(this._fixedDt);return this.ecspresso}}function m(){return`bundle_${Date.now().toString(36)}_${Math.random().toString(36).substring(2,9)}`}class B{_systems=[];_resources=new Map;_assets=new Map;_assetGroups=new Map;_screens=new Map;_id;constructor(j){this._id=j||m()}get id(){return this._id}set id(j){this._id=j}addSystem(j){if(typeof j==="string"){let J=b(j,this);return this._systems.push(J),J}else return this._systems.push(j),j}addResource(j,J){return this._resources.set(j,J),this}addAsset(j,J,X){return this._assets.set(j,{loader:J,eager:X?.eager??!0,group:X?.group}),this}addAssetGroup(j,J){let X=new Map;for(let[Y,Z]of Object.entries(J))X.set(Y,Z),this._assets.set(Y,{loader:Z,eager:!1,group:j});return this._assetGroups.set(j,X),this}addScreen(j,J){return this._screens.set(j,J),this}getAssets(){return new Map(this._assets)}getScreens(){return new Map(this._screens)}_setResource(j,J){this._resources.set(j,J)}_setAsset(j,J){this._assets.set(j,J)}_setScreen(j,J){this._screens.set(j,J)}getSystems(){return this._systems.map((j)=>j.build())}registerSystemsWithEcspresso(j){for(let J of this._systems)J.build(j)}getResources(){return new Map(this._resources)}getResource(j){return this._resources.get(j)}getSystemBuilders(){return[...this._systems]}hasResource(j){return this._resources.has(j)}}function l(j,...J){if(J.length===0)return new B(j);let X=new B(j);for(let Y of J){for(let Z of Y.getSystemBuilders())X.addSystem(Z);for(let[Z,$]of Y.getResources().entries())X._setResource(Z,$);for(let[Z,$]of Y.getAssets().entries())X._setAsset(Z,$);for(let[Z,$]of Y.getScreens().entries())X._setScreen(Z,$)}return X}function Mj(j){return j}var kj=K;export{l as mergeBundles,kj as default,q as createScreenConfigurator,Mj as createQueryDefinition,T as createAssetConfigurator,w as SystemBuilder,R as ScreenManager,P as ResourceManager,z as HierarchyManager,H as EventBus,A as EntityManager,M as CommandBuffer,B as Bundle,E as AssetManager};
|
|
2
|
-
|
|
3
|
-
//# debugId=50CFEDD8E34EDFE064756E2164756E21
|
|
4
|
-
//# sourceMappingURL=index.js.map
|