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 }