-added multiple new function to allocate template and add entity -updated README.md (complete initial version) -empty components now don't take memory -fixedd small bug with TestRunner -added many new tests (HashMap, Vector, EntityMeta, ...) -added default hashing function to HashMap -fixed critical bug with adding entities -fixed small bug with adding entity with remplacement components -added asserts into code to better bug detection -small performance improvement for events -added ComponentRef structure which contain data pointer and componentID -remove EntityID from Event structure -now events are handled before removing entiteis -fixed GDC compilation -fixed rendering of rotated sprites -added weapons as separate entities to space ship and others -added Tower enemy to SpaceInvaders demo -added Boss to SpaceInvaders demo (boss has four tower attached to it) -Boss towers shoot multiple bullets upon death -fixed critical bug with demos switching -fixed critical bug related to adding/removing entities form inside onAdd/onRemove entity callback -added animation support -added particles sypport and particles for firing and explostions, and more -multithreaded rendering now has same rendering order as singlethreaded -application automaticallu detect host CPU threads count -added upgrades to SPaceInvaders demo -fixed texture memory freeing -improved documentation -improved multithreaded performance -improve shader code -fixed registration issue -some additional performance improvements -added depth and colors to rendering parameters -jobs now has names corresponding to their systems -change execute() -> willExecute() -added EntityMeta structure to speedup getting fetching components form entity -improved multithreading rendering -added possibility tio change number of threads runtime -added bullets collision detection in SpaceInvaders demo -some CI changes -added VBO batch rendering (current default, no render mode switch yet) -fixed camera positioning calculation -fixed buffer issue with WebGL -added viewport scalling (at least 300 pixels height). Pixels are scalled if screen is bigger. -center demos gameplay area -added fullpage html template for Emscripten build -added many new sprites to atlas -fixed critical bug with CPU usage in multithreaded mode -snake render tile coresponding to body part -snake is destroyed after collision and emit some particles -added some functionality to vectors -fixed documentation issue in Manager.d -more minor code changes and cleanup
120 lines
4.6 KiB
D
120 lines
4.6 KiB
D
/************************************************************************************************************************
|
|
Entity module.
|
|
|
|
Copyright: Copyright © 2018-2019, Dawid Masiukiewicz, Michał Masiukiewicz
|
|
License: BSD 3-clause, see LICENSE file in project root folder.
|
|
*/
|
|
module bubel.ecs.entity;
|
|
|
|
import bubel.ecs.system;
|
|
import bubel.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;
|
|
|
|
return cast(T*)(cast(void*)block + info.deltas[T.component_id] + block.entityIndex(&this) * T.sizeof);
|
|
}
|
|
|
|
bool hasComponent(ushort component_id)
|
|
{
|
|
EntityManager.EntitiesBlock* block = gEM.getMetaData(&this);
|
|
EntityManager.EntityInfo* info = block.type_info;
|
|
if (component_id >= info.deltas.length || info.deltas[component_id] == 0)return false;
|
|
return true;
|
|
}
|
|
|
|
EntityMeta getMeta()
|
|
{
|
|
EntityMeta meta;
|
|
meta.block = gEM.getMetaData(&this);
|
|
meta.index = meta.block.entityIndex(&this);
|
|
return meta;
|
|
}
|
|
}
|
|
|
|
struct EntityMeta
|
|
{
|
|
EntityManager.EntitiesBlock* block;
|
|
ushort index;
|
|
|
|
T* getComponent(T)() const
|
|
{
|
|
const (EntityManager.EntityInfo)* info = block.type_info;
|
|
if (T.component_id >= info.deltas.length || info.deltas[T.component_id] == 0)
|
|
return null;
|
|
return cast(T*)(cast(void*)block + block.type_info.deltas[T.component_id] + index * T.sizeof);
|
|
}
|
|
|
|
bool hasComponent(ushort component_id)
|
|
{
|
|
EntityManager.EntityInfo* info = block.type_info;
|
|
if (component_id >= info.deltas.length || info.deltas[component_id] == 0)return false;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/************************************************************************************************************************
|
|
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]);
|
|
}
|
|
}
|
|
|
|
/************************************************************************************************************************
|
|
ComponentRef contain component ID and pointer to it. It used to add component data to entity.
|
|
*/
|
|
export struct ComponentRef
|
|
{
|
|
///pointer to component
|
|
void* ptr;
|
|
///component index
|
|
ushort component_id;
|
|
}
|