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 }