-added webpage deploymnet stage -added separate build stage which build all binaries and generate documentation -added Emscripten build stage for merge to master only -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
181 lines
5 KiB
D
181 lines
5 KiB
D
module ecs.events;
|
|
|
|
import ecs.block_allocator;
|
|
import ecs.entity;
|
|
import ecs.manager;
|
|
import 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();
|
|
scope (exit)
|
|
event_block_alloc_mutex.unlock();
|
|
|
|
block = cast(EventBlock*) allocator.getBlock();
|
|
*block = EventBlock();
|
|
data.first_blocks[block_id] = block;
|
|
data.blocks[block_id] = block;
|
|
}
|
|
|
|
if(block.count >= data.max_events)
|
|
{
|
|
event_block_alloc_mutex.lock();
|
|
scope (exit)
|
|
event_block_alloc_mutex.unlock();
|
|
|
|
EventBlock* new_block = cast(EventBlock*) allocator.getBlock();
|
|
*new_block = EventBlock();
|
|
block.next = new_block;
|
|
block = new_block;
|
|
data.blocks[block_id] = block;
|
|
}
|
|
|
|
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);
|
|
|
|
event.max_events = cast(ushort)((events_block_size - event.data_offset) / manager.events[i].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;
|
|
}
|