Common update:
-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
This commit is contained in:
parent
2ddb97e9ce
commit
024356df9b
62 changed files with 5918 additions and 1673 deletions
188
source/bubel/ecs/events.d
Normal file
188
source/bubel/ecs/events.d
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
module bubel.ecs.events;
|
||||
|
||||
import bubel.ecs.block_allocator;
|
||||
import bubel.ecs.entity;
|
||||
import bubel.ecs.manager;
|
||||
import bubel.ecs.std;
|
||||
|
||||
import std.algorithm.comparison : max;
|
||||
|
||||
package struct EventManager
|
||||
{
|
||||
|
||||
void initialize(EntityManager* m) nothrow @nogc
|
||||
{
|
||||
allocator = BlockAllocator(events_block_size, events_blocks_in_allocation);
|
||||
event_block_alloc_mutex = Mallocator.make!Mutex;
|
||||
event_block_alloc_mutex.initialize();
|
||||
manager = m;
|
||||
}
|
||||
|
||||
void destroy() nothrow @nogc
|
||||
{
|
||||
if (event_block_alloc_mutex)
|
||||
{
|
||||
event_block_alloc_mutex.destroy();
|
||||
Mallocator.dispose(event_block_alloc_mutex);
|
||||
event_block_alloc_mutex = null;
|
||||
}
|
||||
}
|
||||
|
||||
export void sendEvent(Ev)(EntityID id, Ev event, uint thread_id = 0) nothrow @nogc
|
||||
{
|
||||
uint block_id = current_index + thread_id;
|
||||
|
||||
EventData* data = &events[Ev.event_id];
|
||||
EventBlock* block = data.blocks[block_id];
|
||||
//EntityManager.EventInfo* info = &manager.events[Ev.event_id];
|
||||
//event.entity_id = id;
|
||||
|
||||
if (block is null)
|
||||
{
|
||||
event_block_alloc_mutex.lock();
|
||||
block = cast(EventBlock*) allocator.getBlock();
|
||||
event_block_alloc_mutex.unlock();
|
||||
|
||||
*block = EventBlock();
|
||||
data.first_blocks[block_id] = block;
|
||||
data.blocks[block_id] = block;
|
||||
}
|
||||
|
||||
if (block.count >= data.max_events)
|
||||
{
|
||||
event_block_alloc_mutex.lock();
|
||||
EventBlock* new_block = cast(EventBlock*) allocator.getBlock();
|
||||
event_block_alloc_mutex.unlock();
|
||||
|
||||
*new_block = EventBlock();
|
||||
block.next = new_block;
|
||||
block = new_block;
|
||||
data.blocks[block_id] = block;
|
||||
}
|
||||
|
||||
uint size = Ev.sizeof + EntityID.sizeof;
|
||||
void* ptr = cast(void*) block + data.data_offset + block.count * size;
|
||||
*cast(EntityID*)ptr = id;
|
||||
*cast(Ev*)(ptr + EntityID.sizeof) = event;
|
||||
//Ev* event_array = cast(Ev*)(cast(void*) block + data.data_offset);
|
||||
//event_array[block.count] = event;
|
||||
block.count++;
|
||||
}
|
||||
|
||||
void swapCurrent() nothrow @nogc
|
||||
{
|
||||
uint threads_count = cast(uint) manager.threads.length;
|
||||
if (current_index == 0)
|
||||
current_index = threads_count;
|
||||
else
|
||||
current_index = 0;
|
||||
|
||||
foreach (ref event; events)
|
||||
{
|
||||
foreach (ref first_block; event.first_blocks[current_index
|
||||
.. current_index + threads_count])
|
||||
{
|
||||
EventBlock* block = first_block;
|
||||
while (block)
|
||||
{
|
||||
EventBlock* to_dispose = block;
|
||||
block = block.next;
|
||||
allocator.freeBlock(to_dispose);
|
||||
}
|
||||
first_block = null;
|
||||
}
|
||||
foreach (ref block; event.blocks[current_index .. current_index + threads_count])
|
||||
{
|
||||
block = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clearEvents() nothrow @nogc
|
||||
{
|
||||
//uint threads_count = cast(uint)manager.threads.length;
|
||||
foreach (ref event; events)
|
||||
{
|
||||
foreach (ref first_block; event.first_blocks)
|
||||
{
|
||||
EventBlock* block = first_block;
|
||||
while (block)
|
||||
{
|
||||
EventBlock* to_dispose = block;
|
||||
block = block.next;
|
||||
allocator.freeBlock(to_dispose);
|
||||
}
|
||||
first_block = null;
|
||||
}
|
||||
foreach (ref block; event.blocks)
|
||||
{
|
||||
block = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void allocateData(uint threads_count) nothrow @nogc
|
||||
{
|
||||
disposeData();
|
||||
events = Mallocator.makeArray!EventData(manager.events.length);
|
||||
foreach (i, ref event; events)
|
||||
{
|
||||
event.blocks = Mallocator.makeArray!(EventBlock*)(threads_count * 2);
|
||||
event.first_blocks = Mallocator.makeArray!(EventBlock*)(threads_count * 2);
|
||||
event.data_offset = EventBlock.sizeof; //manager.events[i].
|
||||
manager.alignNum(event.data_offset, manager.events[i].alignment);
|
||||
|
||||
uint size = manager.events[i].size + EntityID.sizeof;
|
||||
event.max_events = cast(ushort)(
|
||||
(events_block_size - event.data_offset) / size);
|
||||
}
|
||||
}
|
||||
|
||||
private void disposeData() nothrow @nogc
|
||||
{
|
||||
clearEvents();
|
||||
if (events)
|
||||
{
|
||||
foreach (ref event; events)
|
||||
{
|
||||
Mallocator.dispose(event.blocks);
|
||||
Mallocator.dispose(event.first_blocks);
|
||||
}
|
||||
Mallocator.dispose(events);
|
||||
}
|
||||
allocator.freeMemory();
|
||||
}
|
||||
|
||||
~this() nothrow @nogc
|
||||
{
|
||||
disposeData();
|
||||
}
|
||||
|
||||
///Single page size. Must be power of two.
|
||||
enum events_block_size = 1 << 14;
|
||||
///Number of pages in block.
|
||||
enum events_blocks_in_allocation = 128;
|
||||
|
||||
struct EventBlock
|
||||
{
|
||||
EventBlock* next;
|
||||
ushort count = 0;
|
||||
}
|
||||
|
||||
struct EventData
|
||||
{
|
||||
ushort data_offset;
|
||||
ushort max_events;
|
||||
EventBlock*[] blocks;
|
||||
EventBlock*[] first_blocks;
|
||||
|
||||
//EventBlock*[] current_blocks;
|
||||
}
|
||||
|
||||
uint current_index = 0;
|
||||
EventData[] events;
|
||||
Mutex* event_block_alloc_mutex;
|
||||
|
||||
BlockAllocator allocator;
|
||||
EntityManager* manager;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue