ecspresso 0.14.9 → 0.15.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.
@@ -45,7 +45,9 @@ export default class CommandBuffer<Cfg extends WorldConfig = EmptyConfig> {
45
45
  */
46
46
  spawn<T extends {
47
47
  [K in keyof Cfg['components']]?: Cfg['components'][K];
48
- }>(components: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>): void;
48
+ }>(components: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>, options?: {
49
+ scope?: keyof Cfg['screens'] & string;
50
+ }): void;
49
51
  /**
50
52
  * Queue a child entity spawn command
51
53
  * @param parentId The parent entity ID
@@ -53,7 +55,9 @@ export default class CommandBuffer<Cfg extends WorldConfig = EmptyConfig> {
53
55
  */
54
56
  spawnChild<T extends {
55
57
  [K in keyof Cfg['components']]?: Cfg['components'][K];
56
- }>(parentId: number, components: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>): void;
58
+ }>(parentId: number, components: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>, options?: {
59
+ scope?: keyof Cfg['screens'] & string;
60
+ }): void;
57
61
  /**
58
62
  * Queue multiple component additions
59
63
  * @param entityId The entity ID
@@ -68,6 +68,14 @@ export default class ECSpresso<Cfg extends WorldConfig = EmptyConfig, Labels ext
68
68
  private _phaseSystems;
69
69
  /** Track installed plugins to prevent duplicates*/
70
70
  private _installedPlugins;
71
+ /** Per-plugin disposers registered via the install function's second arg */
72
+ private _pluginCleanups;
73
+ /** Defaults applied to systems created via addSystem during a plugin's install */
74
+ private _currentSystemDefaults;
75
+ /** Entity IDs scoped to a specific screen — removed on that screen's exit */
76
+ private _screenScopedEntities;
77
+ /** Reverse index: entity ID -> scope screen name, for O(1) cleanup on remove */
78
+ private _entityScreenScope;
71
79
  /** Disabled system groups */
72
80
  private _disabledGroups;
73
81
  /** Asset manager for loading and accessing assets */
@@ -110,6 +118,8 @@ export default class ECSpresso<Cfg extends WorldConfig = EmptyConfig, Labels ext
110
118
  private _entityEnterFrameSet;
111
119
  /** Pre-allocated process context per system (avoids per-frame allocation) */
112
120
  private _systemContexts;
121
+ /** Shared scratch array for singleton query resolution (cleared and reused each resolution) */
122
+ private _singletonScratch;
113
123
  /** Pending system builder finalizers to run before next update/initialize */
114
124
  private _pendingFinalizers;
115
125
  private _batchingRegistrations;
@@ -405,7 +415,16 @@ export default class ECSpresso<Cfg extends WorldConfig = EmptyConfig, Labels ext
405
415
  */
406
416
  spawn<T extends {
407
417
  [K in keyof Cfg['components']]?: Cfg['components'][K];
408
- }>(components: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>): FilteredEntity<Cfg['components'], keyof T & keyof Cfg['components']>;
418
+ }>(components: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>, options?: {
419
+ scope?: keyof Cfg['screens'] & string;
420
+ }): FilteredEntity<Cfg['components'], keyof T & keyof Cfg['components']>;
421
+ /**
422
+ * Tag an entity as scoped to a screen if `options.scope` is provided.
423
+ * The entity is removed when that screen exits (via `setScreen` away, or
424
+ * `popScreen` if it was on the stack). No-op when `options` or `scope` is
425
+ * undefined.
426
+ */
427
+ private _applyScreenScope;
409
428
  /**
410
429
  * Get all entities with specific components
411
430
  */
@@ -442,7 +461,9 @@ export default class ECSpresso<Cfg extends WorldConfig = EmptyConfig, Labels ext
442
461
  */
443
462
  spawnChild<T extends {
444
463
  [K in keyof Cfg['components']]?: Cfg['components'][K];
445
- }>(parentId: number, components: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>): FilteredEntity<Cfg['components'], keyof T & keyof Cfg['components']>;
464
+ }>(parentId: number, components: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>, options?: {
465
+ scope?: keyof Cfg['screens'] & string;
466
+ }): FilteredEntity<Cfg['components'], keyof T & keyof Cfg['components']>;
446
467
  /**
447
468
  * Set the parent of an entity
448
469
  * @param childId The entity ID to set as a child
@@ -797,6 +818,29 @@ export default class ECSpresso<Cfg extends WorldConfig = EmptyConfig, Labels ext
797
818
  * Get the screen stack depth
798
819
  */
799
820
  getScreenStackDepth(): number;
821
+ /**
822
+ * Subscribe to the `screenEnter` event for a specific screen. The handler
823
+ * fires only when that named screen becomes active (via `setScreen` or
824
+ * `pushScreen`). Multiple handlers can be registered for the same screen
825
+ * and fire in registration order.
826
+ *
827
+ * @returns A disposer function that unregisters the handler.
828
+ */
829
+ onScreenEnter<K extends keyof Cfg['screens'] & string>(name: K, handler: (ctx: {
830
+ config: Cfg['screens'][K] extends ScreenDefinition<infer C, any> ? C : never;
831
+ ecs: ECSpresso<Cfg>;
832
+ }) => void): () => void;
833
+ /**
834
+ * Subscribe to the `screenExit` event for a specific screen. The handler
835
+ * fires only when that named screen exits (via `setScreen` away, or
836
+ * `popScreen` if it was on the stack). Multiple handlers can be registered
837
+ * for the same screen and fire in registration order.
838
+ *
839
+ * @returns A disposer function that unregisters the handler.
840
+ */
841
+ onScreenExit<K extends keyof Cfg['screens'] & string>(name: K, handler: (ctx: {
842
+ ecs: ECSpresso<Cfg>;
843
+ }) => void): () => void;
800
844
  /**
801
845
  * Internal method to set the asset manager and drain pending plugin assets
802
846
  * @internal Used by ECSpressoBuilder
@@ -843,6 +887,25 @@ export default class ECSpresso<Cfg extends WorldConfig = EmptyConfig, Labels ext
843
887
  * at `withPlugin` time via the builder's own constrained overload.
844
888
  */
845
889
  _installPluginUnchecked(plugin: Plugin<WorldConfig, WorldConfig, string, string, string, string>): this;
890
+ /**
891
+ * Uninstall a previously installed plugin by id. Runs registered cleanup
892
+ * disposers in reverse order and removes the plugin from `installedPlugins`.
893
+ * Returns `true` if the plugin was installed (and has now been removed),
894
+ * `false` if no plugin with that id was installed.
895
+ *
896
+ * Disposers that throw are caught and logged via `console.warn` so a single
897
+ * failing disposer does not prevent later ones from running.
898
+ */
899
+ uninstallPlugin(id: string): boolean;
900
+ /**
901
+ * Uninstall every installed plugin, running their cleanup disposers.
902
+ * Plugins are uninstalled in reverse install order so a plugin that depends
903
+ * on another is torn down before its dependency.
904
+ *
905
+ * Does not touch resource disposal — callers that need async resource
906
+ * teardown should `await world.disposeResources()` separately.
907
+ */
908
+ dispose(): void;
846
909
  /**
847
910
  * Create a plugin factory from the built world's types.
848
911
  * Returns a definePlugin equivalent with no manual type parameters.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import ECSpresso from './ecspresso';
2
2
  import { SystemBuilder, type ProcessContext } from './system-builder';
3
- import { type Plugin, type BasePluginOptions, definePlugin } from './plugin';
3
+ import { type Plugin, type BasePluginOptions, type PluginCleanupRegistrar, definePlugin } from './plugin';
4
4
  export * from './types';
5
5
  export * from './asset-types';
6
6
  export * from './screen-types';
@@ -9,6 +9,6 @@ export type { ReactiveQueryDefinition } from './reactive-query-manager';
9
9
  export { default as AssetManager, createAssetConfigurator } from './asset-manager';
10
10
  export { default as ScreenManager, createScreenConfigurator } from './screen-manager';
11
11
  export { SystemBuilder, type ProcessContext };
12
- export { type Plugin, type BasePluginOptions, definePlugin };
12
+ export { type Plugin, type BasePluginOptions, type PluginCleanupRegistrar, definePlugin };
13
13
  export { directValue, type ResourceDirectValue } from './resource-manager';
14
14
  export default ECSpresso;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- var o=((j)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(j,{get:(D,$)=>(typeof require<"u"?require:D)[$]}):j)(function(j){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+j+'" is not supported')});class H{parentMap=new Map;childrenMap=new Map;_bfsQueue=[];setParent(j,D){if(j===D)throw Error(`Cannot set entity ${j} as its own parent`);if(this.wouldCreateCycle(j,D))throw Error("Cannot set parent: would create circular reference");let $=this.parentMap.get(j);if($!==void 0){let J=this.childrenMap.get($);if(J){let X=J.indexOf(j);if(X!==-1)J.splice(X,1)}}this.parentMap.set(j,D);let G=this.childrenMap.get(D);if(G)G.push(j);else this.childrenMap.set(D,[j]);return this}removeParent(j){let D=this.parentMap.get(j);if(D===void 0)return!1;let $=this.childrenMap.get(D);if($){let G=$.indexOf(j);if(G!==-1)$.splice(G,1)}return this.parentMap.delete(j),!0}getParent(j){return this.parentMap.get(j)??null}getChildren(j){let D=this.childrenMap.get(j);return D?[...D]:[]}getChildAt(j,D){if(D<0)return null;let $=this.childrenMap.get(j);if(!$||D>=$.length)return null;return $[D]??null}getChildIndex(j,D){let $=this.childrenMap.get(j);if(!$)return-1;return $.indexOf(D)}removeEntity(j){let D=this.parentMap.get(j)??null;if(D!==null){let J=this.childrenMap.get(D);if(J){let X=J.indexOf(j);if(X!==-1)J.splice(X,1)}}this.parentMap.delete(j);let $=this.childrenMap.get(j)??[],G=[...$];for(let J of $)this.parentMap.delete(J);return this.childrenMap.delete(j),{oldParent:D,orphanedChildren:G}}getAncestors(j){let D=[],$=this.parentMap.get(j);while($!==void 0)D.push($),$=this.parentMap.get($);return D}getDescendants(j){let D=[],$=this.childrenMap.get(j);if(!$)return D;let G=$.slice().reverse();while(G.length>0){let J=G.pop();D.push(J);let X=this.childrenMap.get(J);if(X)for(let Y=X.length-1;Y>=0;Y--)G.push(X[Y])}return D}getRoot(j){let D=j,$=this.parentMap.get(D);while($!==void 0)D=$,$=this.parentMap.get(D);return D}getSiblings(j){let D=this.parentMap.get(j);if(D===void 0)return[];let $=this.childrenMap.get(D);if(!$)return[];return $.filter((G)=>G!==j)}isDescendantOf(j,D){if(j===D)return!1;let $=this.parentMap.get(j);while($!==void 0){if($===D)return!0;$=this.parentMap.get($)}return!1}isAncestorOf(j,D){return this.isDescendantOf(D,j)}get hasHierarchy(){return this.childrenMap.size>0}getRootEntities(){let j=[];for(let D of this.childrenMap.keys())if(!this.parentMap.has(D))j.push(D);return j}wouldCreateCycle(j,D){let $=D;while($!==void 0){if($===j)return!0;$=this.parentMap.get($)}return!1}forEachInHierarchy(j,D){let $=D?.roots??this.getRootEntities(),G=this._bfsQueue;G.length=0;for(let J of $)G.push(J,-1,0);for(let J=0;J<G.length;J+=3){let X=G[J],Y=G[J+1],Z=G[J+2];j(X,Y===-1?null:Y,Z);let _=this.childrenMap.get(X);if(_){let Q=Z+1;for(let W of _)G.push(W,X,Q)}}}*hierarchyIterator(j){let D=j?.roots??this.getRootEntities(),$=[];for(let G of D)$.push({entityId:G,parentId:null,depth:0});for(let G of $){yield G;let J=this.childrenMap.get(G.entityId);if(J)for(let X of J)$.push({entityId:X,parentId:G.entityId,depth:G.depth+1})}}}function v(j,D){for(let $ of D)if(!($ in j))return!1;return!0}function N(j,D){for(let $ of D)if($ in j)return!0;return!1}function p(j,D,$){if(!j)return!1;for(let G of D)if((j.get(G)??-1)>$)return!0;return!1}class T{callbacks=[];_iterDepth=0;_pendingRemovals=[];add(j){this.callbacks.push(j)}remove(j){if(this._iterDepth>0){this._pendingRemovals.push(j);return}let D=this.callbacks.indexOf(j);if(D!==-1)this.callbacks.splice(D,1)}invoke(j){this._iterDepth++;let D=this.callbacks.length;for(let $=0;$<D;$++){let G=this.callbacks[$];if(G)G(j)}if(this._iterDepth--,this._iterDepth===0&&this._pendingRemovals.length>0){for(let $ of this._pendingRemovals){let G=this.callbacks.indexOf($);if(G!==-1)this.callbacks.splice(G,1)}this._pendingRemovals.length=0}}}class z{nextId=1;entities=new Map;componentIndices=new Map;addedCallbacks=new Map;removedCallbacks=new Map;hierarchyManager=new H;disposeCallbacks=new Map;changeSeqs=new Map;_changeSeq=0;_afterComponentAddedHooks=[];_afterEntityMutatedHooks=[];_afterComponentRemovedHooks=[];_beforeEntityRemovedHooks=[];_afterParentChangedHooks=[];_batchingDepth=0;_batchedEntityIds=new Set;_pendingBatchKeys=null;get entityCount(){return this.entities.size}createEntity(){let j=this.nextId++,D={id:j,components:{}};return this.entities.set(j,D),D}registerDispose(j,D){this.disposeCallbacks.set(j,D)}getDisposeCallbacks(){return this.disposeCallbacks}invokeDispose(j,D,$){let G=this.disposeCallbacks.get(j);if(!G)return;try{G({value:D,entityId:$})}catch(J){console.warn(`Component dispose callback for '${String(j)}' threw:`,J)}}addComponent(j,D,$){let G=this.entities.get(j);if(!G)throw Error(`Cannot add component '${String(D)}': Entity with ID ${j} does not exist`);let J=G.components[D];if(J!==void 0)this.invokeDispose(D,J,G.id);if(G.components[D]=$,!this.componentIndices.has(D))this.componentIndices.set(D,new Set);this.componentIndices.get(D)?.add(G.id);let X=this.addedCallbacks.get(D);if(X)X.invoke({value:$,entity:G});this._batchingDepth++;for(let Y of this._afterComponentAddedHooks)Y(G.id,D);if(this._batchedEntityIds.add(G.id),this._batchingDepth--,this._batchingDepth===0){for(let Y of this._batchedEntityIds)for(let Z of this._afterEntityMutatedHooks)Z(Y);this._batchedEntityIds.clear()}return this}addComponents(j,D){let $=this.entities.get(j);if(!$)throw Error(`Cannot add components: Entity with ID ${j} does not exist`);let G=this._pendingBatchKeys;this._pendingBatchKeys=new Set(Object.keys(D)),this._batchingDepth++;for(let J in D)this.addComponent($.id,J,D[J]);if(this._batchingDepth--,this._pendingBatchKeys=G,this._batchingDepth===0){for(let J of this._batchedEntityIds)for(let X of this._afterEntityMutatedHooks)X(J);this._batchedEntityIds.clear()}return this}removeComponent(j,D){let $=this.entities.get(j);if(!$)throw Error(`Cannot remove component '${String(D)}': Entity with ID ${j} does not exist`);let G=$.components[D];if(G!==void 0)this.invokeDispose(D,G,$.id);delete $.components[D];let J=this.removedCallbacks.get(D);if(J&&G!==void 0)J.invoke({value:G,entity:$});if(this.componentIndices.get(D)?.delete($.id),G!==void 0)for(let X of this._afterComponentRemovedHooks)X($.id,D);return this}getComponent(j,D){return this.entities.get(j)?.components[D]}getEntitiesWithQuery(j=[],D=[],$,G,J){return this.getEntitiesWithQueryInto([],j,D,$,G,J)}getEntitiesWithQueryInto(j,D=[],$=[],G,J,X){j.length=0;let Y=G!==void 0&&G.length>0&&J!==void 0,Z=X!==void 0&&X.length>0;if(D.length===0){if($.length===0&&!Y&&!Z){for(let L of this.entities.values())j.push(L);return j}for(let L of this.entities.values()){if($.length>0&&N(L.components,$))continue;if(Y&&!p(this.changeSeqs.get(L.id),G,J))continue;if(Z&&!this.parentHasComponents(L.id,X))continue;j.push(L)}return j}let _=D[0];if(_===void 0)return j;let Q=_,W=this.componentIndices.get(_)?.size??0;for(let L=1;L<D.length;L++){let B=D[L];if(B===void 0)continue;let U=this.componentIndices.get(B)?.size??0;if(U<W)Q=B,W=U}let F=this.componentIndices.get(Q);if(!F||F.size===0)return j;for(let L of F){let B=this.entities.get(L);if(!B)continue;if(!v(B.components,D))continue;if($.length>0&&N(B.components,$))continue;if(Y&&!p(this.changeSeqs.get(L),G,J))continue;if(Z&&!this.parentHasComponents(L,X))continue;j.push(B)}return j}parentHasComponents(j,D){let $=this.hierarchyManager.getParent(j);if($===null)return!1;let G=this.entities.get($);if(!G)return!1;return v(G.components,D)}removeEntity(j,D){let $=this.entities.get(j);if(!$)return!1;if(D?.cascade??!0){let J=this.hierarchyManager.getDescendants($.id);for(let X=J.length-1;X>=0;X--){let Y=J[X];if(Y===void 0)continue;for(let Z of this._beforeEntityRemovedHooks)Z(Y)}for(let X of this._beforeEntityRemovedHooks)X($.id);for(let X=J.length-1;X>=0;X--){let Y=J[X];if(Y===void 0)continue;this.removeEntityInternal(Y)}}else for(let J of this._beforeEntityRemovedHooks)J($.id);return this.removeEntityInternal($.id)}removeEntityInternal(j){let D=this.entities.get(j);if(!D)return!1;this.hierarchyManager.removeEntity(j);for(let $ of Object.keys(D.components)){let G=D.components[$];if(G!==void 0){this.invokeDispose($,G,D.id);let J=this.removedCallbacks.get($);if(J)J.invoke({value:G,entity:D})}this.componentIndices.get($)?.delete(D.id)}return this.changeSeqs.delete(D.id),this.entities.delete(D.id)}getEntity(j){return this.entities.get(j)}onComponentAdded(j,D){let $=D,G=this.addedCallbacks.get(j);if(!G)G=new T,this.addedCallbacks.set(j,G);return G.add($),()=>{this.addedCallbacks.get(j)?.remove($)}}onComponentRemoved(j,D){let $=D,G=this.removedCallbacks.get(j);if(!G)G=new T,this.removedCallbacks.set(j,G);return G.add($),()=>{this.removedCallbacks.get(j)?.remove($)}}onAfterComponentAdded(j){return this._afterComponentAddedHooks.push(j),()=>{let D=this._afterComponentAddedHooks.indexOf(j);if(D!==-1)this._afterComponentAddedHooks.splice(D,1)}}onAfterEntityMutated(j){return this._afterEntityMutatedHooks.push(j),()=>{let D=this._afterEntityMutatedHooks.indexOf(j);if(D!==-1)this._afterEntityMutatedHooks.splice(D,1)}}onAfterComponentRemoved(j){return this._afterComponentRemovedHooks.push(j),()=>{let D=this._afterComponentRemovedHooks.indexOf(j);if(D!==-1)this._afterComponentRemovedHooks.splice(D,1)}}onBeforeEntityRemoved(j){return this._beforeEntityRemovedHooks.push(j),()=>{let D=this._beforeEntityRemovedHooks.indexOf(j);if(D!==-1)this._beforeEntityRemovedHooks.splice(D,1)}}onAfterParentChanged(j){return this._afterParentChangedHooks.push(j),()=>{let D=this._afterParentChangedHooks.indexOf(j);if(D!==-1)this._afterParentChangedHooks.splice(D,1)}}get changeSeq(){return this._changeSeq}markChanged(j,D){let $=++this._changeSeq,G=this.changeSeqs.get(j);if(!G)G=new Map,this.changeSeqs.set(j,G);G.set(D,$)}getChangeSeq(j,D){return this.changeSeqs.get(j)?.get(D)??-1}spawnChild(j,D){let $=this.createEntity();return this.addComponents($.id,D),this.setParent($.id,j),$}setParent(j,D){this.hierarchyManager.setParent(j,D);for(let $ of this._afterParentChangedHooks)$(j);return this}removeParent(j){let D=this.hierarchyManager.removeParent(j);if(D)for(let $ of this._afterParentChangedHooks)$(j);return D}getParent(j){return this.hierarchyManager.getParent(j)}getChildren(j){return this.hierarchyManager.getChildren(j)}getChildAt(j,D){return this.hierarchyManager.getChildAt(j,D)}getChildIndex(j,D){return this.hierarchyManager.getChildIndex(j,D)}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,D){return this.hierarchyManager.isDescendantOf(j,D)}isAncestorOf(j,D){return this.hierarchyManager.isAncestorOf(j,D)}get hasHierarchy(){return this.hierarchyManager.hasHierarchy}getRootEntities(){return this.hierarchyManager.getRootEntities()}forEachInHierarchy(j,D){this.hierarchyManager.forEachInHierarchy(j,D)}hierarchyIterator(j){return this.hierarchyManager.hierarchyIterator(j)}}class V{handlers=new Map;subscribe(j,D){return this.addHandler(j,D,!1)}once(j,D){return this.addHandler(j,D,!0)}unsubscribe(j,D){let $=this.handlers.get(j);if(!$)return!1;let G=$.findIndex((J)=>J.callback===D);if(G===-1)return!1;return $.splice(G,1),!0}addHandler(j,D,$){let G=this.handlers.get(j);if(!G)G=[],this.handlers.set(j,G);let J={callback:D,once:$};return G.push(J),()=>{let X=this.handlers.get(j);if(X){let Y=X.indexOf(J);if(Y!==-1)X.splice(Y,1)}}}publish(...[j,D]){let $=this.handlers.get(j);if(!$||$.length===0)return;let G=!1,J=$.length;for(let X=0;X<J&&X<$.length;X++){let Y=$[X];if(!Y)continue;if(Y.callback(D),Y.once)G=!0}if(G){for(let X=$.length-1;X>=0;X--)if($[X]?.once)$.splice(X,1)}}clear(){this.handlers.clear()}clearEvent(j){this.handlers.delete(j)}}var C=Symbol("resource-direct");function i(j){return{[C]:j}}function x(j){if(typeof j==="object"&&j!==null&&!Array.isArray(j))return{...j};return{$value:j}}function l(j,D){if(typeof j==="object"&&j!==null&&!Array.isArray(j)){let $=j;for(let G in D)if(!Object.is($[G],D[G]))return!0;return!1}return!Object.is(j,D.$value)}function c(j){return typeof j==="object"&&j!==null&&"factory"in j&&typeof j.factory==="function"}function d(j){return typeof j==="object"&&j!==null&&C in j}function b(j,D){let $=[],G=new Set,J=new Set;function X(Y,Z=[]){if(G.has(Y))return;if(J.has(Y))throw Error(`Circular resource dependency: ${[...Z,Y].join(" -> ")}`);J.add(Y);for(let _ of D(Y)){let Q=j.find((W)=>W===_);if(Q)X(Q,[...Z,Y])}J.delete(Y),G.add(Y),$.push(Y)}for(let Y of j)X(Y);return $}class E{resources=new Map;resourceFactories=new Map;resourceDependencies=new Map;resourceDisposers=new Map;initializedResourceKeys=new Set;_changeSubscribers=new Map;_observedSnapshots=new Map;add(j,D){let $=(G)=>{this.resources.set(j,G),this.initializedResourceKeys.add(j),this.resourceDependencies.set(j,[])};if(c(D)){if(this.resourceFactories.set(j,D.factory),this.resourceDependencies.set(j,D.dependsOn??[]),D.onDispose)this.resourceDisposers.set(j,D.onDispose)}else if(d(D))$(D[C]);else if(typeof D==="function")this.resourceFactories.set(j,D),this.resourceDependencies.set(j,[]);else $(D);return this}tryGet(j,...D){if(!this.has(j))return;return this.get(j,...D)}get(j,...D){let $=this.resources.get(j);if($!==void 0)return $;let G=this.resourceFactories.get(j);if(G===void 0)throw Error(`Resource ${String(j)} not found`);let J=D[0],X=G(J);if(!(X instanceof Promise))this.resources.set(j,X),this.initializedResourceKeys.add(j);return X}has(j){return this.resources.has(j)||this.resourceFactories.has(j)}remove(j){let D=this.resources.delete(j),$=this.resourceFactories.delete(j);return this.resourceDependencies.delete(j),this.resourceDisposers.delete(j),this.initializedResourceKeys.delete(j),D||$}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,...D){if(!this.resourceFactories.has(j)||this.initializedResourceKeys.has(j))return;let $=this.resourceFactories.get(j);if(!$)return;let G=D[0],J=await $(G);this.resources.set(j,J),this.initializedResourceKeys.add(j),this.resourceFactories.delete(j)}async initializeResources(...j){let D=j.slice(1),$=D.length===0?this.getPendingInitializationKeys():D;if($.length===0)return;let G=b($,(J)=>[...this.resourceDependencies.get(J)??[]]);for(let J of G)await this.initializeResource(J,...j.slice(0,1))}getDependencies(j){return this.resourceDependencies.get(j)??[]}async disposeResource(j,...D){if(!this.resources.has(j)&&!this.resourceFactories.has(j))return!1;if(this.initializedResourceKeys.has(j)){let $=this.resourceDisposers.get(j),G=this.resources.get(j);if($&&G!==void 0){let J=D[0];await $(G,J)}}return this.resources.delete(j),this.resourceFactories.delete(j),this.resourceDependencies.delete(j),this.resourceDisposers.delete(j),this.initializedResourceKeys.delete(j),this._changeSubscribers.delete(j),!0}onResourceChange(j,D){let $=this._changeSubscribers.get(j),G=$??new Set;if(!$){this._changeSubscribers.set(j,G);let X=this.resources.get(j);this._observedSnapshots.set(j,x(X))}let J=D;return G.add(J),()=>{if(G.delete(J),G.size===0)this._changeSubscribers.delete(j),this._observedSnapshots.delete(j)}}notifyChange(j,D,$){if(Object.is(D,$))return;let G=this._changeSubscribers.get(j);if(!G||G.size===0)return;if(this._observedSnapshots.has(j))this._observedSnapshots.set(j,x(D));let J=[...G];for(let X of J)X(D,$)}isObserved(j){return this._observedSnapshots.has(j)}flushObserved(){if(this._observedSnapshots.size===0)return;for(let[j,D]of this._observedSnapshots){let $=this.resources.get(j);if(!l($,D))continue;let G="$value"in D?D.$value:D,J=x($),X=this._changeSubscribers.get(j);for(let Y of X)Y($,G);this._observedSnapshots.set(j,J)}}async disposeResources(...j){let D=Array.from(this.initializedResourceKeys);if(D.length===0)return;let $=b(D,(G)=>[...this.resourceDependencies.get(G)??[]]).reverse();for(let G of $)await this.disposeResource(G,...j)}}class R{queries=new Map;entityManager;_hasParentHasQueries=!1;constructor(j){this.entityManager=j}get hasParentHasQueries(){return this._hasParentHasQueries}addQuery(j,D){let $={definition:D,matchingEntities:new Set};if(this.queries.set(j,$),D.parentHas?.length)this._hasParentHasQueries=!0;let G=this.entityManager.getEntitiesWithQuery(D.with,D.without??[]);for(let J of G)if(this.entityMatchesQuery(J,$.definition))$.matchingEntities.add(J.id),$.definition.onEnter?.(J)}removeQuery(j){let D=this.queries.delete(j);if(D)this._recalcParentHasFlag();return D}entityMatchesQuery(j,D){for(let $ of D.with)if(!($ in j.components))return!1;if(D.without){for(let $ of D.without)if($ in j.components)return!1}if(D.parentHas?.length){let $=this.entityManager.getParent(j.id);if($===null)return!1;let G=this.entityManager.getEntity($);if(!G)return!1;for(let J of D.parentHas)if(!(J in G.components))return!1}return!0}_applyQueryTransition(j,D){let $=D.matchingEntities.has(j.id),G=this.entityMatchesQuery(j,D.definition);if(!$&&G)D.matchingEntities.add(j.id),D.definition.onEnter?.(j);else if($&&!G)D.matchingEntities.delete(j.id),D.definition.onExit?.(j.id)}onComponentAdded(j,D){for(let[,$]of this.queries)this._applyQueryTransition(j,$);if(this._hasParentHasQueries)this._recheckChildren(j.id)}onComponentRemoved(j,D){for(let[,$]of this.queries)this._applyQueryTransition(j,$);if(this._hasParentHasQueries)this._recheckChildren(j.id)}onEntityRemoved(j){for(let[D,$]of this.queries)if($.matchingEntities.has(j))$.matchingEntities.delete(j),$.definition.onExit?.(j)}recheckEntity(j){for(let[,D]of this.queries)this._applyQueryTransition(j,D)}recheckEntityAndChildren(j){if(this.recheckEntity(j),this._hasParentHasQueries)this._recheckChildren(j.id)}_recheckChildren(j){let D=this.entityManager.getChildren(j);for(let $ of D){let G=this.entityManager.getEntity($);if(G)this.recheckEntity(G)}}_recalcParentHasFlag(){this._hasParentHasQueries=!1;for(let[,j]of this.queries)if(j.definition.parentHas?.length){this._hasParentHasQueries=!0;return}}}class w{commands=[];removeEntity(j,D){this.commands.push(($)=>{$.removeEntity(j,D)})}addComponent(j,D,$){this.commands.push((G)=>{G.addComponent(j,D,$)})}removeComponent(j,D){this.commands.push(($)=>{$.removeComponent(j,D)})}spawn(j){this.commands.push((D)=>{D.spawn(j)})}spawnChild(j,D){this.commands.push(($)=>{$.spawnChild(j,D)})}addComponents(j,D){this.commands.push(($)=>{$.addComponents(j,D)})}setParent(j,D){this.commands.push(($)=>{$.setParent(j,D)})}mutateComponent(j,D,$){this.commands.push((G)=>{G.mutateComponent(j,D,$)})}markChanged(j,D){this.commands.push(($)=>{$.markChanged(j,D)})}removeParent(j){this.commands.push((D)=>{D.removeParent(j)})}playback(j){for(let D of this.commands)try{D(j)}catch($){console.warn("CommandBuffer: Command failed during playback:",$)}this.commands.length=0}clear(){this.commands.length=0}get length(){return this.commands.length}}class h{_id;constructor(j){this._id=j}withComponentTypes(){return this}withEventTypes(){return this}withResourceTypes(){return this}withAssetTypes(){return this}withScreenTypes(){return this}withLabels(){return this}withGroups(){return this}withAssetGroupNames(){return this}withReactiveQueryNames(){return this}requires(){return this}install(j){return{id:this._id,install:j}}}function M(j){return new h(j)}class S{_label;queries={};processFunction;detachFunction;initializeFunction;eventHandlers;_priority=0;_phase="update";_groups=[];_inScreens;_excludeScreens;_requiredAssets;_runWhenEmpty=!1;_entityEnterHandlers={};_resourceKeys;constructor(j){this._label=j}get label(){return this._label}_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;if(this._runWhenEmpty)j.runWhenEmpty=!0;if(Object.keys(this._entityEnterHandlers).length>0)j.onEntityEnter={...this._entityEnterHandlers};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}runWhenEmpty(){return this._runWhenEmpty=!0,this}withResources(j){return this._resourceKeys=[...j],this}addQuery(j,D){let $=this;return $.queries={...this.queries,[j]:D},$}setProcess(j){return this.processFunction=this._wrapWithResources(j),this}_wrapWithResources(j){if(!this._resourceKeys?.length)return j;let D=this._resourceKeys,$={},G=!1;return(J)=>{for(let X of D)if(!G||J.ecs.isResourceObserved(X))$[X]=J.ecs.getResource(X);G=!0,J.resources=$,j(J)}}setProcessEach(j,D){let $=this;if(Object.keys($.queries).length>0||$.processFunction!==void 0)throw Error("setProcessEach requires a SystemBuilder with no prior queries or process function. Use addQuery + setProcess for multi-query systems.");$.queries.__each=j;let G={entity:void 0,dt:0,ecs:void 0,resources:void 0},J=(X)=>{let Y=X,Z=Y.queries.__each;if(!Z)return;G.dt=Y.dt,G.ecs=Y.ecs,G.resources=Y.resources;for(let _ of Z)G.entity=_,D(G)};return $.processFunction=$._wrapWithResources(J),this}setOnEntityEnter(j,D){return this._entityEnterHandlers[j]=D,this}setOnDetach(j){return this.detachFunction=j,this}setOnInitialize(j){return this.initializeFunction=j,this}setEventHandlers(j){return this.eventHandlers=j,this}}function k(j,D,$){let G=new Set,J=[D];while(J.length>0){let X=J.pop();if(X===void 0)break;if(X===j)throw Error(`Circular required component dependency: '${String(j)}' -> '${String(D)}' -> ... -> '${String(j)}'`);if(G.has(X))continue;G.add(X);let Y=$(X);if(Y)for(let Z of Y)J.push(Z.component)}}var I="0.14.9";class K{assets=new Map;groups=new Map;eventBus=null;setEventBus(j){this.eventBus=j}register(j,D){if(this.assets.set(j,{definition:D,status:"pending"}),D.group){let $=this.groups.get(D.group)??new Set;$.add(j),this.groups.set(D.group,$)}}async loadEagerAssets(){let j=[];for(let[D,$]of this.assets)if($.definition.eager&&$.status==="pending")j.push(D);await Promise.all(j.map((D)=>this.loadAsset(D)))}async loadAsset(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);if(D.status==="loaded"&&D.value!==void 0)return D.value;if(D.status==="loading"&&D.loadPromise)return D.loadPromise;if(D.status==="failed")D.status="pending";D.status="loading",D.loadPromise=D.definition.loader();try{let $=await D.loadPromise;return D.value=$,D.status="loaded",D.loadPromise=void 0,this.eventBus?.publish("assetLoaded",{key:j}),this.checkGroupProgress(D.definition.group),$}catch($){let G=$ instanceof Error?$:Error(String($));throw D.status="failed",D.error=G,D.loadPromise=void 0,this.eventBus?.publish("assetFailed",{key:j,error:G}),G}}async loadAssetGroup(j){let D=this.groups.get(j);if(!D||D.size===0)throw Error(`Asset group '${j}' not found or empty`);await Promise.all(Array.from(D).map(($)=>this.loadAsset($)))}get(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);if(D.status!=="loaded"||D.value===void 0)throw Error(`Asset '${String(j)}' is not loaded (status: ${D.status})`);return D.value}tryGet(j){let D=this.assets.get(j);if(!D||D.status!=="loaded")return;return D.value}getHandle(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);let $=this;return{get status(){return D.status},get isLoaded(){return D.status==="loaded"},get(){return $.get(j)},tryGet(){return $.tryGet(j)}}}getStatus(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);return D.status}isLoaded(j){return this.assets.get(j)?.status==="loaded"}isGroupLoaded(j){let D=this.groups.get(j);if(!D||D.size===0)return!1;for(let $ of D){let G=this.assets.get($);if(!G||G.status!=="loaded")return!1}return!0}getGroupProgress(j){return this.getGroupProgressDetails(j).progress}getGroupProgressDetails(j){let D=this.groups.get(j);if(!D||D.size===0)return{loaded:0,total:0,progress:0};let $=0;for(let J of D)if(this.assets.get(J)?.status==="loaded")$++;let G=D.size;return{loaded:$,total:G,progress:$/G}}checkGroupProgress(j){if(!j||!this.eventBus)return;let D=j,$=this.getGroupProgressDetails(D);if(this.eventBus.publish("assetGroupProgress",{group:D,...$}),$.loaded===$.total)this.eventBus.publish("assetGroupLoaded",{group:D})}createResource(){let j=this;return{getStatus(D){return j.getStatus(D)},isLoaded(D){return j.isLoaded(D)},isGroupLoaded(D){return j.isGroupLoaded(D)},getGroupProgress(D){return j.getGroupProgress(D)},get(D){return j.get(D)},tryGet(D){return j.tryGet(D)},getHandle(D){return j.getHandle(D)}}}getKeys(){return Array.from(this.assets.keys())}getGroupNames(){return Array.from(this.groups.keys())}getGroupKeys(j){let D=this.groups.get(j);return D?Array.from(D):[]}}class u{manager;constructor(j){this.manager=j}add(j,D){return this.manager.register(j,{loader:D,eager:!0}),this}addWithConfig(j,D){return this.manager.register(j,D),this}addGroup(j,D){for(let[$,G]of Object.entries(D))this.manager.register($,{loader:G,eager:!1,group:j});return this}getManager(){return this.manager}}function q(j){return new u(j??new K)}class A{screens=new Map;currentScreen=null;screenStack=[];eventBus=null;assetManager=null;ecs=null;setDependencies(j,D,$){this.eventBus=j,this.assetManager=D,this.ecs=$}requireEcs(){if(!this.ecs)throw Error("ScreenManager: dependencies not set. Call setDependencies() first.");return this.ecs}register(j,D){this.screens.set(j,{definition:D})}async setScreen(j,D){let $=this.screens.get(j);if(!$)throw Error(`Screen '${String(j)}' not found`);await this.verifyRequiredAssets($.definition.requiredAssets,$.definition.requiredAssetGroups);while(this.screenStack.length>0){let J=this.screenStack.pop();if(J)await this.exitScreen(J.name)}if(this.currentScreen)await this.exitScreen(this.currentScreen.name);let G=$.definition.initialState(D);this.currentScreen={name:j,config:D,state:G},await $.definition.onEnter?.({config:D,ecs:this.requireEcs()}),this.eventBus?.publish("screenEnter",{screen:j,config:D})}async pushScreen(j,D){let $=this.screens.get(j);if(!$)throw Error(`Screen '${String(j)}' not found`);if(await this.verifyRequiredAssets($.definition.requiredAssets,$.definition.requiredAssetGroups),this.currentScreen)this.screenStack.push(this.currentScreen);let G=$.definition.initialState(D);this.currentScreen={name:j,config:D,state:G},await $.definition.onEnter?.({config:D,ecs:this.requireEcs()}),this.eventBus?.publish("screenPush",{screen:j,config:D})}async popScreen(){if(this.screenStack.length===0)throw Error("Cannot pop screen: stack is empty");if(this.currentScreen)await this.exitScreen(this.currentScreen.name),this.eventBus?.publish("screenPop",{screen:this.currentScreen.name});this.currentScreen=this.screenStack.pop()??null}async exitScreen(j){let D=this.screens.get(j);if(D?.definition.onExit)await D.definition.onExit(this.requireEcs());this.eventBus?.publish("screenExit",{screen:j})}async verifyRequiredAssets(j,D){if(!this.assetManager)return;if(j){for(let $ of j)if(!this.assetManager.isLoaded($))await this.assetManager.loadAsset($)}if(D){for(let $ of D)if(!this.assetManager.isGroupLoaded($))await this.assetManager.loadAssetGroup($)}}getCurrentScreen(){return this.currentScreen?.name??null}getConfig(j){if(!this.currentScreen)throw Error("No current screen");if(j!==void 0&&this.currentScreen.name!==j)throw Error(`Expected current screen '${String(j)}', but current is '${String(this.currentScreen.name)}'`);return this.currentScreen.config}tryGetConfig(j){if(!this.currentScreen)return;if(j!==void 0&&this.currentScreen.name!==j)return;return this.currentScreen.config}getState(j){if(!this.currentScreen)throw Error("No current screen");if(j!==void 0&&this.currentScreen.name!==j)throw Error(`Expected current screen '${String(j)}', but current is '${String(this.currentScreen.name)}'`);return this.currentScreen.state}tryGetState(j){if(!this.currentScreen)return;if(j!==void 0&&this.currentScreen.name!==j)return;return this.currentScreen.state}updateState(j,D){if(!this.currentScreen)throw Error("No current screen");if(D!==void 0&&this.currentScreen.name!==D)throw Error(`Expected current screen '${String(D)}', but current is '${String(this.currentScreen.name)}'`);let $=typeof j==="function"?j(this.currentScreen.state):j;this.currentScreen.state={...this.currentScreen.state,...$}}getStackDepth(){return this.screenStack.length}isOverlay(){return this.screenStack.length>0}isActive(j){if(this.currentScreen?.name===j)return!0;return this.screenStack.some((D)=>D.name===j)}isCurrent(j){return this.currentScreen?.name===j}createResource(){let j=this;return{get current(){return j.getCurrentScreen()},get config(){return j.tryGetConfig()??null},get state(){return j.tryGetState()??null},set state(D){if(j.currentScreen&&D!==null)j.currentScreen.state=D},get stack(){return j.screenStack},get isOverlay(){return j.isOverlay()},get stackDepth(){return j.getStackDepth()},isActive(D){return j.isActive(D)},isCurrent(D){return j.isCurrent(D)}}}getScreenNames(){return Array.from(this.screens.keys())}hasScreen(j){return this.screens.has(j)}}class s{manager;constructor(j){this.manager=j}add(j,D){return this.manager.register(j,D),this}getManager(){return this.manager}}function f(j){return new s(j??new A)}class g{assetConfigurator=null;screenConfigurator=null;pendingResources=[];pendingDisposeCallbacks=[];pendingRequiredComponents=[];pendingPlugins=[];_fixedDt=null;constructor(){}withPlugin(j){return this.pendingPlugins.push(j),this}withComponentTypes(){return this}withEventTypes(){return this}withResourceTypes(){return this}withResource(j,D){return this.pendingResources.push({key:j,value:D}),this}withDispose(j,D){return this.pendingDisposeCallbacks.push({key:j,callback:D}),this}withRequired(j,D,$){return this.pendingRequiredComponents.push({trigger:j,required:D,factory:$}),this}withAssets(j){let D=q();return j(D),this.assetConfigurator=D,this}withScreens(j){let D=f();return j(D),this.screenConfigurator=D,this}withFixedTimestep(j){return this._fixedDt=j,this}withReactiveQueryNames(){return this}pluginFactory(){return(j)=>M(j.id).install(j.install)}build(){let j=new P;for(let D of this.pendingPlugins)j._installPluginUnchecked(D);for(let{key:D,value:$}of this.pendingResources)j.addResource(D,$);for(let{key:D,callback:$}of this.pendingDisposeCallbacks)j.registerDispose(D,$);for(let{trigger:D,required:$,factory:G}of this.pendingRequiredComponents)j.registerRequired(D,$,G);if(this.assetConfigurator)j._setAssetManager(this.assetConfigurator.getManager());else if(j._hasPendingPluginAssets())j._setAssetManager(new K);if(this.screenConfigurator)j._setScreenManager(this.screenConfigurator.getManager());else if(j._hasPendingPluginScreens())j._setScreenManager(new A);if(this._fixedDt!==null)j._setFixedDt(this._fixedDt);return j}}var m=["preUpdate","fixedUpdate","update","postUpdate","render"];class P{static VERSION=I;_entityManager;_eventBus;_resourceManager;_commandBuffer;_systems=[];_phaseSystems={preUpdate:[],fixedUpdate:[],update:[],postUpdate:[],render:[]};_installedPlugins=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;_requiredComponents=new Map;_pendingPluginAssets=[];_pendingPluginScreens=[];_diagnosticsEnabled=!1;_systemTimings=new Map;_phaseTimings={preUpdate:0,fixedUpdate:0,update:0,postUpdate:0,render:0};_entityEnterTracking=new Map;_entityEnterFrameSet=new Set;_systemContexts=new WeakMap;_pendingFinalizers=[];_batchingRegistrations=!1;constructor(){this._entityManager=new z,this._eventBus=new V,this._resourceManager=new E,this._reactiveQueryManager=new R(this._entityManager),this._commandBuffer=new w,this._subscribeLifecycleHooks()}_subscribeLifecycleHooks(){this._entityManager.onAfterComponentAdded((j,D)=>{this._entityManager.markChanged(j,D);let $=this._requiredComponents.get(D);if($){let G=this._entityManager.getEntity(j);if(G){let J=G.components[D];for(let{component:X,factory:Y}of $){if(this._entityManager._pendingBatchKeys?.has(X))continue;if(!(X in G.components))this._entityManager.addComponent(j,X,Y(J))}}}}),this._entityManager.onAfterEntityMutated((j)=>{let D=this._entityManager.getEntity(j);if(D)this._reactiveQueryManager.recheckEntityAndChildren(D)}),this._entityManager.onAfterComponentRemoved((j,D)=>{let $=this._entityManager.getEntity(j);if($)this._reactiveQueryManager.onComponentRemoved($,D)}),this._entityManager.onBeforeEntityRemoved((j)=>{this._reactiveQueryManager.onEntityRemoved(j)}),this._entityManager.onAfterParentChanged((j)=>{if(this._reactiveQueryManager.hasParentHasQueries){let D=this._entityManager.getEntity(j);if(D)this._reactiveQueryManager.recheckEntity(D)}})}static create(){return new g}addSystem(j){let D=new S(j);return this._pendingFinalizers.push(()=>{this._registerSystem(D._createSystemObject())}),D}_finalizePendingBuilders(){if(this._pendingFinalizers.length===0)return;this._batchingRegistrations=!0;while(this._pendingFinalizers.length>0){let j=this._pendingFinalizers;this._pendingFinalizers=[];for(let D of j)D()}this._batchingRegistrations=!1,this._rebuildPhaseSystems()}update(j){this._finalizePendingBuilders();let D=this._screenManager?.getCurrentScreen()??null,$=this._diagnosticsEnabled;this._runPhase("preUpdate",j,D,$);let G=$?performance.now():0;this._fixedAccumulator+=j;let J=0;while(this._fixedAccumulator>=this._fixedDt&&J<this._maxFixedSteps)this._executePhase(this._phaseSystems.fixedUpdate,this._fixedDt,D),this._commandBuffer.playback(this),this._fixedAccumulator-=this._fixedDt,J++;if(this._fixedAccumulator>=this._fixedDt)this._fixedAccumulator=0;if($)this._phaseTimings.fixedUpdate=performance.now()-G;this._interpolationAlpha=this._fixedAccumulator/this._fixedDt,this._runPhase("update",j,D,$),this._runPhase("postUpdate",j,D,$);for(let X of this._postUpdateHooks)X({ecs:this,dt:j});this._runPhase("render",j,D,$),this._resourceManager.flushObserved(),this._changeThreshold=this._entityManager.changeSeq,this._currentTick++}_executePhase(j,D,$){for(let G of j){if(!G.process&&!G.onEntityEnter)continue;if(G.groups?.length){let W=!1;for(let F of G.groups)if(this._disabledGroups.has(F)){W=!0;break}if(W)continue}if(G.inScreens?.length){if($===null||!G.inScreens.includes($))continue}if(G.excludeScreens?.length){if($!==null&&G.excludeScreens.includes($))continue}if(G.requiredAssets?.length&&this._assetManager){let W=!0;for(let F of G.requiredAssets)if(!this._assetManager.isLoaded(F)){W=!1;break}if(!W)continue}let J=this._systemLastSeqs.get(G)??0;this._changeThreshold=J;let X=this._systemContexts.get(G);if(!X)X={queries:{},dt:0,ecs:this},this._systemContexts.set(G,X);X.dt=D;let Y=X.queries,Z=!1,_=!1;if(G.entityQueries)for(let W in G.entityQueries){_=!0;let F=G.entityQueries[W];if(F){let B=Y[W]??(Y[W]=[]);if(this._entityManager.getEntitiesWithQueryInto(B,F.with,F.without||[],F.changed,F.changed?this._changeThreshold:void 0,F.parentHas),B.length)Z=!0}}let Q=this._entityEnterTracking.get(G);if(Q&&G.onEntityEnter)for(let W in G.onEntityEnter){let F=Y[W],L=Q.get(W);if(!F||!L)continue;let B=G.onEntityEnter[W];if(!B)continue;let U=this._entityEnterFrameSet;U.clear();for(let O of F)if(U.add(O.id),!L.has(O.id))L.add(O.id),B({entity:O,ecs:this});for(let O of L)if(!U.has(O))L.delete(O)}if(G.process){if(this._diagnosticsEnabled){let W=performance.now();if(Z||G.runWhenEmpty)G.process(X);else if(!_)G.process(X);this._systemTimings.set(G.label,performance.now()-W)}else if(Z||G.runWhenEmpty)G.process(X);else if(!_)G.process(X)}this._systemLastSeqs.set(G,this._entityManager.changeSeq)}}_runPhase(j,D,$,G){if(G){let J=performance.now();this._executePhase(this._phaseSystems[j],D,$),this._phaseTimings[j]=performance.now()-J}else this._executePhase(this._phaseSystems[j],D,$);this._commandBuffer.playback(this)}async initialize(){if(this._finalizePendingBuilders(),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 m)this._phaseSystems[j]=[];for(let j of this._systems){let D=j.phase??"update";this._phaseSystems[D].push(j)}for(let j of m)this._phaseSystems[j].sort((D,$)=>{let G=D.priority??0;return($.priority??0)-G})}updateSystemPriority(j,D){this._finalizePendingBuilders();let $=this._systems.find((G)=>G.label===j);if(!$)return!1;return $.priority=D,this._rebuildPhaseSystems(),!0}updateSystemPhase(j,D){this._finalizePendingBuilders();let $=this._systems.find((G)=>G.label===j);if(!$)return!1;return $.phase=D,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._finalizePendingBuilders(),this._systems.filter((D)=>D.groups?.includes(j)).map((D)=>D.label)}removeSystem(j){this._finalizePendingBuilders();let D=this._systems.findIndex((G)=>G.label===j);if(D===-1)return!1;let $=this._systems[D];if(!$)return!1;if($.onDetach)$.onDetach(this);return this._systems.splice(D,1),this._systemLastSeqs.delete($),this._entityEnterTracking.delete($),this._rebuildPhaseSystems(),!0}_registerSystem(j){if(this._systems.push(j),this._systemLastSeqs.set(j,this._changeThreshold),!this._batchingRegistrations)this._rebuildPhaseSystems();if(j.onEntityEnter){let D=new Map;for(let $ in j.onEntityEnter)D.set($,new Set);this._entityEnterTracking.set(j,D)}if(!j.eventHandlers)return;for(let D in j.eventHandlers){let $=j.eventHandlers[D];if($)this._eventBus.subscribe(D,(G)=>{$({data:G,ecs:this})})}}hasResource(j){return this._resourceManager.has(j)}getResource(j){if(!this._resourceManager.has(j))throw Error(`Resource '${String(j)}' not found. Available resources: [${this.getResourceKeys().map((D)=>String(D)).join(", ")}]`);return this._resourceManager.get(j,this)}tryGetResource(j){let D=j;if(!this._resourceManager.has(D))return;return this._resourceManager.get(D,this)}addResource(j,D){return this._resourceManager.add(j,D),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,D){let $=this.getResource(j),G=D($);return this._resourceManager.add(j,G),this._resourceManager.notifyChange(j,G,$),this}setResource(j,D){let $=this.tryGetResource(j);if(this._resourceManager.add(j,D),$!==void 0)this._resourceManager.notifyChange(j,D,$);return this}onResourceChange(j,D){return this._resourceManager.onResourceChange(j,D)}isResourceObserved(j){return this._resourceManager.isObserved(j)}getResourceKeys(){return this._resourceManager.getKeys()}resourceNeedsInitialization(j){return this._resourceManager.needsInitialization(j)}getEntity(j){return this._entityManager.getEntity(j)}getComponent(j,D){return this._entityManager.getComponent(j,D)}addComponent(j,D,$){this._entityManager.addComponent(j,D,$)}addComponents(j,D){this._entityManager.addComponents(j,D)}removeComponent(j,D){this._entityManager.removeComponent(j,D)}hasComponent(j,D){return this._entityManager.getComponent(j,D)!==void 0}spawn(j){let D=this._entityManager.createEntity();return this._entityManager.addComponents(D.id,j),D}getEntitiesWithQuery(j,D=[],$,G){return this._entityManager.getEntitiesWithQuery(j,D,$,$?this._changeThreshold:void 0,G)}getSingleton(j,D=[]){let $=this._entityManager.getEntitiesWithQuery(j,D);if($.length===0)throw Error(`getSingleton: no entity matches query with=[${String(j)}] without=[${String(D)}]`);if($.length>1)throw Error(`getSingleton: expected 1 entity but found ${$.length} matching query with=[${String(j)}] without=[${String(D)}]`);let G=$[0];if(!G)throw Error("getSingleton: unexpected empty result");return G}tryGetSingleton(j,D=[]){let $=this._entityManager.getEntitiesWithQuery(j,D);if($.length===0)return;if($.length>1)throw Error(`tryGetSingleton: expected 0 or 1 entity but found ${$.length} matching query with=[${String(j)}] without=[${String(D)}]`);return $[0]}removeEntity(j,D){return this._entityManager.removeEntity(j,D)}spawnChild(j,D){let $=this._entityManager.spawnChild(j,D);return this._emitHierarchyChanged($.id,null,j),$}setParent(j,D){let $=this._entityManager.getParent(j);return this._entityManager.setParent(j,D),this._emitHierarchyChanged(j,$,D),this}removeParent(j){let D=this._entityManager.getParent(j),$=this._entityManager.removeParent(j);if($)this._emitHierarchyChanged(j,D,null);return $}getParent(j){return this._entityManager.getParent(j)}getChildren(j){return this._entityManager.getChildren(j)}getChildAt(j,D){return this._entityManager.getChildAt(j,D)}getChildIndex(j,D){return this._entityManager.getChildIndex(j,D)}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,D){return this._entityManager.isDescendantOf(j,D)}isAncestorOf(j,D){return this._entityManager.isAncestorOf(j,D)}getRootEntities(){return this._entityManager.getRootEntities()}forEachInHierarchy(j,D){this._entityManager.forEachInHierarchy(j,D)}hierarchyIterator(j){return this._entityManager.hierarchyIterator(j)}_emitHierarchyChanged(j,D,$){this._eventBus.publish("hierarchyChanged",{entityId:j,oldParent:D,newParent:$})}get installedPlugins(){return Array.from(this._installedPlugins)}get entityManager(){return this._entityManager}get eventBus(){return this._finalizePendingBuilders(),this._eventBus}get commands(){return this._commandBuffer}get currentTick(){return this._currentTick}get changeThreshold(){return this._changeThreshold}enableDiagnostics(j){if(this._diagnosticsEnabled=j,!j)this._systemTimings.clear(),this._phaseTimings={preUpdate:0,fixedUpdate:0,update:0,postUpdate:0,render:0}}get diagnosticsEnabled(){return this._diagnosticsEnabled}get systemTimings(){return this._systemTimings}get phaseTimings(){return this._phaseTimings}get entityCount(){return this._entityManager.entityCount}mutateComponent(j,D,$){let G=this._entityManager.getComponent(j,D);if(G===void 0)throw Error(`Entity ${j} does not have component "${String(D)}"`);return $(G),this._entityManager.markChanged(j,D),G}markChanged(j,D){this._entityManager.markChanged(j,D)}registerDispose(j,D){this._entityManager.registerDispose(j,D)}registerRequired(j,D,$){if(String(j)===String(D))throw Error(`Cannot require a component to depend on itself: '${String(j)}'`);let G=this._requiredComponents.get(j)??[];if(G.some((J)=>J.component===D))throw Error(`Required component '${String(D)}' already registered for trigger '${String(j)}'`);this._checkRequiredCycle(j,D),G.push({component:D,factory:$}),this._requiredComponents.set(j,G)}_checkRequiredCycle(j,D){k(j,D,($)=>this._requiredComponents.get($))}onComponentAdded(j,D){return this._entityManager.onComponentAdded(j,D)}onComponentRemoved(j,D){return this._entityManager.onComponentRemoved(j,D)}addReactiveQuery(j,D){this._reactiveQueryManager.addQuery(j,D)}removeReactiveQuery(j){return this._reactiveQueryManager.removeQuery(j)}on(j,D){return this._eventBus.subscribe(j,D)}off(j,D){return this._eventBus.unsubscribe(j,D)}onPostUpdate(j){return this._postUpdateHooks.push(j),()=>{let D=this._postUpdateHooks.indexOf(j);if(D!==-1)this._postUpdateHooks.splice(D,1)}}requireAssetManager(){if(!this._assetManager)throw Error("Asset manager not configured. Use withAssets() in builder.");return this._assetManager}getAsset(j){return this.requireAssetManager().get(j)}tryGetAsset(j){return this._assetManager?.tryGet(j)}getAssetHandle(j){return this.requireAssetManager().getHandle(j)}isAssetLoaded(j){return this._assetManager?.isLoaded(j)??!1}async loadAsset(j){return this.requireAssetManager().loadAsset(j)}async loadAssetGroup(j){return this.requireAssetManager().loadAssetGroup(j)}isAssetGroupLoaded(j){return this._assetManager?.isGroupLoaded(j)??!1}getAssetGroupProgress(j){return this._assetManager?.getGroupProgress(j)??0}requireScreenManager(){if(!this._screenManager)throw Error("Screen manager not configured. Use withScreens() in builder.");return this._screenManager}async setScreen(j,D){return this.requireScreenManager().setScreen(j,D)}async pushScreen(j,D){return this.requireScreenManager().pushScreen(j,D)}async popScreen(){return this.requireScreenManager().popScreen()}getCurrentScreen(){return this._screenManager?.getCurrentScreen()??null}getScreenConfig(j){return this.requireScreenManager().getConfig(j)}tryGetScreenConfig(j){return this._screenManager?.tryGetConfig(j)??void 0}getScreenState(j){return this.requireScreenManager().getState(j)}tryGetScreenState(j){return this._screenManager?.tryGetState(j)??void 0}updateScreenState(j,D){if(typeof j==="string")this.requireScreenManager().updateState(D,j);else this.requireScreenManager().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;for(let[D,$]of this._pendingPluginAssets)this._assetManager.register(D,$);this._pendingPluginAssets=[]}_setScreenManager(j){this._screenManager=j;for(let[D,$]of this._pendingPluginScreens)this._screenManager.register(D,$);this._pendingPluginScreens=[]}_hasPendingPluginAssets(){return this._pendingPluginAssets.length>0}_hasPendingPluginScreens(){return this._pendingPluginScreens.length>0}_setFixedDt(j){this._fixedDt=j}_registerAsset(j,D){this._pendingPluginAssets.push([j,D])}_registerScreen(j,D){this._pendingPluginScreens.push([j,D])}installPlugin(j){return this._installPluginUnchecked(j)}_installPluginUnchecked(j){if(this._installedPlugins.has(j.id))return this;return this._installedPlugins.add(j.id),j.install(this),this}pluginFactory(){return(j)=>M(j.id).install(j.install)}getHelpers(j){return j(this)}}function Tj(j){return j}function Cj(j,D){return{x:j,y:D}}function qj(){return{x:0,y:0}}function fj(j,D){return{x:j.x+D.x,y:j.y+D.y}}function gj(j,D){return{x:j.x-D.x,y:j.y-D.y}}function vj(j,D){return{x:j.x*D,y:j.y*D}}function Nj(j){return{x:-j.x,y:-j.y}}function pj(j,D){return j.x*D.x+j.y*D.y}function bj(j,D){return j.x*D.y-j.y*D.x}function hj(j){return j.x*j.x+j.y*j.y}function kj(j){return Math.sqrt(j.x*j.x+j.y*j.y)}function Ij(j){let D=Math.sqrt(j.x*j.x+j.y*j.y);if(D===0)return{x:0,y:0};return{x:j.x/D,y:j.y/D}}function uj(j,D){let $=j.x-D.x,G=j.y-D.y;return $*$+G*G}function sj(j,D){let $=j.x-D.x,G=j.y-D.y;return Math.sqrt($*$+G*G)}function mj(j,D,$=0.0000000001){return Math.abs(j.x-D.x)<=$&&Math.abs(j.y-D.y)<=$}function ij(j,D,$){return{x:j,y:D,z:$}}function lj(){return{x:0,y:0,z:0}}function cj(j,D){return{x:j.x+D.x,y:j.y+D.y,z:j.z+D.z}}function dj(j,D){return{x:j.x-D.x,y:j.y-D.y,z:j.z-D.z}}function yj(j,D){return{x:j.x*D,y:j.y*D,z:j.z*D}}function oj(j){return{x:-j.x,y:-j.y,z:-j.z}}function rj(j,D){return j.x*D.x+j.y*D.y+j.z*D.z}function aj(j,D){return{x:j.y*D.z-j.z*D.y,y:j.z*D.x-j.x*D.z,z:j.x*D.y-j.y*D.x}}function tj(j){return j.x*j.x+j.y*j.y+j.z*j.z}function nj(j){return Math.sqrt(j.x*j.x+j.y*j.y+j.z*j.z)}function ej(j){let D=Math.sqrt(j.x*j.x+j.y*j.y+j.z*j.z);if(D===0)return{x:0,y:0,z:0};return{x:j.x/D,y:j.y/D,z:j.z/D}}function j3(j,D){let $=j.x-D.x,G=j.y-D.y,J=j.z-D.z;return $*$+G*G+J*J}function D3(j,D){let $=j.x-D.x,G=j.y-D.y,J=j.z-D.z;return Math.sqrt($*$+G*G+J*J)}function $3(j,D,$=0.0000000001){return Math.abs(j.x-D.x)<=$&&Math.abs(j.y-D.y)<=$&&Math.abs(j.z-D.z)<=$}var U3=P;export{lj as vec3Zero,dj as vec3Sub,yj as vec3Scale,ej as vec3Normalize,oj as vec3Negate,tj as vec3LengthSq,nj as vec3Length,$3 as vec3Equals,rj as vec3Dot,j3 as vec3DistanceSq,D3 as vec3Distance,aj as vec3Cross,cj as vec3Add,ij as vec3,qj as vec2Zero,gj as vec2Sub,vj as vec2Scale,Ij as vec2Normalize,Nj as vec2Negate,hj as vec2LengthSq,kj as vec2Length,mj as vec2Equals,pj as vec2Dot,uj as vec2DistanceSq,sj as vec2Distance,bj as vec2Cross,fj as vec2Add,Cj as vec2,i as directValue,M as definePlugin,U3 as default,f as createScreenConfigurator,Tj as createQueryDefinition,q as createAssetConfigurator,S as SystemBuilder,A as ScreenManager,K as AssetManager};
1
+ var jj=((j)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(j,{get:(D,$)=>(typeof require<"u"?require:D)[$]}):j)(function(j){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+j+'" is not supported')});class E{parentMap=new Map;childrenMap=new Map;_bfsQueue=[];setParent(j,D){if(j===D)throw Error(`Cannot set entity ${j} as its own parent`);if(this.wouldCreateCycle(j,D))throw Error("Cannot set parent: would create circular reference");let $=this.parentMap.get(j);if($!==void 0){let J=this.childrenMap.get($);if(J){let X=J.indexOf(j);if(X!==-1)J.splice(X,1)}}this.parentMap.set(j,D);let G=this.childrenMap.get(D);if(G)G.push(j);else this.childrenMap.set(D,[j]);return this}removeParent(j){let D=this.parentMap.get(j);if(D===void 0)return!1;let $=this.childrenMap.get(D);if($){let G=$.indexOf(j);if(G!==-1)$.splice(G,1)}return this.parentMap.delete(j),!0}getParent(j){return this.parentMap.get(j)??null}getChildren(j){let D=this.childrenMap.get(j);return D?[...D]:[]}getChildAt(j,D){if(D<0)return null;let $=this.childrenMap.get(j);if(!$||D>=$.length)return null;return $[D]??null}getChildIndex(j,D){let $=this.childrenMap.get(j);if(!$)return-1;return $.indexOf(D)}removeEntity(j){let D=this.parentMap.get(j)??null;if(D!==null){let J=this.childrenMap.get(D);if(J){let X=J.indexOf(j);if(X!==-1)J.splice(X,1)}}this.parentMap.delete(j);let $=this.childrenMap.get(j)??[],G=[...$];for(let J of $)this.parentMap.delete(J);return this.childrenMap.delete(j),{oldParent:D,orphanedChildren:G}}getAncestors(j){let D=[],$=this.parentMap.get(j);while($!==void 0)D.push($),$=this.parentMap.get($);return D}getDescendants(j){let D=[],$=this.childrenMap.get(j);if(!$)return D;let G=$.slice().reverse();while(G.length>0){let J=G.pop();D.push(J);let X=this.childrenMap.get(J);if(X)for(let Z=X.length-1;Z>=0;Z--)G.push(X[Z])}return D}getRoot(j){let D=j,$=this.parentMap.get(D);while($!==void 0)D=$,$=this.parentMap.get(D);return D}getSiblings(j){let D=this.parentMap.get(j);if(D===void 0)return[];let $=this.childrenMap.get(D);if(!$)return[];return $.filter((G)=>G!==j)}isDescendantOf(j,D){if(j===D)return!1;let $=this.parentMap.get(j);while($!==void 0){if($===D)return!0;$=this.parentMap.get($)}return!1}isAncestorOf(j,D){return this.isDescendantOf(D,j)}get hasHierarchy(){return this.childrenMap.size>0}getRootEntities(){let j=[];for(let D of this.childrenMap.keys())if(!this.parentMap.has(D))j.push(D);return j}wouldCreateCycle(j,D){let $=D;while($!==void 0){if($===j)return!0;$=this.parentMap.get($)}return!1}forEachInHierarchy(j,D){let $=D?.roots??this.getRootEntities(),G=this._bfsQueue;G.length=0;for(let J of $)G.push(J,-1,0);for(let J=0;J<G.length;J+=3){let X=G[J],Z=G[J+1],F=G[J+2];j(X,Z===-1?null:Z,F);let _=this.childrenMap.get(X);if(_){let Q=F+1;for(let B of _)G.push(B,X,Q)}}}*hierarchyIterator(j){let D=j?.roots??this.getRootEntities(),$=[];for(let G of D)$.push({entityId:G,parentId:null,depth:0});for(let G of $){yield G;let J=this.childrenMap.get(G.entityId);if(J)for(let X of J)$.push({entityId:X,parentId:G.entityId,depth:G.depth+1})}}}function k(j,D){for(let $ of D)if(!($ in j))return!1;return!0}function I(j,D){for(let $ of D)if($ in j)return!0;return!1}function u(j,D,$){if(!j)return!1;for(let G of D)if((j.get(G)??-1)>$)return!0;return!1}class g{callbacks=[];_iterDepth=0;_pendingRemovals=[];add(j){this.callbacks.push(j)}remove(j){if(this._iterDepth>0){this._pendingRemovals.push(j);return}let D=this.callbacks.indexOf(j);if(D!==-1)this.callbacks.splice(D,1)}invoke(j){this._iterDepth++;let D=this.callbacks.length;for(let $=0;$<D;$++){let G=this.callbacks[$];if(G)G(j)}if(this._iterDepth--,this._iterDepth===0&&this._pendingRemovals.length>0){for(let $ of this._pendingRemovals){let G=this.callbacks.indexOf($);if(G!==-1)this.callbacks.splice(G,1)}this._pendingRemovals.length=0}}}class R{nextId=1;entities=new Map;componentIndices=new Map;addedCallbacks=new Map;removedCallbacks=new Map;hierarchyManager=new E;disposeCallbacks=new Map;changeSeqs=new Map;_changeSeq=0;_afterComponentAddedHooks=[];_afterEntityMutatedHooks=[];_afterComponentRemovedHooks=[];_beforeEntityRemovedHooks=[];_afterParentChangedHooks=[];_batchingDepth=0;_batchedEntityIds=new Set;_pendingBatchKeys=null;get entityCount(){return this.entities.size}createEntity(){let j=this.nextId++,D={id:j,components:{}};return this.entities.set(j,D),D}registerDispose(j,D){this.disposeCallbacks.set(j,D)}getDisposeCallbacks(){return this.disposeCallbacks}invokeDispose(j,D,$){let G=this.disposeCallbacks.get(j);if(!G)return;try{G({value:D,entityId:$})}catch(J){console.warn(`Component dispose callback for '${String(j)}' threw:`,J)}}addComponent(j,D,$){let G=this.entities.get(j);if(!G)throw Error(`Cannot add component '${String(D)}': Entity with ID ${j} does not exist`);let J=G.components[D];if(J!==void 0)this.invokeDispose(D,J,G.id);if(G.components[D]=$,!this.componentIndices.has(D))this.componentIndices.set(D,new Set);this.componentIndices.get(D)?.add(G.id);let X=this.addedCallbacks.get(D);if(X)X.invoke({value:$,entity:G});this._batchingDepth++;for(let Z of this._afterComponentAddedHooks)Z(G.id,D);if(this._batchedEntityIds.add(G.id),this._batchingDepth--,this._batchingDepth===0){for(let Z of this._batchedEntityIds)for(let F of this._afterEntityMutatedHooks)F(Z);this._batchedEntityIds.clear()}return this}addComponents(j,D){let $=this.entities.get(j);if(!$)throw Error(`Cannot add components: Entity with ID ${j} does not exist`);let G=this._pendingBatchKeys;this._pendingBatchKeys=new Set(Object.keys(D)),this._batchingDepth++;for(let J in D)this.addComponent($.id,J,D[J]);if(this._batchingDepth--,this._pendingBatchKeys=G,this._batchingDepth===0){for(let J of this._batchedEntityIds)for(let X of this._afterEntityMutatedHooks)X(J);this._batchedEntityIds.clear()}return this}removeComponent(j,D){let $=this.entities.get(j);if(!$)throw Error(`Cannot remove component '${String(D)}': Entity with ID ${j} does not exist`);let G=$.components[D];if(G!==void 0)this.invokeDispose(D,G,$.id);delete $.components[D];let J=this.removedCallbacks.get(D);if(J&&G!==void 0)J.invoke({value:G,entity:$});if(this.componentIndices.get(D)?.delete($.id),G!==void 0)for(let X of this._afterComponentRemovedHooks)X($.id,D);return this}getComponent(j,D){return this.entities.get(j)?.components[D]}getEntitiesWithQuery(j=[],D=[],$,G,J){return this.getEntitiesWithQueryInto([],j,D,$,G,J)}getEntitiesWithQueryInto(j,D=[],$=[],G,J,X){j.length=0;let Z=G!==void 0&&G.length>0&&J!==void 0,F=X!==void 0&&X.length>0;if(D.length===0){if($.length===0&&!Z&&!F){for(let W of this.entities.values())j.push(W);return j}for(let W of this.entities.values()){if($.length>0&&I(W.components,$))continue;if(Z&&!u(this.changeSeqs.get(W.id),G,J))continue;if(F&&!this.parentHasComponents(W.id,X))continue;j.push(W)}return j}let _=D[0];if(_===void 0)return j;let Q=_,B=this.componentIndices.get(_)?.size??0;for(let W=1;W<D.length;W++){let Y=D[W];if(Y===void 0)continue;let O=this.componentIndices.get(Y)?.size??0;if(O<B)Q=Y,B=O}let L=this.componentIndices.get(Q);if(!L||L.size===0)return j;for(let W of L){let Y=this.entities.get(W);if(!Y)continue;if(!k(Y.components,D))continue;if($.length>0&&I(Y.components,$))continue;if(Z&&!u(this.changeSeqs.get(W),G,J))continue;if(F&&!this.parentHasComponents(W,X))continue;j.push(Y)}return j}parentHasComponents(j,D){let $=this.hierarchyManager.getParent(j);if($===null)return!1;let G=this.entities.get($);if(!G)return!1;return k(G.components,D)}removeEntity(j,D){let $=this.entities.get(j);if(!$)return!1;if(D?.cascade??!0){let J=this.hierarchyManager.getDescendants($.id);for(let X=J.length-1;X>=0;X--){let Z=J[X];if(Z===void 0)continue;for(let F of this._beforeEntityRemovedHooks)F(Z)}for(let X of this._beforeEntityRemovedHooks)X($.id);for(let X=J.length-1;X>=0;X--){let Z=J[X];if(Z===void 0)continue;this.removeEntityInternal(Z)}}else for(let J of this._beforeEntityRemovedHooks)J($.id);return this.removeEntityInternal($.id)}removeEntityInternal(j){let D=this.entities.get(j);if(!D)return!1;this.hierarchyManager.removeEntity(j);for(let $ of Object.keys(D.components)){let G=D.components[$];if(G!==void 0){this.invokeDispose($,G,D.id);let J=this.removedCallbacks.get($);if(J)J.invoke({value:G,entity:D})}this.componentIndices.get($)?.delete(D.id)}return this.changeSeqs.delete(D.id),this.entities.delete(D.id)}getEntity(j){return this.entities.get(j)}onComponentAdded(j,D){let $=D,G=this.addedCallbacks.get(j);if(!G)G=new g,this.addedCallbacks.set(j,G);return G.add($),()=>{this.addedCallbacks.get(j)?.remove($)}}onComponentRemoved(j,D){let $=D,G=this.removedCallbacks.get(j);if(!G)G=new g,this.removedCallbacks.set(j,G);return G.add($),()=>{this.removedCallbacks.get(j)?.remove($)}}onAfterComponentAdded(j){return this._afterComponentAddedHooks.push(j),()=>{let D=this._afterComponentAddedHooks.indexOf(j);if(D!==-1)this._afterComponentAddedHooks.splice(D,1)}}onAfterEntityMutated(j){return this._afterEntityMutatedHooks.push(j),()=>{let D=this._afterEntityMutatedHooks.indexOf(j);if(D!==-1)this._afterEntityMutatedHooks.splice(D,1)}}onAfterComponentRemoved(j){return this._afterComponentRemovedHooks.push(j),()=>{let D=this._afterComponentRemovedHooks.indexOf(j);if(D!==-1)this._afterComponentRemovedHooks.splice(D,1)}}onBeforeEntityRemoved(j){return this._beforeEntityRemovedHooks.push(j),()=>{let D=this._beforeEntityRemovedHooks.indexOf(j);if(D!==-1)this._beforeEntityRemovedHooks.splice(D,1)}}onAfterParentChanged(j){return this._afterParentChangedHooks.push(j),()=>{let D=this._afterParentChangedHooks.indexOf(j);if(D!==-1)this._afterParentChangedHooks.splice(D,1)}}get changeSeq(){return this._changeSeq}markChanged(j,D){let $=++this._changeSeq,G=this.changeSeqs.get(j);if(!G)G=new Map,this.changeSeqs.set(j,G);G.set(D,$)}getChangeSeq(j,D){return this.changeSeqs.get(j)?.get(D)??-1}spawnChild(j,D){let $=this.createEntity();return this.addComponents($.id,D),this.setParent($.id,j),$}setParent(j,D){this.hierarchyManager.setParent(j,D);for(let $ of this._afterParentChangedHooks)$(j);return this}removeParent(j){let D=this.hierarchyManager.removeParent(j);if(D)for(let $ of this._afterParentChangedHooks)$(j);return D}getParent(j){return this.hierarchyManager.getParent(j)}getChildren(j){return this.hierarchyManager.getChildren(j)}getChildAt(j,D){return this.hierarchyManager.getChildAt(j,D)}getChildIndex(j,D){return this.hierarchyManager.getChildIndex(j,D)}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,D){return this.hierarchyManager.isDescendantOf(j,D)}isAncestorOf(j,D){return this.hierarchyManager.isAncestorOf(j,D)}get hasHierarchy(){return this.hierarchyManager.hasHierarchy}getRootEntities(){return this.hierarchyManager.getRootEntities()}forEachInHierarchy(j,D){this.hierarchyManager.forEachInHierarchy(j,D)}hierarchyIterator(j){return this.hierarchyManager.hierarchyIterator(j)}}class w{handlers=new Map;subscribe(j,D){return this.addHandler(j,D,!1)}once(j,D){return this.addHandler(j,D,!0)}unsubscribe(j,D){let $=this.handlers.get(j);if(!$)return!1;let G=$.findIndex((J)=>J.callback===D);if(G===-1)return!1;return $.splice(G,1),!0}addHandler(j,D,$){let G=this.handlers.get(j);if(!G)G=[],this.handlers.set(j,G);let J={callback:D,once:$};return G.push(J),()=>{let X=this.handlers.get(j);if(X){let Z=X.indexOf(J);if(Z!==-1)X.splice(Z,1)}}}publish(...[j,D]){let $=this.handlers.get(j);if(!$||$.length===0)return;let G=!1,J=$.length;for(let X=0;X<J&&X<$.length;X++){let Z=$[X];if(!Z)continue;if(Z.callback(D),Z.once)G=!0}if(G){for(let X=$.length-1;X>=0;X--)if($[X]?.once)$.splice(X,1)}}clear(){this.handlers.clear()}clearEvent(j){this.handlers.delete(j)}}var v=Symbol("resource-direct");function r(j){return{[v]:j}}function f(j){if(typeof j==="object"&&j!==null&&!Array.isArray(j))return{...j};return{$value:j}}function a(j,D){if(typeof j==="object"&&j!==null&&!Array.isArray(j)){let $=j;for(let G in D)if(!Object.is($[G],D[G]))return!0;return!1}return!Object.is(j,D.$value)}function n(j){return typeof j==="object"&&j!==null&&"factory"in j&&typeof j.factory==="function"}function t(j){return typeof j==="object"&&j!==null&&v in j}function m(j,D){let $=[],G=new Set,J=new Set;function X(Z,F=[]){if(G.has(Z))return;if(J.has(Z))throw Error(`Circular resource dependency: ${[...F,Z].join(" -> ")}`);J.add(Z);for(let _ of D(Z)){let Q=j.find((B)=>B===_);if(Q)X(Q,[...F,Z])}J.delete(Z),G.add(Z),$.push(Z)}for(let Z of j)X(Z);return $}class S{resources=new Map;resourceFactories=new Map;resourceDependencies=new Map;resourceDisposers=new Map;initializedResourceKeys=new Set;_changeSubscribers=new Map;_observedSnapshots=new Map;add(j,D){let $=(G)=>{this.resources.set(j,G),this.initializedResourceKeys.add(j),this.resourceDependencies.set(j,[])};if(n(D)){if(this.resourceFactories.set(j,D.factory),this.resourceDependencies.set(j,D.dependsOn??[]),D.onDispose)this.resourceDisposers.set(j,D.onDispose)}else if(t(D))$(D[v]);else if(typeof D==="function")this.resourceFactories.set(j,D),this.resourceDependencies.set(j,[]);else $(D);return this}tryGet(j,...D){if(!this.has(j))return;return this.get(j,...D)}get(j,...D){let $=this.resources.get(j);if($!==void 0)return $;let G=this.resourceFactories.get(j);if(G===void 0)throw Error(`Resource ${String(j)} not found`);let J=D[0],X=G(J);if(!(X instanceof Promise))this.resources.set(j,X),this.initializedResourceKeys.add(j);return X}has(j){return this.resources.has(j)||this.resourceFactories.has(j)}remove(j){let D=this.resources.delete(j),$=this.resourceFactories.delete(j);return this.resourceDependencies.delete(j),this.resourceDisposers.delete(j),this.initializedResourceKeys.delete(j),D||$}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,...D){if(!this.resourceFactories.has(j)||this.initializedResourceKeys.has(j))return;let $=this.resourceFactories.get(j);if(!$)return;let G=D[0],J=await $(G);this.resources.set(j,J),this.initializedResourceKeys.add(j),this.resourceFactories.delete(j)}async initializeResources(...j){let D=j.slice(1),$=D.length===0?this.getPendingInitializationKeys():D;if($.length===0)return;let G=m($,(J)=>[...this.resourceDependencies.get(J)??[]]);for(let J of G)await this.initializeResource(J,...j.slice(0,1))}getDependencies(j){return this.resourceDependencies.get(j)??[]}async disposeResource(j,...D){if(!this.resources.has(j)&&!this.resourceFactories.has(j))return!1;if(this.initializedResourceKeys.has(j)){let $=this.resourceDisposers.get(j),G=this.resources.get(j);if($&&G!==void 0){let J=D[0];await $(G,J)}}return this.resources.delete(j),this.resourceFactories.delete(j),this.resourceDependencies.delete(j),this.resourceDisposers.delete(j),this.initializedResourceKeys.delete(j),this._changeSubscribers.delete(j),!0}onResourceChange(j,D){let $=this._changeSubscribers.get(j),G=$??new Set;if(!$){this._changeSubscribers.set(j,G);let X=this.resources.get(j);this._observedSnapshots.set(j,f(X))}let J=D;return G.add(J),()=>{if(G.delete(J),G.size===0)this._changeSubscribers.delete(j),this._observedSnapshots.delete(j)}}notifyChange(j,D,$){if(Object.is(D,$))return;let G=this._changeSubscribers.get(j);if(!G||G.size===0)return;if(this._observedSnapshots.has(j))this._observedSnapshots.set(j,f(D));let J=[...G];for(let X of J)X(D,$)}isObserved(j){return this._observedSnapshots.has(j)}flushObserved(){if(this._observedSnapshots.size===0)return;for(let[j,D]of this._observedSnapshots){let $=this.resources.get(j);if(!a($,D))continue;let G="$value"in D?D.$value:D,J=f($),X=this._changeSubscribers.get(j);for(let Z of X)Z($,G);this._observedSnapshots.set(j,J)}}async disposeResources(...j){let D=Array.from(this.initializedResourceKeys);if(D.length===0)return;let $=m(D,(G)=>[...this.resourceDependencies.get(G)??[]]).reverse();for(let G of $)await this.disposeResource(G,...j)}}class T{queries=new Map;entityManager;_hasParentHasQueries=!1;constructor(j){this.entityManager=j}get hasParentHasQueries(){return this._hasParentHasQueries}addQuery(j,D){let $={definition:D,matchingEntities:new Set};if(this.queries.set(j,$),D.parentHas?.length)this._hasParentHasQueries=!0;let G=this.entityManager.getEntitiesWithQuery(D.with,D.without??[]);for(let J of G)if(this.entityMatchesQuery(J,$.definition))$.matchingEntities.add(J.id),$.definition.onEnter?.(J)}removeQuery(j){let D=this.queries.delete(j);if(D)this._recalcParentHasFlag();return D}entityMatchesQuery(j,D){for(let $ of D.with)if(!($ in j.components))return!1;if(D.without){for(let $ of D.without)if($ in j.components)return!1}if(D.parentHas?.length){let $=this.entityManager.getParent(j.id);if($===null)return!1;let G=this.entityManager.getEntity($);if(!G)return!1;for(let J of D.parentHas)if(!(J in G.components))return!1}return!0}_applyQueryTransition(j,D){let $=D.matchingEntities.has(j.id),G=this.entityMatchesQuery(j,D.definition);if(!$&&G)D.matchingEntities.add(j.id),D.definition.onEnter?.(j);else if($&&!G)D.matchingEntities.delete(j.id),D.definition.onExit?.(j.id)}onComponentAdded(j,D){for(let[,$]of this.queries)this._applyQueryTransition(j,$);if(this._hasParentHasQueries)this._recheckChildren(j.id)}onComponentRemoved(j,D){for(let[,$]of this.queries)this._applyQueryTransition(j,$);if(this._hasParentHasQueries)this._recheckChildren(j.id)}onEntityRemoved(j){for(let[D,$]of this.queries)if($.matchingEntities.has(j))$.matchingEntities.delete(j),$.definition.onExit?.(j)}recheckEntity(j){for(let[,D]of this.queries)this._applyQueryTransition(j,D)}recheckEntityAndChildren(j){if(this.recheckEntity(j),this._hasParentHasQueries)this._recheckChildren(j.id)}_recheckChildren(j){let D=this.entityManager.getChildren(j);for(let $ of D){let G=this.entityManager.getEntity($);if(G)this.recheckEntity(G)}}_recalcParentHasFlag(){this._hasParentHasQueries=!1;for(let[,j]of this.queries)if(j.definition.parentHas?.length){this._hasParentHasQueries=!0;return}}}class x{commands=[];removeEntity(j,D){this.commands.push(($)=>{$.removeEntity(j,D)})}addComponent(j,D,$){this.commands.push((G)=>{G.addComponent(j,D,$)})}removeComponent(j,D){this.commands.push(($)=>{$.removeComponent(j,D)})}spawn(j,D){this.commands.push(($)=>{$.spawn(j,D)})}spawnChild(j,D,$){this.commands.push((G)=>{G.spawnChild(j,D,$)})}addComponents(j,D){this.commands.push(($)=>{$.addComponents(j,D)})}setParent(j,D){this.commands.push(($)=>{$.setParent(j,D)})}mutateComponent(j,D,$){this.commands.push((G)=>{G.mutateComponent(j,D,$)})}markChanged(j,D){this.commands.push(($)=>{$.markChanged(j,D)})}removeParent(j){this.commands.push((D)=>{D.removeParent(j)})}playback(j){for(let D of this.commands)try{D(j)}catch($){console.warn("CommandBuffer: Command failed during playback:",$)}this.commands.length=0}clear(){this.commands.length=0}get length(){return this.commands.length}}class l{_id;constructor(j){this._id=j}_systemDefaults;setSystemDefaults(j){return this._systemDefaults=j,this}withComponentTypes(){return this}withEventTypes(){return this}withResourceTypes(){return this}withAssetTypes(){return this}withScreenTypes(){return this}withLabels(){return this}withGroups(){return this}withAssetGroupNames(){return this}withReactiveQueryNames(){return this}requires(){return this}install(j){return{id:this._id,install:j,...this._systemDefaults?{systemDefaults:this._systemDefaults}:{}}}}function V(j){return new l(j)}var s="__each";class C{_label;queries={};singletons={};processFunction;detachFunction;initializeFunction;eventHandlers;_priority=0;_phase="update";_groups=[];_inScreens;_excludeScreens;_requiredAssets;_runWhenEmpty=!1;_entityEnterHandlers={};_resourceKeys;constructor(j,D){this._label=j;if(D){if(D.phase!==void 0)this._phase=D.phase;if(D.priority!==void 0)this._priority=D.priority;if(D.inScreens!==void 0)this._inScreens=D.inScreens;if(D.excludeScreens!==void 0)this._excludeScreens=D.excludeScreens}}get label(){return this._label}_createSystemObject(){let j={label:this._label,entityQueries:this.queries,priority:this._priority,phase:this._phase};if(Object.keys(this.singletons).length>0)j.entitySingletons=this.singletons;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;if(this._runWhenEmpty)j.runWhenEmpty=!0;if(Object.keys(this._entityEnterHandlers).length>0)j.onEntityEnter={...this._entityEnterHandlers};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}runWhenEmpty(){return this._runWhenEmpty=!0,this}withResources(j){return this._resourceKeys=[...j],this}addQuery(j,D){let $=this;return $.queries={...this.queries,[j]:D},$}addSingleton(j,D){let $=this;return $.singletons={...this.singletons,[j]:D},$}setProcess(j){return this.processFunction=this._wrapWithResources(j),this}_wrapWithResources(j){if(!this._resourceKeys?.length)return j;let D=this._resourceKeys,$={},G=!1;return(J)=>{for(let X of D)if(!G||J.ecs.isResourceObserved(X))$[X]=J.ecs.getResource(X);G=!0,J.resources=$,j(J)}}setProcessEach(j,D){let $=this;if(Object.keys($.queries).length>0||Object.keys($.singletons).length>0||$.processFunction!==void 0)throw Error("setProcessEach requires a SystemBuilder with no prior queries, singletons, or process function. Use addQuery + setProcess for multi-query systems.");$.queries.__each=j;let G={entity:void 0,dt:0,ecs:void 0,resources:void 0},J=j.mutates&&j.mutates.length>0?j.mutates:void 0,X=(Z)=>{let F=Z,_=F.queries.__each;if(!_)return;G.dt=F.dt,G.ecs=F.ecs,G.resources=F.resources;for(let Q=0;Q<_.length;Q++){let B=_[Q];if(!B)continue;G.entity=B;let L=D(G);if(J===void 0||L===!1)continue;for(let W=0;W<J.length;W++){let Y=J[W];if(Y!==void 0)F.ecs.markChanged(B.id,Y)}}};return $.processFunction=$._wrapWithResources(X),this}setOnEntityEnter(j,D){return this._entityEnterHandlers[j]=D,this}setOnDetach(j){return this.detachFunction=j,this}setOnInitialize(j){return this.initializeFunction=j,this}setEventHandlers(j){return this.eventHandlers=j,this}}function i(j,D,$){let G=new Set,J=[D];while(J.length>0){let X=J.pop();if(X===void 0)break;if(X===j)throw Error(`Circular required component dependency: '${String(j)}' -> '${String(D)}' -> ... -> '${String(j)}'`);if(G.has(X))continue;G.add(X);let Z=$(X);if(Z)for(let F of Z)J.push(F.component)}}var c="0.15.0";class z{assets=new Map;groups=new Map;eventBus=null;setEventBus(j){this.eventBus=j}register(j,D){if(this.assets.set(j,{definition:D,status:"pending"}),D.group){let $=this.groups.get(D.group)??new Set;$.add(j),this.groups.set(D.group,$)}}async loadEagerAssets(){let j=[];for(let[D,$]of this.assets)if($.definition.eager&&$.status==="pending")j.push(D);await Promise.all(j.map((D)=>this.loadAsset(D)))}async loadAsset(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);if(D.status==="loaded"&&D.value!==void 0)return D.value;if(D.status==="loading"&&D.loadPromise)return D.loadPromise;if(D.status==="failed")D.status="pending";D.status="loading",D.loadPromise=D.definition.loader();try{let $=await D.loadPromise;return D.value=$,D.status="loaded",D.loadPromise=void 0,this.eventBus?.publish("assetLoaded",{key:j}),this.checkGroupProgress(D.definition.group),$}catch($){let G=$ instanceof Error?$:Error(String($));throw D.status="failed",D.error=G,D.loadPromise=void 0,this.eventBus?.publish("assetFailed",{key:j,error:G}),G}}async loadAssetGroup(j){let D=this.groups.get(j);if(!D||D.size===0)throw Error(`Asset group '${j}' not found or empty`);await Promise.all(Array.from(D).map(($)=>this.loadAsset($)))}get(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);if(D.status!=="loaded"||D.value===void 0)throw Error(`Asset '${String(j)}' is not loaded (status: ${D.status})`);return D.value}tryGet(j){let D=this.assets.get(j);if(!D||D.status!=="loaded")return;return D.value}getHandle(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);let $=this;return{get status(){return D.status},get isLoaded(){return D.status==="loaded"},get(){return $.get(j)},tryGet(){return $.tryGet(j)}}}getStatus(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);return D.status}isLoaded(j){return this.assets.get(j)?.status==="loaded"}isGroupLoaded(j){let D=this.groups.get(j);if(!D||D.size===0)return!1;for(let $ of D){let G=this.assets.get($);if(!G||G.status!=="loaded")return!1}return!0}getGroupProgress(j){return this.getGroupProgressDetails(j).progress}getGroupProgressDetails(j){let D=this.groups.get(j);if(!D||D.size===0)return{loaded:0,total:0,progress:0};let $=0;for(let J of D)if(this.assets.get(J)?.status==="loaded")$++;let G=D.size;return{loaded:$,total:G,progress:$/G}}checkGroupProgress(j){if(!j||!this.eventBus)return;let D=j,$=this.getGroupProgressDetails(D);if(this.eventBus.publish("assetGroupProgress",{group:D,...$}),$.loaded===$.total)this.eventBus.publish("assetGroupLoaded",{group:D})}createResource(){let j=this;return{getStatus(D){return j.getStatus(D)},isLoaded(D){return j.isLoaded(D)},isGroupLoaded(D){return j.isGroupLoaded(D)},getGroupProgress(D){return j.getGroupProgress(D)},get(D){return j.get(D)},tryGet(D){return j.tryGet(D)},getHandle(D){return j.getHandle(D)}}}getKeys(){return Array.from(this.assets.keys())}getGroupNames(){return Array.from(this.groups.keys())}getGroupKeys(j){let D=this.groups.get(j);return D?Array.from(D):[]}}class d{manager;constructor(j){this.manager=j}add(j,D){return this.manager.register(j,{loader:D,eager:!0}),this}addWithConfig(j,D){return this.manager.register(j,D),this}addGroup(j,D){for(let[$,G]of Object.entries(D))this.manager.register($,{loader:G,eager:!1,group:j});return this}getManager(){return this.manager}}function N(j){return new d(j??new z)}class H{screens=new Map;currentScreen=null;screenStack=[];eventBus=null;assetManager=null;ecs=null;setDependencies(j,D,$){this.eventBus=j,this.assetManager=D,this.ecs=$}requireEcs(){if(!this.ecs)throw Error("ScreenManager: dependencies not set. Call setDependencies() first.");return this.ecs}register(j,D){this.screens.set(j,{definition:D})}async setScreen(j,D){let $=this.screens.get(j);if(!$)throw Error(`Screen '${String(j)}' not found`);await this.verifyRequiredAssets($.definition.requiredAssets,$.definition.requiredAssetGroups);while(this.screenStack.length>0){let J=this.screenStack.pop();if(J)await this.exitScreen(J.name)}if(this.currentScreen)await this.exitScreen(this.currentScreen.name);let G=$.definition.initialState(D);this.currentScreen={name:j,config:D,state:G},await $.definition.onEnter?.({config:D,ecs:this.requireEcs()}),this.eventBus?.publish("screenEnter",{screen:j,config:D})}async pushScreen(j,D){let $=this.screens.get(j);if(!$)throw Error(`Screen '${String(j)}' not found`);if(await this.verifyRequiredAssets($.definition.requiredAssets,$.definition.requiredAssetGroups),this.currentScreen)this.screenStack.push(this.currentScreen);let G=$.definition.initialState(D);this.currentScreen={name:j,config:D,state:G},await $.definition.onEnter?.({config:D,ecs:this.requireEcs()}),this.eventBus?.publish("screenPush",{screen:j,config:D})}async popScreen(){if(this.screenStack.length===0)throw Error("Cannot pop screen: stack is empty");if(this.currentScreen)await this.exitScreen(this.currentScreen.name),this.eventBus?.publish("screenPop",{screen:this.currentScreen.name});this.currentScreen=this.screenStack.pop()??null}async exitScreen(j){let D=this.screens.get(j);if(D?.definition.onExit)await D.definition.onExit(this.requireEcs());this.eventBus?.publish("screenExit",{screen:j})}async verifyRequiredAssets(j,D){if(!this.assetManager)return;if(j){for(let $ of j)if(!this.assetManager.isLoaded($))await this.assetManager.loadAsset($)}if(D){for(let $ of D)if(!this.assetManager.isGroupLoaded($))await this.assetManager.loadAssetGroup($)}}getCurrentScreen(){return this.currentScreen?.name??null}getConfig(j){if(!this.currentScreen)throw Error("No current screen");if(j!==void 0&&this.currentScreen.name!==j)throw Error(`Expected current screen '${String(j)}', but current is '${String(this.currentScreen.name)}'`);return this.currentScreen.config}tryGetConfig(j){if(!this.currentScreen)return;if(j!==void 0&&this.currentScreen.name!==j)return;return this.currentScreen.config}getState(j){if(!this.currentScreen)throw Error("No current screen");if(j!==void 0&&this.currentScreen.name!==j)throw Error(`Expected current screen '${String(j)}', but current is '${String(this.currentScreen.name)}'`);return this.currentScreen.state}tryGetState(j){if(!this.currentScreen)return;if(j!==void 0&&this.currentScreen.name!==j)return;return this.currentScreen.state}updateState(j,D){if(!this.currentScreen)throw Error("No current screen");if(D!==void 0&&this.currentScreen.name!==D)throw Error(`Expected current screen '${String(D)}', but current is '${String(this.currentScreen.name)}'`);let $=typeof j==="function"?j(this.currentScreen.state):j;this.currentScreen.state={...this.currentScreen.state,...$}}getStackDepth(){return this.screenStack.length}isOverlay(){return this.screenStack.length>0}isActive(j){if(this.currentScreen?.name===j)return!0;return this.screenStack.some((D)=>D.name===j)}isCurrent(j){return this.currentScreen?.name===j}createResource(){let j=this;return{get current(){return j.getCurrentScreen()},get config(){return j.tryGetConfig()??null},get state(){return j.tryGetState()??null},set state(D){if(j.currentScreen&&D!==null)j.currentScreen.state=D},get stack(){return j.screenStack},get isOverlay(){return j.isOverlay()},get stackDepth(){return j.getStackDepth()},isActive(D){return j.isActive(D)},isCurrent(D){return j.isCurrent(D)}}}getScreenNames(){return Array.from(this.screens.keys())}hasScreen(j){return this.screens.has(j)}}class y{manager;constructor(j){this.manager=j}add(j,D){return this.manager.register(j,D),this}getManager(){return this.manager}}function b(j){return new y(j??new H)}class p{assetConfigurator=null;screenConfigurator=null;pendingResources=[];pendingDisposeCallbacks=[];pendingRequiredComponents=[];pendingPlugins=[];_fixedDt=null;constructor(){}withPlugin(j){return this.pendingPlugins.push(j),this}withComponentTypes(){return this}withEventTypes(){return this}withResourceTypes(){return this}withResource(j,D){return this.pendingResources.push({key:j,value:D}),this}withDispose(j,D){return this.pendingDisposeCallbacks.push({key:j,callback:D}),this}withRequired(j,D,$){return this.pendingRequiredComponents.push({trigger:j,required:D,factory:$}),this}withAssets(j){let D=N();return j(D),this.assetConfigurator=D,this}withScreens(j){let D=b();return j(D),this.screenConfigurator=D,this}withFixedTimestep(j){return this._fixedDt=j,this}withReactiveQueryNames(){return this}pluginFactory(){return(j)=>V(j.id).install(j.install)}build(){let j=new P;for(let D of this.pendingPlugins)j._installPluginUnchecked(D);for(let{key:D,value:$}of this.pendingResources)j.addResource(D,$);for(let{key:D,callback:$}of this.pendingDisposeCallbacks)j.registerDispose(D,$);for(let{trigger:D,required:$,factory:G}of this.pendingRequiredComponents)j.registerRequired(D,$,G);if(this.assetConfigurator)j._setAssetManager(this.assetConfigurator.getManager());else if(j._hasPendingPluginAssets())j._setAssetManager(new z);if(this.screenConfigurator)j._setScreenManager(this.screenConfigurator.getManager());else if(j._hasPendingPluginScreens())j._setScreenManager(new H);if(this._fixedDt!==null)j._setFixedDt(this._fixedDt);return j}}var o=["preUpdate","fixedUpdate","update","postUpdate","render"];class P{static VERSION=c;_entityManager;_eventBus;_resourceManager;_commandBuffer;_systems=[];_phaseSystems={preUpdate:[],fixedUpdate:[],update:[],postUpdate:[],render:[]};_installedPlugins=new Set;_pluginCleanups=new Map;_currentSystemDefaults;_screenScopedEntities=new Map;_entityScreenScope=new Map;_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;_requiredComponents=new Map;_pendingPluginAssets=[];_pendingPluginScreens=[];_diagnosticsEnabled=!1;_systemTimings=new Map;_phaseTimings={preUpdate:0,fixedUpdate:0,update:0,postUpdate:0,render:0};_entityEnterTracking=new Map;_entityEnterFrameSet=new Set;_systemContexts=new WeakMap;_singletonScratch=[];_pendingFinalizers=[];_batchingRegistrations=!1;constructor(){this._entityManager=new R,this._eventBus=new w,this._resourceManager=new S,this._reactiveQueryManager=new T(this._entityManager),this._commandBuffer=new x,this._subscribeLifecycleHooks()}_subscribeLifecycleHooks(){this._entityManager.onAfterComponentAdded((j,D)=>{this._entityManager.markChanged(j,D);let $=this._requiredComponents.get(D);if($){let G=this._entityManager.getEntity(j);if(G){let J=G.components[D];for(let{component:X,factory:Z}of $){if(this._entityManager._pendingBatchKeys?.has(X))continue;if(!(X in G.components))this._entityManager.addComponent(j,X,Z(J))}}}}),this._entityManager.onAfterEntityMutated((j)=>{let D=this._entityManager.getEntity(j);if(D)this._reactiveQueryManager.recheckEntityAndChildren(D)}),this._entityManager.onAfterComponentRemoved((j,D)=>{let $=this._entityManager.getEntity(j);if($)this._reactiveQueryManager.onComponentRemoved($,D)}),this._entityManager.onBeforeEntityRemoved((j)=>{this._reactiveQueryManager.onEntityRemoved(j);let D=this._entityScreenScope.get(j);if(D!==void 0)this._entityScreenScope.delete(j),this._screenScopedEntities.get(D)?.delete(j)}),this._entityManager.onAfterParentChanged((j)=>{if(this._reactiveQueryManager.hasParentHasQueries){let D=this._entityManager.getEntity(j);if(D)this._reactiveQueryManager.recheckEntity(D)}})}static create(){return new p}addSystem(j){let D=new C(j,this._currentSystemDefaults);return this._pendingFinalizers.push(()=>{this._registerSystem(D._createSystemObject())}),D}_finalizePendingBuilders(){if(this._pendingFinalizers.length===0)return;this._batchingRegistrations=!0;while(this._pendingFinalizers.length>0){let j=this._pendingFinalizers;this._pendingFinalizers=[];for(let D of j)D()}this._batchingRegistrations=!1,this._rebuildPhaseSystems()}update(j){this._finalizePendingBuilders();let D=this._screenManager?.getCurrentScreen()??null,$=this._diagnosticsEnabled;this._runPhase("preUpdate",j,D,$);let G=$?performance.now():0;this._fixedAccumulator+=j;let J=0;while(this._fixedAccumulator>=this._fixedDt&&J<this._maxFixedSteps)this._executePhase(this._phaseSystems.fixedUpdate,this._fixedDt,D),this._commandBuffer.playback(this),this._fixedAccumulator-=this._fixedDt,J++;if(this._fixedAccumulator>=this._fixedDt)this._fixedAccumulator=0;if($)this._phaseTimings.fixedUpdate=performance.now()-G;this._interpolationAlpha=this._fixedAccumulator/this._fixedDt,this._runPhase("update",j,D,$),this._runPhase("postUpdate",j,D,$);for(let X of this._postUpdateHooks)X({ecs:this,dt:j});this._runPhase("render",j,D,$),this._resourceManager.flushObserved(),this._changeThreshold=this._entityManager.changeSeq,this._currentTick++}_executePhase(j,D,$){for(let G of j){if(!G.process&&!G.onEntityEnter)continue;if(G.groups?.length){let L=!1;for(let W of G.groups)if(this._disabledGroups.has(W)){L=!0;break}if(L)continue}if(G.inScreens?.length){if($===null||!G.inScreens.includes($))continue}if(G.excludeScreens?.length){if($!==null&&G.excludeScreens.includes($))continue}if(G.requiredAssets?.length&&this._assetManager){let L=!0;for(let W of G.requiredAssets)if(!this._assetManager.isLoaded(W)){L=!1;break}if(!L)continue}let J=this._systemLastSeqs.get(G)??0;this._changeThreshold=J;let X=this._systemContexts.get(G);if(!X)X={queries:{},dt:0,ecs:this},this._systemContexts.set(G,X);X.dt=D;let Z=X.queries,F=!1,_=!1;if(G.entityQueries)for(let L in G.entityQueries){_=!0;let W=G.entityQueries[L];if(W){let O=Z[L]??(Z[L]=[]);if(this._entityManager.getEntitiesWithQueryInto(O,W.with,W.without||[],W.changed,W.changed?this._changeThreshold:void 0,W.parentHas),O.length)F=!0}}if(G.entitySingletons){let L=this._singletonScratch;for(let W in G.entitySingletons){_=!0;let Y=G.entitySingletons[W];if(Y){if(this._entityManager.getEntitiesWithQueryInto(L,Y.with,Y.without||[],Y.changed,Y.changed?this._changeThreshold:void 0,Y.parentHas),Z[W]=L[0],L.length)F=!0}}}let Q=this._entityEnterTracking.get(G);if(Q&&G.onEntityEnter)for(let L in G.onEntityEnter){let W=Z[L],Y=Q.get(L);if(!W||!Y)continue;let O=G.onEntityEnter[L];if(!O)continue;let A=this._entityEnterFrameSet;A.clear();for(let K of W)if(A.add(K.id),!Y.has(K.id))Y.add(K.id),O({entity:K,ecs:this});for(let K of Y)if(!A.has(K))Y.delete(K)}if(G.process){if(this._diagnosticsEnabled){let L=performance.now();if(F||G.runWhenEmpty)G.process(X);else if(!_)G.process(X);this._systemTimings.set(G.label,performance.now()-L)}else if(F||G.runWhenEmpty)G.process(X);else if(!_)G.process(X)}let B=G._autoMarkPairs;if(B){let L=this._entityManager;for(let W=0;W<B.length;W++){let Y=B[W];if(!Y)continue;let O=Y.mutates,A=O.length;if(Y.kind==="list"){let K=Z[Y.queryName];if(!K)continue;for(let U=0;U<K.length;U++){let M=K[U];if(!M)continue;for(let q=0;q<A;q++){let h=O[q];if(h!==void 0)L.markChanged(M.id,h)}}}else{let K=Z[Y.queryName];if(!K)continue;for(let U=0;U<A;U++){let M=O[U];if(M!==void 0)L.markChanged(K.id,M)}}}}this._systemLastSeqs.set(G,this._entityManager.changeSeq)}}_runPhase(j,D,$,G){if(G){let J=performance.now();this._executePhase(this._phaseSystems[j],D,$),this._phaseTimings[j]=performance.now()-J}else this._executePhase(this._phaseSystems[j],D,$);this._commandBuffer.playback(this)}async initialize(){if(this._finalizePendingBuilders(),await this.initializeResources(),this._assetManager)this._assetManager.setEventBus(this._eventBus),await this._assetManager.loadEagerAssets(),this._resourceManager.add("$assets",this._assetManager.createResource());if(this._screenManager){let j=this._eventBus;this._screenManager.setDependencies(j,this._assetManager,this),this._resourceManager.add("$screen",this._screenManager.createResource()),j.subscribe("screenExit",({screen:D})=>{let $=this._screenScopedEntities.get(D);if(!$||$.size===0)return;this._screenScopedEntities.delete(D);for(let G of Array.from($))this._entityScreenScope.delete(G),this.removeEntity(G)})}for(let j of this._systems)await j.onInitialize?.(this)}async initializeResources(...j){await this._resourceManager.initializeResources(this,...j)}_rebuildPhaseSystems(){for(let j of o)this._phaseSystems[j]=[];for(let j of this._systems){let D=j.phase??"update";this._phaseSystems[D].push(j)}for(let j of o)this._phaseSystems[j].sort((D,$)=>{let G=D.priority??0;return($.priority??0)-G})}updateSystemPriority(j,D){this._finalizePendingBuilders();let $=this._systems.find((G)=>G.label===j);if(!$)return!1;return $.priority=D,this._rebuildPhaseSystems(),!0}updateSystemPhase(j,D){this._finalizePendingBuilders();let $=this._systems.find((G)=>G.label===j);if(!$)return!1;return $.phase=D,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._finalizePendingBuilders(),this._systems.filter((D)=>D.groups?.includes(j)).map((D)=>D.label)}removeSystem(j){this._finalizePendingBuilders();let D=this._systems.findIndex((G)=>G.label===j);if(D===-1)return!1;let $=this._systems[D];if(!$)return!1;if($.onDetach)$.onDetach(this);return this._systems.splice(D,1),this._systemLastSeqs.delete($),this._entityEnterTracking.delete($),this._rebuildPhaseSystems(),!0}_registerSystem(j){if(this._systems.push(j),this._systemLastSeqs.set(j,this._changeThreshold),!this._batchingRegistrations)this._rebuildPhaseSystems();let D=[];if(j.entityQueries)for(let $ in j.entityQueries){if($===s)continue;let J=j.entityQueries[$]?.mutates;if(J&&J.length>0)D.push({queryName:$,mutates:J,kind:"list"})}if(j.entitySingletons)for(let $ in j.entitySingletons){let J=j.entitySingletons[$]?.mutates;if(J&&J.length>0)D.push({queryName:$,mutates:J,kind:"singleton"})}if(j._autoMarkPairs=D.length>0?D:null,j.onEntityEnter){let $=new Map;for(let G in j.onEntityEnter)$.set(G,new Set);this._entityEnterTracking.set(j,$)}if(!j.eventHandlers)return;for(let $ in j.eventHandlers){let G=j.eventHandlers[$];if(G)this._eventBus.subscribe($,(J)=>{G({data:J,ecs:this})})}}hasResource(j){return this._resourceManager.has(j)}getResource(j){if(!this._resourceManager.has(j))throw Error(`Resource '${String(j)}' not found. Available resources: [${this.getResourceKeys().map((D)=>String(D)).join(", ")}]`);return this._resourceManager.get(j,this)}tryGetResource(j){let D=j;if(!this._resourceManager.has(D))return;return this._resourceManager.get(D,this)}addResource(j,D){return this._resourceManager.add(j,D),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,D){let $=this.getResource(j),G=D($);return this._resourceManager.add(j,G),this._resourceManager.notifyChange(j,G,$),this}setResource(j,D){let $=this.tryGetResource(j);if(this._resourceManager.add(j,D),$!==void 0)this._resourceManager.notifyChange(j,D,$);return this}onResourceChange(j,D){return this._resourceManager.onResourceChange(j,D)}isResourceObserved(j){return this._resourceManager.isObserved(j)}getResourceKeys(){return this._resourceManager.getKeys()}resourceNeedsInitialization(j){return this._resourceManager.needsInitialization(j)}getEntity(j){return this._entityManager.getEntity(j)}getComponent(j,D){return this._entityManager.getComponent(j,D)}addComponent(j,D,$){this._entityManager.addComponent(j,D,$)}addComponents(j,D){this._entityManager.addComponents(j,D)}removeComponent(j,D){this._entityManager.removeComponent(j,D)}hasComponent(j,D){return this._entityManager.getComponent(j,D)!==void 0}spawn(j,D){let $=this._entityManager.createEntity();return this._entityManager.addComponents($.id,j),this._applyScreenScope($.id,D),$}_applyScreenScope(j,D){let $=D?.scope;if($===void 0)return;let G=this._screenScopedEntities.get($)??new Set;G.add(j),this._screenScopedEntities.set($,G),this._entityScreenScope.set(j,$)}getEntitiesWithQuery(j,D=[],$,G){return this._entityManager.getEntitiesWithQuery(j,D,$,$?this._changeThreshold:void 0,G)}getSingleton(j,D=[]){let $=this._entityManager.getEntitiesWithQuery(j,D);if($.length===0)throw Error(`getSingleton: no entity matches query with=[${String(j)}] without=[${String(D)}]`);if($.length>1)throw Error(`getSingleton: expected 1 entity but found ${$.length} matching query with=[${String(j)}] without=[${String(D)}]`);let G=$[0];if(!G)throw Error("getSingleton: unexpected empty result");return G}tryGetSingleton(j,D=[]){let $=this._entityManager.getEntitiesWithQuery(j,D);if($.length===0)return;if($.length>1)throw Error(`tryGetSingleton: expected 0 or 1 entity but found ${$.length} matching query with=[${String(j)}] without=[${String(D)}]`);return $[0]}removeEntity(j,D){return this._entityManager.removeEntity(j,D)}spawnChild(j,D,$){let G=this._entityManager.spawnChild(j,D);return this._emitHierarchyChanged(G.id,null,j),this._applyScreenScope(G.id,$),G}setParent(j,D){let $=this._entityManager.getParent(j);return this._entityManager.setParent(j,D),this._emitHierarchyChanged(j,$,D),this}removeParent(j){let D=this._entityManager.getParent(j),$=this._entityManager.removeParent(j);if($)this._emitHierarchyChanged(j,D,null);return $}getParent(j){return this._entityManager.getParent(j)}getChildren(j){return this._entityManager.getChildren(j)}getChildAt(j,D){return this._entityManager.getChildAt(j,D)}getChildIndex(j,D){return this._entityManager.getChildIndex(j,D)}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,D){return this._entityManager.isDescendantOf(j,D)}isAncestorOf(j,D){return this._entityManager.isAncestorOf(j,D)}getRootEntities(){return this._entityManager.getRootEntities()}forEachInHierarchy(j,D){this._entityManager.forEachInHierarchy(j,D)}hierarchyIterator(j){return this._entityManager.hierarchyIterator(j)}_emitHierarchyChanged(j,D,$){this._eventBus.publish("hierarchyChanged",{entityId:j,oldParent:D,newParent:$})}get installedPlugins(){return Array.from(this._installedPlugins)}get entityManager(){return this._entityManager}get eventBus(){return this._finalizePendingBuilders(),this._eventBus}get commands(){return this._commandBuffer}get currentTick(){return this._currentTick}get changeThreshold(){return this._changeThreshold}enableDiagnostics(j){if(this._diagnosticsEnabled=j,!j)this._systemTimings.clear(),this._phaseTimings={preUpdate:0,fixedUpdate:0,update:0,postUpdate:0,render:0}}get diagnosticsEnabled(){return this._diagnosticsEnabled}get systemTimings(){return this._systemTimings}get phaseTimings(){return this._phaseTimings}get entityCount(){return this._entityManager.entityCount}mutateComponent(j,D,$){let G=this._entityManager.getComponent(j,D);if(G===void 0)throw Error(`Entity ${j} does not have component "${String(D)}"`);return $(G),this._entityManager.markChanged(j,D),G}markChanged(j,D){this._entityManager.markChanged(j,D)}registerDispose(j,D){this._entityManager.registerDispose(j,D)}registerRequired(j,D,$){if(String(j)===String(D))throw Error(`Cannot require a component to depend on itself: '${String(j)}'`);let G=this._requiredComponents.get(j)??[];if(G.some((J)=>J.component===D))throw Error(`Required component '${String(D)}' already registered for trigger '${String(j)}'`);this._checkRequiredCycle(j,D),G.push({component:D,factory:$}),this._requiredComponents.set(j,G)}_checkRequiredCycle(j,D){i(j,D,($)=>this._requiredComponents.get($))}onComponentAdded(j,D){return this._entityManager.onComponentAdded(j,D)}onComponentRemoved(j,D){return this._entityManager.onComponentRemoved(j,D)}addReactiveQuery(j,D){this._reactiveQueryManager.addQuery(j,D)}removeReactiveQuery(j){return this._reactiveQueryManager.removeQuery(j)}on(j,D){return this._eventBus.subscribe(j,D)}off(j,D){return this._eventBus.unsubscribe(j,D)}onPostUpdate(j){return this._postUpdateHooks.push(j),()=>{let D=this._postUpdateHooks.indexOf(j);if(D!==-1)this._postUpdateHooks.splice(D,1)}}requireAssetManager(){if(!this._assetManager)throw Error("Asset manager not configured. Use withAssets() in builder.");return this._assetManager}getAsset(j){return this.requireAssetManager().get(j)}tryGetAsset(j){return this._assetManager?.tryGet(j)}getAssetHandle(j){return this.requireAssetManager().getHandle(j)}isAssetLoaded(j){return this._assetManager?.isLoaded(j)??!1}async loadAsset(j){return this.requireAssetManager().loadAsset(j)}async loadAssetGroup(j){return this.requireAssetManager().loadAssetGroup(j)}isAssetGroupLoaded(j){return this._assetManager?.isGroupLoaded(j)??!1}getAssetGroupProgress(j){return this._assetManager?.getGroupProgress(j)??0}requireScreenManager(){if(!this._screenManager)throw Error("Screen manager not configured. Use withScreens() in builder.");return this._screenManager}async setScreen(j,D){return this.requireScreenManager().setScreen(j,D)}async pushScreen(j,D){return this.requireScreenManager().pushScreen(j,D)}async popScreen(){return this.requireScreenManager().popScreen()}getCurrentScreen(){return this._screenManager?.getCurrentScreen()??null}getScreenConfig(j){return this.requireScreenManager().getConfig(j)}tryGetScreenConfig(j){return this._screenManager?.tryGetConfig(j)??void 0}getScreenState(j){return this.requireScreenManager().getState(j)}tryGetScreenState(j){return this._screenManager?.tryGetState(j)??void 0}updateScreenState(j,D){if(typeof j==="string")this.requireScreenManager().updateState(D,j);else this.requireScreenManager().updateState(j)}isCurrentScreen(j){return this._screenManager?.isCurrent(j)??!1}isScreenActive(j){return this._screenManager?.isActive(j)??!1}getScreenStackDepth(){return this._screenManager?.getStackDepth()??0}onScreenEnter(j,D){let $=this._eventBus,G=(Z)=>{if(Z.screen!==j)return;D({config:Z.config,ecs:this})},J=$.subscribe("screenEnter",G),X=$.subscribe("screenPush",G);return()=>{J(),X()}}onScreenExit(j,D){return this._eventBus.subscribe("screenExit",(G)=>{if(G.screen!==j)return;D({ecs:this})})}_setAssetManager(j){this._assetManager=j;for(let[D,$]of this._pendingPluginAssets)this._assetManager.register(D,$);this._pendingPluginAssets=[]}_setScreenManager(j){this._screenManager=j;for(let[D,$]of this._pendingPluginScreens)this._screenManager.register(D,$);this._pendingPluginScreens=[]}_hasPendingPluginAssets(){return this._pendingPluginAssets.length>0}_hasPendingPluginScreens(){return this._pendingPluginScreens.length>0}_setFixedDt(j){this._fixedDt=j}_registerAsset(j,D){this._pendingPluginAssets.push([j,D])}_registerScreen(j,D){this._pendingPluginScreens.push([j,D])}installPlugin(j){return this._installPluginUnchecked(j)}_installPluginUnchecked(j){if(this._installedPlugins.has(j.id))return this;this._installedPlugins.add(j.id);let D=[];this._pluginCleanups.set(j.id,D);let $=(J)=>{D.push(J)},G=this._currentSystemDefaults;this._currentSystemDefaults=j.systemDefaults;try{j.install(this,$)}finally{this._currentSystemDefaults=G}return this}uninstallPlugin(j){if(!this._installedPlugins.has(j))return!1;let D=this._pluginCleanups.get(j);if(this._pluginCleanups.delete(j),this._installedPlugins.delete(j),D)for(let $=D.length-1;$>=0;$--){let G=D[$];if(!G)continue;try{G()}catch(J){console.warn(`Plugin '${j}' cleanup threw:`,J)}}return!0}dispose(){let j=Array.from(this._installedPlugins);for(let D=j.length-1;D>=0;D--){let $=j[D];if($!==void 0)this.uninstallPlugin($)}}pluginFactory(){return(j)=>V(j.id).install(j.install)}getHelpers(j){return j(this)}}function vj(j){return j}function bj(j,D){return{x:j,y:D}}function pj(){return{x:0,y:0}}function hj(j,D){return{x:j.x+D.x,y:j.y+D.y}}function kj(j,D){return{x:j.x-D.x,y:j.y-D.y}}function Ij(j,D){return{x:j.x*D,y:j.y*D}}function uj(j){return{x:-j.x,y:-j.y}}function mj(j,D){return j.x*D.x+j.y*D.y}function lj(j,D){return j.x*D.y-j.y*D.x}function sj(j){return j.x*j.x+j.y*j.y}function ij(j){return Math.sqrt(j.x*j.x+j.y*j.y)}function cj(j){let D=Math.sqrt(j.x*j.x+j.y*j.y);if(D===0)return{x:0,y:0};return{x:j.x/D,y:j.y/D}}function dj(j,D){let $=j.x-D.x,G=j.y-D.y;return $*$+G*G}function yj(j,D){let $=j.x-D.x,G=j.y-D.y;return Math.sqrt($*$+G*G)}function oj(j,D,$=0.0000000001){return Math.abs(j.x-D.x)<=$&&Math.abs(j.y-D.y)<=$}function rj(j,D,$){return{x:j,y:D,z:$}}function aj(){return{x:0,y:0,z:0}}function nj(j,D){return{x:j.x+D.x,y:j.y+D.y,z:j.z+D.z}}function tj(j,D){return{x:j.x-D.x,y:j.y-D.y,z:j.z-D.z}}function ej(j,D){return{x:j.x*D,y:j.y*D,z:j.z*D}}function j3(j){return{x:-j.x,y:-j.y,z:-j.z}}function D3(j,D){return j.x*D.x+j.y*D.y+j.z*D.z}function $3(j,D){return{x:j.y*D.z-j.z*D.y,y:j.z*D.x-j.x*D.z,z:j.x*D.y-j.y*D.x}}function G3(j){return j.x*j.x+j.y*j.y+j.z*j.z}function J3(j){return Math.sqrt(j.x*j.x+j.y*j.y+j.z*j.z)}function X3(j){let D=Math.sqrt(j.x*j.x+j.y*j.y+j.z*j.z);if(D===0)return{x:0,y:0,z:0};return{x:j.x/D,y:j.y/D,z:j.z/D}}function Z3(j,D){let $=j.x-D.x,G=j.y-D.y,J=j.z-D.z;return $*$+G*G+J*J}function W3(j,D){let $=j.x-D.x,G=j.y-D.y,J=j.z-D.z;return Math.sqrt($*$+G*G+J*J)}function Y3(j,D,$=0.0000000001){return Math.abs(j.x-D.x)<=$&&Math.abs(j.y-D.y)<=$&&Math.abs(j.z-D.z)<=$}var M3=P;export{aj as vec3Zero,tj as vec3Sub,ej as vec3Scale,X3 as vec3Normalize,j3 as vec3Negate,G3 as vec3LengthSq,J3 as vec3Length,Y3 as vec3Equals,D3 as vec3Dot,Z3 as vec3DistanceSq,W3 as vec3Distance,$3 as vec3Cross,nj as vec3Add,rj as vec3,pj as vec2Zero,kj as vec2Sub,Ij as vec2Scale,cj as vec2Normalize,uj as vec2Negate,sj as vec2LengthSq,ij as vec2Length,oj as vec2Equals,mj as vec2Dot,dj as vec2DistanceSq,yj as vec2Distance,lj as vec2Cross,hj as vec2Add,bj as vec2,r as directValue,V as definePlugin,M3 as default,b as createScreenConfigurator,vj as createQueryDefinition,N as createAssetConfigurator,C as SystemBuilder,H as ScreenManager,z as AssetManager};
2
2
 
3
- //# debugId=82B4E2F9008BA76064756E2164756E21
3
+ //# debugId=FACF9E287ECCDD9D64756E2164756E21
4
4
  //# sourceMappingURL=index.js.map