ecspresso
Version:
A minimal Entity-Component-System library for typescript and javascript.
1 lines • 58.1 kB
JavaScript
var Gj=((j)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(j,{get:(D,G)=>(typeof require<"u"?require:D)[G]}):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 G=this.parentMap.get(j);if(G!==void 0){let J=this.childrenMap.get(G);if(J){let X=J.indexOf(j);if(X!==-1)J.splice(X,1)}}this.parentMap.set(j,D);let $=this.childrenMap.get(D);if($)$.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 G=this.childrenMap.get(D);if(G){let $=G.indexOf(j);if($!==-1)G.splice($,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 G=this.childrenMap.get(j);if(!G||D>=G.length)return null;return G[D]??null}getChildIndex(j,D){let G=this.childrenMap.get(j);if(!G)return-1;return G.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 G=this.childrenMap.get(j)??[],$=[...G];for(let J of G)this.parentMap.delete(J);return this.childrenMap.delete(j),{oldParent:D,orphanedChildren:$}}getAncestors(j){let D=[],G=this.parentMap.get(j);while(G!==void 0)D.push(G),G=this.parentMap.get(G);return D}getDescendants(j){let D=[],G=this.childrenMap.get(j);if(!G)return D;let $=G.slice().reverse();while($.length>0){let J=$.pop();D.push(J);let X=this.childrenMap.get(J);if(X)for(let Z=X.length-1;Z>=0;Z--)$.push(X[Z])}return D}getRoot(j){let D=j,G=this.parentMap.get(D);while(G!==void 0)D=G,G=this.parentMap.get(D);return D}getSiblings(j){let D=this.parentMap.get(j);if(D===void 0)return[];let G=this.childrenMap.get(D);if(!G)return[];return G.filter(($)=>$!==j)}isDescendantOf(j,D){if(j===D)return!1;let G=this.parentMap.get(j);while(G!==void 0){if(G===D)return!0;G=this.parentMap.get(G)}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 G=D;while(G!==void 0){if(G===j)return!0;G=this.parentMap.get(G)}return!1}forEachInHierarchy(j,D){let G=D?.roots??this.getRootEntities(),$=this._bfsQueue;$.length=0;for(let J of G)$.push(J,-1,0);for(let J=0;J<$.length;J+=3){let X=$[J],Z=$[J+1],Y=$[J+2];j(X,Z===-1?null:Z,Y);let F=this.childrenMap.get(X);if(F){let O=Y+1;for(let A of F)$.push(A,X,O)}}}*hierarchyIterator(j){let D=j?.roots??this.getRootEntities(),G=[];for(let $ of D)G.push({entityId:$,parentId:null,depth:0});for(let $ of G){yield $;let J=this.childrenMap.get($.entityId);if(J)for(let X of J)G.push({entityId:X,parentId:$.entityId,depth:$.depth+1})}}}function R(j,D,G,$,J){let X=j.components;for(let Z of D)if(!(Z in X))return!1;if(G){for(let Z of G)if(Z in X)return!1}if($&&$.length>0){let Z=J.getParent(j.id);if(Z===null)return!1;let Y=J.getEntity(Z);if(!Y)return!1;let F=Y.components;for(let O of $)if(!(O in F))return!1}return!0}function a(j,D,G){let $=j.length===0?"":[...j].map(String).sort().join(","),J=D.length===0?"":[...D].map(String).sort().join(","),X=G.length===0?"":[...G].map(String).sort().join(",");return`${$}|${J}|${X}`}class S{host;caches=new Map;byComp=new Map;byParentComp=new Map;constructor(j){this.host=j}getOrCreate(j,D,G){let $=a(j,D,G),J=this.caches.get($);if(J)return J.members;let X={with:[...j],without:[...D],parentHas:[...G],members:new Map};this.caches.set($,X);for(let Z of X.with)v(this.byComp,Z,X);for(let Z of X.without)v(this.byComp,Z,X);for(let Z of X.parentHas)v(this.byParentComp,Z,X);return this.populate(X),X.members}get cacheCount(){return this.caches.size}populate(j){let D=this.host,G=j.with;if(G.length===0){for(let Z of D.allEntities())if(this.matches(Z,j))j.members.set(Z.id,Z);return}let $=G[0];if($===void 0)return;let J=D.componentIndex($)?.size??0;for(let Z=1;Z<G.length;Z++){let Y=G[Z];if(Y===void 0)continue;let F=D.componentIndex(Y)?.size??0;if(F<J)$=Y,J=F}let X=D.componentIndex($);if(!X||X.size===0)return;for(let Z of X){let Y=D.getEntity(Z);if(!Y)continue;if(this.matches(Y,j))j.members.set(Z,Y)}}matches(j,D){return R(j,D.with,D.without,D.parentHas,this.host)}reeval(j,D){let G=this.host.getEntity(j);if(!G){D.members.delete(j);return}if(this.matches(G,D))D.members.set(j,G);else D.members.delete(j)}onComponentChanged(j,D){let G=this.byComp.get(D);if(G)for(let J of G)this.reeval(j,J);let $=this.byParentComp.get(D);if($&&$.length>0){let J=this.host.getChildren(j);if(J.length>0)for(let X of $)for(let Z of J)this.reeval(Z,X)}}onParentChanged(j){for(let D of this.caches.values())if(D.parentHas.length>0)this.reeval(j,D)}onEntityRemoved(j){let D=!1;for(let $ of this.caches.values())if($.members.delete(j),$.parentHas.length>0)D=!0;if(!D)return;let G=this.host.getChildren(j);if(G.length===0)return;for(let $ of this.caches.values()){if($.parentHas.length===0)continue;for(let J of G)$.members.delete(J)}}}function v(j,D,G){let $=j.get(D);if($)$.push(G);else j.set(D,[G])}function l(j,D,G){if(!j||!D)return!1;for(let $=0;$<D.length;$++){let J=D[$];if(J===void 0||J>=j.length)continue;let X=j[J];if(X!==void 0&&X>G)return!0}return!1}class N{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 G=0;G<D;G++){let $=this.callbacks[G];if($)$(j)}if(this._iterDepth--,this._iterDepth===0&&this._pendingRemovals.length>0){for(let G of this._pendingRemovals){let $=this.callbacks.indexOf(G);if($!==-1)this.callbacks.splice($,1)}this._pendingRemovals.length=0}}}class T{nextId=1;entities=new Map;componentIndices=new Map;addedCallbacks=new Map;removedCallbacks=new Map;hierarchyManager=new H;disposeCallbacks=new Map;changeSeqs=[];componentNameToIdx=new Map;_idxCache0Name;_idxCache0Idx=-1;_idxCache1Name;_idxCache1Idx=-1;_subscribedComponentIdx=null;_changeSeq=0;_afterComponentAddedHooks=[];_afterEntityMutatedHooks=[];_afterComponentRemovedHooks=[];_beforeEntityRemovedHooks=[];_afterParentChangedHooks=[];_queryCache=new S({getEntity:(j)=>this.entities.get(j),getParent:(j)=>this.hierarchyManager.getParent(j),getChildren:(j)=>this.hierarchyManager.getChildren(j),allEntities:()=>this.entities.values(),componentIndex:(j)=>this.componentIndices.get(j)});_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,G){let $=this.disposeCallbacks.get(j);if(!$)return;try{$({value:D,entityId:G})}catch(J){console.warn(`Component dispose callback for '${String(j)}' threw:`,J)}}addComponent(j,D,G){let $=this.entities.get(j);if(!$)throw Error(`Cannot add component '${String(D)}': Entity with ID ${j} does not exist`);let J=$.components[D];if(J!==void 0)this.invokeDispose(D,J,$.id);if($.components[D]=G,!this.componentIndices.has(D))this.componentIndices.set(D,new Set);this.componentIndices.get(D)?.add($.id);let X=this.addedCallbacks.get(D);if(X)X.invoke({value:G,entity:$});this._queryCache.onComponentChanged($.id,D),this._batchingDepth++;for(let Z of this._afterComponentAddedHooks)Z($.id,D);if(this._batchedEntityIds.add($.id),this._batchingDepth--,this._batchingDepth===0){for(let Z of this._batchedEntityIds)for(let Y of this._afterEntityMutatedHooks)Y(Z);this._batchedEntityIds.clear()}return this}addComponents(j,D){let G=this.entities.get(j);if(!G)throw Error(`Cannot add components: Entity with ID ${j} does not exist`);let $=this._pendingBatchKeys;this._pendingBatchKeys=new Set(Object.keys(D)),this._batchingDepth++;for(let J in D)this.addComponent(G.id,J,D[J]);if(this._batchingDepth--,this._pendingBatchKeys=$,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 G=this.entities.get(j);if(!G)throw Error(`Cannot remove component '${String(D)}': Entity with ID ${j} does not exist`);let $=G.components[D];if($!==void 0)this.invokeDispose(D,$,G.id);delete G.components[D];let J=this.removedCallbacks.get(D);if(J&&$!==void 0)J.invoke({value:$,entity:G});if(this.componentIndices.get(D)?.delete(G.id),$!==void 0){this._queryCache.onComponentChanged(G.id,D);for(let X of this._afterComponentRemovedHooks)X(G.id,D)}return this}getComponent(j,D){return this.entities.get(j)?.components[D]}getEntitiesWithQuery(j=[],D=[],G,$,J,X){return this.getEntitiesWithQueryInto([],j,D,G,$,J,X)}getEntitiesWithQueryInto(j,D=[],G=[],$,J,X,Z){j.length=0;let Y=$!==void 0&&$.length>0&&J!==void 0,F=Z;if(Y&&F===void 0){let W=[];for(let _ of $){let L=this.componentNameToIdx.get(_);if(L!==void 0)W.push(L)}F=W}if(Y&&F.length===0)return j;let O=X!==void 0&&X.length>0;if(D.length===0&&G.length===0&&!O){if(!Y){for(let W of this.entities.values())j.push(W);return j}for(let W of this.entities.values()){if(!l(this.changeSeqs[W.id],F,J??0))continue;j.push(W)}return j}let A=this._queryCache.getOrCreate(D,G,X??[]);if(A.size===0)return j;if(Y){for(let W of A.values()){if(!l(this.changeSeqs[W.id],F,J??0))continue;j.push(W)}return j}for(let W of A.values())j.push(W);return j}get _queryCacheForTesting(){return this._queryCache}removeEntity(j,D){let G=this.entities.get(j);if(!G)return!1;if(D?.cascade??!0){let J=this.hierarchyManager.getDescendants(G.id);for(let X=J.length-1;X>=0;X--){let Z=J[X];if(Z===void 0)continue;this._queryCache.onEntityRemoved(Z);for(let Y of this._beforeEntityRemovedHooks)Y(Z)}this._queryCache.onEntityRemoved(G.id);for(let X of this._beforeEntityRemovedHooks)X(G.id);for(let X=J.length-1;X>=0;X--){let Z=J[X];if(Z===void 0)continue;this.removeEntityInternal(Z)}}else{this._queryCache.onEntityRemoved(G.id);for(let J of this._beforeEntityRemovedHooks)J(G.id)}return this.removeEntityInternal(G.id)}removeEntityInternal(j){let D=this.entities.get(j);if(!D)return!1;this.hierarchyManager.removeEntity(j);for(let G of Object.keys(D.components)){let $=D.components[G];if($!==void 0){this.invokeDispose(G,$,D.id);let J=this.removedCallbacks.get(G);if(J)J.invoke({value:$,entity:D})}this.componentIndices.get(G)?.delete(D.id)}return this.changeSeqs[D.id]=void 0,this.entities.delete(D.id)}getEntity(j){return this.entities.get(j)}onComponentAdded(j,D){let G=D,$=this.addedCallbacks.get(j);if(!$)$=new N,this.addedCallbacks.set(j,$);return $.add(G),()=>{this.addedCallbacks.get(j)?.remove(G)}}onComponentRemoved(j,D){let G=D,$=this.removedCallbacks.get(j);if(!$)$=new N,this.removedCallbacks.set(j,$);return $.add(G),()=>{this.removedCallbacks.get(j)?.remove(G)}}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){this.markChangedByIdx(j,this.getOrAssignComponentIdx(D))}markChangedByIdx(j,D){let G=this._subscribedComponentIdx;if(G!==null&&(D>=G.length||G[D]===0))return;let $=++this._changeSeq,J=this.changeSeqs[j];if(J===void 0)J=new Uint32Array(Math.max(D+1,8)),this.changeSeqs[j]=J;else if(D>=J.length){let X=new Uint32Array(Math.max(D+1,J.length*2));X.set(J),J=X,this.changeSeqs[j]=J}J[D]=$}getOrAssignComponentIdx(j){if(j===this._idxCache0Name)return this._idxCache0Idx;if(j===this._idxCache1Name){let G=this._idxCache1Idx;return this._idxCache1Name=this._idxCache0Name,this._idxCache1Idx=this._idxCache0Idx,this._idxCache0Name=j,this._idxCache0Idx=G,G}let D=this.componentNameToIdx.get(j);if(D===void 0)D=this.componentNameToIdx.size,this.componentNameToIdx.set(j,D);return this._idxCache1Name=this._idxCache0Name,this._idxCache1Idx=this._idxCache0Idx,this._idxCache0Name=j,this._idxCache0Idx=D,D}subscribeChanged(j){let D=this.getOrAssignComponentIdx(j),G=this._subscribedComponentIdx;if(G===null)G=new Uint8Array(Math.max(D+1,8)),this._subscribedComponentIdx=G;else if(D>=G.length){let $=new Uint8Array(Math.max(D+1,G.length*2));$.set(G),G=$,this._subscribedComponentIdx=G}G[D]=1}disableChangeTracking(){this._subscribedComponentIdx=new Uint8Array(0)}hasAnySubscribed(j){let D=this._subscribedComponentIdx;if(D===null)return!0;for(let G=0;G<j.length;G++){let $=j[G];if($!==void 0&&$<D.length&&D[$]!==0)return!0}return!1}getChangeSeq(j,D){let G=this.componentNameToIdx.get(D);if(G===void 0)return-1;let $=this.changeSeqs[j];if(!$||G>=$.length)return-1;let J=$[G]??0;return J===0?-1:J}spawnChild(j,D){let G=this.createEntity();return this.addComponents(G.id,D),this.setParent(G.id,j),G}setParent(j,D){this.hierarchyManager.setParent(j,D),this._queryCache.onParentChanged(j);for(let G of this._afterParentChangedHooks)G(j);return this}removeParent(j){let D=this.hierarchyManager.removeParent(j);if(D){this._queryCache.onParentChanged(j);for(let G of this._afterParentChangedHooks)G(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 G=this.handlers.get(j);if(!G)return!1;let $=G.findIndex((J)=>J.callback===D);if($===-1)return!1;return G.splice($,1),!0}addHandler(j,D,G){let $=this.handlers.get(j);if(!$)$=[],this.handlers.set(j,$);let J={callback:D,once:G};return $.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 G=this.handlers.get(j);if(!G||G.length===0)return;let $=!1,J=G.length;for(let X=0;X<J&&X<G.length;X++){let Z=G[X];if(!Z)continue;if(Z.callback(D),Z.once)$=!0}if($){for(let X=G.length-1;X>=0;X--)if(G[X]?.once)G.splice(X,1)}}clear(){this.handlers.clear()}clearEvent(j){this.handlers.delete(j)}}var k=Symbol("resource-direct");function n(j){return{[k]:j}}function b(j){if(typeof j==="object"&&j!==null&&!Array.isArray(j))return{...j};return{$value:j}}function t(j,D){if(typeof j==="object"&&j!==null&&!Array.isArray(j)){let G=j;for(let $ in D)if(!Object.is(G[$],D[$]))return!0;return!1}return!Object.is(j,D.$value)}function e(j){return typeof j==="object"&&j!==null&&"factory"in j&&typeof j.factory==="function"}function jj(j){return typeof j==="object"&&j!==null&&k in j}function m(j,D){let G=[],$=new Set,J=new Set;function X(Z,Y=[]){if($.has(Z))return;if(J.has(Z))throw Error(`Circular resource dependency: ${[...Y,Z].join(" -> ")}`);J.add(Z);for(let F of D(Z)){let O=j.find((A)=>A===F);if(O)X(O,[...Y,Z])}J.delete(Z),$.add(Z),G.push(Z)}for(let Z of j)X(Z);return G}class C{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,$),this.initializedResourceKeys.add(j),this.resourceDependencies.set(j,[])};if(e(D)){if(this.resourceFactories.set(j,D.factory),this.resourceDependencies.set(j,D.dependsOn??[]),D.onDispose)this.resourceDisposers.set(j,D.onDispose)}else if(jj(D))G(D[k]);else if(typeof D==="function")this.resourceFactories.set(j,D),this.resourceDependencies.set(j,[]);else G(D);return this}tryGet(j,...D){if(!this.has(j))return;return this.get(j,...D)}get(j,...D){let G=this.resources.get(j);if(G!==void 0)return G;let $=this.resourceFactories.get(j);if($===void 0)throw Error(`Resource ${String(j)} not found`);let J=D[0],X=$(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),G=this.resourceFactories.delete(j);return this.resourceDependencies.delete(j),this.resourceDisposers.delete(j),this.initializedResourceKeys.delete(j),D||G}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 G=this.resourceFactories.get(j);if(!G)return;let $=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),G=D.length===0?this.getPendingInitializationKeys():D;if(G.length===0)return;let $=m(G,(J)=>[...this.resourceDependencies.get(J)??[]]);for(let J of $)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 G=this.resourceDisposers.get(j),$=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 G=this._changeSubscribers.get(j),$=G??new Set;if(!G){this._changeSubscribers.set(j,$);let X=this.resources.get(j);this._observedSnapshots.set(j,b(X))}let J=D;return $.add(J),()=>{if($.delete(J),$.size===0)this._changeSubscribers.delete(j),this._observedSnapshots.delete(j)}}notifyChange(j,D,G){if(Object.is(D,G))return;let $=this._changeSubscribers.get(j);if(!$||$.size===0)return;if(this._observedSnapshots.has(j))this._observedSnapshots.set(j,b(D));let J=[...$];for(let X of J)X(D,G)}isObserved(j){return this._observedSnapshots.has(j)}flushObserved(){if(this._observedSnapshots.size===0)return;for(let[j,D]of this._observedSnapshots){let G=this.resources.get(j);if(!t(G,D))continue;let $="$value"in D?D.$value:D,J=b(G),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 G=m(D,($)=>[...this.resourceDependencies.get($)??[]]).reverse();for(let $ of G)await this.disposeResource($,...j)}}class q{queries=new Map;entityManager;_hasParentHasQueries=!1;constructor(j){this.entityManager=j}get hasParentHasQueries(){return this._hasParentHasQueries}addQuery(j,D){let G={definition:D,matchingEntities:new Set};if(this.queries.set(j,G),D.parentHas?.length)this._hasParentHasQueries=!0;let $=this.entityManager.getEntitiesWithQuery(D.with,D.without??[]);for(let J of $)if(this.entityMatchesQuery(J,G.definition))G.matchingEntities.add(J.id),G.definition.onEnter?.(J)}removeQuery(j){let D=this.queries.delete(j);if(D)this._recalcParentHasFlag();return D}entityMatchesQuery(j,D){return R(j,D.with,D.without,D.parentHas,this.entityManager)}_applyQueryTransition(j,D){let G=D.matchingEntities.has(j.id),$=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[,G]of this.queries)this._applyQueryTransition(j,G);if(this._hasParentHasQueries)this._recheckChildren(j.id)}onComponentRemoved(j,D){for(let[,G]of this.queries)this._applyQueryTransition(j,G);if(this._hasParentHasQueries)this._recheckChildren(j.id)}onEntityRemoved(j){for(let[D,G]of this.queries)if(G.matchingEntities.has(j))G.matchingEntities.delete(j),G.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 G of D){let $=this.entityManager.getEntity(G);if($)this.recheckEntity($)}}_recalcParentHasFlag(){this._hasParentHasQueries=!1;for(let[,j]of this.queries)if(j.definition.parentHas?.length){this._hasParentHasQueries=!0;return}}}class g{parent;commands=[];constructor(j){this.parent=j}removeEntity(j,D){this.commands.push((G)=>{G.removeEntity(j,D)})}addComponent(j,D,G){this.commands.push(($)=>{$.addComponent(j,D,G)})}removeComponent(j,D){this.commands.push((G)=>{G.removeComponent(j,D)})}spawn(j,D){let G=this._resolveScope(D);this.commands.push(($)=>{$.spawn(j,G)})}spawnChild(j,D,G){let $=this._resolveScope(G);this.commands.push((J)=>{J.spawnChild(j,D,$)})}_resolveScope(j){if(j?.scope!==void 0)return j;let D=this.parent?._getActiveScopeHint();if(!D)return j;return{scope:D}}addComponents(j,D){this.commands.push((G)=>{G.addComponents(j,D)})}setParent(j,D){this.commands.push((G)=>{G.setParent(j,D)})}mutateComponent(j,D,G){this.commands.push(($)=>{$.mutateComponent(j,D,G)})}markChanged(j,D){this.commands.push((G)=>{G.markChanged(j,D)})}removeParent(j){this.commands.push((D)=>{D.removeParent(j)})}playback(j){for(let D of this.commands)try{D(j)}catch(G){console.warn("CommandBuffer: Command failed during playback:",G)}this.commands.length=0}clear(){this.commands.length=0}get length(){return this.commands.length}}class s{_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 E(j){return new s(j)}var c="__each";class x{_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 G=this;return G.queries={...this.queries,[j]:D},G}addSingleton(j,D){let G=this;return G.singletons={...this.singletons,[j]:D},G}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(!$||J.ecs.isResourceObserved(X))G[X]=J.ecs.getResource(X);$=!0,J.resources=G,j(J)}}setProcessEach(j,D){let G=this;if(Object.keys(G.queries).length>0||Object.keys(G.singletons).length>0||G.processFunction!==void 0)throw Error("setProcessEach requires a SystemBuilder with no prior queries, singletons, or process function. Use addQuery + setProcess for multi-query systems.");G.queries.__each=j;let $={entity:void 0,dt:0,ecs:void 0,resources:void 0},J=(X)=>{let Z=X,Y=Z.queries.__each;if(!Y)return;let F=j._mutatesIdx;$.dt=Z.dt,$.ecs=Z.ecs,$.resources=Z.resources;let O=Z.ecs.entityManager;for(let A=0;A<Y.length;A++){let W=Y[A];if(!W)continue;$.entity=W;let _=D($);if(F===void 0||_===!1)continue;for(let L=0;L<F.length;L++){let U=F[L];if(U!==void 0)O.markChangedByIdx(W.id,U)}}};return G.processFunction=G._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 i(j,D,G){let $=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($.has(X))continue;$.add(X);let Z=G(X);if(Z)for(let Y of Z)J.push(Y.component)}}var y="0.18.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 G=this.groups.get(D.group)??new Set;G.add(j),this.groups.set(D.group,G)}}async loadEagerAssets(){let j=[];for(let[D,G]of this.assets)if(G.definition.eager&&G.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 G=await D.loadPromise;return D.value=G,D.status="loaded",D.loadPromise=void 0,this.eventBus?.publish("assetLoaded",{key:j}),this.checkGroupProgress(D.definition.group),G}catch(G){let $=G instanceof Error?G:Error(String(G));throw D.status="failed",D.error=$,D.loadPromise=void 0,this.eventBus?.publish("assetFailed",{key:j,error:$}),$}}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((G)=>this.loadAsset(G)))}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 G=this;return{get status(){return D.status},get isLoaded(){return D.status==="loaded"},get(){return G.get(j)},tryGet(){return G.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 G of D){let $=this.assets.get(G);if(!$||$.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 G=0;for(let J of D)if(this.assets.get(J)?.status==="loaded")G++;let $=D.size;return{loaded:G,total:$,progress:G/$}}checkGroupProgress(j){if(!j||!this.eventBus)return;let D=j,G=this.getGroupProgressDetails(D);if(this.eventBus.publish("assetGroupProgress",{group:D,...G}),G.loaded===G.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(G,{loader:$,eager:!1,group:j});return this}getManager(){return this.manager}}function p(j){return new d(j??new z)}class P{screens=new Map;currentScreen=null;screenStack=[];eventBus=null;assetManager=null;ecs=null;setDependencies(j,D,G){this.eventBus=j,this.assetManager=D,this.ecs=G}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 G=this.screens.get(j);if(!G)throw Error(`Screen '${String(j)}' not found`);await this.verifyRequiredAssets(G.definition.requiredAssets,G.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:$},await G.definition.onEnter?.({config:D,ecs:this.requireEcs()}),this.eventBus?.publish("screenEnter",{screen:j,config:D})}async pushScreen(j,D){let G=this.screens.get(j);if(!G)throw Error(`Screen '${String(j)}' not found`);if(await this.verifyRequiredAssets(G.definition.requiredAssets,G.definition.requiredAssetGroups),this.currentScreen)this.screenStack.push(this.currentScreen);let $=G.definition.initialState(D);this.currentScreen={name:j,config:D,state:$},await G.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 G of j)if(!this.assetManager.isLoaded(G))await this.assetManager.loadAsset(G)}if(D){for(let G of D)if(!this.assetManager.isGroupLoaded(G))await this.assetManager.loadAssetGroup(G)}}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 G=typeof j==="function"?j(this.currentScreen.state):j;this.currentScreen.state={...this.currentScreen.state,...G}}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 o{manager;constructor(j){this.manager=j}add(j,D){return this.manager.register(j,D),this}getManager(){return this.manager}}function h(j){return new o(j??new P)}class I{assetConfigurator=null;screenConfigurator=null;pendingResources=[];pendingDisposeCallbacks=[];pendingRequiredComponents=[];pendingPlugins=[];_fixedDt=null;_disableChangeTracking=!1;constructor(){}withPlugin(j){return this.pendingPlugins.push(j),this}withComponentTypes(){return this}withEventTypes(){return this}withResourceTypes(){return this}disableChangeTracking(){return this._disableChangeTracking=!0,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,G){return this.pendingRequiredComponents.push({trigger:j,required:D,factory:G}),this}withAssets(j){let D=p();return j(D),this.assetConfigurator=D,this}withScreens(j){let D=h();return j(D),this.screenConfigurator=D,this}withFixedTimestep(j){return this._fixedDt=j,this}withReactiveQueryNames(){return this}pluginFactory(){return(j)=>E(j.id).install(j.install)}build(){let j=new V;if(this._disableChangeTracking)j.entityManager.disableChangeTracking();for(let D of this.pendingPlugins)j._installPluginUnchecked(D);for(let{key:D,value:G}of this.pendingResources)j.addResource(D,G);for(let{key:D,callback:G}of this.pendingDisposeCallbacks)j.registerDispose(D,G);for(let{trigger:D,required:G,factory:$}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 P);if(this._fixedDt!==null)j._setFixedDt(this._fixedDt);return j}}var r=["preUpdate","fixedUpdate","update","postUpdate","render"];class V{static VERSION=y;_entityManager;_eventBus;_resourceManager;_commandBuffer;_systems=[];_phaseSystems={preUpdate:[],fixedUpdate:[],update:[],postUpdate:[],render:[]};_installedPlugins=new Set;_pluginCleanups=new Map;_currentSystemDefaults;_screenScopedEntities=new Map;_entityScreenScope=new Map;_activeScopeHint=null;_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;_initializeFired=!1;_systemsInitialized=new WeakSet;constructor(){this._entityManager=new T,this._eventBus=new w,this._resourceManager=new C,this._reactiveQueryManager=new q(this._entityManager),this._commandBuffer=new g(this),this._subscribeLifecycleHooks()}_subscribeLifecycleHooks(){this._entityManager.onAfterComponentAdded((j,D)=>{this._entityManager.markChanged(j,D);let G=this._requiredComponents.get(D);if(G){let $=this._entityManager.getEntity(j);if($){let J=$.components[D];for(let{component:X,factory:Z}of G){if(this._entityManager._pendingBatchKeys?.has(X))continue;if(!(X in $.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 G=this._entityManager.getEntity(j);if(G)this._reactiveQueryManager.onComponentRemoved(G,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 I}addSystem(j){let D=new x(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,G=this._diagnosticsEnabled;this._runPhase("preUpdate",j,D,G);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(G)this._phaseTimings.fixedUpdate=performance.now()-$;this._interpolationAlpha=this._fixedAccumulator/this._fixedDt,this._runPhase("update",j,D,G),this._runPhase("postUpdate",j,D,G);for(let X of this._postUpdateHooks)X({ecs:this,dt:j});this._runPhase("render",j,D,G),this._resourceManager.flushObserved(),this._changeThreshold=this._entityManager.changeSeq,this._currentTick++}_executePhase(j,D,G){for(let $ of j){if(!$.process&&!$.onEntityEnter)continue;if($.groups?.length){let W=!1;for(let _ of $.groups)if(this._disabledGroups.has(_)){W=!0;break}if(W)continue}if($.inScreens?.length){if(G===null||!$.inScreens.includes(G))continue}if($.excludeScreens?.length){if(G!==null&&$.excludeScreens.includes(G))continue}if($.requiredAssets?.length&&this._assetManager){let W=!0;for(let _ of $.requiredAssets)if(!this._assetManager.isLoaded(_)){W=!1;break}if(!W)continue}let J=this._systemLastSeqs.get($)??0;this._changeThreshold=J;let X=this._systemContexts.get($);if(!X)X={queries:{},dt:0,ecs:this},this._systemContexts.set($,X);X.dt=D;let Z=X.queries,Y=!1,F=!1;if($.entityQueries)for(let W in $.entityQueries){F=!0;let _=$.entityQueries[W];if(_){let U=Z[W]??(Z[W]=[]);if(this._entityManager.getEntitiesWithQueryInto(U,_.with,_.without||[],_.changed,_.changed?this._changeThreshold:void 0,_.parentHas,_._changedIdx),U.length)Y=!0}}if($.entitySingletons){let W=this._singletonScratch;for(let _ in $.entitySingletons){F=!0;let L=$.entitySingletons[_];if(L){if(this._entityManager.getEntitiesWithQueryInto(W,L.with,L.without||[],L.changed,L.changed?this._changeThreshold:void 0,L.parentHas,L._changedIdx),Z[_]=W[0],W.length)Y=!0}}}let O=this._entityEnterTracking.get($);if(O&&$.onEntityEnter)for(let W in $.onEntityEnter){let _=Z[W],L=O.get(W);if(!_||!L)continue;let U=$.onEntityEnter[W];if(!U)continue;let Q=this._entityEnterFrameSet;Q.clear();for(let B of _)if(Q.add(B.id),!L.has(B.id))L.add(B.id),U({entity:B,ecs:this});for(let B of L)if(!Q.has(B))L.delete(B)}if($.process){if(Y||$.runWhenEmpty||!F){let _=this._activeScopeHint;this._activeScopeHint=$.inScreens?.length&&G!==null?G:null;let L=this._diagnosticsEnabled?performance.now():0;try{$.process(X)}finally{if(this._activeScopeHint=_,this._diagnosticsEnabled)this._systemTimings.set($.label,performance.now()-L)}}}let A=$._autoMarkPairs;if(A){let W=this._entityManager;for(let _=0;_<A.length;_++){let L=A[_];if(!L)continue;let U=L.mutatesIdx,Q=U.length;if(!W.hasAnySubscribed(U))continue;if(L.kind==="list"){let B=Z[L.queryName];if(!B)continue;for(let K=0;K<B.length;K++){let M=B[K];if(!M)continue;for(let f=0;f<Q;f++){let u=U[f];if(u!==void 0)W.markChangedByIdx(M.id,u)}}}else{let B=Z[L.queryName];if(!B)continue;for(let K=0;K<Q;K++){let M=U[K];if(M!==void 0)W.markChangedByIdx(B.id,M)}}}}this._systemLastSeqs.set($,this._entityManager.changeSeq)}}_runPhase(j,D,G,$){if($){let J=performance.now();this._executePhase(this._phaseSystems[j],D,G),this._phaseTimings[j]=performance.now()-J}else this._executePhase(this._phaseSystems[j],D,G);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 G=this._screenScopedEntities.get(D);if(!G||G.size===0)return;this._screenScopedEntities.delete(D);for(let $ of Array.from(G))this._entityScreenScope.delete($),this.removeEntity($)})}for(let j of this._systems){if(this._systemsInitialized.has(j))continue;this._systemsInitialized.add(j),await j.onInitialize?.(this)}this._initializeFired=!0}async initializeResources(...j){await this._resourceManager.initializeResources(this,...j)}_rebuildPhaseSystems(){for(let j of r)this._phaseSystems[j]=[];for(let j of this._systems){let D=j.phase??"update";this._phaseSystems[D].push(j)}for(let j of r)this._phaseSystems[j].sort((D,G)=>{let $=D.priority??0;return(G.priority??0)-$})}updateSystemPriority(j,D){this._finalizePendingBuilders();let G=this._systems.find(($)=>$.label===j);if(!G)return!1;return G.priority=D,this._rebuildPhaseSystems(),!0}updateSystemPhase(j,D){this._finalizePendingBuilders();let G=this._systems.find(($)=>$.label===j);if(!G)return!1;return G.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(($)=>$.label===j);if(D===-1)return!1;let G=this._systems[D];if(!G)return!1;if(G.onDetach)G.onDetach(this);return this._systems.splice(D,1),this._systemLastSeqs.delete(G),this._entityEnterTracking.delete(G),this._systemsInitialized.delete(G),this._rebuildPhaseSystems(),!0}_registerSystem(j){if(this._systems.push(j),this._systemLastSeqs.set(j,this._changeThreshold),!this._batchingRegistrations)this._rebuildPhaseSystems();let D=[],G=this._entityManager,$=(J,X,Z)=>{let Y=X.changed;if(Y&&Y.length>0){let O=[];for(let A=0;A<Y.length;A++){let W=Y[A];if(W===void 0)continue;G.subscribeChanged(W),O.push(G.getOrAssignComponentIdx(W))}X._changedIdx=O}let F=X.mutates;if(F&&F.length>0){let O=[];for(let A=0;A<F.length;A++){let W=F[A];if(W!==void 0)O.push(G.getOrAssignComponentIdx(W))}if(X._mutatesIdx=O,J!==c)D.push({queryName:J,mutatesIdx:O,kind:Z})}};if(j.entityQueries)for(let J in j.entityQueries){let X=j.entityQueries[J];if(X)$(J,X,"list")}if(j.entitySingletons)for(let J in j.entitySingletons){let X=j.entitySingletons[J];if(X)$(J,X,"singleton")}if(j._autoMarkPairs=D.length>0?D:null,j.onEntityEnter){let J=new Map;for(let X in j.onEntityEnter)J.set(X,new Set);this._entityEnterTracking.set(j,J)}if(j.eventHandlers)for(let J in j.eventHandlers){let X=j.eventHandlers[J];if(X)this._eventBus.subscribe(J,(Z)=>{X({data:Z,ecs:this})})}if(this._initializeFired&&!this._systemsInitialized.has(j)){this._systemsInitialized.add(j);let J=j.onInitialize?.(this);if(J instanceof Promise)J.catch((X)=>{console.error(`onInitialize for system "${j.label}" rejected:`,X)})}}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 G=this.getResource(j),$=D(G);return this._resourceManager.add(j,$),this._resourceManager.notifyChange(j,$,G),this}setResource(j,D){let G=this.tryGetResource(j);if(this._resourceManager.add(j,D),G!==void 0)this._resourceManager.notifyChange(j,D,G);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,G){this._entityManager.addComponent(j,D,G)}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 G=this._entityManager.createEntity();return this._entityManager.addComponents(G.id,j),this._applyScreenScope(G.id,D),G}_getActiveScopeHint(){return this._activeScopeHint}_applyScreenScope(j,D){let G=D?.scope!==void 0?D.scope:this._activeScopeHint;if(G===null)return;let $=this._screenScopedEntities.get(G)??new Set;$.add(j),this._screenScopedEntities.set(G,$),this._entityScreenScope.set(j,G)}getEntitiesWithQuery(j,D=[],G,$){return this._entityManager.getEntitiesWithQuery(j,D,G,G?this._changeThreshold:void 0,$)}getSingleton(j,D=[]){let G=this._entityManager.getEntitiesWithQuery(j,D);if(G.length===0)throw Error(`getSingleton: no entity matches query with=[${String(j)}] without=[${String(D)}]`);if(G.length>1)throw Error(`getSingleton: expected 1 entity but found ${G.length} matching query with=[${String(j)}] without=[${String(D)}]`);let $=G[0];if(!$)throw Error("getSingleton: unexpected empty result");return $}tryGetSingleton(j,D=[]){let G=this._entityManager.getEntitiesWithQuery(j,D);if(G.length===0)return;if(G.length>1)throw Error(`tryGetSingleton: expected 0 or 1 entity but found ${G.length} matching query with=[${String(j)}] without=[${String(D)}]`);return G[0]}removeEntity(j,D){return this._entityManager.removeEntity(j,D)}spawnChild(j,D,G){let $=this._entityManager.spawnChild(j,D);return this._emitHierarchyChanged($.id,null,j),this._applyScreenScope($.id,G),$}setParent(j,D){let G=this._entityManager.getParent(j);return this._entityManager.setParent(j,D),this._emitHierarchyChanged(j,G,D),this}removeParent(j){let D=this._entityManager.getParent(j),G=this._entityManager.removeParent(j);if(G)this._emitHierarchyChanged(j,D,null);return G}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(){ret