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