/************************************************************************************************************************ *Entity module. */ module ecs.entity; import ecs.system; import ecs.manager; /************************************************************************************************************************ *Entity ID structure. Used as reference to Entity. Pointer to entity should be ever used to store entity reference! */ struct EntityID { ///Index to entity in IDManager. uint id; ///Counter required for reusing ID. uint counter; } /************************************************************************************************************************ *Structure of Entity. It's have only ID, but have full konwlege to get to components memory (If pointer to it is proper). */ struct Entity { ///Entity ID. EntityID id; /************************************************************************************************************************ *Get specified component. If component doesn't exist function retun null. Pointer is valid only before next "commit()", "begin()" or "end()" *function is called. Returned pointer shouldn't be used to store reference to entity data. */ T* getComponent(T)() const { EntityManager.EntitiesBlock* block = gEM.getMetaData(&this); EntityManager.EntityInfo* info = block.type_info; if (T.component_id >= info.deltas.length || info.deltas[T.component_id] == 0) return null; static if (EntityID.sizeof == 8) uint ind = cast(uint)((cast(void*)&this - block.dataBegin()) >> 3); else uint ind = cast(uint)((cast(void*)&this - block.dataBegin()) / EntityID.sizeof()); return cast(T*)(cast(void*)block + info.deltas[T.component_id] + ind * T.sizeof); } } /************************************************************************************************************************ *Entity template structure. *Entity contain whole information needed to create new entity. Allocating EntityTemplate is considered as more expensive operation *than adding entity. Whole components memory is stored in EntityTemplate and is copyied to newly added entity. *If you want to place several entity with small difference in data then you should take pointer to component and change it before every *entity addition. *There is no restriction about number of allocated templates. Single template can be used from multiple threads, but if you *want to changes some components data before add entity (entity position for example) it's better to use multiple templates. */ export struct EntityTemplate { ///Entity components data ubyte[] entity_data; ///Pointer to entity type info. EntityManager.EntityInfo* info; /************************************************************************************************************************ *Get specified component. If component doesn't exist function return null. Returned pointer is valid during EntityTemplate lifetime. */ T* getComponent(T)() nothrow @nogc { if(T.component_id >= info.tmpl_deltas.length || info.tmpl_deltas[T.component_id] == ushort.max)return null; return cast(T*)(entity_data.ptr + info.tmpl_deltas[T.component_id]); } }