1 module Engine.Entity;
2 
3 import Engine.Component;
4 import t = Engine.Transform;
5 import Engine.Core;
6 import Engine.Coroutine;
7 import std.stdio;
8 import Engine.Sprite;
9 import Engine.util;
10 import Engine.CStorage;
11 import std.bitmanip;
12 
13 class Entity
14 {
15 	package Component[] components;
16 	package t.Transform transform_;
17 	package ptrdiff_t arrayIndex;
18 	BitArray componentsBits;
19 	bool active;
20 	Sprite sprite;
21 	string name;
22 	bool valid;
23 	
24 	@property package bool inScene() {
25 		return arrayIndex >= 0;
26 	};
27 	
28 	this(bool addTransform = true)
29 	{
30 		components = new Component[5];
31 		components.length = 0;
32 		componentsBits.length = ComponentStorage.bitCounter+1;
33 		if (addTransform)
34 			AddComponent!(t.Transform)();
35 		active = true;
36 		valid = true;
37 		arrayIndex = -1;
38 	}
39 
40 	final @property t.Transform transform() { return transform_; }
41 
42 	final @property public auto Components() {
43 		return ConstArray!Component(components);	
44 	};
45 	
46 	public void SendMessage(Args...)(string name, Args args) {
47 		foreach( c; components) {
48 			c.RunFunction(name, args);
49 		}
50 	}
51 	
52 	public auto AddComponent(T, Args...)(Args args)  {
53 		auto t = StorageImpl!(T).allocate(args);
54 		components ~= new Component(t);
55 		StorageImpl!(T).Bind(t,this);	
56 		setComponentBit(StorageImpl!(T)._bitIndex, true);
57 		return t;	
58 	}	
59 	
60 	public auto AddComponent()(Component component)  {
61 		components ~= component;
62 		component.storage.Bind(component.component,this);
63 		setComponentBit(component.storage.bitIndex, true);
64 		return component;
65 	}	
66 
67 	public auto AddComponent(T)(T component) if (!is(T == Component))  {
68 		auto c = new Component(component);
69 		components ~= c;
70 		c.storage.Bind(c.component,this);
71 		setComponentBit(c.storage.bitIndex, true);
72 		return component;
73 	}
74 
75 	package void setComponentBit(int bit, bool flag) {
76 		if (bit >= componentsBits.length) {
77 			componentsBits.length = ComponentStorage.bitCounter;
78 		}
79 		componentsBits[bit] = flag;
80 	}
81 
82 	public auto GetComponent(T)() {
83 		alias Tp = pointerType!T;
84 		foreach( c; components) {
85 			auto t = c.Cast!Tp();
86 			if (t !is null) {
87 				return t;
88 			}
89 		}
90 		return null;
91 	}
92 
93 	public Entity Clone()
94 	{		
95 		Entity t = new Entity(false);
96 		foreach (ref c ; this.components) {
97 			t.AddComponent(c.Clone());
98 		}
99 		return t;
100 	}
101 
102 	public void Destory()
103 	{
104 		if (!valid)
105 			return;
106 		Core.RemoveEntity(this);
107 		foreach( c; components) {	
108 			c.storage.Remove(c.component);
109 		}
110 		components.length = 0;
111 		components = null;	
112 		active = false;
113 		valid = false;
114 	}
115 
116 	package void onActive() {
117 		foreach( c; components) {
118 			c.storage.Active(c.component);
119 		}
120 	}
121 
122 	public bool RemoveComponent(T)(T component) if (!is(T == Component))  {
123 		ComponentStorage storage = StorageImpl!(baseType!T).it;
124 		auto found = false;	
125 		auto left = 0;	
126 		for (int i=0;i<components.length;i++) {
127 			auto c = components[i];
128 			if (c.storage == storage) {
129 				if (cast(void*)component == c.component) {
130 					components[i] = components[components.length-1];
131 					components.length--;
132 					storage.Remove(component.component);
133 					found = true;
134 				} else {
135 					left++;
136 				}
137 			}	
138 		}
139 		if (found && left == 0) {
140 			setComponentBit(storage.bitIndex, false);
141 		}		
142 		return found;
143 	}
144 	
145 	
146 	public bool RemoveComponent()(Component component) {
147 		ComponentStorage storage = component.storage;
148 		auto found = false;
149 		auto left = 0;
150 		for (int i=0;i<components.length;i++) {
151 			auto c = components[i];
152 			if (c.storage == storage) {
153 				if (component.component == c.component) {
154 					components[i] = components[components.length-1];
155 					components.length--;
156 					storage.Remove(component.component);
157 					found = true;
158 				} else {
159 					left++;
160 				}
161 			}	
162 		}
163 		if (found && left == 0) {
164 			setComponentBit(storage.bitIndex, false);
165 		}		
166 		return found;
167 	}	
168 
169 	public bool RemoveComponents(T)() {
170 		auto found = false;
171 		for (int i=0;i<components.length;i++) {
172 			auto component = components[i];
173 			if (component.Cast!T() !is null) {
174 				setComponentBit(component.storage.bitIndex, false);
175 				components[i] = components[components.length-1];
176 				components.length--;	
177 				component.storage.Remove(component.component);	
178 				found = true;
179 			}
180 		}	
181 		return found;
182 	}
183 }
184 
185