Merge branch 'master' of https://gitlab.com/Mergul/bubel-ecs.git into Demos

This commit is contained in:
Mergul 2021-02-27 17:43:05 +01:00
commit 1acd0df0ef
17 changed files with 332 additions and 293 deletions

View file

@ -1,6 +1,6 @@
/************************************************************************************************************************
This module contain main templates for user.
There are three structure templates (mixins) which should be added on top of structure:
This module contain main helper templates for user.
There are three structure templates (mixins) which can be added on top of structure:
$(LIST
* System: make system structure
* Component: make component structure
@ -46,6 +46,26 @@ Struct System1
}
---
Templates ReadOnlyDependencies nad WritableDependencies are used to create list of dependencies for System.
Writable dependencies are bloking parallel execution of system which has same dependency (as writable or readonly).
This dependencies works same as Component dependencies but can be used for creating external dependencies (e.g. dependency on spatial partitioning tree access).
---
enum ExternalDependency1 = "ExternalDependency1";
Struct System1
{
mixin!ECS.System;
struct EntitiesData
{
... //used components
}
ReadOnlyDependencies!(ExternalDependency1);
}
---
Copyright: Copyright © 2018-2019, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
@ -53,6 +73,7 @@ module bubel.ecs.core;
public import bubel.ecs.manager;
public import bubel.ecs.entity;
public import bubel.ecs.traits : becsID;
/************************************************************************************************************************
Main struct used as namespace for templates.
@ -60,33 +81,30 @@ Main struct used as namespace for templates.
static struct ECS
{
/************************************************************************************************************************
Mark structure as System. Should be added on top of structure (before any data).
Set default system parameters (number of parallel jobs)
*/
mixin template System(uint jobs_count = 32)
{
__gshared ushort system_id = ushort.max;
uint __ecs_jobs_count = jobs_count;
__gshared uint __becs_jobs_count = jobs_count;
}
/************************************************************************************************************************
Mark structure as Component. Should be added on top of structure (before any data).
Mark structure as Component
*/
mixin template Component()
{
__gshared ushort component_id = ushort.max;
ComponentRef ref_() @nogc nothrow return
{
return ComponentRef(&this, component_id);
return ComponentRef(&this, becsID!(typeof(this)));
}
}
/************************************************************************************************************************
Mark structure as Event. Should be added on top of structure (before any data).
Mark structure as Event
*/
mixin template Event()
{
__gshared ushort event_id = ushort.max;
}
/************************************************************************************************************************

View file

@ -8,6 +8,7 @@ module bubel.ecs.entity;
import bubel.ecs.system;
import bubel.ecs.manager;
public import bubel.ecs.traits : becsID;
/************************************************************************************************************************
Entity ID structure. Used as reference to Entity. Pointer to entity should be ever used to store entity reference!
@ -40,7 +41,7 @@ struct Entity
return null;
return cast(T*)(cast(void*)block + info.deltas[T.component_id] + block.entityIndex(&this) * T.sizeof);*/
return cast(T*)getComponent(T.component_id);
return cast(T*)getComponent(becsID!T);
}
void* getComponent(ushort component_id) const
@ -81,7 +82,7 @@ struct EntityMeta
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] + index * T.sizeof);*/
return cast(T*)getComponent(T.component_id);
return cast(T*)getComponent(becsID!T);
}
void* getComponent(ushort component_id) const
@ -125,8 +126,8 @@ export struct EntityTemplate
*/
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]);
if(becsID!T >= info.tmpl_deltas.length || info.tmpl_deltas[becsID!T] == ushort.max)return null;
return cast(T*)(entity_data.ptr + info.tmpl_deltas[becsID!T]);
}
/************************************************************************************************************************

View file

@ -4,6 +4,7 @@ import bubel.ecs.block_allocator;
import bubel.ecs.entity;
import bubel.ecs.manager;
import bubel.ecs.std;
import bubel.ecs.traits : becsID;
import std.algorithm.comparison : max;
@ -32,7 +33,7 @@ package struct EventManager
{
uint block_id = current_index + thread_id;
EventData* data = &events[Ev.event_id];
EventData* data = &events[becsID!Ev];
EventBlock* block = data.blocks[block_id];
//EntityManager.EventInfo* info = &manager.events[Ev.event_id];
//event.entity_id = id;

View file

@ -367,10 +367,10 @@ export struct EntityManager
System system;
system.m_pass = pass;
static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort))
{
static assert(0, "Add \"mixin ECS.System;\" in top of system structure;");
}
// static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort))
// {
// static assert(0, "Add \"mixin ECS.System;\" in top of system structure;");
// }
static if (!(hasMember!(Sys, "EntitiesData")))
{
@ -408,7 +408,7 @@ export struct EntityManager
~ "\" due to non existing event \"" ~ EventName ~ "\".");
callers[i].callback = cast(void*)&callEventHandler!(EventParamType);
callers[i].id = EventParamType.event_id;
callers[i].id = becsID!EventParamType;
i++;
}
}
@ -1153,8 +1153,8 @@ export struct EntityManager
system.m_priority = priority;
//(cast(Sys*) system.m_system_pointer).__ecsInitialize();
//system.jobs = (cast(Sys*) system.m_system_pointer)._ecs_jobs;
system.jobs = Mallocator.makeArray!(Job)((cast(Sys*) system.m_system_pointer)
.__ecs_jobs_count);
static if(__traits(hasMember, Sys ,"__becs_jobs_count"))system.jobs = Mallocator.makeArray!(Job)(Sys.__becs_jobs_count);
else system.jobs = Mallocator.makeArray!(Job)(32);
static if (OnUpdateOverloadNum != -1)
{
@ -1222,7 +1222,7 @@ export struct EntityManager
systems[$ - 1].enable();
}
Sys.system_id = system.id;
becsID!Sys = system.id;
}
/************************************************************************************************************************
@ -1240,9 +1240,9 @@ export struct EntityManager
*/
Sys* getSystem(Sys)() nothrow @nogc
{
if (Sys.system_id >= systems.length)
if (becsID!Sys >= systems.length)
return null;
return cast(Sys*) systems[Sys.system_id].m_system_pointer;
return cast(Sys*) systems[becsID!Sys].m_system_pointer;
}
export ushort registerPass(const(char)[] name)
@ -1272,10 +1272,10 @@ export struct EntityManager
enum ComponentName = fullName!Comp;
// enum ComponentName = Comp.stringof;
static if (!(hasMember!(Comp, "component_id")) || !is(typeof(Comp.component_id) == ushort))
{
static assert(0, "Add \"mixin ECS.Component;\" in top of component structure;");
}
// static if (!(hasMember!(Comp, "component_id")) || !is(typeof(Comp.component_id) == ushort))
// {
// static assert(0, "Add \"mixin ECS.Component;\" in top of component structure;");
// }
static if (hasMember!(Comp, "onDestroy") && isFunction!(Comp.onDestroy)
&& is(ReturnType!(Comp.onDestroy) == void)
@ -1311,7 +1311,7 @@ export struct EntityManager
ushort comp_id = components_map.get(cast(char[]) ComponentName, ushort.max);
if (comp_id < components.length)
{
Comp.component_id = comp_id;
becsID!Comp = comp_id;
if (components[comp_id].init_data)
Mallocator.dispose(components[comp_id].init_data);
components[comp_id] = info;
@ -1319,7 +1319,7 @@ export struct EntityManager
else
{
components.add(info);
Comp.component_id = cast(ushort)(components.length - 1);
becsID!Comp = cast(ushort)(components.length - 1);
char[] name = Mallocator.makeArray(cast(char[]) ComponentName);
components_map.add(name, cast(ushort)(components.length - 1));
}
@ -1329,10 +1329,10 @@ export struct EntityManager
{
EventInfo info;
static if (!(hasMember!(Ev, "event_id")) || !is(typeof(Ev.event_id) == ushort))
{
static assert(0, "Add \"mixin ECS.Event;\" in top of event structure;");
}
// static if (!(hasMember!(Ev, "event_id")) || !is(typeof(Ev.event_id) == ushort))
// {
// static assert(0, "Add \"mixin ECS.Event;\" in top of event structure;");
// }
static if (hasMember!(Ev, "onDestroy") && isFunction!(Ev.onDestroy)
&& is(ReturnType!(Ev.onDestroy) == void) && Parameters!(Ev.onDestroy).length == 0)
@ -1352,12 +1352,12 @@ export struct EntityManager
ushort event_id = events_map.get(fullName!Ev, ushort.max);
if (event_id < events.length)
{
Ev.event_id = event_id;
becsID!Ev = event_id;
}
else
{
events.add(info);
Ev.event_id = cast(ushort)(events.length - 1);
becsID!Ev = cast(ushort)(events.length - 1);
// events_map.add(Ev.stringof, cast(ushort)(events.length - 1));
events_map.add(fullName!Ev, cast(ushort)(events.length - 1));
}
@ -1376,9 +1376,9 @@ export struct EntityManager
// static assert(is(SetFunctionAttributes!(T, functionLinkage!(s.onUpdate),
// functionAttributes!(s.onUpdate)) == typeof(&s.onUpdate)),
// "Function must match system update function."); FIXME: It's lead to crash on android build
static assert(__traits(hasMember, Sys, "system_id"), "Sys must be system type.");
// static assert(__traits(hasMember, Sys, "system_id"), "Sys must be system type.");
System* system = getSystem(Sys.system_id);
System* system = getSystem(becsID!Sys);
assert(system != null,
"System must be registered in EntityManager before any funcion can be called.");
if (!system.m_any_system_caller)
@ -2265,7 +2265,7 @@ export struct EntityManager
ushort[num] del_ids;
static foreach (i, comp; Components)
{
del_ids[i] = comp.component_id;
del_ids[i] = becsID!comp;
}
removeComponents(entity_id, del_ids);

View file

@ -2,6 +2,24 @@ module bubel.ecs.traits;
import std.traits;
/************************************************************************************************************************
Return Component/System/Event unique ID
*/
ref ushort becsID(T)()
{
__gshared ushort id = ushort.max;
return id;
}
/************************************************************************************************************************
Return Component/System/Event unique ID
*/
ref ushort becsID(T)(T obj)
{
static if(isPointer!T)return becsID!(PointerTarget!T);
else return becsID!T;
}
bool isForeachDelegateWithTypes(DG, Types...)()
{
return is(DG == delegate) && is(ReturnType!DG == int) && is(Parameters!DG == Types);