1 module main;
2 
3 import std.stdio;
4 import std.conv;
5 import std.random;
6 import Engine.Material;
7 import Engine.UI.all;
8 import std.math;
9 import std.variant;
10 import Engine.math;
11 import Engine.all;
12 import Engine.CStorage;
13 import dbox;
14 
15 Shader shader;
16 Camera camera; 
17 Texture ballTexture;
18 
19 import std.parallelism;
20 import std.datetime;
21 import Engine.util;
22 
23 class Physics : System {
24 
25 	public static b2World* world;
26 
27 	override void start() {
28 		// Define the gravity vector.
29 		b2Vec2 gravity = b2Vec2(0.0f, -20.0f);
30 
31 		// Construct a world object, which will hold and simulate the rigid bodies.
32 		Physics.world = new b2World(gravity);
33 
34 		
35 		b2BodyDef groundBodyDef;
36 		groundBodyDef.position.Set(0.0f, -10.0f);
37 		
38 		// Call the body factory which allocates memory for the ground body
39 		// from a pool and creates the ground box shape (also from a pool).
40 		// The body is also added to the world.
41 		b2Body* groundBody = world.CreateBody(&groundBodyDef);
42 		
43 		// Define the ground box shape.
44 		b2PolygonShape groundBox = new b2PolygonShape;
45 		
46 		// The extents are the half-widths of the box.
47 		groundBox.SetAsBox(10000.0f, 10.0f);
48 		
49 		// Add the ground fixture to the ground body.
50 		groundBody.CreateFixture(groundBox, 0.0f);
51 	}
52 
53 	@property override Timing timing() { 
54 		return cast(Timing)(Timing.Update+1);
55 	}
56 	
57 	override void process() {
58 		auto bounds = camera.bounds();
59 		auto mpos = vec3(camera.MouseWorldPosition(),0);
60 		auto delta = Core.DeltaTime;
61 		auto components = ComponentStorage.components!(Rigidbody)();
62 
63 		StopWatch timer;
64 		timer.start();
65 
66 		float32 timeStep = 1.0f / 60.0f;
67 		int32 velocityIterations = 6;
68 		int32 positionIterations = 2;
69 		
70 		world.Step(timeStep, velocityIterations, positionIterations);
71 
72 		foreach (c; components) {
73 			auto pos = c.Body.GetPosition();
74 			c.transform.position = vec3(pos.x, pos.y, 0);
75 		}
76 		timer.stop();
77 		if (timer.peek.msecs > 10) {
78 			//writeln("slowdown ", timer.peek.msecs);
79 		}
80 	} 	
81 
82 	override void onEntityEnter(Entity e) {
83 		
84 	}
85 	override void onEntityLeave(Entity e) {
86 
87 	}
88 }
89 
90 class Rigidbody  {
91 	mixin ComponentBase;
92 
93 	b2BodyDef bodyDef;
94 	b2Body* Body;
95 
96 	void Awake() {
97 		// Define the ground body.
98 		bodyDef.type = b2_dynamicBody;
99 		bodyDef.position.Set(this.transform.position.x, this.transform.position.y);
100 		
101 		// Call the body factory which allocates memory for the ground body
102 		// from a pool and creates the ground box shape (also from a pool).
103 		// The body is also added to the world.
104 		Body = Physics.world.CreateBody(&bodyDef);
105 
106 		b2CircleShape shape = new b2CircleShape();
107 		shape.m_radius = (this.transform.scale.x + this.transform.scale.y) / 4f;
108 		
109 		// Define the dynamic body fixture.
110 		b2FixtureDef fixtureDef;
111 		fixtureDef.shape = shape;
112 		
113 		// Set the box density to be non-zero, so it will be dynamic.
114 		fixtureDef.density = 1.0f;
115 		
116 		// Override the default friction.
117 		fixtureDef.friction = 0.3f;
118 
119 		fixtureDef.restitution = 0.5f;
120 		
121 		// Add the shape to the body.
122 		Body.CreateFixture(&fixtureDef);	
123 		
124 	}
125 }	
126 
127 struct InputHandle  {
128 	mixin ComponentBase;
129 
130 	
131 	void Start() {
132 		writeln("InputHandler started");
133 	}
134 
135 	void Update() {
136 		if (Input.MouseScroll().y > 0)  {
137 			Core.camera.size += 3*Core.DeltaTime;
138 			Core.camera.UpdateResolution();
139 		}	
140 		if (Input.MouseScroll().y < 0) {
141 			Core.camera.size -= 3*Core.DeltaTime;
142 			Core.camera.UpdateResolution();
143 		}
144 		if (Input.KeyDown(Key.A)) {
145 			Core.camera.transform.rotation.y = Core.camera.transform.rotation.y - Core.DeltaTime;
146 		}
147 		if (Input.KeyDown(Key.S)) {
148 			Core.camera.transform.rotation.y = Core.camera.transform.rotation.y - Core.DeltaTime;
149 		}
150 		if (Input.KeyDown(Key.MOUSE_BUTTON_1)) {
151 			{
152 				auto mpos = vec3(Core.camera.MouseWorldPosition(),0);
153 				for (int i=0;i<5;i++) {
154 					auto ship = new Entity();
155 					ship.AddComponent!(Sprite)(ballTexture);
156 					ship.AddComponent(new Rigidbody());
157 					ship.transform.rotation = vec3(0,0,0);
158 					ship.transform.position = mpos + vec3(-5+i/2,-5+i/2,0) ;
159 					ship.transform.scale = vec3(10, 10, 1);
160 					Core.AddEntity(ship);
161 				}		
162 			}
163 		}
164 	}
165 }
166 
167 
168 class HTest {
169 	int b;
170 }
171 
172 class Test : HTest {
173 	mixin ComponentBase;
174 	
175 	public void Hello() {
176 		writeln("Hello");
177 	}
178 	
179 	public int Hello(int b) {
180 		writeln("Hello int ",b);
181 		this.b = b;
182 		return 0;
183 	}
184 }
185 
186 struct TestA {
187 	int a;
188 	
189 	public void Foo() {
190 		writeln("Foo");
191 	}
192 }
193 
194 
195 bool tests() {
196 	
197 	void testComponent(Tp, Args...)(Args args) {
198 		alias T = baseType!Tp;
199 		Entity e = new Entity(false);   
200 		auto hTest = e.AddComponent!T(args);
201 		assert(e.GetComponent!T() == hTest);
202 		assert(e.RemoveComponents!T());
203 		assert(e.GetComponent!T() is null);
204 		e.AddComponent(new Component(hTest));
205 		assert(e.GetComponent!T() == hTest);
206 		assert(e.RemoveComponents!T());
207 		assert(e.GetComponent!T() is null); 
208 		e.Destory();
209 	}   
210 
211 	testComponent!HTest();
212 	testComponent!TestA();
213 	testComponent!Test();   
214 	testComponent!(HTest*)();
215 	testComponent!(TestA*)();
216 	testComponent!(Test*)();  
217 
218 	return true;
219 }
220 
221 void main(string[] args) { 
222 	try {
223 		assert(tests());  
224 		run();
225 	}
226 	catch (Exception e) {
227 		writeln(e.msg);
228 		scanf("\n");
229 	}
230 }
231 
232 void run() {
233 	Core.Start();
234 
235 	Font t = new Font("./public/arial.ttf\0", 32, Font.ASCII);
236 	ballTexture = new Texture("./public/sprite.png\0");
237 	//ballTexture.SetFiltering(GL_LINEAR,GL_LINEAR);
238 
239 	Core.AddSystem(new Physics());
240 
241 	auto mmouse = new Entity();
242 	//mmouse.AddComponent!(Sprite)(ballTexture);
243 	mmouse.transform.scale = vec3(100, 100, 1);
244 
245 	auto gravityBall = new Entity();
246 	gravityBall.AddComponent!(Sprite)(ballTexture);
247 	gravityBall.AddComponent!(Rigidbody)();
248 	gravityBall.transform.scale = vec3(15, 15, 1);
249 	
250 
251 	float entities = 1000;
252 	float m = sqrt(entities/(Core.width*Core.height));
253 	for (int x=0;x<Core.width*m;x++) {
254 		for (int y=0;y<Core.height*m;y++) {
255 			auto gball = gravityBall.Clone();
256 			gball.name = to!string(x);
257 			gball.transform.position = vec3(x/m + cast(float)(y&20),y/m,0);
258 			Core.AddEntity(gball);
259 		}
260 	}
261 	
262 	
263 
264 	for (int i=0;i<10;i++) {
265 		auto e2 = new Entity();
266 		e2.transform.scale.x = 32;
267 		e2.transform.scale.y = 32;
268 		e2.AddComponent!Rigidbody();
269 		e2.transform.position = vec3(((i%100)*10)%Core.width,(i*25)%Core.height,0);
270 		e2.AddComponent!Label(t,to!string(i));
271 		Core.AddEntity(e2);	
272 	}
273 
274 	auto cam = new Entity();
275 	camera = cam.AddComponent!Camera();
276 	cam.AddComponent!InputHandle();
277 	Core.AddEntity(cam);
278 	Core.camera = cam.GetComponent!Camera();
279 
280 	cam.transform.position = vec3(Core.width/2,+Core.height/2,0);
281 	
282 	auto e3 = new Entity();
283 	e3.transform.scale.x = 32;
284 	e3.transform.scale.y = 32;
285 	e3.transform.position = vec3(100,Core.height-50,0);
286 	auto fps = e3.AddComponent!Label(t,"FPS");
287 	Core.AddEntity(e3);	
288 
289 	
290 
291 	StartCoroutine( {
292 		float time = 0;
293 		int frames = 0;
294 		while (true) {
295 			time += Core.DeltaTime;
296 			frames++;
297 			if (time >= 1) {
298 				fps.SetText("FPS: " ~ to!string(frames) ~ " Entities:" ~ to!string(Core.EntitiesCount) );
299 				writeln(to!string(frames));
300 				time -= 1;
301 				frames = 0;
302 			}	
303 			auto camRect = Core.camera.bounds();
304 			fps.entity.transform.position = vec3((camRect.max.x+camRect.min.x) / 2, camRect.max.y - 50*Core.camera.size,0);
305 			fps.entity.transform.scale = vec3(1,1,1) * Core.camera.size * 34;
306 			mmouse.transform.position = vec3(Core.camera.MouseWorldPosition(),0);
307 
308 			Coroutine.yield();
309 		}
310 	});
311 	/*
312 	 StartCoroutine( {
313 	 auto sprite = mmouse.GetComponent!Sprite();
314 	 auto dTexture = new DynamicTexture(sprite.material.texture);
315 	 float t = 0;
316 	 while (true) {
317 	 if (sprite.color.r > 1)
318 	 sprite.color.r = 0;
319 
320 	 alias Vector!(ubyte,4) color;
321 
322 	 dTexture.Update!(color)((pixels){
323 	 for (int i=0;i<pixels.length;i++) {
324 	 pixels[i].r = cast(ubyte)(i + t);
325 	 pixels[i].g = cast(ubyte)(i + t);
326 	 pixels[i].b = 0xff;
327 	 pixels[i].a = 0xff;
328 	 }
329 	 });
330 	 t += Core.DeltaTime*1000;
331 	 //sprite.color.r += 0.1;
332 	 Coroutine.yield();
333 	 }
334 	 });
335 	 */
336 
337 	Core.Run();
338 }