1 module Engine.CStorage; 2 3 import std.traits; 4 import Engine.util; 5 import std.stdio; 6 import std.typetuple; 7 import Engine.Entity; 8 9 class ComponentStorage { 10 package static __gshared ComponentStorage[TypeInfo] Storages; 11 package static __gshared int bitCounter = 0; 12 public int bitIndex = -1; 13 14 public static ComponentStorage get(T)() { 15 return StorageImpl!(baseType!T).it; 16 } 17 18 public static ComponentStorage[] getDeep(T)() { 19 ComponentStorage[] storages = null; 20 foreach (s; Storages.values) { 21 void* dummy = cast(void*)1; 22 if (cast(void*)s.Cast!T(dummy) == cast(void*)1) { 23 storages ~= s; 24 } 25 } 26 return storages; 27 } 28 29 public static ConstArray!(pointerType!T) components(T)() { 30 return ConstArray!(pointerType!T)(StorageImpl!(baseType!T).active); 31 } 32 33 public static ConstArray!(pointerType!T)[] componentsDeep(T)() { 34 alias U = pointerType!T; 35 static if (is(T == struct)) { 36 //struct cannot have/be inhereted. 37 return [ components!T() ]; 38 } else { 39 ConstArray!(U)[] comps = null; 40 foreach (s; Storages.values) { 41 void* dummy = cast(void*)1; 42 //checking if its possible to cast the value to T. 43 if (cast(void*)s.Cast!T(dummy) !is null) { 44 comps ~= cast(ConstArray!U)s.Components(); 45 } 46 } 47 return comps; 48 } 49 } 50 51 public static ConstArray!(ComponentStorage) all()() { 52 return ConstArray!(ComponentStorage)(Storages.values); 53 } 54 55 public void RunFunction(T,Args...)(string name, Args args) { 56 auto func = FindFunction!T(name); 57 if (func is null) 58 return; 59 static if (is(T == delegate)) { 60 auto comps = Components(); 61 foreach (c; comps) { 62 func.ptr = c; 63 func(args); 64 } 65 } else { 66 func(args); 67 } 68 } 69 70 public void RunFunction(Args...)(string name, Args args) { 71 RunFunction!(void delegate(Args))(name, args); 72 } 73 74 public T FindFunction(T)(string name) { 75 static if (isSomeFunction!T) { 76 static if (is(T == delegate)) { 77 T t; 78 t.funcptr = cast(typeof(t.funcptr))FindFunctionType(name,typeid(t.funcptr)); 79 return t; 80 } else { 81 return cast(T)FindFunctionType(name,typeid(T)); 82 } 83 } 84 assert(0, "T is not function"); 85 } 86 87 public bool FindFunction(T)(auto ref T t, string name) { 88 static if (isSomeFunction!T) { 89 static if (is(T == delegate)) { 90 t.funcptr = cast(typeof(t.funcptr))FindFunctionType(name,typeid(t.funcptr)); 91 return t is null; 92 } else { 93 t = FindFunctionType(name,typeid(T)); 94 return t is null; 95 } 96 } 97 assert(0, "T is not function"); 98 } 99 100 public auto Cast(T)(void* component) { 101 return cast(pointerType!T)TypeCast(typeid(pointerType!T), component); 102 } 103 104 abstract TypeInfo Type(); 105 abstract void* TypeCast(TypeInfo type, void* component); 106 abstract ConstArray!(void*) Components(); 107 abstract void* FindFunctionType(string name, TypeInfo type); 108 abstract void* Clone(void*); 109 abstract void Bind(void*,Entity); 110 abstract void Active(void*); 111 abstract void Deactive(void*); 112 abstract void Remove(void*); 113 } 114 115 class StorageImpl(T) : ComponentStorage { 116 static if (is(T == class)) { 117 enum size = __traits(classInstanceSize, T); 118 alias Tp = T; 119 } 120 else { 121 enum size = T.sizeof; 122 alias Tp = T*; 123 } 124 125 package struct EPair { 126 Entity entity; 127 size_t index; 128 bool active; 129 } 130 131 package static __gshared Tp[] storage; 132 package static __gshared size_t totalIndex = 0; 133 package static __gshared size_t activeIndex = 0; 134 package static __gshared EPair[Tp] map; 135 package static __gshared int _bitIndex = -1; 136 137 public static __gshared StorageImpl!T it() { 138 if (!_it) { 139 init(); 140 } 141 return _it; 142 }; 143 package static __gshared StorageImpl!T _it; 144 145 146 public static void init() { 147 if (!_it) { 148 _it = new StorageImpl!T(); 149 ComponentStorage.Storages[typeid(T)] = _it; 150 _bitIndex = bitCounter++; 151 _it.bitIndex = _bitIndex; 152 } 153 } 154 155 public static Tp allocate(Args...)(Args args) { 156 return new T(args); 157 } 158 159 public override TypeInfo Type() { 160 return typeid(T); 161 } 162 163 public override void Bind(void* component, Entity entity) { 164 Bind(cast(Tp)component, entity); 165 } 166 167 @property final public static Tp[] active() { 168 return storage[0..activeIndex]; 169 }; 170 171 public static void Bind(Tp component, Entity entity) { 172 if (totalIndex >= storage.length) { 173 if (storage.length == 0) { 174 init(); 175 storage.length = 8; 176 } else { 177 storage.length *= 2; 178 } 179 } 180 storage[totalIndex] = component; 181 map[component] = EPair(entity,totalIndex,false); 182 totalIndex++; 183 static if (__traits(compiles, component._entity = entity)) { 184 component._entity = entity; 185 } 186 static if (__traits(compiles, component.OnComponentAdd())) { 187 component.OnComponentAdd(); 188 } 189 } 190 191 public override void Active(void* component) { 192 Active(cast(Tp)component); 193 } 194 195 public override void Deactive(void* component) { 196 Deactive(cast(Tp)component); 197 } 198 199 public override void Remove(void* component) { 200 Remove(cast(Tp)component); 201 } 202 203 public static void Active(Tp component) { 204 auto epair = &map[component]; 205 assert (!epair.active); 206 auto index = activeIndex; 207 //Check if we are activating the last index 208 if (epair.index == index) { 209 activeIndex++; 210 epair.active = true; 211 } else { 212 //get first deactived component 213 auto component2 = storage[index]; 214 auto epair2 = &map[component2]; 215 assert (!epair2.active); 216 //replace first deactived with the activated component 217 storage[index] = component; 218 storage[epair.index] = component2; 219 //replace indecies and change active to true 220 epair2.index = epair.index; 221 epair.index = index; 222 epair.active = true; 223 //we added an active component 224 activeIndex++; 225 } 226 } 227 228 public static void Deactive(Tp component) { 229 auto epair = &map[component]; 230 assert (epair.active); 231 auto index = activeIndex-1; 232 //Check if we are deactivating the last index 233 if (epair.index == index) { 234 activeIndex--; 235 epair.active = false; 236 } else { 237 //get last active component 238 auto component2 = storage[index]; 239 auto epair2 = &map[component2]; 240 assert (epair2.active); 241 //replace last active with the deactivated component 242 storage[index] = component; 243 storage[epair.index] = component2; 244 //replace indecies and change active to false 245 epair2.index = epair.index; 246 epair.index = index; 247 epair.active = false; 248 //we removed an active component 249 activeIndex--; 250 } 251 } 252 253 public static void Remove(Tp component) { 254 auto epair = map[component]; 255 map.remove(component); 256 if (epair.index != totalIndex-1) { 257 auto dstIndex = epair.index; 258 auto srcIndex = activeIndex-1; 259 if (epair.active && activeIndex != totalIndex) { 260 //Replace with last active 261 if (dstIndex != srcIndex) { 262 auto component2 = storage[srcIndex]; 263 auto epair2 = &map[component2]; 264 epair2.index = dstIndex; 265 assert (epair2.active); 266 storage[dstIndex] = component2; 267 dstIndex = srcIndex; 268 } 269 } 270 srcIndex = totalIndex-1; 271 //Replace with the last element 272 auto component2 = storage[srcIndex]; 273 auto epair2 = &map[component2]; 274 epair2.index = dstIndex; 275 storage[dstIndex] = component2; 276 } 277 if (epair.active) { 278 activeIndex--; 279 } 280 totalIndex--; 281 if (totalIndex > 0 && totalIndex == storage.length / 4) { 282 storage.length /= 2; 283 } 284 } 285 286 public static Tp Clone(Tp component) { 287 auto c = (cast(void*)component)[0..size].dup.ptr; 288 static if (is(T == class)) { 289 (cast(Object)c).__monitor = null; 290 } 291 return cast(Tp)c; 292 } 293 294 public override void* Clone(void* component) { 295 return cast(void*)Clone(cast(Tp)component); 296 } 297 298 public override void* FindFunctionType(string name, TypeInfo type) { 299 return _FindFunctionType(name, type); 300 } 301 302 package static void* _FindFunctionType(string name, TypeInfo type) { 303 foreach (member_string ; __traits(allMembers, T)) 304 { 305 static if (__traits(compiles, __traits(getMember, T, member_string))) 306 { 307 bool found = false; 308 foreach(overload; __traits(getOverloads, T, member_string)) { 309 static if (__traits(compiles, &overload)) { 310 if (!found) { 311 if (name == member_string) { 312 found = true; 313 } else { 314 break; 315 } 316 } 317 if (typeid(&overload) == type) 318 return cast(void*)&overload; 319 } 320 } 321 } 322 323 } 324 return null; 325 } 326 327 public override void* TypeCast(TypeInfo type, void* component) { 328 static if (is(T == class)) 329 return _Cast(type, component); 330 else { 331 if (type == typeid(Tp)) 332 return cast(Tp)component; 333 return null; 334 } 335 } 336 337 static if (is(T == class)) 338 package static void* _Cast(TypeInfo type, void* component) 339 { 340 alias TypeTuple!(T, ImplicitConversionTargets!T) AllTypes; 341 foreach (F ; AllTypes) 342 { 343 if (type != typeid(F) && 344 type != typeid(const(F))) 345 { 346 static if (isImplicitlyConvertible!(F, immutable(F))) 347 { 348 if (type != typeid(immutable(F))) 349 { 350 continue; 351 } 352 } 353 else 354 { 355 continue; 356 } 357 } 358 return cast(void*)cast(F)(cast(T)component); 359 } 360 return null; 361 } 362 363 364 public override ConstArray!(void*) Components() { 365 return ConstArray!(void*)(cast(void*[])active); 366 } 367 }