const module entitas { "use strict" ; import Pool = entitas . Pool ; import Signal = entitas . utils . Signal ; import ISignal = entitas . utils . ISignal ; import IComponent = entitas . IComponent ; import EntityChanged = Entity . EntityChanged ; import EntityReleased = Entity . EntityReleased ; import IEntityChanged = Entity . IEntityChanged ; import IEntityReleased = Entity . IEntityReleased ; import ComponentReplaced = Entity . ComponentReplaced ; import IComponentReplaced = Entity . IComponentReplaced ; import EntityIsNotEnabledException = entitas . exceptions . EntityIsNotEnabledException ; import EntityIsAlreadyReleasedException = entitas . exceptions . EntityIsAlreadyReleasedException ; import EntityAlreadyHasComponentException = entitas . exceptions . EntityAlreadyHasComponentException ; import EntityDoesNotHaveComponentException = entitas . exceptions . EntityDoesNotHaveComponentException ; export module Entity { /**
         * Event EntityReleased
         *
         * All references to the entity have been released
         */ export interface EntityReleased { ( e ) : void ; } export interface IEntityReleased < T > extends ISignal < T > { dispatch ( e ) : void ; } /**
         * Event EntityChanged
         *
         * The entity has been changed
         **/ export interface EntityChanged { ( e , index , component ) : void ; } export interface IEntityChanged < T > extends ISignal < T > { dispatch ( e , index , component ) : void ; } /**
         * Event ComponentReplaced
         *
         * A component was replaced
         */ export interface ComponentReplaced { ( e , index , component , replacement ) : void ; } export interface IComponentReplaced < T > extends ISignal < T > { dispatch ( e , index , component , replacement ) : void ; } } export class Entity { static type { number } public static instanceIndex : number = 0 ; static type { Array < Array < IComponent > > } public static alloc : Array < Array < IComponent > > = null ; static type { number } public static size : number = 0 ; type { number } name public get creationIndex ( ) : number { return this . _creationIndex ; } type { entitas . ISignal } public onEntityReleased : IEntityReleased < EntityReleased > = null ; type { entitas . ISignal } public onComponentAdded : IEntityChanged < EntityChanged > = null ; type { entitas . ISignal } public onComponentRemoved : IEntityChanged < EntityChanged > = null ; type { entitas . ISignal } public onComponentReplaced : Entity . IComponentReplaced < ComponentReplaced > = null ; type { string } public name : string = '' ; type { string } public id : string = '' ; type { number } public instanceIndex : number = 0 ; public _creationIndex : number = 0 ; public _isEnabled : boolean = true ; public _components : Array < IComponent > = null ; public _componentsCache = null ; public _componentIndicesCache : number [ ] = null ; public _toStringCache : string = '' ; public _refCount : number = 0 ; private _pool : Pool = null ; private _componentsEnum : { } = null ; param { Object } componentsEnum param { number } totalComponents constructor constructor ( componentsEnum , totalComponents = 16 ) { this . onEntityReleased = new Signal < EntityReleased > ( this ) ; this . onComponentAdded = new Signal < EntityChanged > ( this ) ; this . onComponentRemoved = new Signal < EntityChanged > ( this ) ; this . onComponentReplaced = new Signal < ComponentReplaced > ( this ) ; this . _componentsEnum = componentsEnum ; this . _pool = entitas . Pool . instance ; this . _components = this . initialize ( totalComponents ) ; } public static initialize ( totalComponents , options ) { Entity . size = options . entities || 100 ; } param count param size public static dim ( count , size ) { Entity . alloc = new Array ( size ) ; for ( let e = 0 ; e < size ; e ++ ) { Entity . alloc [ e ] = new Array ( count ) ; for ( let k = 0 ; k < count ; k ++ ) { Entity . alloc [ e ] [ k ] = null ; } } } param { number } totalComponents returns { Array < entitas . IComponent > } public initialize ( totalComponents ) { let mem ; const size = Entity . size ; if ( Entity . alloc == null ) Entity . dim ( totalComponents , size ) ; const alloc = Entity . alloc ; this . instanceIndex = Entity . instanceIndex ++ ; if ( mem = alloc [ this . instanceIndex ] ) return mem ; console . log ( 'Insufficient memory allocation at ' , this . instanceIndex , '. Allocating ' , size , ' entities.' ) ; for ( let i = this . instanceIndex , l = i + size ; i < l ; i ++ ) { alloc [ i ] = new Array ( totalComponents ) ; for ( let k = 0 ; k < totalComponents ; k ++ ) { alloc [ i ] [ k ] = null ; } } mem = alloc [ this . instanceIndex ] ; return mem ; } param { number } index param { entitas . IComponent } component returns { entitas . Entity } public addComponent ( index , component ) { if ( ! this . _isEnabled ) { throw new EntityIsNotEnabledException ( "Cannot add component!" ) ; } if ( this . hasComponent ( index ) ) { const errorMsg = "Cannot add component at index " + index + " to " + this ; throw new EntityAlreadyHasComponentException ( errorMsg , index ) ; } this . _components [ index ] = component ; this . _componentsCache = null ; this . _componentIndicesCache = null ; this . _toStringCache = null ; const onComponentAdded = this . onComponentAdded ; if ( onComponentAdded . active ) onComponentAdded . dispatch ( this , index , component ) ; return this ; } param { number } index returns { entitas . Entity } public removeComponent ( index ) { if ( ! this . _isEnabled ) { throw new EntityIsNotEnabledException ( "Cannot remove component!" ) ; } if ( ! this . hasComponent ( index ) ) { const errorMsg = "Cannot remove component at index " + index + " from " + this ; throw new EntityDoesNotHaveComponentException ( errorMsg , index ) ; } this . _replaceComponent ( index , null ) ; return this ; } param { number } index param { entitas . IComponent } component returns { entitas . Entity } public replaceComponent ( index , component ) { if ( ! this . _isEnabled ) { throw new EntityIsNotEnabledException ( "Cannot replace component!" ) ; } if ( this . hasComponent ( index ) ) { this . _replaceComponent ( index , component ) ; } else if ( component != null ) { this . addComponent ( index , component ) ; } return this ; } protected _replaceComponent ( index , replacement ) { const components = this . _components ; const previousComponent = components [ index ] ; if ( previousComponent === replacement ) { let onComponentReplaced = this . onComponentReplaced ; if ( onComponentReplaced . active ) onComponentReplaced . dispatch ( this , index , previousComponent , replacement ) ; } else { components [ index ] = replacement ; this . _componentsCache = null ; if ( replacement == null ) { components [ index ] = null ; this . _componentIndicesCache = null ; this . _toStringCache = null ; const onComponentRemoved = this . onComponentRemoved ; if ( onComponentRemoved . active ) onComponentRemoved . dispatch ( this , index , previousComponent ) ; } else { const onComponentReplaced = this . onComponentReplaced ; if ( onComponentReplaced . active ) onComponentReplaced . dispatch ( this , index , previousComponent , replacement ) ; } } } param { number } index param { entitas . IComponent } component public getComponent ( index ) { if ( ! this . hasComponent ( index ) ) { const errorMsg = "Cannot get component at index " + index + " from " + this ; throw new EntityDoesNotHaveComponentException ( errorMsg , index ) ; } return this . _components [ index ] ; } returns { Array < entitas . IComponent > } public getComponents ( ) { if ( this . _componentsCache == null ) { const components = [ ] ; const _components = this . _components ; for ( let i = 0 , j = 0 , componentsLength = _components . length ; i < componentsLength ; i ++ ) { const component = _components [ i ] ; if ( component != null ) { components [ j ++ ] = component ; } } this . _componentsCache = components ; } return this . _componentsCache ; } returns { Array < number > } public getComponentIndices ( ) { if ( this . _componentIndicesCache == null ) { const indices = [ ] ; const _components = this . _components ; for ( let i = 0 , j = 0 , componentsLength = _components . length ; i < componentsLength ; i ++ ) { if ( _components [ i ] != null ) { indices [ j ++ ] = i ; } } this . _componentIndicesCache = indices ; } return this . _componentIndicesCache ; } param { number } index returns { boolean } public hasComponent ( index ) { return this . _components [ index ] != null ; } param { Array < number > } indices returns { boolean } public hasComponents ( indices ) { const _components = this . _components ; for ( let i = 0 , indicesLength = indices . length ; i < indicesLength ; i ++ ) { if ( _components [ indices [ i ] ] == null ) { return false ; } } return true ; } param { Array < number > } indices returns { boolean } public hasAnyComponent ( indices ) { const _components = this . _components ; for ( let i = 0 , indicesLength = indices . length ; i < indicesLength ; i ++ ) { if ( _components [ indices [ i ] ] != null ) { return true ; } } return false ; } /**
         * RemoveAllComponents
         *
         */ public removeAllComponents ( ) { this . _toStringCache = null ; const _components = this . _components ; for ( let i = 0 , componentsLength = _components . length ; i < componentsLength ; i ++ ) { if ( _components [ i ] != null ) { this . _replaceComponent ( i , null ) ; } } } /**
         * Destroy
         *
         */ public destroy ( ) { this . removeAllComponents ( ) ; this . onComponentAdded . clear ( ) ; this . onComponentReplaced . clear ( ) ; this . onComponentRemoved . clear ( ) ; this . _isEnabled = false ; } returns { string } public toString ( ) { if ( this . _toStringCache == null ) { const sb = [ ] ; const seperator = ", " ; const components = this . getComponents ( ) ; const lastSeperator = components . length - 1 ; for ( let i = 0 , j = 0 , componentsLength = components . length ; i < componentsLength ; i ++ ) { sb [ j ++ ] = components [ i ] . constructor [ 'name' ] . replace ( 'Component' , '' ) || i + '' ; if ( i < lastSeperator ) { sb [ j ++ ] = seperator ; } } this . _toStringCache = sb . join ( '' ) ; } return this . _toStringCache ; } returns { entitas . Entity } public addRef ( ) { this . _refCount += 1 ; return this ; } /**
         * Release
         *
         */ public release ( ) { this . _refCount -= 1 ; if ( this . _refCount === 0 ) { let onEntityReleased = this . onEntityReleased ; if ( onEntityReleased . active ) onEntityReleased . dispatch ( this ) ; } else if ( this . _refCount < 0 ) { throw new EntityIsAlreadyReleasedException ( ) ; } } } }