-added more documentation
-remove update() function from entity -currently max supported components count is 64 per type
This commit is contained in:
parent
546b73c567
commit
845f468d59
10 changed files with 199 additions and 64 deletions
|
|
@ -1,3 +1,9 @@
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*It's internal code. Can be used for atomics if emscripten backend will be used.
|
||||||
|
*
|
||||||
|
*This module contain atomic operations which include support for emscripten atomics functions.
|
||||||
|
*Emscripten functions are contained in API similar to druntime.
|
||||||
|
*/
|
||||||
module ecs.atomic;
|
module ecs.atomic;
|
||||||
|
|
||||||
version(Emscripten)version = ECSEmscripten;
|
version(Emscripten)version = ECSEmscripten;
|
||||||
|
|
@ -35,7 +41,7 @@ version(ECSEmscripten)
|
||||||
extern(C) ushort emscripten_atomic_sub_u16(void *addr, ushort val) @nogc nothrow pure;
|
extern(C) ushort emscripten_atomic_sub_u16(void *addr, ushort val) @nogc nothrow pure;
|
||||||
extern(C) uint emscripten_atomic_sub_u32(void *addr, uint val) @nogc nothrow pure;
|
extern(C) uint emscripten_atomic_sub_u32(void *addr, uint val) @nogc nothrow pure;
|
||||||
|
|
||||||
pure nothrow @nogc Unqual!T atomicOp(string op, T, V1)(ref shared T val, V1 mod)
|
public pure nothrow @nogc Unqual!T atomicOp(string op, T, V1)(ref shared T val, V1 mod)
|
||||||
{
|
{
|
||||||
static if(op == "+=")
|
static if(op == "+=")
|
||||||
{
|
{
|
||||||
|
|
@ -53,7 +59,7 @@ version(ECSEmscripten)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pure nothrow @nogc @trusted void atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(ref T val, V newval)
|
public pure nothrow @nogc @trusted void atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(ref T val, V newval)
|
||||||
{
|
{
|
||||||
alias UT = Unqual!T;
|
alias UT = Unqual!T;
|
||||||
static if(is(UT == bool) || is(UT == byte) || is(UT == ubyte))emscripten_atomic_store_u8(cast(void*)&val, cast(UT)newval);
|
static if(is(UT == bool) || is(UT == byte) || is(UT == ubyte))emscripten_atomic_store_u8(cast(void*)&val, cast(UT)newval);
|
||||||
|
|
@ -62,7 +68,7 @@ version(ECSEmscripten)
|
||||||
else static assert(0);
|
else static assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pure nothrow @nogc @trusted T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(ref const T val)
|
public pure nothrow @nogc @trusted T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(ref const T val)
|
||||||
{
|
{
|
||||||
alias UT = Unqual!T;
|
alias UT = Unqual!T;
|
||||||
static if(is(UT == bool))return emscripten_atomic_load_u8(cast(const void*)&val) != 0;
|
static if(is(UT == bool))return emscripten_atomic_load_u8(cast(const void*)&val) != 0;
|
||||||
|
|
@ -72,7 +78,7 @@ version(ECSEmscripten)
|
||||||
else static assert(0);
|
else static assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pure nothrow @nogc @trusted bool cas(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T, V1, V2)(T* here, V1 ifThis, V2 writeThis)
|
public pure nothrow @nogc @trusted bool cas(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T, V1, V2)(T* here, V1 ifThis, V2 writeThis)
|
||||||
{
|
{
|
||||||
alias UT = Unqual!T;
|
alias UT = Unqual!T;
|
||||||
static if(is(UT == bool))return emscripten_atomic_cas_u8(cast(void*)here, cast(Unqual!T)ifThis, cast(Unqual!T)writeThis) == ifThis;
|
static if(is(UT == bool))return emscripten_atomic_cas_u8(cast(void*)here, cast(Unqual!T)ifThis, cast(Unqual!T)writeThis) == ifThis;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,21 @@
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*This module contain attributes used to mark components.
|
||||||
|
*Currently only two attributes are supported:
|
||||||
|
* - optional: mark component as optional for system update
|
||||||
|
* - readonly: mark component access as read only (used for multithreading)
|
||||||
|
*
|
||||||
|
*By default components are required and mutable. "const" attribute can be used insteac od readonly mark.
|
||||||
|
*ex.
|
||||||
|
*Struct EntitiesData
|
||||||
|
*{
|
||||||
|
* Comp1[] cmp; //mutable required component
|
||||||
|
* @readonly @optional Comp2[] cmp2; //optional read only component
|
||||||
|
* @optional const (Comp3)[] cmp3; //same as cmp2
|
||||||
|
*}
|
||||||
|
*/
|
||||||
module ecs.attributes;
|
module ecs.attributes;
|
||||||
|
|
||||||
///Used to mark optional components for system.
|
///Used to mark optional components for system.
|
||||||
enum optional = "optional";
|
enum optional = "optional";
|
||||||
//Used to mark components excluded from update for system. Enum 'ExcludedComponents' should be used instead of it.
|
|
||||||
//enum excluded = "excluded";
|
|
||||||
///Used to mark readonly components for system. "const" can be used insted.
|
///Used to mark readonly components for system. "const" can be used insted.
|
||||||
enum readonly = "readonly";
|
enum readonly = "readonly";
|
||||||
|
|
@ -1,23 +1,23 @@
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*It's internal code.
|
||||||
|
*
|
||||||
|
*Module contain memory allocator.
|
||||||
|
*/
|
||||||
module ecs.block_allocator;
|
module ecs.block_allocator;
|
||||||
|
|
||||||
import ecs.manager;
|
import ecs.manager;
|
||||||
import ecs.std;
|
import ecs.std;
|
||||||
|
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*Allocator allocate large blocks and return smaller blocks. When there is no more blocks then next large block is allocated.
|
||||||
|
*By default freeing memory only returns it to allocator. To free large memory chunks freeMemory function is used.
|
||||||
|
*freeMemory function return to system memory even if chunk blocks wasn't freed.
|
||||||
|
*/
|
||||||
struct BlockAllocator
|
struct BlockAllocator
|
||||||
{
|
{
|
||||||
private uint block_size;
|
/************************************************************************************************************************
|
||||||
private uint blocks_in_allocation;
|
*Get new block. Allocator automatically allocate next memory chunk if needed.
|
||||||
|
*/
|
||||||
struct BlockPointers
|
|
||||||
{
|
|
||||||
void*[32] blocks;
|
|
||||||
uint numberof = 0;
|
|
||||||
BlockPointers* next_pointers = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* next_block = null;
|
|
||||||
BlockPointers* pointers = null;
|
|
||||||
|
|
||||||
void* getBlock() nothrow @nogc
|
void* getBlock() nothrow @nogc
|
||||||
{
|
{
|
||||||
if (next_block is null)
|
if (next_block is null)
|
||||||
|
|
@ -27,13 +27,35 @@ struct BlockAllocator
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*Return block to allocator for further use.
|
||||||
|
*/
|
||||||
void freeBlock(void* block) nothrow @nogc
|
void freeBlock(void* block) nothrow @nogc
|
||||||
{
|
{
|
||||||
*cast(void**)block = next_block;
|
*cast(void**)block = next_block;
|
||||||
next_block = block;
|
next_block = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void allocBlock() nothrow @nogc
|
/************************************************************************************************************************
|
||||||
|
*Free whole used memory. This function return to system all memory chunks even if not every black was freed.
|
||||||
|
*/
|
||||||
|
void freeMemory() nothrow @nogc
|
||||||
|
{
|
||||||
|
while(pointers)
|
||||||
|
{
|
||||||
|
foreach(i;0..pointers.numberof)
|
||||||
|
{
|
||||||
|
Mallocator.alignDispose(pointers.blocks[i]);
|
||||||
|
}
|
||||||
|
BlockPointers* next_pointers = pointers.next_pointers;
|
||||||
|
Mallocator.dispose(pointers);
|
||||||
|
pointers = next_pointers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void allocBlock() nothrow @nogc
|
||||||
{
|
{
|
||||||
next_block = cast(void*) Mallocator.alignAlloc(
|
next_block = cast(void*) Mallocator.alignAlloc(
|
||||||
block_size * blocks_in_allocation, block_size);
|
block_size * blocks_in_allocation, block_size);
|
||||||
|
|
@ -57,17 +79,16 @@ struct BlockAllocator
|
||||||
*pointer = null;
|
*pointer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeMemory() nothrow @nogc
|
struct BlockPointers
|
||||||
{
|
{
|
||||||
while(pointers)
|
void*[32] blocks;
|
||||||
{
|
uint numberof = 0;
|
||||||
foreach(i;0..pointers.numberof)
|
BlockPointers* next_pointers = null;
|
||||||
{
|
|
||||||
Mallocator.alignDispose(pointers.blocks[i]);
|
|
||||||
}
|
|
||||||
BlockPointers* next_pointers = pointers.next_pointers;
|
|
||||||
Mallocator.dispose(pointers);
|
|
||||||
pointers = next_pointers;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint block_size;
|
||||||
|
uint blocks_in_allocation;
|
||||||
|
|
||||||
|
void* next_block = null;
|
||||||
|
BlockPointers* pointers = null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,74 @@
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*This module contain main templates for user.
|
||||||
|
*There are three structure templates (mixins) which should be added on top of structure:
|
||||||
|
* - System: make system structure
|
||||||
|
* - Component: make component structure
|
||||||
|
* - Event: make event structure
|
||||||
|
*
|
||||||
|
*ex.
|
||||||
|
*Struct System1
|
||||||
|
*{
|
||||||
|
* mixin!ECS.System;
|
||||||
|
*}
|
||||||
|
*
|
||||||
|
*Struct System2
|
||||||
|
*{
|
||||||
|
* mixin!ECS.System(16);//set number of jobs generated for system by multithreaded update
|
||||||
|
*}
|
||||||
|
*
|
||||||
|
*Struct Component1
|
||||||
|
*{
|
||||||
|
* mixin!ECS.Component;
|
||||||
|
*}
|
||||||
|
*
|
||||||
|
*Struct Event1
|
||||||
|
*{
|
||||||
|
* mixin!ECS.Event;
|
||||||
|
*}
|
||||||
|
*
|
||||||
|
*There is also template for generating list of excluded components "ExcludedComponets(T...)".
|
||||||
|
*This template takes component structure types and making list of excluded components used in "registerSystem" function.
|
||||||
|
*
|
||||||
|
*/
|
||||||
module ecs.core;
|
module ecs.core;
|
||||||
|
|
||||||
public import ecs.manager;
|
public import ecs.manager;
|
||||||
public import ecs.entity;
|
public import ecs.entity;
|
||||||
|
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*Main struct used as namespace for templates.
|
||||||
|
*/
|
||||||
static struct ECS
|
static struct ECS
|
||||||
{
|
{
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*Mark structure as System. Should be added on top of structure (before any data).
|
||||||
|
*/
|
||||||
mixin template System(uint jobs_count = 32)
|
mixin template System(uint jobs_count = 32)
|
||||||
{
|
{
|
||||||
__gshared ushort system_id;
|
__gshared ushort system_id;
|
||||||
uint __ecs_jobs_count = jobs_count;
|
uint __ecs_jobs_count = jobs_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*Mark structure as Component. Should be added on top of structure (before any data).
|
||||||
|
*/
|
||||||
mixin template Component()
|
mixin template Component()
|
||||||
{
|
{
|
||||||
__gshared ushort component_id;
|
__gshared ushort component_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*Mark structure as Event. Should be added on top of structure (before any data).
|
||||||
|
*/
|
||||||
mixin template Event()
|
mixin template Event()
|
||||||
{
|
{
|
||||||
__gshared ushort event_id;
|
__gshared ushort event_id;
|
||||||
EntityID entity_id;
|
EntityID entity_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*Make list of excluded components. This template get structure types as argument. Should be added inside System structure.
|
||||||
|
*/
|
||||||
mixin template ExcludedComponents(T...)
|
mixin template ExcludedComponents(T...)
|
||||||
{
|
{
|
||||||
alias ExcludedComponents = T;
|
alias ExcludedComponents = T;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import ecs.system;
|
||||||
import ecs.manager;
|
import ecs.manager;
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
*Entity ID structure.
|
*Entity ID structure. Used as reference to Entity. Pointer to entity should be ever used to store entity reference!
|
||||||
*/
|
*/
|
||||||
struct EntityID
|
struct EntityID
|
||||||
{
|
{
|
||||||
|
|
@ -26,15 +26,8 @@ struct Entity
|
||||||
EntityID id;
|
EntityID id;
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
*Update pointer to it in IDManager
|
*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.
|
||||||
void updateID() nothrow @nogc
|
|
||||||
{
|
|
||||||
EntityManager.instance.id_manager.update(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************************************************************
|
|
||||||
*Get specified component. If component doesn't exist function retun null.
|
|
||||||
*/
|
*/
|
||||||
T* getComponent(T)() const
|
T* getComponent(T)() const
|
||||||
{
|
{
|
||||||
|
|
@ -49,10 +42,21 @@ struct Entity
|
||||||
uint ind = cast(uint)((cast(void*)&this - block.dataBegin()) / EntityID.sizeof());
|
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);
|
return cast(T*)(cast(void*)block + info.deltas[T.component_id] + ind * T.sizeof);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*package void updateID() nothrow @nogc
|
||||||
|
{
|
||||||
|
EntityManager.instance.id_manager.update(this);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
*Entity template structure.
|
*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
|
export struct EntityTemplate
|
||||||
{
|
{
|
||||||
|
|
@ -62,7 +66,7 @@ export struct EntityTemplate
|
||||||
EntityManager.EntityInfo* info;
|
EntityManager.EntityInfo* info;
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
*Get specified component. If component doesn't exist function return null.
|
*Get specified component. If component doesn't exist function return null. Returned pointer is valid during EntityTemplate lifetime.
|
||||||
*/
|
*/
|
||||||
T* getComponent(T)() nothrow @nogc
|
T* getComponent(T)() nothrow @nogc
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import ecs.std;
|
||||||
|
|
||||||
import std.algorithm.comparison : max;
|
import std.algorithm.comparison : max;
|
||||||
|
|
||||||
struct EventManager
|
package struct EventManager
|
||||||
{
|
{
|
||||||
|
|
||||||
void initialize(EntityManager* m) nothrow @nogc
|
void initialize(EntityManager* m) nothrow @nogc
|
||||||
|
|
@ -34,7 +34,7 @@ struct EventManager
|
||||||
|
|
||||||
EventData* data = &events[Ev.event_id];
|
EventData* data = &events[Ev.event_id];
|
||||||
EventBlock* block = data.blocks[block_id];
|
EventBlock* block = data.blocks[block_id];
|
||||||
EntityManager.EventInfo* info = &gEM.events[Ev.event_id];
|
//EntityManager.EventInfo* info = &gEM.events[Ev.event_id];
|
||||||
event.entity_id = id;
|
event.entity_id = id;
|
||||||
|
|
||||||
if(block is null)
|
if(block is null)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ struct IDManager
|
||||||
{
|
{
|
||||||
//uint current = m_next_id;
|
//uint current = m_next_id;
|
||||||
//uint next;// = m_ids_array[m_next_id].next_id;
|
//uint next;// = m_ids_array[m_next_id].next_id;
|
||||||
begin:
|
//begin:
|
||||||
//if (current == uint.max)//> m_last_id)
|
//if (current == uint.max)//> m_last_id)
|
||||||
int current = m_stack_top.atomicOp!"-="(1) + 1;
|
int current = m_stack_top.atomicOp!"-="(1) + 1;
|
||||||
if(current < 0)
|
if(current < 0)
|
||||||
|
|
@ -142,6 +142,9 @@ begin:
|
||||||
return data.counter == id.counter;
|
return data.counter == id.counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*Initialize manager.
|
||||||
|
*/
|
||||||
void initialize() nothrow @nogc
|
void initialize() nothrow @nogc
|
||||||
{
|
{
|
||||||
m_ids_array = Mallocator.makeArray!Data(65536);
|
m_ids_array = Mallocator.makeArray!Data(65536);
|
||||||
|
|
@ -158,6 +161,9 @@ begin:
|
||||||
optimize();
|
optimize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*Free manager memory.
|
||||||
|
*/
|
||||||
void deinitialize() @trusted @nogc nothrow
|
void deinitialize() @trusted @nogc nothrow
|
||||||
{
|
{
|
||||||
if(m_ids_array)Mallocator.dispose(m_ids_array);
|
if(m_ids_array)Mallocator.dispose(m_ids_array);
|
||||||
|
|
@ -178,6 +184,9 @@ begin:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*Optimize memory. Must be called if any ID was added and some ID will be removed.
|
||||||
|
*/
|
||||||
void optimize() nothrow @nogc
|
void optimize() nothrow @nogc
|
||||||
{
|
{
|
||||||
if(m_stack_top < -1)m_stack_top = -1;
|
if(m_stack_top < -1)m_stack_top = -1;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
*Most important module.
|
*Most important module. Almost every function is called from EntityManager.
|
||||||
*/
|
*/
|
||||||
module ecs.manager;
|
module ecs.manager;
|
||||||
|
|
||||||
|
|
@ -25,11 +25,35 @@ import ecs.atomic;
|
||||||
|
|
||||||
export alias gEM = EntityManager.instance;
|
export alias gEM = EntityManager.instance;
|
||||||
export alias gEntityManager = EntityManager.instance;
|
export alias gEntityManager = EntityManager.instance;
|
||||||
export alias gEventManager = EntityManager.instance;
|
|
||||||
alias SerializeVector = ecs.vector.Vector!ubyte;
|
alias SerializeVector = ecs.vector.Vector!ubyte;
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
*Entity manager is responsible for everything.
|
*Entity manager is responsible for everything.
|
||||||
|
*
|
||||||
|
*Entity manager can be in three states:
|
||||||
|
* - registration: time between beginRegister() and endRegister() calls.
|
||||||
|
* - update: time between being() and end() calls.
|
||||||
|
* - default: when it's not in registration or update time
|
||||||
|
*
|
||||||
|
*Manager can be only in one state simultaneously.
|
||||||
|
*
|
||||||
|
*Manager must be initialized before use. There is global instance of EntityManager: EntityManager.instance or gEM as alias.
|
||||||
|
*
|
||||||
|
*Registration process consist of registration of passes, systems, entities and events.
|
||||||
|
*
|
||||||
|
*Pass is group of system which should be used inside one update() call. Passes are added as name (string) and can be referenced by name or id.<br/>
|
||||||
|
*System is structure responsible for update of specified group of entities. System consist of EntitiesData structure which contain components used
|
||||||
|
*by system and some callback. Main callback is onUpdate() which is called by update() entity manager function. Other callbacks are used as listeners for
|
||||||
|
*adding entites, tracking system lifetime and events handling.<br/>
|
||||||
|
*Component is basicly small fraction of data which is considered to be used as whole. In best scenario every byte of component is used when it's refered to.
|
||||||
|
*In practice sometimes it's better to join data into one component even if it's can be accessed separetly.<br/>
|
||||||
|
*Events are structures with data used to handle events. Event can contain for exmaple one floating point number used as damage dealt to entity.<br/>
|
||||||
|
*Entity is group of components. In memory entity is only ID which makes it's possible to take it's components. Components are grouped into chunks, and
|
||||||
|
*grouped by component type so entity can be fracted in big memory chunk.<br/>
|
||||||
|
*
|
||||||
|
*There is two types of update:
|
||||||
|
*<br/> - update(): function used to call update pass.
|
||||||
|
*<br/> - updateMT(): function used to call update pass multithreaded. This call only generates jobs which must be called by user.
|
||||||
*/
|
*/
|
||||||
export struct EntityManager
|
export struct EntityManager
|
||||||
{
|
{
|
||||||
|
|
@ -353,7 +377,7 @@ export struct EntityManager
|
||||||
|
|
||||||
static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort))
|
static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort))
|
||||||
{
|
{
|
||||||
static assert(0); //, "Add \"mixin ECS.System;\" in top of system structure;"); //"System should have \"__gshared ushort system_id");
|
static assert(0); //, "Add \"mixin ECS.System;\" in top of system structure;");
|
||||||
}
|
}
|
||||||
|
|
||||||
static if (!(hasMember!(Sys, "EntitiesData")))
|
static if (!(hasMember!(Sys, "EntitiesData")))
|
||||||
|
|
@ -463,11 +487,11 @@ export struct EntityManager
|
||||||
m_req[m_req_counter++] = info;
|
m_req[m_req_counter++] = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
CompInfo[32] m_readonly;
|
CompInfo[64] m_readonly;
|
||||||
CompInfo[32] m_mutable;
|
CompInfo[64] m_mutable;
|
||||||
CompInfo[32] m_excluded;
|
CompInfo[64] m_excluded;
|
||||||
CompInfo[32] m_optional;
|
CompInfo[64] m_optional;
|
||||||
CompInfo[32] m_req;
|
CompInfo[64] m_req;
|
||||||
|
|
||||||
uint m_readonly_counter;
|
uint m_readonly_counter;
|
||||||
uint m_mutable_counter;
|
uint m_mutable_counter;
|
||||||
|
|
@ -635,7 +659,12 @@ export struct EntityManager
|
||||||
foreach (iii, comp_info; components_info.req)
|
foreach (iii, comp_info; components_info.req)
|
||||||
{
|
{
|
||||||
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
|
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
|
||||||
assert(comp != ushort.max); //, "Can't register system \""~Sys.stringof~"\" due to non existing component \""~comp_info.type~"\".");
|
version (betterC)
|
||||||
|
assert(comp != ushort.max,
|
||||||
|
"Can't register system due to non existing component.");
|
||||||
|
else
|
||||||
|
assert(comp != ushort.max, "Can't register system \"" ~ Sys.stringof
|
||||||
|
~ "\" due to non existing component \"" ~ comp_info.type ~ "\".");
|
||||||
system.m_components[iii] = comp;
|
system.m_components[iii] = comp;
|
||||||
}
|
}
|
||||||
foreach (iii, comp_info; components_info.excluded)
|
foreach (iii, comp_info; components_info.excluded)
|
||||||
|
|
@ -1319,7 +1348,7 @@ export struct EntityManager
|
||||||
*Allocate EntityTemplate with all components from entity witch it's data and returns pointer to it.
|
*Allocate EntityTemplate with all components from entity witch it's data and returns pointer to it.
|
||||||
*
|
*
|
||||||
*Params:
|
*Params:
|
||||||
*id = ID of entity from which should be created template
|
*entity_id = ID of entity from which should be created template
|
||||||
*fill_default = if true, components will be filled with default data, instead entity data will be taken
|
*fill_default = if true, components will be filled with default data, instead entity data will be taken
|
||||||
*/
|
*/
|
||||||
export EntityTemplate* allocateTemplate(EntityID entity_id, bool fill_default = false)
|
export EntityTemplate* allocateTemplate(EntityID entity_id, bool fill_default = false)
|
||||||
|
|
@ -1756,7 +1785,7 @@ export struct EntityManager
|
||||||
|
|
||||||
Entity* new_entity = cast(Entity*) start;
|
Entity* new_entity = cast(Entity*) start;
|
||||||
new_entity.id = entity.id;
|
new_entity.id = entity.id;
|
||||||
new_entity.updateID();
|
id_manager.update(*new_entity); //new_entity.updateID();
|
||||||
|
|
||||||
uint ind = block.entityIndex(entity);
|
uint ind = block.entityIndex(entity);
|
||||||
|
|
||||||
|
|
@ -1876,7 +1905,7 @@ export struct EntityManager
|
||||||
|
|
||||||
Entity* new_entity = cast(Entity*) start;
|
Entity* new_entity = cast(Entity*) start;
|
||||||
new_entity.id = entity.id;
|
new_entity.id = entity.id;
|
||||||
new_entity.updateID();
|
id_manager.update(*new_entity); //new_entity.updateID();
|
||||||
|
|
||||||
uint j = 0;
|
uint j = 0;
|
||||||
uint k = 0;
|
uint k = 0;
|
||||||
|
|
@ -2001,7 +2030,7 @@ export struct EntityManager
|
||||||
*instead of pointer.
|
*instead of pointer.
|
||||||
*
|
*
|
||||||
*Params:
|
*Params:
|
||||||
*tmpl = pointer entity template allocated by EntityManager.
|
*id = ID of entity to be copyied.
|
||||||
*/
|
*/
|
||||||
export Entity* addEntityCopy(EntityID id)
|
export Entity* addEntityCopy(EntityID id)
|
||||||
{
|
{
|
||||||
|
|
@ -2044,7 +2073,7 @@ export struct EntityManager
|
||||||
//add_mutex.lock_nothrow();
|
//add_mutex.lock_nothrow();
|
||||||
new_entity.id = id_manager.getNewID();
|
new_entity.id = id_manager.getNewID();
|
||||||
//add_mutex.unlock_nothrow();
|
//add_mutex.unlock_nothrow();
|
||||||
new_entity.updateID();
|
id_manager.update(*new_entity); //new_entity.updateID();
|
||||||
|
|
||||||
return new_entity;
|
return new_entity;
|
||||||
}
|
}
|
||||||
|
|
@ -2094,7 +2123,7 @@ export struct EntityManager
|
||||||
//add_mutex.lock_nothrow();
|
//add_mutex.lock_nothrow();
|
||||||
entity.id = id_manager.getNewID();
|
entity.id = id_manager.getNewID();
|
||||||
//add_mutex.unlock_nothrow();
|
//add_mutex.unlock_nothrow();
|
||||||
entity.updateID();
|
id_manager.update(*entity); //entity.updateID();
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
@ -2237,7 +2266,7 @@ export struct EntityManager
|
||||||
block = info.last_block;
|
block = info.last_block;
|
||||||
entity.id = *cast(EntityID*)(block.dataBegin() + block.entities_count * EntityID.sizeof);
|
entity.id = *cast(EntityID*)(block.dataBegin() + block.entities_count * EntityID.sizeof);
|
||||||
|
|
||||||
entity.updateID();
|
id_manager.update(*entity); //entity.updateID();
|
||||||
}
|
}
|
||||||
|
|
||||||
block = info.last_block;
|
block = info.last_block;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*It's internal code!
|
||||||
|
*This module contain implementation of standard functionality.
|
||||||
|
*/
|
||||||
module ecs.std;
|
module ecs.std;
|
||||||
|
|
||||||
version(Emscripten)version = ECSEmscripten;
|
version(Emscripten)version = ECSEmscripten;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ import ecs.manager;
|
||||||
*<br/>-void onDestroy();
|
*<br/>-void onDestroy();
|
||||||
*<br/>-void onAddEntity(EntitesData);
|
*<br/>-void onAddEntity(EntitesData);
|
||||||
*<br/>-void onRemoveEntity(EntitiesData);
|
*<br/>-void onRemoveEntity(EntitiesData);
|
||||||
|
*<br/>-void onChangeEntity(EntitiesData);
|
||||||
|
*<br/>-void handleEvent(Entity*, Event);
|
||||||
*/
|
*/
|
||||||
struct System
|
struct System
|
||||||
{
|
{
|
||||||
|
|
@ -82,14 +84,14 @@ struct System
|
||||||
return cast(const(char)[]) m_name;
|
return cast(const(char)[]) m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
package:
|
||||||
|
|
||||||
struct EventCaller
|
struct EventCaller
|
||||||
{
|
{
|
||||||
ushort id;
|
ushort id;
|
||||||
void* callback;
|
void* callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
package:
|
|
||||||
|
|
||||||
///should system be executed in current update?
|
///should system be executed in current update?
|
||||||
bool m_execute = true;
|
bool m_execute = true;
|
||||||
///system id
|
///system id
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue