Merge branch 'master' of https://Mergul@bitbucket.org/mmcomando/ecs.git
This commit is contained in:
commit
86d91bc11c
8 changed files with 444 additions and 65 deletions
|
|
@ -10,7 +10,15 @@ struct BlockAllocator//(uint block_size, uint blocks_in_allocation)
|
||||||
private uint block_size;
|
private uint block_size;
|
||||||
private uint blocks_in_allocation;
|
private uint blocks_in_allocation;
|
||||||
|
|
||||||
|
struct BlockPointers
|
||||||
|
{
|
||||||
|
void*[32] blocks;
|
||||||
|
uint numberof = 0;
|
||||||
|
BlockPointers* next_pointers = null;
|
||||||
|
}
|
||||||
|
|
||||||
void* next_block = null;
|
void* next_block = null;
|
||||||
|
BlockPointers* pointers = null;
|
||||||
|
|
||||||
void* getBlock() nothrow @nogc
|
void* getBlock() nothrow @nogc
|
||||||
{
|
{
|
||||||
|
|
@ -31,6 +39,16 @@ struct BlockAllocator//(uint block_size, uint blocks_in_allocation)
|
||||||
{
|
{
|
||||||
next_block = cast(void*) AlignedMallocator.instance.alignedAllocate(
|
next_block = cast(void*) AlignedMallocator.instance.alignedAllocate(
|
||||||
block_size * blocks_in_allocation, block_size);
|
block_size * blocks_in_allocation, block_size);
|
||||||
|
|
||||||
|
if(pointers is null)pointers = Mallocator.instance.make!BlockPointers;
|
||||||
|
if(pointers.numberof >= 32)
|
||||||
|
{
|
||||||
|
BlockPointers* new_pointers = Mallocator.instance.make!BlockPointers;
|
||||||
|
new_pointers.next_pointers = pointers;
|
||||||
|
pointers = new_pointers;
|
||||||
|
}
|
||||||
|
pointers.blocks[pointers.numberof++] = next_block;
|
||||||
|
|
||||||
foreach (i; 0 .. blocks_in_allocation - 1)
|
foreach (i; 0 .. blocks_in_allocation - 1)
|
||||||
{
|
{
|
||||||
void** pointer = cast(void**)(next_block + i * block_size);
|
void** pointer = cast(void**)(next_block + i * block_size);
|
||||||
|
|
@ -40,4 +58,18 @@ struct BlockAllocator//(uint block_size, uint blocks_in_allocation)
|
||||||
next_block + (blocks_in_allocation - 1) * block_size);
|
next_block + (blocks_in_allocation - 1) * block_size);
|
||||||
*pointer = null;
|
*pointer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void freeMemory() nothrow @nogc
|
||||||
|
{
|
||||||
|
while(pointers)
|
||||||
|
{
|
||||||
|
foreach(i;0..pointers.numberof)
|
||||||
|
{
|
||||||
|
AlignedMallocator.instance.dispose(pointers.blocks[i]);
|
||||||
|
}
|
||||||
|
BlockPointers* next_pointers = pointers.next_pointers;
|
||||||
|
Mallocator.instance.dispose(pointers);
|
||||||
|
pointers = next_pointers;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ static struct ECS
|
||||||
mixin template System(uint jobs_count = 32)
|
mixin template System(uint jobs_count = 32)
|
||||||
{
|
{
|
||||||
__gshared ushort system_id;
|
__gshared ushort system_id;
|
||||||
EntityManager.Job[] _ecs_jobs;
|
uint __ecs_jobs_count = jobs_count;
|
||||||
|
/*EntityManager.Job[] _ecs_jobs;
|
||||||
|
|
||||||
void __ecsInitialize() nothrow @nogc
|
void __ecsInitialize() nothrow @nogc
|
||||||
{
|
{
|
||||||
|
|
@ -16,6 +17,13 @@ static struct ECS
|
||||||
import std.experimental.allocator;
|
import std.experimental.allocator;
|
||||||
_ecs_jobs = Mallocator.instance.makeArray!(EntityManager.Job)(jobs_count);
|
_ecs_jobs = Mallocator.instance.makeArray!(EntityManager.Job)(jobs_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __ecsDeinitialize() nothrow @nogc
|
||||||
|
{
|
||||||
|
import std.experimental.allocator.mallocator;
|
||||||
|
import std.experimental.allocator;
|
||||||
|
Mallocator.instance.dispose(_ecs_jobs);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin template Component()
|
mixin template Component()
|
||||||
|
|
|
||||||
|
|
@ -175,15 +175,7 @@ struct EventManager
|
||||||
|
|
||||||
void allocateData(uint threads_count) nothrow @nogc
|
void allocateData(uint threads_count) nothrow @nogc
|
||||||
{
|
{
|
||||||
if(events)
|
disposeData();
|
||||||
{
|
|
||||||
foreach(ref event;events)
|
|
||||||
{
|
|
||||||
Mallocator.instance.dispose(event.blocks);
|
|
||||||
Mallocator.instance.dispose(event.first_blocks);
|
|
||||||
}
|
|
||||||
Mallocator.instance.dispose(events);
|
|
||||||
}
|
|
||||||
events = Mallocator.instance.makeArray!EventData(gEM.events.length);
|
events = Mallocator.instance.makeArray!EventData(gEM.events.length);
|
||||||
foreach(i,ref event;events)
|
foreach(i,ref event;events)
|
||||||
{
|
{
|
||||||
|
|
@ -196,8 +188,44 @@ struct EventManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void disposeData() nothrow @nogc
|
||||||
|
{
|
||||||
|
if(events)
|
||||||
|
{
|
||||||
|
foreach(ref event;events)
|
||||||
|
{
|
||||||
|
foreach(first_block; event.first_blocks)
|
||||||
|
{
|
||||||
|
EventBlock* block = first_block;
|
||||||
|
EventBlock* next_block;
|
||||||
|
if(block)next_block = first_block.next;
|
||||||
|
while(block)
|
||||||
|
{
|
||||||
|
Mallocator.instance.dispose(block);
|
||||||
|
block = next_block;
|
||||||
|
if(block)next_block = block.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Mallocator.instance.dispose(event.blocks);
|
||||||
|
Mallocator.instance.dispose(event.first_blocks);
|
||||||
|
}
|
||||||
|
Mallocator.instance.dispose(events);
|
||||||
|
}
|
||||||
|
allocator.freeMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
~this() nothrow @nogc
|
||||||
|
{
|
||||||
|
disposeData();
|
||||||
|
/*foreach(i,ref event;events)
|
||||||
|
{
|
||||||
|
EventBlock* block = event.first_blocks;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
///Single page size. Must be power of two.
|
///Single page size. Must be power of two.
|
||||||
enum events_block_size = 1 << 12;
|
enum events_block_size = 1 << 14;
|
||||||
///Number of pages in block.
|
///Number of pages in block.
|
||||||
enum events_blocks_in_allocation = 128;
|
enum events_blocks_in_allocation = 128;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,24 @@ begin:
|
||||||
add_mutex = Mallocator.instance.make!Mutex();
|
add_mutex = Mallocator.instance.make!Mutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void deinitialize() @trusted @nogc
|
||||||
|
{
|
||||||
|
if(m_ids_array)Mallocator.instance.dispose(m_ids_array);
|
||||||
|
if(m_free_stack)Mallocator.instance.dispose(m_free_stack);
|
||||||
|
if(m_blocks)
|
||||||
|
{
|
||||||
|
foreach(ref block;m_blocks)
|
||||||
|
{
|
||||||
|
if(block.data)block.free();
|
||||||
|
}
|
||||||
|
Mallocator.instance.dispose(m_blocks);
|
||||||
|
}
|
||||||
|
if(add_mutex)
|
||||||
|
{
|
||||||
|
Mallocator.instance.dispose(cast(void*)add_mutex); //workaround for compiler bug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
@ -176,7 +194,7 @@ begin:
|
||||||
begin += 65536;
|
begin += 65536;
|
||||||
}
|
}
|
||||||
memcpy(cast(void*)m_ids_array.ptr + begin * Data.sizeof, m_blocks[m_blocks_count-1].data.ptr, (m_last_id - begin) * Data.sizeof);
|
memcpy(cast(void*)m_ids_array.ptr + begin * Data.sizeof, m_blocks[m_blocks_count-1].data.ptr, (m_last_id - begin) * Data.sizeof);
|
||||||
foreach(block;m_blocks[1..m_blocks_count])block.free();
|
foreach(ref block;m_blocks[1..m_blocks_count])block.free();
|
||||||
m_blocks_count = 1;
|
m_blocks_count = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -193,9 +211,10 @@ begin:
|
||||||
{
|
{
|
||||||
assert(data !is null);
|
assert(data !is null);
|
||||||
Mallocator.instance.dispose(data);
|
Mallocator.instance.dispose(data);
|
||||||
|
data = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Data[] data; //65536
|
Data[] data = null; //65536
|
||||||
}
|
}
|
||||||
|
|
||||||
private static struct Data
|
private static struct Data
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import ecs.block_allocator;
|
||||||
import ecs.hash_map;
|
import ecs.hash_map;
|
||||||
import ecs.id_manager;
|
import ecs.id_manager;
|
||||||
import ecs.vector;
|
import ecs.vector;
|
||||||
|
import ecs.simple_vector;
|
||||||
import ecs.events;
|
import ecs.events;
|
||||||
import ecs.traits;
|
import ecs.traits;
|
||||||
|
|
||||||
|
|
@ -36,7 +37,17 @@ export class EntityManager
|
||||||
export static void initialize(uint threads_count)
|
export static void initialize(uint threads_count)
|
||||||
{
|
{
|
||||||
if (instance is null)
|
if (instance is null)
|
||||||
|
{
|
||||||
instance = Mallocator.instance.make!EntityManager(threads_count);
|
instance = Mallocator.instance.make!EntityManager(threads_count);
|
||||||
|
|
||||||
|
with(instance)
|
||||||
|
{
|
||||||
|
UpdatePass* pass = Mallocator.instance.make!UpdatePass;
|
||||||
|
pass.name = Mallocator.instance.makeArray("update");
|
||||||
|
passes.add(pass);
|
||||||
|
passes_map.add(cast(string) pass.name, cast(ushort)(passes.length - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export static void destroy()
|
export static void destroy()
|
||||||
|
|
@ -44,19 +55,58 @@ export class EntityManager
|
||||||
if (instance is null)
|
if (instance is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (ref system; instance.systems)
|
with(instance)
|
||||||
|
{
|
||||||
|
foreach (ref system; systems)
|
||||||
{
|
{
|
||||||
system.disable();
|
system.disable();
|
||||||
}
|
|
||||||
|
|
||||||
foreach (ref system; instance.systems)
|
|
||||||
{
|
|
||||||
if (system.m_destroy)
|
if (system.m_destroy)
|
||||||
(cast(void function(void*)) system.m_destroy)(system.m_system_pointer);
|
(cast(void function(void*)) system.m_destroy)(system.m_system_pointer);
|
||||||
|
|
||||||
|
if(system.jobs)Mallocator.instance.dispose(system.jobs);
|
||||||
|
if(system.m_read_only_components)Mallocator.instance.dispose(system.m_read_only_components);
|
||||||
|
if(system.m_modified_components)Mallocator.instance.dispose(system.m_modified_components);
|
||||||
|
if(system.m_components)Mallocator.instance.dispose(system.m_components);
|
||||||
|
if(system.m_excluded_components)Mallocator.instance.dispose(system.m_excluded_components);
|
||||||
|
if(system.m_optional_components)Mallocator.instance.dispose(system.m_optional_components);
|
||||||
|
if(system.name)Mallocator.instance.dispose(system.name);
|
||||||
|
if(system.m_event_callers)Mallocator.instance.dispose(system.m_event_callers);
|
||||||
|
|
||||||
|
if(system.m_system_pointer)Mallocator.instance.dispose(system.m_system_pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(EntityInfo* info;&entities_infos.byValue)
|
||||||
|
{
|
||||||
|
//if(info.components)Mallocator.instance.dispose(info.components);
|
||||||
|
|
||||||
|
Mallocator.instance.dispose(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(UpdatePass* pass; passes)
|
||||||
|
{
|
||||||
|
Mallocator.instance.dispose(pass);
|
||||||
|
}
|
||||||
|
passes.clear();
|
||||||
|
|
||||||
|
foreach(ComponentInfo info; components)
|
||||||
|
{
|
||||||
|
if(info.init_data)Mallocator.instance.dispose(info.init_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(EventInfo info; events)
|
||||||
|
{
|
||||||
|
if(info.callers)Mallocator.instance.dispose(info.callers);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(name; &components_map.byKey)
|
||||||
|
{
|
||||||
|
if(name)Mallocator.instance.dispose(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Mallocator.instance.dispose(instance);
|
Mallocator.instance.dispose(instance);
|
||||||
instance = null;
|
instance = null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
|
|
@ -198,12 +248,16 @@ export class EntityManager
|
||||||
entity_block_alloc_mutex = Mallocator.instance.make!Mutex;
|
entity_block_alloc_mutex = Mallocator.instance.make!Mutex;
|
||||||
//event_manager = EventManager(this);
|
//event_manager = EventManager(this);
|
||||||
//event_manager.manager = this;
|
//event_manager.manager = this;
|
||||||
|
}
|
||||||
|
|
||||||
UpdatePass* pass = Mallocator.instance.make!UpdatePass;
|
~this()
|
||||||
pass.name = Mallocator.instance.makeArray("update");
|
{
|
||||||
passes.add(pass);
|
id_manager.deinitialize();
|
||||||
|
|
||||||
passes_map.add(cast(string) pass.name, cast(ushort)(passes.length - 1));
|
if(threads)Mallocator.instance.dispose(threads);
|
||||||
|
if(entity_block_alloc_mutex)Mallocator.instance.dispose(entity_block_alloc_mutex);
|
||||||
|
|
||||||
|
allocator.freeMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
|
|
@ -451,7 +505,7 @@ export class EntityManager
|
||||||
|
|
||||||
enum ComponentsIndices components_info = getComponentsInfo();
|
enum ComponentsIndices components_info = getComponentsInfo();
|
||||||
|
|
||||||
static void genCompList()(ref System system, ref HashMap!(const(char)[], ushort) components_map)
|
static void genCompList()(ref System system, ref HashMap!(char[], ushort) components_map)
|
||||||
{
|
{
|
||||||
|
|
||||||
foreach (member; __traits(allMembers, Sys.EntitiesData))
|
foreach (member; __traits(allMembers, Sys.EntitiesData))
|
||||||
|
|
@ -661,12 +715,13 @@ export class EntityManager
|
||||||
|
|
||||||
system.m_system_pointer = cast(void*) Mallocator.instance.make!Sys;
|
system.m_system_pointer = cast(void*) Mallocator.instance.make!Sys;
|
||||||
system.m_priority = priority;
|
system.m_priority = priority;
|
||||||
(cast(Sys*) system.m_system_pointer).__ecsInitialize();
|
//(cast(Sys*) system.m_system_pointer).__ecsInitialize();
|
||||||
system.jobs = (cast(Sys*) system.m_system_pointer)._ecs_jobs;
|
//system.jobs = (cast(Sys*) system.m_system_pointer)._ecs_jobs;
|
||||||
|
system.jobs = Mallocator.instance.makeArray!(Job)((cast(Sys*) system.m_system_pointer).__ecs_jobs_count);
|
||||||
|
|
||||||
genCompList(system, components_map);
|
genCompList(system, components_map);
|
||||||
|
|
||||||
ushort sys_id = systems_map.get(Sys.stringof, ushort.max);
|
ushort sys_id = systems_map.get(cast(char[])Sys.stringof, ushort.max);
|
||||||
if (sys_id < systems.length)
|
if (sys_id < systems.length)
|
||||||
{
|
{
|
||||||
system.enable();
|
system.enable();
|
||||||
|
|
@ -761,7 +816,7 @@ export class EntityManager
|
||||||
info.init_data = Mallocator.instance.makeArray!ubyte(Comp.sizeof);
|
info.init_data = Mallocator.instance.makeArray!ubyte(Comp.sizeof);
|
||||||
*cast(Comp*) info.init_data.ptr = Comp.init; // = Comp();
|
*cast(Comp*) info.init_data.ptr = Comp.init; // = Comp();
|
||||||
|
|
||||||
ushort comp_id = components_map.get(Comp.stringof, ushort.max);
|
ushort comp_id = components_map.get(cast(char[])Comp.stringof, ushort.max);
|
||||||
if (comp_id < components.length)
|
if (comp_id < components.length)
|
||||||
{
|
{
|
||||||
Comp.component_id = comp_id;
|
Comp.component_id = comp_id;
|
||||||
|
|
@ -771,7 +826,7 @@ export class EntityManager
|
||||||
{
|
{
|
||||||
components.add(info);
|
components.add(info);
|
||||||
Comp.component_id = cast(ushort)(components.length - 1);
|
Comp.component_id = cast(ushort)(components.length - 1);
|
||||||
const(char)[] name = Mallocator.instance.makeArray(Comp.stringof);
|
char[] name = Mallocator.instance.makeArray(Comp.stringof);
|
||||||
components_map.add(name, cast(ushort)(components.length - 1));
|
components_map.add(name, cast(ushort)(components.length - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1331,9 +1386,9 @@ export class EntityManager
|
||||||
ThreadData* data = &threads[thread_id];
|
ThreadData* data = &threads[thread_id];
|
||||||
uint num = cast(uint) del_ids.length;
|
uint num = cast(uint) del_ids.length;
|
||||||
data.change_entities_list.add(0);
|
data.change_entities_list.add(0);
|
||||||
data.change_entities_list.add((cast(ubyte*)&entity_id)[0 .. 8]);
|
data.change_entities_list.add((cast(ubyte*)&entity_id)[0 .. EntityID.sizeof]);
|
||||||
data.change_entities_list.add((cast(ubyte*)&num)[0 .. 4]);
|
data.change_entities_list.add((cast(ubyte*)&num)[0 .. uint.sizeof]);
|
||||||
data.change_entities_list.add(cast(ubyte[]) del_ids);
|
data.change_entities_list.add((cast(ubyte*)del_ids.ptr)[0 .. num * 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void __removeComponents(EntityID entity_id, ushort[] del_ids)
|
private void __removeComponents(EntityID entity_id, ushort[] del_ids)
|
||||||
|
|
@ -1349,7 +1404,9 @@ export class EntityManager
|
||||||
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length)))[0
|
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length)))[0
|
||||||
.. info.components.length];
|
.. info.components.length];
|
||||||
|
|
||||||
uint j = 0;
|
EntityInfo* new_info = info;
|
||||||
|
|
||||||
|
/*uint j = 0;
|
||||||
uint k = 0;
|
uint k = 0;
|
||||||
foreach (id; info.components)
|
foreach (id; info.components)
|
||||||
{
|
{
|
||||||
|
|
@ -1362,15 +1419,23 @@ export class EntityManager
|
||||||
else if (del_ids[k] == info.components[j])
|
else if (del_ids[k] == info.components[j])
|
||||||
{
|
{
|
||||||
k++;
|
k++;
|
||||||
|
new_info = new_info.getNewInfoAdd(del_ids[k]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ids[j++] = id;
|
ids[j++] = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j == info.components.length)
|
if (j == info.components.length)
|
||||||
return;
|
return;*/
|
||||||
|
|
||||||
EntityInfo* new_info = getEntityInfo(ids[0 .. j]);
|
foreach(id;del_ids)
|
||||||
|
{
|
||||||
|
new_info = new_info.getNewInfoRemove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(new_info == info)return;
|
||||||
|
|
||||||
|
//EntityInfo* new_info = getEntityInfo(ids[0 .. j]);
|
||||||
|
|
||||||
EntitiesBlock* new_block = findBlockWithFreeSpace(new_info);
|
EntitiesBlock* new_block = findBlockWithFreeSpace(new_info);
|
||||||
|
|
||||||
|
|
@ -1459,8 +1524,8 @@ export class EntityManager
|
||||||
return;
|
return;
|
||||||
EntitiesBlock* block = getMetaData(entity);
|
EntitiesBlock* block = getMetaData(entity);
|
||||||
EntityInfo* info = block.type_info;
|
EntityInfo* info = block.type_info;
|
||||||
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0
|
/*ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0
|
||||||
.. info.components.length + num];
|
.. info.components.length + num];*/
|
||||||
/*ushort[num] new_ids;
|
/*ushort[num] new_ids;
|
||||||
|
|
||||||
static foreach (i, comp; Components)
|
static foreach (i, comp; Components)
|
||||||
|
|
@ -1498,7 +1563,9 @@ export class EntityManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint j = 0;
|
EntityInfo* new_info = info;
|
||||||
|
|
||||||
|
/* uint j = 0;
|
||||||
uint k = 0;
|
uint k = 0;
|
||||||
uint len = 0;
|
uint len = 0;
|
||||||
//foreach (ref id; ids)
|
//foreach (ref id; ids)
|
||||||
|
|
@ -1515,6 +1582,7 @@ export class EntityManager
|
||||||
else if (j >= info.components.length)
|
else if (j >= info.components.length)
|
||||||
{
|
{
|
||||||
*id = new_ids[k++];
|
*id = new_ids[k++];
|
||||||
|
new_info = new_info.getNewInfoAdd(*id);
|
||||||
//continue;
|
//continue;
|
||||||
}
|
}
|
||||||
else if (new_ids[k] == info.components[j])
|
else if (new_ids[k] == info.components[j])
|
||||||
|
|
@ -1523,18 +1591,26 @@ export class EntityManager
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
/*debug if (new_ids[k] == info.components[j])
|
/*debug if (new_ids[k] == info.components[j])
|
||||||
assert(0, "Trying to add already existing component!");*/
|
assert(0, "Trying to add already existing component!");//*
|
||||||
else if (new_ids[k] < info.components[j])
|
else if (new_ids[k] < info.components[j])
|
||||||
{
|
{
|
||||||
*id = new_ids[k++];
|
*id = new_ids[k++];
|
||||||
|
new_info = new_info.getNewInfoAdd(*id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*id = info.components[j++];
|
*id = info.components[j++];
|
||||||
}
|
}
|
||||||
if (len == info.components.length)
|
if (len == info.components.length)
|
||||||
return;
|
return;*/
|
||||||
|
|
||||||
EntityInfo* new_info = getEntityInfo(ids[0 .. len]);
|
foreach(id;new_ids)
|
||||||
|
{
|
||||||
|
new_info = new_info.getNewInfoAdd(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(new_info == info)return;
|
||||||
|
|
||||||
|
//EntityInfo* new_info = getEntityInfo(ids[0 .. len]);
|
||||||
|
|
||||||
EntitiesBlock* new_block = findBlockWithFreeSpace(new_info);
|
EntitiesBlock* new_block = findBlockWithFreeSpace(new_info);
|
||||||
|
|
||||||
|
|
@ -1544,8 +1620,8 @@ export class EntityManager
|
||||||
new_entity.id = entity.id;
|
new_entity.id = entity.id;
|
||||||
new_entity.updateID();
|
new_entity.updateID();
|
||||||
|
|
||||||
j = 0;
|
uint j = 0;
|
||||||
k = 0;
|
uint k = 0;
|
||||||
static if (EntityID.sizeof == 8)
|
static if (EntityID.sizeof == 8)
|
||||||
uint ind = cast(uint)((cast(void*) entity - block.dataBegin()) >> 3);
|
uint ind = cast(uint)((cast(void*) entity - block.dataBegin()) >> 3);
|
||||||
else
|
else
|
||||||
|
|
@ -1562,7 +1638,7 @@ export class EntityManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (ref id; ids[0 .. len])
|
foreach (ref id; new_info.components)//ids[0 .. len])
|
||||||
{
|
{
|
||||||
void* dst = cast(void*) new_block + new_info.deltas[id] + (
|
void* dst = cast(void*) new_block + new_info.deltas[id] + (
|
||||||
new_block.entities_count /*+ new_block.added_count*/ ) * components[id].size;
|
new_block.entities_count /*+ new_block.added_count*/ ) * components[id].size;
|
||||||
|
|
@ -1646,9 +1722,9 @@ export class EntityManager
|
||||||
pointers[i] = ∁
|
pointers[i] = ∁
|
||||||
}*/
|
}*/
|
||||||
ThreadData* data = &threads[thread_id];
|
ThreadData* data = &threads[thread_id];
|
||||||
data.change_entities_list.add(1);
|
data.change_entities_list.add(cast(ubyte)1u);
|
||||||
data.change_entities_list.add((cast(ubyte*)&entity_id)[0 .. 8]);
|
data.change_entities_list.add((cast(ubyte*)&entity_id)[0 .. EntityID.sizeof]);
|
||||||
data.change_entities_list.add((cast(ubyte*)&num)[0 .. 4]);
|
data.change_entities_list.add((cast(ubyte*)&num)[0 .. uint.sizeof]);
|
||||||
data.change_entities_list.add(cast(ubyte[]) new_ids);
|
data.change_entities_list.add(cast(ubyte[]) new_ids);
|
||||||
static foreach (i, comp; comps)
|
static foreach (i, comp; comps)
|
||||||
{
|
{
|
||||||
|
|
@ -1903,6 +1979,7 @@ export class EntityManager
|
||||||
{
|
{
|
||||||
uint index = 0;
|
uint index = 0;
|
||||||
uint len = cast(uint) thread.change_entities_list.length;
|
uint len = cast(uint) thread.change_entities_list.length;
|
||||||
|
void*[32] pointers;// = (cast(void**) alloca(num * (void*).sizeof))[0 .. num];
|
||||||
while (index < len)
|
while (index < len)
|
||||||
{
|
{
|
||||||
if (!thread.change_entities_list[index++])
|
if (!thread.change_entities_list[index++])
|
||||||
|
|
@ -1911,8 +1988,8 @@ export class EntityManager
|
||||||
index += EntityID.sizeof;
|
index += EntityID.sizeof;
|
||||||
uint num = *cast(uint*)&thread.change_entities_list[index];
|
uint num = *cast(uint*)&thread.change_entities_list[index];
|
||||||
index += uint.sizeof;
|
index += uint.sizeof;
|
||||||
ushort[] ids = (cast(ushort*) alloca(num * ushort.sizeof))[0 .. num];
|
ushort[] ids;// = (cast(ushort*) alloca(num * ushort.sizeof))[0 .. num];
|
||||||
ids[0 .. $] = (cast(ushort*)&thread.change_entities_list[index])[0 .. num];
|
ids = (cast(ushort*)&thread.change_entities_list[index])[0 .. num];
|
||||||
index += ushort.sizeof * num;
|
index += ushort.sizeof * num;
|
||||||
__removeComponents(id, ids);
|
__removeComponents(id, ids);
|
||||||
}
|
}
|
||||||
|
|
@ -1922,16 +1999,16 @@ export class EntityManager
|
||||||
index += EntityID.sizeof;
|
index += EntityID.sizeof;
|
||||||
uint num = *cast(uint*)&thread.change_entities_list[index];
|
uint num = *cast(uint*)&thread.change_entities_list[index];
|
||||||
index += uint.sizeof;
|
index += uint.sizeof;
|
||||||
ushort[] ids = (cast(ushort*) alloca(num * ushort.sizeof))[0 .. num];
|
ushort[] ids;// = (cast(ushort*) alloca(num * ushort.sizeof))[0 .. num];
|
||||||
ids[0 .. $] = (cast(ushort*)&thread.change_entities_list[index])[0 .. num];
|
ids = (cast(ushort*)&thread.change_entities_list[index])[0 .. num];
|
||||||
index += ushort.sizeof * num;
|
index += ushort.sizeof * num;
|
||||||
void*[] pointers = (cast(void**) alloca(num * (void*).sizeof))[0 .. num];
|
//void*[] pointers = (cast(void**) alloca(num * (void*).sizeof))[0 .. num];
|
||||||
foreach (i; 0 .. num)
|
foreach (i; 0 .. num)
|
||||||
{
|
{
|
||||||
pointers[i] = &thread.change_entities_list[index];
|
pointers[i] = &thread.change_entities_list[index];
|
||||||
index += components[ids[i]].size;
|
index += components[ids[i]].size;
|
||||||
}
|
}
|
||||||
__addComponents(id, ids, pointers);
|
__addComponents(id, ids, pointers[0..num]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thread.change_entities_list.clear();
|
thread.change_entities_list.clear();
|
||||||
|
|
@ -2361,6 +2438,93 @@ export class EntityManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EntityInfo* getNewInfoAdd(ushort id)
|
||||||
|
{
|
||||||
|
if(comp_add_info.length < id)
|
||||||
|
{
|
||||||
|
EntityInfo*[] new_infos = Mallocator.instance.makeArray!(EntityInfo*)(instance.components.length);
|
||||||
|
if(comp_add_info !is null)
|
||||||
|
{
|
||||||
|
new_infos[0 .. comp_add_info.length] = comp_add_info[0 .. $];
|
||||||
|
Mallocator.instance.dispose(comp_add_info);
|
||||||
|
}
|
||||||
|
comp_add_info = new_infos;
|
||||||
|
}
|
||||||
|
if(comp_add_info[id])return comp_add_info[id];
|
||||||
|
|
||||||
|
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (components.length + 1)))[0
|
||||||
|
.. components.length + 1];
|
||||||
|
uint len = 0;
|
||||||
|
|
||||||
|
foreach(comp; components)
|
||||||
|
{
|
||||||
|
if(id > comp)
|
||||||
|
{
|
||||||
|
ids[len++] = comp;
|
||||||
|
}
|
||||||
|
else if(id == comp)return &this;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ids[len++] = id;
|
||||||
|
ids[len++] = comp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(id > components[$ - 1])ids[len++] = id;
|
||||||
|
|
||||||
|
assert(len == components.length + 1);
|
||||||
|
|
||||||
|
EntityInfo* new_info = instance.getEntityInfo(ids[0 .. len]);
|
||||||
|
|
||||||
|
comp_add_info[id] = new_info;
|
||||||
|
return new_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityInfo* getNewInfoRemove(ushort id)
|
||||||
|
{
|
||||||
|
if(comp_rem_info.length < id)
|
||||||
|
{
|
||||||
|
EntityInfo*[] new_infos = Mallocator.instance.makeArray!(EntityInfo*)(instance.components.length);
|
||||||
|
if(comp_rem_info !is null)
|
||||||
|
{
|
||||||
|
new_infos[0 .. comp_rem_info.length] = comp_rem_info[0 .. $];
|
||||||
|
Mallocator.instance.dispose(comp_rem_info);
|
||||||
|
}
|
||||||
|
comp_rem_info = new_infos;
|
||||||
|
}
|
||||||
|
if(comp_rem_info[id])return comp_rem_info[id];
|
||||||
|
|
||||||
|
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (components.length - 1)))[0
|
||||||
|
.. components.length - 1];
|
||||||
|
uint len = 0;
|
||||||
|
|
||||||
|
foreach(comp; components)
|
||||||
|
{
|
||||||
|
if(id != comp)
|
||||||
|
{
|
||||||
|
ids[len++] = comp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(len == components.length)return &this;
|
||||||
|
|
||||||
|
assert(len == components.length - 1);
|
||||||
|
|
||||||
|
EntityInfo* new_info = instance.getEntityInfo(ids[0 .. len]);
|
||||||
|
|
||||||
|
comp_rem_info[id] = new_info;
|
||||||
|
return new_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
~this()
|
||||||
|
{
|
||||||
|
if(components)Mallocator.instance.dispose(components);
|
||||||
|
if(deltas)Mallocator.instance.dispose(deltas);
|
||||||
|
if(tmpl_deltas)Mallocator.instance.dispose(tmpl_deltas);
|
||||||
|
if(systems)Mallocator.instance.dispose(systems);
|
||||||
|
if(add_listeners)Mallocator.instance.dispose(add_listeners);
|
||||||
|
if(remove_listeners)Mallocator.instance.dispose(remove_listeners);
|
||||||
|
if(change_listeners)Mallocator.instance.dispose(change_listeners);
|
||||||
|
}
|
||||||
|
|
||||||
///entity components
|
///entity components
|
||||||
ushort[] components;
|
ushort[] components;
|
||||||
|
|
||||||
|
|
@ -2369,6 +2533,11 @@ export class EntityManager
|
||||||
///deltas in memory for components in EntityTemplate
|
///deltas in memory for components in EntityTemplate
|
||||||
ushort[] tmpl_deltas;
|
ushort[] tmpl_deltas;
|
||||||
|
|
||||||
|
///cached new infos after adding component
|
||||||
|
EntityInfo*[] comp_add_info;
|
||||||
|
///cached new infos after removing component
|
||||||
|
EntityInfo*[] comp_rem_info;
|
||||||
|
|
||||||
///alignment of whole entity
|
///alignment of whole entity
|
||||||
ushort alignment; //unused in linear-layout
|
ushort alignment; //unused in linear-layout
|
||||||
///size of entity (with alignment respect)
|
///size of entity (with alignment respect)
|
||||||
|
|
@ -2497,6 +2666,9 @@ export class EntityManager
|
||||||
if (dependencies)
|
if (dependencies)
|
||||||
{
|
{
|
||||||
Mallocator.instance.dispose(dependencies);
|
Mallocator.instance.dispose(dependencies);
|
||||||
|
}
|
||||||
|
if(exclusion)
|
||||||
|
{
|
||||||
Mallocator.instance.dispose(exclusion);
|
Mallocator.instance.dispose(exclusion);
|
||||||
}
|
}
|
||||||
if (job_group.dependencies)
|
if (job_group.dependencies)
|
||||||
|
|
@ -2514,7 +2686,8 @@ export class EntityManager
|
||||||
struct ThreadData
|
struct ThreadData
|
||||||
{
|
{
|
||||||
Vector!EntityID entities_to_remove;
|
Vector!EntityID entities_to_remove;
|
||||||
Vector!ubyte change_entities_list;
|
//Vector!ubyte change_entities_list;
|
||||||
|
SimpleVector change_entities_list;
|
||||||
Vector!(EntitiesBlock*) blocks_to_update;
|
Vector!(EntitiesBlock*) blocks_to_update;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2525,6 +2698,11 @@ export class EntityManager
|
||||||
assert(name);
|
assert(name);
|
||||||
if (name)
|
if (name)
|
||||||
Mallocator.instance.dispose(name);
|
Mallocator.instance.dispose(name);
|
||||||
|
foreach(caller; system_callers)
|
||||||
|
{
|
||||||
|
Mallocator.instance.dispose(caller);
|
||||||
|
}
|
||||||
|
system_callers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
char[] name;
|
char[] name;
|
||||||
|
|
@ -2555,8 +2733,8 @@ export class EntityManager
|
||||||
uint delegate() m_thread_id_func;
|
uint delegate() m_thread_id_func;
|
||||||
|
|
||||||
HashMap!(ushort[], EntityInfo*) entities_infos;
|
HashMap!(ushort[], EntityInfo*) entities_infos;
|
||||||
HashMap!(const(char)[], ushort) systems_map;
|
HashMap!(char[], ushort) systems_map;
|
||||||
HashMap!(const(char)[], ushort) components_map;
|
HashMap!(char[], ushort) components_map;
|
||||||
HashMap!(const(char)[], ushort) events_map;
|
HashMap!(const(char)[], ushort) events_map;
|
||||||
HashMap!(const(char)[], ushort) passes_map;
|
HashMap!(const(char)[], ushort) passes_map;
|
||||||
Vector!System systems;
|
Vector!System systems;
|
||||||
|
|
@ -2575,6 +2753,15 @@ export class EntityManager
|
||||||
uint allocated = 0;
|
uint allocated = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~this()
|
||||||
|
{
|
||||||
|
foreach(block;blocks)
|
||||||
|
{
|
||||||
|
Mallocator.instance.dispose(block);
|
||||||
|
}
|
||||||
|
blocks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
Vector!(Block*) blocks;
|
Vector!(Block*) blocks;
|
||||||
uint id;
|
uint id;
|
||||||
|
|
||||||
|
|
|
||||||
66
source/ecs/simple_vector.d
Normal file
66
source/ecs/simple_vector.d
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
module ecs.simple_vector;
|
||||||
|
|
||||||
|
import std.experimental.allocator;
|
||||||
|
import std.experimental.allocator.mallocator;
|
||||||
|
|
||||||
|
import core.stdc.string;
|
||||||
|
|
||||||
|
struct SimpleVector
|
||||||
|
{
|
||||||
|
|
||||||
|
@disable this(this);
|
||||||
|
|
||||||
|
void add(ubyte el) nothrow @nogc
|
||||||
|
{
|
||||||
|
while(used >= data.length)
|
||||||
|
{
|
||||||
|
if(data is null)data = Mallocator.instance.makeArray!ubyte(1024);
|
||||||
|
else Mallocator.instance.expandArray(data,data.length);
|
||||||
|
}
|
||||||
|
data[used++] = el;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(ubyte[] el) nothrow @nogc
|
||||||
|
{
|
||||||
|
while(used + el.length >= data.length)
|
||||||
|
{
|
||||||
|
if(data is null)data = Mallocator.instance.makeArray!ubyte(1024);
|
||||||
|
else Mallocator.instance.expandArray(data,data.length);
|
||||||
|
}
|
||||||
|
memcpy(data.ptr + used, el.ptr, el.length);
|
||||||
|
used += el.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t length() nothrow @nogc
|
||||||
|
{
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
|
export ref ubyte opIndex(size_t pos) nothrow @nogc
|
||||||
|
{
|
||||||
|
return data[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
export ubyte[] opSlice() nothrow @nogc
|
||||||
|
{
|
||||||
|
return data[0 .. used];
|
||||||
|
}
|
||||||
|
|
||||||
|
export ubyte[] opSlice(size_t x, size_t y) nothrow @nogc
|
||||||
|
{
|
||||||
|
return data[x .. y];
|
||||||
|
}
|
||||||
|
|
||||||
|
export size_t opDollar() nothrow @nogc
|
||||||
|
{
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() nothrow @nogc
|
||||||
|
{
|
||||||
|
used = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ubyte[] data = null;
|
||||||
|
size_t used = 0;
|
||||||
|
}
|
||||||
|
|
@ -97,7 +97,7 @@ package:
|
||||||
int m_pass;
|
int m_pass;
|
||||||
|
|
||||||
///system name
|
///system name
|
||||||
const(char)[] name;
|
char[] name;
|
||||||
|
|
||||||
///required components
|
///required components
|
||||||
ushort[] m_components;
|
ushort[] m_components;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
module tests.tests;
|
module tests.tests;
|
||||||
|
|
||||||
|
import std.experimental.allocator;
|
||||||
|
import std.experimental.allocator.mallocator;
|
||||||
|
|
||||||
import ecs.entity;
|
import ecs.entity;
|
||||||
import ecs.events;
|
import ecs.events;
|
||||||
import ecs.manager;
|
import ecs.manager;
|
||||||
|
|
@ -136,18 +139,22 @@ struct ChangeTestSystem
|
||||||
|
|
||||||
void onAddEntity(EntitiesData data)
|
void onAddEntity(EntitiesData data)
|
||||||
{
|
{
|
||||||
|
//printf("Entity added! ID: ");
|
||||||
foreach (i; 0 .. data.length)
|
foreach (i; 0 .. data.length)
|
||||||
writeln("Entity added! ID: ", data.entites[i].id.id);
|
printf("Entity added! ID: %u\n",data.entites[i].id);
|
||||||
|
//writeln("Entity added! ID: ", data.entites[i].id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onRemoveEntity(EntitiesData data)
|
void onRemoveEntity(EntitiesData data)
|
||||||
{
|
{
|
||||||
writeln("Entity removed! ID: ", data.entites[0].id);
|
//writeln("Entity removed! ID: ", data.entites[0].id);
|
||||||
|
printf("Entity removed! ID: %u\n",data.entites[0].id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onChangeEntity(EntitiesData data)
|
void onChangeEntity(EntitiesData data)
|
||||||
{
|
{
|
||||||
writeln("Entity changed! ID: ", data.entites[0].id);
|
//writeln("Entity changed! ID: ", data.entites[0].id);
|
||||||
|
printf("Entity changed! ID: %u\n",data.entites[0].id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onBegin()
|
bool onBegin()
|
||||||
|
|
@ -532,7 +539,8 @@ int main()
|
||||||
|
|
||||||
//foreach(i; 0..1_000_000)gEM.removeEntity(gEM.addEntity(tmpl).id);
|
//foreach(i; 0..1_000_000)gEM.removeEntity(gEM.addEntity(tmpl).id);
|
||||||
|
|
||||||
EntityID[5000] idss;
|
EntityID[] idss = Mallocator.instance.makeArray!EntityID(5000);//[5000]
|
||||||
|
scope(exit)Mallocator.instance.dispose(idss);
|
||||||
|
|
||||||
foreach (i; 0 .. 200)
|
foreach (i; 0 .. 200)
|
||||||
{
|
{
|
||||||
|
|
@ -563,7 +571,7 @@ int main()
|
||||||
//foreach(j; 0..1_000)gEM.addEntity(tmpl);
|
//foreach(j; 0..1_000)gEM.addEntity(tmpl);
|
||||||
|
|
||||||
gEM.beginRegister();
|
gEM.beginRegister();
|
||||||
gEM.registerSystem!TestSystem2(0);
|
//gEM.registerSystem!TestSystem2(0);
|
||||||
gEM.endRegister();
|
gEM.endRegister();
|
||||||
|
|
||||||
//gEM.generateDependencies();
|
//gEM.generateDependencies();
|
||||||
|
|
@ -575,10 +583,12 @@ int main()
|
||||||
|
|
||||||
time = MonoTime.currTime;
|
time = MonoTime.currTime;
|
||||||
|
|
||||||
|
EntityID[] entities = Mallocator.instance.makeArray!EntityID(1_000_000);
|
||||||
foreach (i; 0 .. 500_000)
|
foreach (i; 0 .. 500_000)
|
||||||
{
|
{
|
||||||
entity2 = gEM.addEntity(tmpl);
|
entity2 = gEM.addEntity(tmpl);
|
||||||
gEM.addEntity(tmpl2);
|
entities[i*2] = entity2.id;
|
||||||
|
entities[i*2+1] = gEM.addEntity(tmpl2).id;
|
||||||
}
|
}
|
||||||
|
|
||||||
gEM.commit();
|
gEM.commit();
|
||||||
|
|
@ -587,6 +597,32 @@ int main()
|
||||||
|
|
||||||
time = MonoTime.currTime;
|
time = MonoTime.currTime;
|
||||||
|
|
||||||
|
foreach (i; 0 .. 1_000_000)
|
||||||
|
{
|
||||||
|
EntityManager.instance.addComponents(entities[i],TestComp5());
|
||||||
|
if((i & 0x00FFFF) == 0)gEM.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
gEM.commit();
|
||||||
|
dur = (MonoTime.currTime - time).total!"usecs";
|
||||||
|
writeln("Components adding: ", dur, " usecs");
|
||||||
|
|
||||||
|
time = MonoTime.currTime;
|
||||||
|
|
||||||
|
foreach (i; 0 .. 1_000_000)
|
||||||
|
{
|
||||||
|
EntityManager.instance.removeComponents!TestComp5(entities[i]);
|
||||||
|
//if((i & 0x00FFFF) == 0)gEM.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
gEM.commit();
|
||||||
|
dur = (MonoTime.currTime - time).total!"usecs";
|
||||||
|
writeln("Components removing: ", dur, " usecs");
|
||||||
|
|
||||||
|
Mallocator.instance.dispose(entities);
|
||||||
|
|
||||||
|
time = MonoTime.currTime;
|
||||||
|
|
||||||
gEM.begin();
|
gEM.begin();
|
||||||
//gEM.updateMT();
|
//gEM.updateMT();
|
||||||
gEM.update();
|
gEM.update();
|
||||||
|
|
@ -653,13 +689,16 @@ int main()
|
||||||
|
|
||||||
gEM.removeComponents!(TestComp4)(entity.id);
|
gEM.removeComponents!(TestComp4)(entity.id);
|
||||||
|
|
||||||
gEM.commit();
|
gEM.commit();//*/
|
||||||
|
|
||||||
writeEntityComponents(gEM.getEntity(entity.id));
|
writeEntityComponents(gEM.getEntity(entity.id));
|
||||||
//import std.stdio;
|
//import std.stdio;
|
||||||
//writeln((cast(uint*)tmpl.info.first_block)[0..48]);
|
//writeln((cast(uint*)tmpl.info.first_block)[0..48]);
|
||||||
gEM.freeTemplate(tmpl);
|
gEM.freeTemplate(tmpl);
|
||||||
|
gEM.freeTemplate(tmpl2);
|
||||||
EntityManager.destroy();
|
EntityManager.destroy();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue