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 
12 class Entity
13 {
14 	package Component[] components;
15 	package t.Transform transform_;
16 	package ptrdiff_t arrayIndex;
17 	bool active;
18 	Sprite sprite;
19 	string name;
20 	bool valid;
21 	
22 	@property package bool inScene() {
23 		return arrayIndex >= 0;
24 	};
25 
26 	this(bool addTransform = true)
27 	{
28 		components = new Component[5];
29 		components.length = 0;
30 		if (addTransform)
31 			AddComponent!(t.Transform)();
32 		active = true;
33 		valid = true;
34 		arrayIndex = -1;
35 	}
36 
37 	final @property t.Transform transform() { return transform_; }
38 
39 	final @property public auto Components() {
40 		return ConstArray!Component(components);	
41 	};
42 	
43 	public void SendMessage(Args...)(string name, Args args) {
44 		foreach( c; components) {
45 			c.RunFunction(name, args);
46 		}
47 	}
48 	
49 	public auto AddComponent(T, Args...)(Args args)  {
50 		auto t = StorageImpl!(T).allocate(args);
51 		components ~= new Component(t);
52 		StorageImpl!(T).Bind(t,this);	
53 		return t;	
54 	}	
55 
56 	public auto AddComponent()(Component component)  {
57 		components ~= component;
58 		component.storage.Bind(component.component,this);
59 		return component;
60 	}	
61 
62 	public auto AddComponent(T)(T component) if (!is(T == Component))  {
63 		auto c = new Component(component);
64 		components ~= c;
65 		c.storage.Bind(c.component,this);
66 		return component;
67 	}
68 
69 	public auto GetComponent(T)() {
70 		alias Tp = pointerType!T;
71 		foreach( c; components) {
72 			auto t = c.Cast!Tp();
73 			if (t !is null) {
74 				return t;
75 			}
76 		}
77 		return null;
78 	}
79 
80 	public Entity Clone()
81 	{		
82 		Entity t = new Entity(false);
83 		foreach (ref c ; this.components) {
84 			t.AddComponent(c.Clone());
85 		}
86 		return t;
87 	}
88 
89 	public void Destory()
90 	{
91 		if (!valid)
92 			return;
93 		Core.RemoveEntity(this);
94 		foreach( c; components) {	
95 			c.storage.Remove(c.component);
96 		}
97 		components = null;
98 		active = false;
99 		valid = false;
100 	}
101 
102 	package void onActive() {
103 		foreach( c; components) {
104 			c.storage.Active(c.component);
105 		}
106 	}
107 	
108 
109 	public bool RemoveComponent()(Component component) {
110 		for (int i=0;i<components.length;i++) {
111 			auto component2 = components[i];
112 			if (component.component == component2.component) {
113 				component2.storage.Remove(component.component);
114 				components[i] = components[components.length-1];
115 				components.length--;
116 				return true;
117 			}
118 		}
119 		return false;
120 	}
121 
122 	public bool RemoveComponent(T)() {
123 		for (int i=0;i<components.length;i++) {
124 			auto component = components[i];
125 			if (component.Cast!T() !is null) {
126 				component.storage.Remove(component.component);
127 				components[i] = components[components.length-1];
128 				components.length--;  
129 				return true;
130 			}
131 		}
132 		return false;
133 	}
134 	
135 	public bool RemoveComponents(T)() {
136 		bool removed = false;
137 		for (int i=0;i<components.length;i++) {
138 			auto component = components[i];
139 			if (component.Cast!T() !is null) {
140 				component.storage.Remove(component.component);
141 				components[i] = components[components.length-1];
142 				components.length--;
143 				removed = true;
144 			}
145 		}
146 		return removed;
147 	}
148 }
149 
150