1 /*
2 Copyright (C) 2007, 2010 - Bit-Blot
3 
4 This file is part of Aquaria.
5 
6 Aquaria is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 
15 See the GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */
21 #include "Core.h"
22 #include "Texture.h"
23 #include "AfterEffect.h"
24 #include "Particles.h"
25 
26 #include <time.h>
27 #include <iostream>
28 
29 #ifdef BBGE_BUILD_UNIX
30 #include <limits.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <unistd.h>
34 #endif
35 
36 #include <assert.h>
37 
38 #if __APPLE__
39 #include <Carbon/Carbon.h>
40 #endif
41 
42 #if BBGE_BUILD_WINDOWS
43 #include <shlobj.h>
44 #include <direct.h>
45 #endif
46 
47 #ifdef BBGE_BUILD_SDL
48 	#include "SDL_syswm.h"
49 	#ifdef BBGE_BUILD_SDL2
50 	static SDL_Window *gScreen=0;
51 	static SDL_GLContext gGLctx=0;
52 	#else
53 	static SDL_Surface *gScreen=0;
54 	#endif
55 
56 	bool ignoreNextMouse=false;
57 	Vector unchange;
58 #endif
59 
60 #ifdef BBGE_BUILD_VFS
61 #include "ttvfs.h"
62 #endif
63 
64 Core *core = 0;
65 
66 #ifdef BBGE_BUILD_WINDOWS
67 	HICON icon_windows = 0;
68 #endif
69 
70 #ifndef KMOD_GUI
71 	#define KMOD_GUI KMOD_META
72 #endif
73 
initIcon()74 void Core::initIcon()
75 {
76 #ifdef BBGE_BUILD_WINDOWS
77 	HINSTANCE handle = ::GetModuleHandle(NULL);
78 	//if (icon_windows)
79 	//	::DestroyIcon(icon_windows);
80 
81 	icon_windows = ::LoadIcon(handle, "icon");
82 
83 	SDL_SysWMinfo wminfo;
84 	SDL_VERSION(&wminfo.version)
85 	if (SDL_GetWindowWMInfo(gScreen, &wminfo) != 1)
86 	{
87 		//errorLog("wrong SDL version");
88 		// error: wrong SDL version
89 	}
90 
91 	HWND hwnd = wminfo.info.win.window;
92 
93 	::SetClassLong(hwnd, GCL_HICON, (LONG) icon_windows);
94 #endif
95 }
96 
resetCamera()97 void Core::resetCamera()
98 {
99 	cameraPos = Vector(0,0);
100 }
101 
createParticleEffect(const std::string & name,const Vector & position,int layer,float rotz)102 ParticleEffect* Core::createParticleEffect(const std::string &name, const Vector &position, int layer, float rotz)
103 {
104 	ParticleEffect *e = new ParticleEffect();
105 	e->load(name);
106 	e->position = position;
107 	e->start();
108 	e->setDie(true);
109 	e->rotation.z = rotz;
110 	core->getTopStateData()->addRenderObject(e, layer);
111 	return e;
112 }
113 
unloadDevice()114 void Core::unloadDevice()
115 {
116 	for (int i = 0; i < renderObjectLayers.size(); i++)
117 	{
118 		RenderObjectLayer *r = &renderObjectLayers[i];
119 		RenderObject *robj = r->getFirst();
120 		while (robj)
121 		{
122 			robj->unloadDevice();
123 			robj = r->getNext();
124 		}
125 	}
126 	frameBuffer.unloadDevice();
127 
128 	if (afterEffectManager)
129 		afterEffectManager->unloadDevice();
130 }
131 
reloadDevice()132 void Core::reloadDevice()
133 {
134 	for (int i = 0; i < renderObjectLayers.size(); i++)
135 	{
136 		RenderObjectLayer *r = &renderObjectLayers[i];
137 		r->reloadDevice();
138 		RenderObject *robj = r->getFirst();
139 		while (robj)
140 		{
141 			robj->reloadDevice();
142 			robj = r->getNext();
143 		}
144 	}
145 	frameBuffer.reloadDevice();
146 
147 	if (afterEffectManager)
148 		afterEffectManager->reloadDevice();
149 }
150 
resetGraphics(int w,int h,int fullscreen,int vsync,int bpp)151 void Core::resetGraphics(int w, int h, int fullscreen, int vsync, int bpp)
152 {
153 	if (fullscreen == -1)
154 		fullscreen = _fullscreen;
155 
156 	if (vsync == -1)
157 		vsync = _vsync;
158 
159 	if (w == -1)
160 		w = width;
161 
162 	if (h == -1)
163 		h = height;
164 
165 	if (bpp == -1)
166 		bpp = _bpp;
167 
168 	unloadDevice();
169 	unloadResources();
170 
171 	shutdownGraphicsLibrary();
172 
173 	initGraphicsLibrary(w, h, fullscreen, vsync, bpp);
174 
175 	enable2DWide(w, h);
176 
177 	reloadResources();
178 	reloadDevice();
179 
180 
181 	resetTimer();
182 }
183 
toggleScreenMode(int t)184 void Core::toggleScreenMode(int t)
185 {
186 #ifdef BBGE_BUILD_GLFW
187 /*
188 		glfwCloseWindow();
189 
190 		createWindow(800,600,32,false,"");
191 		initGraphicsLibrary(false, true);
192 		enable2D(800);
193 		//reloadResources();
194 		*/
195 #endif
196 #ifdef BBGE_BUILD_SDL
197 	sound->pause();
198 	resetGraphics(-1, -1, t);
199 	cacheRender();
200 	resetTimer();
201 	sound->resume();
202 #endif
203 }
204 
updateCursorFromJoystick(float dt,int spd)205 void Core::updateCursorFromJoystick(float dt, int spd)
206 {
207 	//debugLog("updating mouse from joystick");
208 
209 	core->mouse.position += joystick.position*dt*spd;
210 
211 /*
212 	if (!joystick.position.isZero())
213 		setMousePosition(core->mouse.position);
214 	*/
215 
216 	doMouseConstraint();
217 }
218 
setWindowCaption(const std::string & caption,const std::string & icon)219 void Core::setWindowCaption(const std::string &caption, const std::string &icon)
220 {
221 #ifdef BBGE_BUILD_SDL
222 #ifndef BBGE_BUILD_SDL2
223 	SDL_WM_SetCaption(caption.c_str(), icon.c_str());
224 #endif
225 #endif
226 }
227 
getRenderObjectLayer(int i)228 RenderObjectLayer *Core::getRenderObjectLayer(int i)
229 {
230 	if (i == LR_NONE)
231 		return 0;
232 	return &renderObjectLayers[i];
233 }
234 
235 #if defined(BBGE_BUILD_WINDOWS) && !defined(BBGE_BUILD_SDL)
236 	LPDIRECTINPUT8			g_pDI       = NULL; // The DirectInput object
237 	LPDIRECTINPUTDEVICE8	g_pKeyboard = NULL; // The keyboard device
238 	LPDIRECTINPUTDEVICE8	g_pMouse	= NULL;
239 
240 	D3DCOLOR				d3dColor	=0xFFFFFFFF;
241 #endif
242 
243 #ifdef BBGE_BUILD_DIRECTX
244 
245 	__int64 timerStart=0, timerEnd=0, timerFreq=0;
246 	//Direct3D 9 interface
247 	IDirect3D9* d3d						= NULL;
248 	//Capabilities of graphics adapter
249 	D3DCAPS9 d3dCaps;
250 
251 	//Direct3D present parameters
252 	D3DPRESENT_PARAMETERS d3dPresent;
253 	LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // Our rendering device
254 	LPD3DXSPRITE			d3dSprite	= NULL;
255 	LPD3DXMATRIXSTACK		d3dMatrixStack = NULL;
256 	IDirect3DVertexBuffer9* vertexBuffer	= NULL;
257 	IDirect3DVertexBuffer9* preTransVertexBuffer = NULL;
258 
259 	//Custom vertex
260 	struct TLVERTEX
261 	{
262 	    float x;
263 	    float y;
264 	    float z;
265 	    //float rhw;
266 	    D3DCOLOR colour;
267 	    float u;
268 	    float v;
269 	};
270 	const DWORD D3DFVF_TLVERTEX = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;
271 	struct PTLVERTEX
272 	{
273 	    float x;
274 	    float y;
275 	    float z;
276 	    float rhw;
277 	    D3DCOLOR colour;
278 	    float u;
279 	    float v;
280 	};
281 
282 	const DWORD D3DFVF_PTLVERTEX = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1;
283 #endif
284 
285 
286 
287 	#ifdef BBGE_BUILD_DIRECTX
288 	/*
289 	LPDIRECT3DVERTEXBUFFER9 g_pVB        = NULL; // Buffer to hold vertices
290 	LPDIRECT3DTEXTURE9      g_pTexture   = NULL; // Our texture
291 	*/
292 	// A structure for our custom vertex type
293 	struct CUSTOMVERTEX
294 	{
295 	    FLOAT x, y, z, rhw; // The transformed position for the vertex
296 	    DWORD color;        // The vertex color
297 	};
298 
299 	// Our custom FVF, which describes our custom vertex structure
300 	#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
301 
getD3DMatrixStack()302 	LPD3DXMATRIXSTACK Core::getD3DMatrixStack()
303 	{
304 		return d3dMatrixStack;
305 	}
306 
getD3DDevice()307 	LPDIRECT3DDEVICE9 Core::getD3DDevice()
308 	{
309 		return g_pd3dDevice;
310 	}
311 
getD3DSprite()312 	LPD3DXSPRITE Core::getD3DSprite()
313 	{
314 		return d3dSprite;
315 	}
316 
MsgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)317 	LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
318 	{
319 		switch( msg )
320 		{
321 	        case WM_DESTROY:
322 				//Cleanup();
323 				PostQuitMessage( 0 );
324 				return 0;
325 		}
326 
327 	    return DefWindowProc( hWnd, msg, wParam, lParam );
328 }
blitD3DVerts(IDirect3DTexture9 * texture,float v1x,float v1y,float v2x,float v2y,float v3x,float v3y,float v4x,float v4y)329 	void Core::blitD3DVerts(IDirect3DTexture9 *texture, float v1x, float v1y, float v2x, float v2y, float v3x, float v3y, float v4x, float v4y)
330 	{
331 		TLVERTEX* vertices;
332 
333 		//Lock the vertex buffer
334 		vertexBuffer->Lock(0, 0, (void**)&vertices, NULL);
335 
336 		vertices[0].colour = d3dColor;
337 		vertices[0].x = v1x;
338 		vertices[0].y = v1y;
339 		vertices[0].z = 1.0f;
340 		vertices[0].u = 0.0f;
341 		vertices[0].v = 1.0f-1.0f;
342 
343 		vertices[1].colour = d3dColor;
344 		vertices[1].x = v2x;
345 		vertices[1].y = v2y;
346 		vertices[1].z = 1.0f;
347 		vertices[1].u = 1.0f;
348 		vertices[1].v = 1.0f-1.0f;
349 
350 		vertices[2].colour = d3dColor;
351 		vertices[2].x = v3x;
352 		vertices[2].y = v3y;
353 		vertices[2].z = 1.0f;
354 		vertices[2].u = 1.0f;
355 		vertices[2].v = 1.0f-0.0f;
356 
357 		vertices[3].colour = d3dColor;
358 		vertices[3].x = v4x;
359 		vertices[3].y = v4y;
360 		vertices[3].z = 1.0f;
361 		vertices[3].u = 0.0f;
362 		vertices[3].v = 1.0f-0.0f;
363 		//Unlock the vertex buffer
364 		vertexBuffer->Unlock();
365 
366 		//Set texture
367 		g_pd3dDevice->SetTexture (0, texture);
368 
369 		//Draw image
370 		g_pd3dDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);
371 	}
372 
blitD3DEx(IDirect3DTexture9 * texture,int w2,int h2,float u1,float v1,float u2,float v2)373 	void Core::blitD3DEx (IDirect3DTexture9 *texture, int w2, int h2, float u1, float v1, float u2, float v2)
374 	{
375 		TLVERTEX* vertices;
376 
377 		/*
378 		int w2=width/2;
379 		int h2=height/2;
380 		*/
381 		//Lock the vertex buffer
382 		vertexBuffer->Lock(0, 0, (void**)&vertices, NULL);
383 
384 		//Setup vertices
385 		//A -0.5f modifier is applied to vertex coordinates to match texture
386 		//and screen coords. Some drivers may compensate for this
387 		//automatically, but on others texture alignment errors are introduced
388 		//More information on this can be found in the Direct3D 9 documentation
389 		vertices[0].colour = d3dColor;
390 		vertices[0].x = -0.5f*w2;
391 		vertices[0].y = -0.5f*h2;
392 		vertices[0].z = 1.0f;
393 		//vertices[0].rhw = 1.0f;
394 		vertices[0].u = u1;
395 		vertices[0].v = 1.0f-v2;
396 
397 		vertices[1].colour = d3dColor;
398 		vertices[1].x = 0.5f*w2;
399 		vertices[1].y = -0.5f*h2;
400 		vertices[1].z = 1.0f;
401 		//vertices[1].rhw = 1.0f;
402 		vertices[1].u = u2;
403 		vertices[1].v = 1.0f-v2;
404 
405 		vertices[2].colour = d3dColor;
406 		vertices[2].x = 0.5f*w2;
407 		vertices[2].y = 0.5f*h2;
408 		vertices[2].z = 1.0f;
409 		//vertices[2].rhw = 1.0f;
410 		vertices[2].u = u2;
411 		vertices[2].v = 1.0f-v1;
412 
413 		vertices[3].colour = d3dColor;
414 		vertices[3].x = -0.5f*w2;
415 		vertices[3].y = 0.5f*h2;
416 		vertices[3].z = 1.0f;
417 		//vertices[3].rhw = 1.0f;
418 		vertices[3].u = u1;
419 		vertices[3].v = 1.0f-v1;
420 		//Unlock the vertex buffer
421 		vertexBuffer->Unlock();
422 
423 		//Set texture
424 		g_pd3dDevice->SetTexture (0, texture);
425 
426 		//Draw image
427 		g_pd3dDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);
428 	}
429 
blitD3DGradient(D3DCOLOR ulc0,D3DCOLOR ulc1,D3DCOLOR ulc2,D3DCOLOR ulc3)430 	void Core::blitD3DGradient(D3DCOLOR ulc0, D3DCOLOR ulc1, D3DCOLOR ulc2, D3DCOLOR ulc3)
431 	{
432 		TLVERTEX* vertices;
433 
434 		//Lock the vertex buffer
435 		vertexBuffer->Lock(0, 0, (void**)&vertices, NULL);
436 		vertices[0].colour = ulc0;
437 		vertices[0].x = -0.5f;
438 		vertices[0].y = -0.5f;
439 		vertices[0].z = 1.0f;
440 		//vertices[0].rhw = 1.0f;
441 		vertices[0].u = 0.0f;
442 		vertices[0].v = 1.0f-1.0f;
443 
444 		vertices[1].colour = ulc1;
445 		vertices[1].x = 0.5f;
446 		vertices[1].y = -0.5f;
447 		vertices[1].z = 1.0f;
448 		//vertices[1].rhw = 1.0f;
449 		vertices[1].u = 1.0f;
450 		vertices[1].v = 1.0f-1.0f;
451 
452 		vertices[2].colour = ulc2;
453 		vertices[2].x = 0.5f;
454 		vertices[2].y = 0.5f;
455 		vertices[2].z = 1.0f;
456 		//vertices[2].rhw = 1.0f;
457 		vertices[2].u = 1.0f;
458 		vertices[2].v = 1.0f-0.0f;
459 
460 		vertices[3].colour = ulc3;
461 		vertices[3].x = -0.5f;
462 		vertices[3].y = 0.5f;
463 		vertices[3].z = 1.0f;
464 		//vertices[3].rhw = 1.0f;
465 		vertices[3].u = 0.0f;
466 		vertices[3].v = 1.0f-0.0f;
467 		//Unlock the vertex buffer
468 		vertexBuffer->Unlock();
469 
470 		//Set texture
471 		//g_pd3dDevice->SetTexture (0, texture);
472 		g_pd3dDevice->SetTexture (0, 0);
473 
474 		//Draw image
475 		g_pd3dDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);
476 	}
477 
blitD3DPreTrans(IDirect3DTexture9 * texture,float x,float y,int w2,int h2)478 	void Core::blitD3DPreTrans(IDirect3DTexture9 *texture, float x, float y, int w2, int h2)
479 	{
480 		/*
481 		PTLVERTEX* vertices;
482 		//Lock the vertex buffer
483 		preTransVertexBuffer->Lock(0, 0, (void**)&vertices, NULL);
484 		*/
485 		TLVERTEX* vertices;
486 		//Lock the vertex buffer
487 		vertexBuffer->Lock(0, 0, (void**)&vertices, NULL);
488 
489 
490 		//Setup vertices
491 		//A -0.5f modifier is applied to vertex coordinates to match texture
492 		//and screen coords. Some drivers may compensate for this
493 		//automatically, but on others texture alignment errors are introduced
494 		//More information on this can be found in the Direct3D 9 documentation
495 		vertices[0].colour = d3dColor;
496 		vertices[0].x = x-0.5f*w2;
497 		vertices[0].y = y-0.5f*h2;
498 		vertices[0].z = 1.0f;
499 		//vertices[0].rhw = 1.0f;
500 		vertices[0].u = 0.0f;
501 		vertices[0].v = 1.0f-1.0f;
502 
503 		vertices[1].colour = d3dColor;
504 		vertices[1].x = x+0.5f*w2;
505 		vertices[1].y = y-0.5f*h2;
506 		vertices[1].z = 1.0f;
507 		//vertices[1].rhw = 1.0f;
508 		vertices[1].u = 1.0f;
509 		vertices[1].v = 1.0f-1.0f;
510 
511 		vertices[2].colour = d3dColor;
512 		vertices[2].x = x+0.5f*w2;
513 		vertices[2].y = y+0.5f*h2;
514 		vertices[2].z = 1.0f;
515 		//vertices[2].rhw = 1.0f;
516 		vertices[2].u = 1.0f;
517 		vertices[2].v = 1.0f-0.0f;
518 
519 		vertices[3].colour = d3dColor;
520 		vertices[3].x = x-0.5f*w2;
521 		vertices[3].y = y+0.5f*h2;
522 		vertices[3].z = 1.0f;
523 		//vertices[3].rhw = 1.0f;
524 		vertices[3].u = 0.0f;
525 		vertices[3].v = 1.0f-0.0f;
526 		/*
527 		//Unlock the vertex buffer
528 		preTransVertexBuffer->Unlock();
529 		*/
530 		vertexBuffer->Unlock();
531 
532 
533 		//Set texture
534 		g_pd3dDevice->SetTexture (0, texture);
535 
536 		//Draw image
537 		g_pd3dDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);
538 	}
blitD3D(IDirect3DTexture9 * texture,int w2,int h2)539 	void Core::blitD3D (IDirect3DTexture9 *texture, int w2, int h2)
540 	{
541 		TLVERTEX* vertices;
542 		//D3DCOLOR d3dColor = 0xFFFFFFFF;
543 
544 		/*
545 		int w2=width/2;
546 		int h2=height/2;
547 		*/
548 		//Lock the vertex buffer
549 		vertexBuffer->Lock(0, 0, (void**)&vertices, NULL);
550 
551 		//Setup verticeserr
552 		//A -0.5f modifier is applied to vertex coordinates to match texture
553 		//and screen coords. Some drivers may compensate for this
554 		//automatically, but on others texture alignment ors are introduced
555 		//More information on this can be found in the Direct3D 9 documentation
556 		vertices[0].colour = d3dColor;
557 		vertices[0].x = -0.5f*w2;
558 		vertices[0].y = -0.5f*h2;
559 		vertices[0].z = 1.0f;
560 		//vertices[0].rhw = 1.0f;
561 		vertices[0].u = 0.0f;
562 		vertices[0].v = 1.0f-1.0f;
563 
564 		vertices[1].colour = d3dColor;
565 		vertices[1].x = 0.5f*w2;
566 		vertices[1].y = -0.5f*h2;
567 		vertices[1].z = 1.0f;
568 		//vertices[1].rhw = 1.0f;
569 		vertices[1].u = 1.0f;
570 		vertices[1].v = 1.0f-1.0f;
571 
572 		vertices[2].colour = d3dColor;
573 		vertices[2].x = 0.5f*w2;
574 		vertices[2].y = 0.5f*h2;
575 		vertices[2].z = 1.0f;
576 		//vertices[2].rhw = 1.0f;
577 		vertices[2].u = 1.0f;
578 		vertices[2].v = 1.0f-0.0f;
579 
580 		vertices[3].colour = d3dColor;
581 		vertices[3].x = -0.5f*w2;
582 		vertices[3].y = 0.5f*h2;
583 		vertices[3].z = 1.0f;
584 		//vertices[3].rhw = 1.0f;
585 		vertices[3].u = 0.0f;
586 		vertices[3].v = 1.0f-0.0f;
587 		//Unlock the vertex buffer
588 		vertexBuffer->Unlock();
589 
590 		//Set texture
591 		g_pd3dDevice->SetTexture (0, texture);
592 
593 		//Draw image
594 		g_pd3dDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);
595 	}
596 
InitD3D(HWND hWnd,bool fullscreen,int vsync)597 	HRESULT InitD3D( HWND hWnd, bool fullscreen, int vsync)
598 	{
599 		// Create the D3D object.
600 		HRESULT hr;
601 
602 		//Make Direct3D object
603 		d3d = Direct3DCreate9(D3D_SDK_VERSION);
604 
605 		//Make sure NULL pointer was not returned
606 		if (!d3d)
607 			return FALSE;
608 
609 		//Get device capabilities
610 		ZeroMemory (&d3dCaps, sizeof(d3dCaps));
611 		if (FAILED(d3d->GetDeviceCaps (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps)))
612 			return FALSE;
613 
614 		//Setup present parameters
615 		ZeroMemory(&d3dPresent,sizeof(d3dPresent));
616 		d3dPresent.hDeviceWindow = hWnd;
617 
618 		//Check if windowed
619 		if (!fullscreen)
620 		{
621 			D3DDISPLAYMODE d3ddm;
622 			RECT rWindow;
623 
624 			//Get display mode
625 			d3d->GetAdapterDisplayMode (D3DADAPTER_DEFAULT, &d3ddm);
626 
627 			//Get window bounds
628 			GetClientRect (hWnd, &rWindow);
629 
630 			//Setup screen dimensions
631 			core->width = rWindow.right - rWindow.left;
632 			core->height = rWindow.bottom - rWindow.top;
633 
634 			//Setup backbuffer
635 			d3dPresent.Windowed = true;
636 			d3dPresent.BackBufferWidth = rWindow.right - rWindow.left;
637 			d3dPresent.BackBufferHeight = rWindow.bottom - rWindow.top;
638 		}
639 		else
640 		{
641 			d3dPresent.Windowed = false;
642 			d3dPresent.BackBufferWidth = core->width;
643 			d3dPresent.BackBufferHeight = core->height;
644 		}
645 		d3dPresent.BackBufferFormat = D3DFMT_A8R8G8B8;
646 		d3dPresent.BackBufferCount = 1;
647 		d3dPresent.SwapEffect = D3DSWAPEFFECT_DISCARD;
648 
649 		if (vsync>0)
650 			d3dPresent.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
651 		else
652 			d3dPresent.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
653 
654 
655 		//Check if hardware vertex processing is available
656 		if (d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
657 		{
658 			debugLog("hardware T&L!");
659 			//Create device with hardware vertex processing
660 			hr = d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hWnd,
661 				D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dPresent, &g_pd3dDevice);
662 		}
663 		else
664 		{
665 			debugLog("no hardware T&L.");
666 			//Create device with software vertex processing
667 			hr = d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hWnd,
668 				D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dPresent, &g_pd3dDevice);
669 		}
670 
671 		//Make sure device was created
672 		if (FAILED(hr))
673 		{
674 			errorLog ("directx init failed");
675 			return false;
676 		}
677 
678 		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
679 		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
680 		// Turn off culling
681 		g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
682 		/*
683 			D3DCULL_NONE = 1,
684 			D3DCULL_CW = 2,
685 			D3DCULL_CCW = 3,
686 		*/
687 		// Turn off D3D lighting
688 		g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
689 		// Turn on the zbuffer
690 		g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE);
691 
692 		D3DXCreateSprite(core->getD3DDevice(), &d3dSprite);
693 		D3DXCreateMatrixStack(0, &d3dMatrixStack);
694 
695 		//Set vertex shader
696 		g_pd3dDevice->SetVertexShader(NULL);
697 		g_pd3dDevice->SetFVF(D3DFVF_TLVERTEX);
698 
699 		//Create vertex buffer
700 		g_pd3dDevice->CreateVertexBuffer(sizeof(TLVERTEX) * 4, NULL, D3DFVF_TLVERTEX, D3DPOOL_MANAGED, &vertexBuffer, NULL);
701 		g_pd3dDevice->SetStreamSource(0, vertexBuffer, 0, sizeof(TLVERTEX));
702 
703 		/*
704 		g_pd3dDevice->CreateVertexBuffer(sizeof(PTLVERTEX) * 4, NULL, D3DFVF_TLVERTEX, D3DPOOL_MANAGED, &preTransVertexBuffer, NULL);
705 		g_pd3dDevice->SetStreamSource(0, preTransVertexBuffer, 0, sizeof(PTLVERTEX));
706 		*/
707 
708 		g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
709 
710 		g_pd3dDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
711 		g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
712 		g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
713 		g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
714 
715 		return S_OK;
716 	}
717 #endif
718 
719 
setColor(float r,float g,float b,float a)720 void Core::setColor(float r, float g, float b, float a)
721 {
722 #ifdef BBGE_BUILD_OPENGL
723 	glColor4f(r, g, b, a);
724 #endif
725 #ifdef BBGE_BUILD_DIRECTX
726 	d3dColor = D3DCOLOR_RGBA(int(r*255), int(g*255), int(b*255), int(a*255));
727 #endif
728 }
729 
bindTexture(int stage,unsigned int handle)730 void Core::bindTexture(int stage, unsigned int handle)
731 {
732 #ifdef BBGE_BUILD_DIRECTX
733 	getD3DDevice()->SetTexture(stage, (IDirect3DBaseTexture9*)handle);
734 #endif
735 #ifdef BBGE_BUILD_OPENGL
736 	//glBindTexture(GL_TEXTURE_2D, handle);
737 #endif
738 }
739 
translateMatrixStack(float x,float y,float z)740 void Core::translateMatrixStack(float x, float y, float z)
741 {
742 #ifdef BBGE_BUILD_OPENGL
743 	glTranslatef(x, y, z);
744 #endif
745 #ifdef BBGE_BUILD_DIRECTX
746 	/*
747 	D3DXMATRIX matTranslation;
748 	D3DXMatrixTranslation (&matTranslation, x, y, 0);
749 	*/
750 	/*
751 	float usex, usey;
752     usex = x - (float)core->getWindowWidth() / 2;
753     usey = -y + (float)core->getWindowHeight() / 2;
754 	*/
755 	//core->getD3DMatrixStack()->MultMatrixLocal(&matTranslation);
756 	core->getD3DMatrixStack()->TranslateLocal(x, y, z);
757 #endif
758 }
759 
scaleMatrixStack(float x,float y,float z)760 void Core::scaleMatrixStack(float x, float y, float z)
761 {
762 #ifdef BBGE_BUILD_OPENGL
763 	glScalef(x, y, z);
764 #endif
765 #ifdef BBGE_BUILD_DIRECTX
766 	if (x != 1 || y != 1)
767 		core->getD3DMatrixStack()->ScaleLocal(x, y, 1);
768 #endif
769 }
770 
rotateMatrixStack(float x,float y,float z)771 void Core::rotateMatrixStack(float x, float y, float z)
772 {
773 #ifdef BBGE_BUILD_OPENGL
774 	glRotatef(0, 0, 1, z);
775 #endif
776 #ifdef BBGE_BUILD_DIRECTX
777 	if (z != 0)
778 	{
779 		D3DXVECTOR3 axis(0,0,1);
780 		core->getD3DMatrixStack()->RotateAxisLocal(&axis,D3DXToRadian(z));
781 	}
782 #endif
783 }
784 
applyMatrixStackToWorld()785 void Core::applyMatrixStackToWorld()
786 {
787 #ifdef BBGE_BUILD_DIRECTX
788 	g_pd3dDevice->SetTransform(D3DTS_WORLD, core->getD3DMatrixStack()->GetTop());
789 #endif
790 }
791 
rotateMatrixStack(float z)792 void Core::rotateMatrixStack(float z)
793 {
794 #ifdef BBGE_BUILD_OPENGL
795 	glRotatef(0, 0, 1, z);
796 #endif
797 #ifdef BBGE_BUILD_DIRECTX
798 	//core->getD3DMatrixStack()->RotateAxis(0, 0, z);
799 	/*
800 	D3DXVECTOR3 axis(0,0,1);
801 	float angle = D3DXToRadian(z);
802 	if (angle == D3DX_PI)
803 		angle += 0.001f;
804 	core->getD3DMatrixStack()->RotateAxisLocal(&axis,angle);
805 	*/
806 	if (z != 0)
807 	{
808 		D3DXMATRIX mat;
809 		D3DXMatrixRotationZ(&mat,D3DXToRadian(z));
810 		core->getD3DMatrixStack()->MultMatrixLocal(&mat);
811 	}
812 #endif
813 }
814 
getShiftState()815 bool Core::getShiftState()
816 {
817 	return getKeyState(KEY_LSHIFT) || getKeyState(KEY_RSHIFT);
818 }
819 
getAltState()820 bool Core::getAltState()
821 {
822 	return getKeyState(KEY_LALT) || getKeyState(KEY_RALT);
823 }
824 
getCtrlState()825 bool Core::getCtrlState()
826 {
827 	return getKeyState(KEY_LCONTROL) || getKeyState(KEY_RCONTROL);
828 }
829 
getMetaState()830 bool Core::getMetaState()
831 {
832 	return getKeyState(KEY_LMETA) || getKeyState(KEY_RMETA);
833 }
834 
errorLog(const std::string & s)835 void Core::errorLog(const std::string &s)
836 {
837 	messageBox("Error!", s);
838 	debugLog(s);
839 }
840 
messageBox(const std::string & title,const std::string & msg)841 void Core::messageBox(const std::string &title, const std::string &msg)
842 {
843 	::messageBox(title, msg);
844 }
845 
debugLog(const std::string & s)846 void Core::debugLog(const std::string &s)
847 {
848 	if (debugLogActive)
849 	{
850 		_logOut << s << std::endl;
851 	}
852 #ifdef _DEBUG
853 	std::cout << s << std::endl;
854 #endif
855 }
856 
857 #ifdef BBGE_BUILD_WINDOWS
checkWritable(const std::string & path,bool warn,bool critical)858 static bool checkWritable(const std::string& path, bool warn, bool critical)
859 {
860 	bool writeable = false;
861 	std::string f = path + "/~chk_wrt.tmp";
862 	FILE *fh = fopen(f.c_str(), "w");
863 	if(fh)
864 	{
865 		writeable = fwrite("abcdef", 5, 1, fh) == 1;
866 		fclose(fh);
867 		unlink(f.c_str());
868 	}
869 	if(!writeable)
870 	{
871 		if(warn)
872 		{
873 			std::ostringstream os;
874 			os << "Trying to use \"" << path << "\" as user data path, but it is not writeable.\n"
875 				<< "Please make sure the game is allowed to write to that directory.\n"
876 				<< "You can move the game to another location and run it there,\n"
877 				<< "or try running it as administrator, that may help as well.";
878 			if(critical)
879 				os << "\n\nWill now exit.";
880 			MessageBoxA(NULL, os.str().c_str(), "Need to write but can't!", MB_OK | MB_ICONERROR);
881 		}
882 		if(critical)
883 			exit(1);
884 	}
885 	return writeable;
886 }
887 #endif
888 
889 
890 const float SORT_DELAY = 10;
Core(const std::string & filesystem,const std::string & extraDataDir,int numRenderLayers,const std::string & appName,int particleSize,std::string userDataSubFolder)891 Core::Core(const std::string &filesystem, const std::string& extraDataDir, int numRenderLayers, const std::string &appName, int particleSize, std::string userDataSubFolder)
892 : ActionMapper(), StateManager(), appName(appName)
893 {
894 	sound = NULL;
895 	screenCapScale = Vector(1,1,1);
896 	timeUpdateType = TIMEUPDATE_DYNAMIC;
897 	_extraDataDir = extraDataDir;
898 
899 	fixedFPS = 60;
900 
901 	if (userDataSubFolder.empty())
902 		userDataSubFolder = appName;
903 
904 #if defined(BBGE_BUILD_UNIX)
905 	const char *envr = getenv("HOME");
906 	if (envr == NULL)
907         envr = ".";  // oh well.
908 	const std::string home(envr);
909 
910 	createDir(home);  // just in case.
911 
912 	// "/home/icculus/.Aquaria" or something. Spaces are okay.
913 	#ifdef BBGE_BUILD_MACOSX
914 	const std::string prefix("Library/Application Support/");
915 	#else
916 	const std::string prefix(".");
917 	#endif
918 
919 	userDataFolder = home + "/" + prefix + userDataSubFolder;
920 	createDir(userDataFolder);
921 	debugLogPath = userDataFolder + "/";
922 	createDir(userDataFolder + "/screenshots");
923 	std::string prefpath(getPreferencesFolder());
924 	createDir(prefpath);
925 
926 #else
927 	debugLogPath = "";
928 	userDataFolder = ".";
929 
930 	#ifdef BBGE_BUILD_WINDOWS
931 	{
932 		if(checkWritable(userDataFolder, true, true)) // working dir?
933 		{
934 			puts("Using working directory as user directory.");
935 		}
936 		// TODO: we may want to use a user-specific path under windows as well
937 		// if the code below gets actually used, pass 2x false to checkWritable() above.
938 		// not sure about this right now -- FG
939 		/*else
940 		{
941 			puts("Working directory is not writable...");
942 			char pathbuf[MAX_PATH];
943 			if(SHGetSpecialFolderPathA(NULL, &pathbuf[0], CSIDL_APPDATA, 0))
944 			{
945 				userDataFolder = pathbuf;
946 				userDataFolder += '/';
947 				userDataFolder += userDataSubFolder;
948 				for(uint32 i = 0; i < userDataFolder.length(); ++i)
949 					if(userDataFolder[i] == '\\')
950 						userDataFolder[i] = '/';
951 				debugLogPath = userDataFolder + "/";
952 				puts(("Using \"" + userDataFolder + "\" as user directory.").c_str());
953 				createDir(userDataFolder);
954 				checkWritable(userDataFolder, true, true);
955 			}
956 			else
957 				puts("Failed to retrieve appdata path, using working dir."); // too bad, but can't do anything about it
958 		}
959 		*/
960 	}
961 	#endif
962 #endif
963 
964 	_logOut.open((debugLogPath + "debug.log").c_str());
965 	debugLogActive = true;
966 
967 	debugLogTextures = true;
968 
969 	grabInputOnReentry = -1;
970 
971 	srand(time(NULL));
972 	old_dt = 0;
973 	current_dt = 0;
974 
975 	aspectX = 4;
976 	aspectY = 3;
977 
978 	virtualOffX = virtualOffY = 0;
979 	vw2 = 0;
980 	vh2 = 0;
981 
982 	viewOffX = viewOffY = 0;
983 
984 	/*
985 	aspectX = 1440;  //4.0f;
986 	aspectY = 900;   //3.0f;
987 	*/
988 
989 	particleManager = new ParticleManager(particleSize);
990 #ifdef BBGE_BUILD_SDL
991 	nowTicks = thenTicks = 0;
992 #endif
993 	_hasFocus = false;
994 	lib_graphics = lib_sound = lib_input = false;
995 	clearColor = Vector(0,0,0);
996 	updateCursorFromMouse = true;
997 	mouseConstraint = false;
998 	mouseCircle = 0;
999 	overrideStartLayer = 0;
1000 	overrideEndLayer = 0;
1001 	coreVerboseDebug = false;
1002 	frameOutputMode = false;
1003 	updateMouse = true;
1004 	particlesPaused = false;
1005 	joystickAsMouse = false;
1006 	currentLayerPass = 0;
1007 	flipMouseButtons = 0;
1008 	joystickOverrideMouse = false;
1009 	joystickEnabled = false;
1010 	doScreenshot = false;
1011 	baseCullRadius = 1;
1012 	width = height = 0;
1013 	afterEffectManagerLayer = 0;
1014 	renderObjectLayers.resize(1);
1015 	invGlobalScale = 1.0;
1016 	invGlobalScaleSqr = 1.0;
1017 	renderObjectCount = 0;
1018 	avgFPS.resize(1);
1019 	minimized = false;
1020 	sortFlag = true;
1021 	sortTimer = SORT_DELAY;
1022 	numSavedScreenshots = 0;
1023 	shuttingDown = false;
1024 	clearedGarbageFlag = false;
1025 	nestedMains = 0;
1026 	afterEffectManager = 0;
1027 	loopDone = false;
1028 	core = this;
1029 
1030 	#ifdef BBGE_BUILD_WINDOWS
1031 		hRC = 0;
1032 		hDC = 0;
1033 		hWnd = 0;
1034 	#endif
1035 
1036 	for (int i = 0; i < KEY_MAXARRAY; i++)
1037 	{
1038 		keys[i] = 0;
1039 	}
1040 
1041 	aspect = (aspectX/aspectY);//320.0f/240.0f;
1042 	//1.3333334f;
1043 
1044 	globalResolutionScale = globalScale = Vector(1,1,1);
1045 
1046 	initRenderObjectLayers(numRenderLayers);
1047 
1048 	initPlatform(filesystem);
1049 }
1050 
initPlatform(const std::string & filesystem)1051 void Core::initPlatform(const std::string &filesystem)
1052 {
1053 #if defined(BBGE_BUILD_MACOSX) && !defined(BBGE_BUILD_MACOSX_NOBUNDLEPATH)
1054 	// FIXME: filesystem not handled
1055 	CFBundleRef mainBundle = CFBundleGetMainBundle();
1056 	//CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
1057 	CFURLRef resourcesURL = CFBundleCopyBundleURL(mainBundle);
1058 	char path[PATH_MAX];
1059 	if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX))
1060 	{
1061 		// error!
1062 		debugLog("CFURLGetFileSystemRepresentation");
1063 	}
1064 	CFRelease(resourcesURL);
1065 	debugLog(path);
1066 	chdir(path);
1067 #elif defined(BBGE_BUILD_UNIX)
1068 	if (!filesystem.empty())
1069 	{
1070 		if (chdir(filesystem.c_str()) == 0)
1071 			return;
1072 		else
1073 			debugLog("Failed to chdir to filesystem path " + filesystem);
1074 	}
1075 #ifdef BBGE_DATA_PREFIX
1076 	if (chdir(BBGE_DATA_PREFIX) == 0 && chdir(appName.c_str()) == 0)
1077 		return;
1078 	else
1079 		debugLog("Failed to chdir to filesystem path " BBGE_DATA_PREFIX + appName);
1080 #endif
1081 	char path[PATH_MAX];
1082 	// always a symlink to this process's binary, on modern Linux systems.
1083 	const ssize_t rc = readlink("/proc/self/exe", path, sizeof (path));
1084 	if ( (rc == -1) || (rc >= sizeof (path)) )
1085 	{
1086 		// error!
1087 		debugLog("readlink");
1088 	}
1089 	else
1090 	{
1091 		path[rc] = '\0';
1092 		char *ptr = strrchr(path, '/');
1093 		if (ptr != NULL)
1094 		{
1095 			*ptr = '\0';
1096 			debugLog(path);
1097 			if (chdir(path) != 0)
1098 				debugLog("Failed to chdir to executable path" + std::string(path));
1099 		}
1100 	}
1101 #endif
1102 #ifdef BBGE_BUILD_WINDOWS
1103 	if(filesystem.length())
1104 	{
1105 		if(_chdir(filesystem.c_str()) != 0)
1106 		{
1107 			debugLog("chdir failed: " + filesystem);
1108 		}
1109 	}
1110 	// FIXME: filesystem not handled
1111 #endif
1112 }
1113 
getPreferencesFolder()1114 std::string Core::getPreferencesFolder()
1115 {
1116 #ifdef BBGE_BUILD_UNIX
1117 	return userDataFolder + "/preferences";
1118 #endif
1119 #ifdef BBGE_BUILD_WINDOWS
1120 	return "";
1121 #endif
1122 }
1123 
getUserDataFolder()1124 std::string Core::getUserDataFolder()
1125 {
1126 	return userDataFolder;
1127 }
1128 
1129 #if BBGE_BUILD_UNIX
1130 #include <sys/types.h>
1131 #include <pwd.h>
1132 #include <fcntl.h>
1133 #include <unistd.h>
1134 #include <dirent.h>
1135 
1136 // based on code I wrote for PhysicsFS: http://icculus.org/physfs/
1137 //  the zlib license on physfs allows this cut-and-pasting.
locateOneElement(char * buf)1138 static int locateOneElement(char *buf)
1139 {
1140 	char *ptr;
1141 	DIR *dirp;
1142 
1143 	if (access(buf, F_OK) == 0)
1144 		return(1);  // quick rejection: exists in current case.
1145 
1146 	ptr = strrchr(buf, '/');  // find entry at end of path.
1147 	if (ptr == NULL)
1148 	{
1149 		dirp = opendir(".");
1150 		ptr = buf;
1151 	}
1152 	else
1153 	{
1154 		*ptr = '\0';
1155 		dirp = opendir(buf);
1156 		*ptr = '/';
1157 		ptr++;  // point past dirsep to entry itself.
1158 	}
1159 
1160 	struct dirent *dent;
1161 	while ((dent = readdir(dirp)) != NULL)
1162 	{
1163 		if (strcasecmp(dent->d_name, ptr) == 0)
1164 		{
1165 			strcpy(ptr, dent->d_name); // found a match. Overwrite with this case.
1166 			closedir(dirp);
1167 			return(1);
1168 		}
1169 	}
1170 
1171 	// no match at all...
1172 	closedir(dirp);
1173 	return(0);
1174 }
1175 #endif
1176 
1177 
adjustFilenameCase(const char * _buf)1178 std::string Core::adjustFilenameCase(const char *_buf)
1179 {
1180 #ifdef BBGE_BUILD_UNIX  // any case is fine if not Linux.
1181 	int rc = 1;
1182 	char *buf = (char *) alloca(strlen(_buf) + 1);
1183 	strcpy(buf, _buf);
1184 
1185 	char *ptr = buf;
1186 	while ((ptr = strchr(ptr + 1, '/')) != 0)
1187 	{
1188 		*ptr = '\0';  // block this path section off
1189 		rc = locateOneElement(buf);
1190 		*ptr = '/'; // restore path separator
1191 		if (!rc)
1192 			break;  // missing element in path.
1193 	}
1194 
1195 	// check final element...
1196 	if (rc)
1197 		rc = locateOneElement(buf);
1198 
1199 	#if 0
1200 	if (strcmp(_buf, buf) != 0)
1201 	{
1202 		fprintf(stderr, "Corrected filename case: '%s' => '%s (%s)'\n",
1203 		        _buf, buf, rc ? "found" : "not found");
1204 	}
1205 	#endif
1206 
1207 	return std::string(buf);
1208 #else
1209 	return std::string(_buf);
1210 #endif
1211 }
1212 
1213 
~Core()1214 Core::~Core()
1215 {
1216 	if (particleManager)
1217 	{
1218 		delete particleManager;
1219 	}
1220 	if (sound)
1221 	{
1222 		delete sound;
1223 		sound = 0;
1224 	}
1225 	debugLog("~Core()");
1226 	_logOut.close();
1227 	core = 0;
1228 }
1229 
hasFocus()1230 bool Core::hasFocus()
1231 {
1232 	return _hasFocus;
1233 }
1234 
setInputGrab(bool on)1235 void Core::setInputGrab(bool on)
1236 {
1237 	if (isWindowFocus())
1238 	{
1239 #ifdef BBGE_BUILD_SDL
1240 		#ifdef BBGE_BUILD_SDL2
1241 		SDL_SetWindowGrab(gScreen, on ? SDL_TRUE : SDL_FALSE);
1242 		#else
1243 		SDL_WM_GrabInput(on?SDL_GRAB_ON:SDL_GRAB_OFF);
1244 		#endif
1245 #endif
1246 	}
1247 }
1248 
setReentryInputGrab(int on)1249 void Core::setReentryInputGrab(int on)
1250 {
1251 	if (grabInputOnReentry == -1)
1252 	{
1253 		setInputGrab(on);
1254 	}
1255 	else
1256 	{
1257 		setInputGrab(grabInputOnReentry);
1258 	}
1259 }
1260 
isFullscreen()1261 bool Core::isFullscreen()
1262 {
1263 	return _fullscreen;
1264 }
1265 
isShuttingDown()1266 bool Core::isShuttingDown()
1267 {
1268 	return shuttingDown;
1269 }
1270 
init()1271 void Core::init()
1272 {
1273 	setupFileAccess();
1274 
1275 	flags.set(CF_CLEARBUFFERS);
1276 	quitNestedMainFlag = false;
1277 #ifdef BBGE_BUILD_GLFW
1278 	if (!glfwInit())
1279 		exit(0);
1280 #endif
1281 #ifdef BBGE_BUILD_SDL
1282 #ifndef BBGE_BUILD_SDL2
1283 	// Disable relative mouse motion at the edges of the screen, which breaks
1284 	// mouse control for absolute input devices like Wacom tablets and touchscreens.
1285 	SDL_putenv((char *) "SDL_MOUSE_RELATIVE=0");
1286 #endif
1287 
1288 	if((SDL_Init(0))==-1)
1289 	{
1290 		exit_error("Failed to init SDL");
1291 	}
1292 
1293 #endif
1294 	/*
1295 #ifdef BBGE_BUILD_DIRECTX
1296 	if (!glfwInit())
1297 		exit(0);
1298 #endif
1299 		*/
1300 	loopDone = false;
1301 	clearedGarbageFlag = false;
1302 
1303 	initInputCodeMap();
1304 
1305 	initLocalization();
1306 
1307 	//glfwSetWindowSizeCallback(lockWindowSize);
1308 }
1309 
initRenderObjectLayers(int num)1310 void Core::initRenderObjectLayers(int num)
1311 {
1312 	renderObjectLayers.resize(num);
1313 	renderObjectLayerOrder.resize(num);
1314 	for (int i = 0; i < num; i++)
1315 	{
1316 		renderObjectLayerOrder[i] = i;
1317 	}
1318 }
1319 
initSoundLibrary(const std::string & defaultDevice)1320 bool Core::initSoundLibrary(const std::string &defaultDevice)
1321 {
1322 	debugLog("Creating SoundManager");
1323 	sound = new SoundManager(defaultDevice);
1324 	debugLog("Done");
1325 	return sound != 0;
1326 }
1327 
getGameCursorPosition()1328 Vector Core::getGameCursorPosition()
1329 {
1330 	return getGamePosition(mouse.position);
1331 }
1332 
getGamePosition(const Vector & v)1333 Vector Core::getGamePosition(const Vector &v)
1334 {
1335 	return cameraPos + (v * invGlobalScale);
1336 }
1337 
getMouseButtonState(int m)1338 bool Core::getMouseButtonState(int m)
1339 {
1340 #ifdef BBGE_BUILD_SDL
1341 	int mcode=m;
1342 
1343 	switch(m)
1344 	{
1345 	case 0: mcode=1; break;
1346 	case 1: mcode=3; break;
1347 	case 2: mcode=2; break;
1348 	}
1349 
1350 	Uint8 mousestate = SDL_GetMouseState(0,0);
1351 
1352 	return mousestate & SDL_BUTTON(mcode);
1353 #endif
1354 	return false;
1355 }
1356 
getKeyState(int k)1357 bool Core::getKeyState(int k)
1358 {
1359 #ifdef BBGE_BUILD_GLFW
1360 	return glfwGetKey(k)==GLFW_PRESS;
1361 #endif
1362 
1363 #ifdef BBGE_BUILD_SDL
1364 	if (k >= KEY_MAXARRAY || k < 0)
1365 	{
1366 		return 0;
1367 	}
1368 	return keys[k];
1369 #endif
1370 
1371 #ifdef BBGE_BUILD_WINDOWS
1372 	if (k >= KEY_MAXARRAY || k < 0)
1373 	{
1374 		return 0;
1375 	}
1376 	return keys[k];
1377 #endif
1378 
1379 	return 0;
1380 }
1381 
1382 //#ifdef BBGE_BUILD_DIRECTX
1383 
1384 //float sensitivity = 1.0;
1385 
1386 Vector joychange;
1387 Vector lastjoy;
readJoystickData()1388 void readJoystickData()
1389 {
1390 	/*
1391 	if (core->joystickEnabled && core->numJoysticks > 0)
1392 	{
1393 		//DIJOYSTATE2 js;
1394 		core->joysticks[0]->poll(&core->joystate);
1395 
1396 		Vector joy = Vector(core->joystate.lX, core->joystate.lY);
1397 		joychange = joy-lastjoy;
1398 		lastjoy = joy;
1399 		core->joystickPosition = Vector(core->joystate.lX - (65536/2), core->joystate.lY - (65536/2));
1400 		core->joystickPosition /= (65536/2);
1401 
1402 		// HACK: super hacky!!
1403 		core->mouse.buttons.left = (core->joystate.rgbButtons[0] & 0x80) ? Buttons::DOWN : Buttons::UP;
1404 		core->mouse.buttons.right = (core->joystate.rgbButtons[1] & 0x80) ? Buttons::DOWN : Buttons::UP;
1405 	}
1406 	*/
1407 }
1408 
readMouseData()1409 void readMouseData()
1410 {
1411 #if defined(BBGE_BUILD_WINDOWS) && !defined(BBGE_BUILD_SDL)
1412 	if (!core->updateMouse) return;
1413     HRESULT       hr;
1414     DIMOUSESTATE2 dims2;      // DirectInput Mouse state structure
1415 
1416     if( NULL == g_pMouse )
1417         return;
1418 
1419     // Get the input's device state, and put the state in dims
1420     ZeroMemory( &dims2, sizeof(dims2) );
1421     hr = g_pMouse->GetDeviceState( sizeof(DIMOUSESTATE2), &dims2 );
1422     if( FAILED(hr) )
1423     {
1424         // DirectInput may be telling us that the input stream has been
1425         // interrupted.  We aren't tracking any state between polls, so
1426         // we don't have any special reset that needs to be done.
1427         // We just re-acquire and try again.
1428 
1429         // If input is lost then acquire and keep trying
1430         hr = g_pMouse->Acquire();
1431         while( hr == DIERR_INPUTLOST )
1432             hr = g_pMouse->Acquire();
1433 
1434         // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
1435         // may occur when the app is minimized or in the process of
1436         // switching, so just try again later
1437         return;
1438     }
1439 
1440 	//float sensitivity = float(core->width) / float(core->getVirtualWidth());
1441 	float sensitivity = 1;
1442 	core->mouse.position.x += dims2.lX*sensitivity;
1443 	core->mouse.position.y += dims2.lY*sensitivity;
1444 	core->mouse.position.z += dims2.lZ;
1445 	core->mouse.change.x = dims2.lX*sensitivity;
1446 	core->mouse.change.y = dims2.lY*sensitivity;
1447 	core->mouse.change.z = dims2.lZ;
1448 	core->mouse.scrollWheelChange = dims2.lZ;
1449 	if (!core->flipMouseButtons)
1450 	{
1451 		core->mouse.buttons.left = (dims2.rgbButtons[0] & 0x80) ? DOWN : UP;
1452 		core->mouse.buttons.right = (dims2.rgbButtons[1] & 0x80) ? DOWN : UP;
1453 	}
1454 	else
1455 	{
1456 		core->mouse.buttons.left = (dims2.rgbButtons[1] & 0x80) ? DOWN : UP;
1457 		core->mouse.buttons.right = (dims2.rgbButtons[0] & 0x80) ? DOWN : UP;
1458 	}
1459 	core->mouse.buttons.middle = (dims2.rgbButtons[2] & 0x80) ? DOWN : UP;
1460 
1461 #elif defined(BBGE_BUILD_SDL)
1462 	//core->mouse.position += dMouse;
1463 #elif defined(BBGE_BUILD_GLFW)
1464 	//HACK: may not always want 800x600 virtual
1465 	/*
1466 	static int lastx=400, lasty=300;
1467 	int x, y;
1468 	glfwGetMousePos(&x,&y);
1469 	int mickeyx,mickeyy;
1470 	mickeyx = x - lastx;
1471 	mickeyy = y - lasty;
1472 	lastx = x;
1473 	lasty = y;
1474 	core->mouse.position.x += mickeyx;
1475 	core->mouse.position.y += mickeyy;
1476 	*/
1477 
1478 	int x,y;
1479 	glfwGetMousePos(&x,&y);
1480 	core->mouse.position = Vector(x, y);
1481 
1482 
1483 /*
1484 	int mid_x = core->width / 2;
1485 	int mid_y = core->height / 2;
1486 	int dx=0,dy=0;
1487 	int x,y;
1488 	glfwGetMousePos(&x, &y);
1489 	// Don't do anything if mouse hasn't moved
1490 	if (x == mid_x && y == mid_y)
1491 	{
1492 	}
1493 	else
1494 	{
1495 		dx = x - mid_x;
1496 		dy = y - mid_y;
1497 	}
1498 
1499 	std::ostringstream os;
1500 	os << "d(" << dx << ", " << dy <<")";
1501 	debugLog(os.str());
1502 
1503 	core->mouse.position += Vector(dx, dy);
1504 
1505 
1506 	// Now move the mouse back to the middle, because
1507 	// we don't care where it really is, just how much
1508 	// it moves.
1509 	glfwSetMousePos(mid_x, mid_y);
1510 	*/
1511 
1512 
1513 
1514 	core->mouse.buttons.left = glfwGetMouseButton(GLFW_MOUSE_BUTTON_LEFT) ? DOWN : UP;
1515 	core->mouse.buttons.right = glfwGetMouseButton(GLFW_MOUSE_BUTTON_RIGHT) ? DOWN : UP;
1516 	core->mouse.buttons.middle = glfwGetMouseButton(GLFW_MOUSE_BUTTON_MIDDLE) ? DOWN : UP;
1517 	core->mouse.scrollWheel = glfwGetMouseWheel();
1518 #endif
1519 }
1520 
readKeyData()1521 void readKeyData()
1522 {
1523 
1524 #if defined(BBGE_BUILD_WINDOWS) && !defined(BBGE_BUILD_SDL)
1525 	if( NULL == g_pKeyboard )
1526 		return;
1527 	HRESULT hr;
1528 	BYTE    diks[256];
1529     // Get the input's device state, and put the state in dims
1530     ZeroMemory( diks, sizeof(diks) );
1531     hr = g_pKeyboard->GetDeviceState( sizeof(diks), diks );
1532     if( FAILED(hr) )
1533     {
1534         // DirectInput may be telling us that the input stream has been
1535         // interrupted.  We aren't tracking any state between polls, so
1536         // we don't have any special reset that needs to be done.
1537         // We just re-acquire and try again.
1538 
1539         // If input is lost then acquire and keep trying
1540         hr = g_pKeyboard->Acquire();
1541         while( hr == DIERR_INPUTLOST )
1542             hr = g_pKeyboard->Acquire();
1543 
1544         // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
1545         // may occur when the app is minimized or in the process of
1546         // switching, so just try again later
1547         return;
1548     }
1549 
1550     // Make a string of the index values of the keys that are down
1551     for(int i = 0; i < 256; i++ )
1552     {
1553         core->keys[i] = ( diks[i] & 0x80 );
1554     }
1555 #endif
1556 }
1557 //#endif
1558 
1559 
initJoystickLibrary(int numSticks)1560 bool Core::initJoystickLibrary(int numSticks)
1561 {
1562 	//joystickEnabled = false;
1563 #ifdef BBGE_BUILD_SDL
1564 #ifdef BBGE_BUILD_SDL2
1565 	SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER);
1566 #else
1567 	SDL_InitSubSystem(SDL_INIT_JOYSTICK);
1568 #endif
1569 #endif
1570 
1571 	if (numSticks > 0)
1572 		joystick.init(0);
1573 
1574 	joystickEnabled = true;
1575 	/*
1576 	numJoysticks = Joystick::deviceCount();
1577 	std::ostringstream os;
1578 	os << "Found " << numJoysticks << " joysticks";
1579 	debugLog(os.str());
1580 	if (numJoysticks > 0)
1581 	{
1582 		if (numJoysticks > 4)
1583 			numJoysticks = 4;
1584 
1585 		// HACK: memory leak... add code to clean this up!
1586 		for (int i = 0; i < numJoysticks; i++) {
1587 			joysticks[i] = new Joystick(i);
1588 			joysticks[i]->open();
1589 
1590 			// Print the name of the joystick.
1591 			char name[MAX_PATH];
1592 			joysticks[i]->deviceName(name);
1593 			std::ostringstream os;
1594 			os << "   Joystick " << i << ": " << name;
1595 			debugLog(os.str());
1596 		}
1597 		joystickEnabled = true;
1598 		return true;
1599 	}
1600 	*/
1601 
1602 	return true;
1603 }
1604 
initInputLibrary()1605 bool Core::initInputLibrary()
1606 {
1607 	core->mouse.position = Vector(getWindowWidth()/2, getWindowHeight()/2);
1608 
1609 #ifdef BBGE_BUILD_GFLW
1610 	glfwDisable(GLFW_MOUSE_CURSOR);
1611 	//glfwEnable( GLFW_SYSTEM_KEYS );
1612 #endif
1613 	for (int i = 0; i < KEY_MAXARRAY; i++)
1614 	{
1615 		keys[i] = 0;
1616 	}
1617 #if defined(BBGE_BUILD_WINDOWS) && !defined(BBGE_BUILD_SDL)
1618 
1619 	HRESULT hr;
1620     BOOL    bExclusive = true;
1621     BOOL    bForeground = true;
1622     //BOOL    bImmediate = true;
1623     BOOL    bDisableWindowsKey = false;
1624     DWORD   dwCoopFlags;
1625 
1626     if( bExclusive )
1627         dwCoopFlags = DISCL_EXCLUSIVE;
1628     else
1629         dwCoopFlags = DISCL_NONEXCLUSIVE;
1630 
1631     if( bForeground )
1632         dwCoopFlags |= DISCL_FOREGROUND;
1633     else
1634         dwCoopFlags |= DISCL_BACKGROUND;
1635 
1636     // Disabling the windows key is only allowed only if we are in foreground nonexclusive
1637     if( bDisableWindowsKey && !bExclusive && bForeground )
1638         dwCoopFlags |= DISCL_NOWINKEY;
1639 
1640     // Create a DInput object
1641     if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION,
1642                                          IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) )
1643         return false;
1644 
1645     // Obtain an interface to the system keyboard device.
1646     if( FAILED( hr = g_pDI->CreateDevice( GUID_SysKeyboard, &g_pKeyboard, NULL ) ) )
1647         return false;
1648 
1649     // Set the data format to "Keyboard format" - a predefined data format
1650     //
1651     // A data format specifies which controls on a device we
1652     // are interested in, and how they should be reported.
1653     //
1654     // This tells DirectInput that we will be passing an array
1655     // of 256 bytes to IDirectInputDevice::GetDeviceState.
1656     if( FAILED( hr = g_pKeyboard->SetDataFormat( &c_dfDIKeyboard ) ) )
1657         return false;
1658 
1659     // Set the cooperativity level to let DirectInput know how
1660     // this device should interact with the system and with other
1661     // DirectInput applications.
1662     hr = g_pKeyboard->SetCooperativeLevel( this->hWnd, dwCoopFlags );
1663     if( hr == DIERR_UNSUPPORTED && !bForeground && bExclusive )
1664     {
1665 		debugLog("could not set cooperative level");
1666         //FreeDirectInput();
1667 		//errorLog ("failed to init input");
1668 		/*
1669         MessageBox( hDlg, _T("SetCooperativeLevel() returned DIERR_UNSUPPORTED.\n")
1670                           _T("For security reasons, background exclusive Keyboard\n")
1671                           _T("access is not allowed."), _T("Keyboard"), MB_OK );
1672 		*/
1673         //return false;;
1674     }
1675 
1676 	/*
1677     if( FAILED(hr) )
1678 	{
1679 		errorLog("failed to init input");
1680 		return false;
1681 	}
1682 	*/
1683 
1684 
1685     // Acquire the newly created device
1686     g_pKeyboard->Acquire();
1687 
1688 
1689 //#ifdef BBGE_BUILD_DIRECTX
1690 
1691 	if( FAILED( hr = g_pDI->CreateDevice( GUID_SysMouse, &g_pMouse, NULL ) ) )
1692         return false;
1693 
1694     // Set the data format to "Mouse format" - a predefined data format
1695     //
1696     // A data format specifies which controls on a device we
1697     // are interested in, and how they should be reported.
1698     //
1699     // This tells DirectInput that we will be passing a
1700     // DIMOUSESTATE2 structure to IDirectInputDevice::GetDeviceState.
1701     if( FAILED( hr = g_pMouse->SetDataFormat( &c_dfDIMouse2 ) ) )
1702         return false;
1703 
1704     // Set the cooperativity level to let DirectInput know how
1705     // this device should interact with the system and with other
1706     // DirectInput applications.
1707     hr = g_pMouse->SetCooperativeLevel( this->hWnd, dwCoopFlags );
1708     if( hr == DIERR_UNSUPPORTED && !bForeground && bExclusive )
1709     {
1710         //FreeDirectInput();
1711 		//errorLog ("mouse failed");
1712 		debugLog("could not set cooperative level");
1713         //return false;
1714     }
1715 
1716 	/*
1717     if( FAILED(hr) )
1718 		return false;
1719 	*/
1720 
1721     // Acquire the newly created device
1722     g_pMouse->Acquire();
1723 
1724 #endif
1725 
1726 
1727 
1728 	// joystick init
1729 //#endif
1730 	return true;
1731 }
1732 
onUpdate(float dt)1733 void Core::onUpdate(float dt)
1734 {
1735 	if (minimized) return;
1736 	ActionMapper::onUpdate(dt);
1737 	StateManager::onUpdate(dt);
1738 
1739 
1740 	core->mouse.lastPosition = core->mouse.position;
1741 	core->mouse.lastScrollWheel = core->mouse.scrollWheel;
1742 
1743 	readKeyData();
1744 	readMouseData();
1745 	readJoystickData();
1746 	pollEvents();
1747 	joystick.update(dt);
1748 
1749 
1750 
1751 
1752 
1753 
1754 	/*
1755 	std::ostringstream os;
1756 	os << "x: " << joystate.lX << " y: " << joystate.lY;
1757 	os << " frx: " << joystate.lFRx << " fry: " << joystate.lFRy;
1758 	debugLog(os.str());
1759 	*/
1760 
1761 	/*
1762 	if (joystickOverrideMouse && !joychange.isZero())
1763 	{
1764 		Vector joy(joystate.lX, joystate.lY);
1765 		//core->mouse.position += joychange * 0.001f;
1766 		core->mouse.position = Vector(400,300) + ((joy * 600) / (65536/2))-300;
1767 	}
1768 	*/
1769 
1770 
1771 	/*
1772 
1773 	*/
1774 
1775 
1776 	/*
1777 	if (mouse.position.x < 0)
1778 		mouse.position.x = 0;
1779 	if (mouse.position.x > core->getVirtualWidth())
1780 		mouse.position.x = core->getVirtualWidth();
1781 	if (mouse.position.y < 0)
1782 		mouse.position.y = 0;
1783 	if (mouse.position.y > core->getVirtualHeight())
1784 		mouse.position.y = core->getVirtualHeight();
1785 	*/
1786 
1787 	onMouseInput();
1788 
1789 	/*
1790 #ifdef BBGE_BUILD_GLFW
1791 	glfwSetMousePos(mouse.position.x, mouse.position.y);
1792 #endif
1793 	*/
1794 #ifdef BBGE_BUILD_DIRECTX
1795 #endif
1796 	//core->mouse.change = core->mouse.position - core->mouse.lastPosition;
1797 
1798 	//core->mouse.scrollWheelChange = core->mouse.scrollWheel - core->mouse.lastScrollWheel;
1799 
1800 
1801 
1802 
1803 
1804 	//script.update(dt);
1805 
1806 	globalScale.update(dt);
1807 	core->globalScaleChanged();
1808 
1809 	if (afterEffectManager)
1810 	{
1811 		afterEffectManager->update(dt);
1812 	}
1813 
1814 	if (!sortFlag)
1815 	{
1816 		if (sortTimer>0)
1817 		{
1818 			sortTimer -= dt;
1819 			if (sortTimer <= 0)
1820 			{
1821 				sortTimer = SORT_DELAY;
1822 				sort();
1823 			}
1824 		}
1825 	}
1826 }
1827 
globalScaleChanged()1828 void Core::globalScaleChanged()
1829 {
1830 	invGlobalScale = 1.0f/globalScale.x;
1831 	invGlobalScaleSqr = invGlobalScale * invGlobalScale;
1832 }
1833 
getClearColor()1834 Vector Core::getClearColor()
1835 {
1836 	return clearColor;
1837 }
1838 
setClearColor(const Vector & c)1839 void Core::setClearColor(const Vector &c)
1840 {
1841 	clearColor = c;
1842 
1843 #ifdef BBGE_BUILD_OPENGL
1844 	glClearColor(c.x, c.y, c.z, 0.0);
1845 #endif
1846 
1847 #ifdef BBGE_BUILD_DIRECTX
1848 
1849 #endif
1850 }
1851 
setSDLGLAttributes()1852 void Core::setSDLGLAttributes()
1853 {
1854 	std::ostringstream os;
1855 	os << "setting vsync: " << _vsync;
1856 	debugLog(os.str());
1857 
1858 #ifdef BBGE_BUILD_SDL
1859 #ifndef BBGE_BUILD_SDL2
1860 	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, _vsync);
1861 #endif
1862 
1863 	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
1864 #endif
1865 }
1866 
1867 
1868 #ifdef GLAPIENTRY
1869 #undef GLAPIENTRY
1870 #endif
1871 
1872 #ifdef BBGE_BUILD_WINDOWS
1873 #define GLAPIENTRY APIENTRY
1874 #else
1875 #define GLAPIENTRY
1876 #endif
1877 
1878 unsigned int Core::dbg_numRenderCalls = 0;
1879 
1880 #ifdef BBGE_BUILD_OPENGL_DYNAMIC
1881 #define GL_FUNC(ret,fn,params,call,rt) \
1882     extern "C" { \
1883         static ret (GLAPIENTRY *p##fn) params = NULL; \
1884         ret GLAPIENTRY fn params { ++Core::dbg_numRenderCalls; rt p##fn call; } \
1885     }
1886 #include "OpenGLStubs.h"
1887 #undef GL_FUNC
1888 
lookup_glsym(const char * funcname,void ** func)1889 static bool lookup_glsym(const char *funcname, void **func)
1890 {
1891 	*func = SDL_GL_GetProcAddress(funcname);
1892 	if (*func == NULL)
1893 	{
1894 		std::ostringstream os;
1895 		os << "Failed to find OpenGL symbol \"" << funcname << "\"\n";
1896 		errorLog(os.str());
1897 		return false;
1898 	}
1899 	return true;
1900 }
1901 
lookup_all_glsyms(void)1902 static bool lookup_all_glsyms(void)
1903 {
1904 	bool retval = true;
1905 	#define GL_FUNC(ret,fn,params,call,rt) \
1906 		if (!lookup_glsym(#fn, (void **) &p##fn)) retval = false;
1907 	#include "OpenGLStubs.h"
1908 	#undef GL_FUNC
1909 	return retval;
1910 }
1911 #endif
1912 
1913 
initGraphicsLibrary(int width,int height,bool fullscreen,int vsync,int bpp,bool recreate)1914 bool Core::initGraphicsLibrary(int width, int height, bool fullscreen, int vsync, int bpp, bool recreate)
1915 {
1916 	static bool didOnce = false;
1917 
1918 	aspectX = width;
1919 	aspectY = height;
1920 
1921 	aspect = (aspectX/aspectY);
1922 
1923 
1924 
1925 	this->width = width;
1926 	this->height = height;
1927 	_vsync = vsync;
1928 	_fullscreen = fullscreen;
1929 	_bpp = bpp;
1930 
1931 	_hasFocus = false;
1932 
1933 #if defined(BBGE_BUILD_SDL)
1934 
1935 	//setenv("SDL_VIDEO_CENTERED", "1", 1);
1936 	//SDL_putenv("SDL_VIDEO_WINDOW_POS=400,300");
1937 
1938 #ifndef BBGE_BUILD_SDL2
1939 #if !defined(BBGE_BUILD_MACOSX)
1940 	// have to cast away constness, since SDL_putenv() might be #defined to
1941 	//  putenv(), which takes a (char *), and freaks out newer GCC releases
1942 	//  when you try to pass a (const!) string literal here...  --ryan.
1943 	SDL_putenv((char *) "SDL_VIDEO_CENTERED=1");
1944 #endif
1945 #endif
1946 	//SDL_putenv((char *) "LIBGL_DEBUG=verbose"); // temp, to track errors on linux with nouveau drivers.
1947 
1948 	if (recreate)
1949 	{
1950 		if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
1951 		{
1952 			exit_error(std::string("SDL Error: ") + std::string(SDL_GetError()));
1953 		}
1954 
1955 #if BBGE_BUILD_OPENGL_DYNAMIC
1956 		if (SDL_GL_LoadLibrary(NULL) == -1)
1957 		{
1958 			std::string err = std::string("SDL_GL_LoadLibrary Error: ") + std::string(SDL_GetError());
1959 			SDL_Quit();
1960 			exit_error(err);
1961 		}
1962 #endif
1963 	}
1964 
1965 	setWindowCaption(appName, appName);
1966 
1967 	initIcon();
1968     // Create window
1969 
1970 	setSDLGLAttributes();
1971 
1972 	//if (!didOnce)
1973 	{
1974 #ifdef BBGE_BUILD_SDL2
1975 		Uint32 flags = 0;
1976 		flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
1977 		if (fullscreen)
1978 			flags |= SDL_WINDOW_FULLSCREEN;
1979 		gScreen = SDL_CreateWindow(appName.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, flags);
1980 		if (gScreen == NULL)
1981 		{
1982 			std::ostringstream os;
1983 			os << "Couldn't set resolution [" << width << "x" << height << "]\n" << SDL_GetError();
1984 			errorLog(os.str());
1985 			SDL_Quit();
1986 			exit(0);
1987 		}
1988 		gGLctx = SDL_GL_CreateContext(gScreen);
1989 		if (gGLctx == NULL)
1990 		{
1991 			std::ostringstream os;
1992 			os << "Couldn't create OpenGL context!\n" << SDL_GetError();
1993 			errorLog(os.str());
1994 			SDL_Quit();
1995 			exit(0);
1996 		}
1997 #else
1998 		Uint32 flags = 0;
1999 		flags = SDL_OPENGL;
2000 		if (fullscreen)
2001 			flags |= SDL_FULLSCREEN;
2002 
2003 		gScreen = SDL_SetVideoMode(width, height, bpp, flags);
2004 		if (gScreen == NULL)
2005 		{
2006 			std::ostringstream os;
2007 			os << "Couldn't set resolution [" << width << "x" << height << "]\n" << SDL_GetError();
2008 			SDL_Quit();
2009 			exit_error(os.str());
2010 		}
2011 #endif
2012 
2013 #if BBGE_BUILD_OPENGL_DYNAMIC
2014 		if (!lookup_all_glsyms())
2015 		{
2016 			std::ostringstream os;
2017 			os << "Couldn't load OpenGL symbols we need\n";
2018 			SDL_Quit();
2019 			exit_error(os.str());
2020 		}
2021 #endif
2022 	}
2023 
2024 	setWindowCaption(appName, appName);
2025 
2026 #ifdef BBGE_BUILD_SDL2
2027 	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
2028 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2029 	SDL_GL_SwapWindow(gScreen);
2030 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2031 	SDL_GL_SwapWindow(gScreen);
2032 	if ((_vsync != 1) || (SDL_GL_SetSwapInterval(-1) == -1))
2033 		SDL_GL_SetSwapInterval(_vsync);
2034 	const char *name = SDL_GetCurrentVideoDriver();
2035 	SDL_SetWindowGrab(gScreen, SDL_TRUE);
2036 #else
2037 	SDL_WM_GrabInput(grabInputOnReentry==0 ? SDL_GRAB_OFF : SDL_GRAB_ON);
2038 	char name[256];
2039 	SDL_VideoDriverName((char*)name, 256);
2040 #endif
2041 
2042 	glViewport(0, 0, width, height);
2043 	glScissor(0, 0, width, height);
2044 
2045 	std::ostringstream os2;
2046 	os2 << "Video Driver Name [" << name << "]";
2047 	debugLog(os2.str());
2048 
2049 	SDL_ShowCursor(SDL_DISABLE);
2050 	SDL_PumpEvents();
2051 
2052 	for (int i = 0; i < KEY_MAXARRAY; i++)
2053 	{
2054 		keys[i] = 0;
2055 	}
2056 
2057 /*
2058 #ifdef BBGE_BUILD_WINDOWS
2059 	SDL_SysWMinfo wmInfo;
2060 	SDL_GetWMInfo(&wmInfo);
2061 	hWnd = wmInfo.window;
2062 #endif
2063 */
2064 
2065 #endif
2066 
2067 #if defined(BBGE_BUILD_OPENGL)
2068 	glEnable(GL_TEXTURE_2D);							// Enable Texture Mapping
2069 	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);				// Black Background
2070 	glClearDepth(1.0);								// Depth Buffer Setup
2071 	glDisable(GL_CULL_FACE);
2072 
2073 	//glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
2074 	//glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
2075 
2076 	glLoadIdentity();
2077 
2078 	glFinish();
2079 
2080 #ifdef BBGE_BUILD_GLFW
2081 	glfwSwapInterval(vsync);
2082 #endif
2083 
2084 #endif
2085 
2086 
2087 
2088 #if defined(BBGE_BUILD_DIRECTX)
2089 
2090 	// Initialize Direct3D
2091 	if( SUCCEEDED( InitD3D( this->hWnd, fullscreen, vsync ) ) )
2092 	{
2093 		// Show the window
2094 		ShowWindow( this->hWnd, SW_SHOWDEFAULT );
2095 		UpdateWindow( this->hWnd );
2096 		//initPipeline(PT_NORMAL);
2097 	}
2098 	else
2099 	{
2100 		errorLog("Could not init D3D");
2101 		exit(-1);
2102 	}
2103 
2104 #endif
2105 
2106 	setClearColor(clearColor);
2107 
2108 	clearBuffers();
2109 	showBuffer();
2110 
2111 	lib_graphics = true;
2112 
2113 	_hasFocus = true;
2114 
2115 	enumerateScreenModes();
2116 
2117 	if (!didOnce)
2118 		didOnce = true;
2119 
2120 	// init success
2121 	return true;
2122 }
2123 
enumerateScreenModes()2124 void Core::enumerateScreenModes()
2125 {
2126 	screenModes.clear();
2127 
2128 #ifdef BBGE_BUILD_SDL
2129 #ifdef BBGE_BUILD_SDL2
2130 	SDL_DisplayMode mode;
2131 	const int modecount = SDL_GetNumDisplayModes(0);
2132 	if(modecount == 0){
2133 		debugLog("No modes available!");
2134 		return;
2135 	}
2136 
2137 	for (int i = 0; i < modecount; i++) {
2138 		SDL_GetDisplayMode(0, i, &mode);
2139 		if (mode.w && mode.h && (mode.w > mode.h))
2140 		{
2141 			screenModes.push_back(ScreenMode(i, mode.w, mode.h, mode.refresh_rate));
2142 		}
2143 	}
2144 
2145 #else
2146 	SDL_Rect **modes;
2147 	int i;
2148 
2149 	modes=SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE);
2150 
2151 	if(modes == (SDL_Rect **)0){
2152 		debugLog("No modes available!");
2153 		return;
2154 	}
2155 
2156 	if(modes == (SDL_Rect **)-1){
2157 		debugLog("All resolutions available.");
2158 	}
2159 	else{
2160 		int c=0;
2161 		for(i=0;modes[i];++i){
2162 			c++;
2163 		}
2164 		for (i=c-1;i>=0;i--)
2165 		{
2166 			if (modes[i]->w > modes[i]->h)
2167 			{
2168 				screenModes.push_back(ScreenMode(i, modes[i]->w, modes[i]->h, 0));
2169 			}
2170 		}
2171 	}
2172 #endif
2173 #endif
2174 }
2175 
shutdownSoundLibrary()2176 void Core::shutdownSoundLibrary()
2177 {
2178 }
2179 
shutdownGraphicsLibrary(bool killVideo)2180 void Core::shutdownGraphicsLibrary(bool killVideo)
2181 {
2182 #ifdef BBGE_BUILD_SDL
2183 	glFinish();
2184 	if (killVideo) {
2185 		#ifdef BBGE_BUILD_SDL2
2186 		SDL_SetWindowGrab(gScreen, SDL_FALSE);
2187 		SDL_GL_MakeCurrent(gScreen, NULL);
2188 		SDL_GL_DeleteContext(gGLctx);
2189 		SDL_DestroyWindow(gScreen);
2190 		gGLctx = 0;
2191 		SDL_QuitSubSystem(SDL_INIT_VIDEO);
2192 		#else
2193 		SDL_QuitSubSystem(SDL_INIT_VIDEO);
2194 		SDL_WM_GrabInput(SDL_GRAB_OFF);
2195 		#endif
2196 
2197 		FrameBuffer::resetOpenGL();
2198 
2199 		gScreen = 0;
2200 
2201 #if BBGE_BUILD_OPENGL_DYNAMIC
2202 		// reset all the entry points to NULL, so we know exactly what happened
2203 		//  if we call a GL function after shutdown.
2204 		#define GL_FUNC(ret,fn,params,call,rt) \
2205 			p##fn = NULL;
2206 		#include "OpenGLStubs.h"
2207 		#undef GL_FUNC
2208 #endif
2209 	}
2210 #endif
2211 
2212 	_hasFocus = false;
2213 
2214 	lib_graphics = false;
2215 
2216 #ifdef BBGE_BUILD_WINDOWS
2217 	if (icon_windows)
2218 	{
2219 		::DestroyIcon(icon_windows);
2220 		icon_windows = 0;
2221 	}
2222 #endif
2223 
2224 }
2225 
quit()2226 void Core::quit()
2227 {
2228 	enqueueJumpState("STATE_QUIT");
2229 	//loopDone = true;
2230 	//popAllStates();
2231 }
2232 
applyState(const std::string & state)2233 void Core::applyState(const std::string &state)
2234 {
2235 	if (nocasecmp(state, "state_quit")==0)
2236 	{
2237 		loopDone = true;
2238 	}
2239 	StateManager::applyState(state);
2240 }
2241 
2242 #ifdef BBGE_BUILD_GLFW
windowResize(int w,int h)2243 void GLFWCALL windowResize(int w, int h)
2244 {
2245 	// this gets called on minimize + restore?
2246 	if (w == 0 && h == 0)
2247 	{
2248 		core->minimized = true;
2249 		return;
2250 	}
2251 	else
2252 		core->minimized = false;
2253 	if (w != core->width || h != core->height)
2254 		glfwSetWindowSize(core->width,core->height);
2255 }
2256 #endif
2257 
2258 
2259 #ifdef BBGE_BUILD_WINDOWS
centerWindow(HWND hwnd)2260 void centerWindow(HWND hwnd)
2261 {
2262     int x, y;
2263     HWND hwndDeskTop;
2264     RECT rcWnd, rcDeskTop;
2265     // Get a handle to the desktop window
2266     hwndDeskTop = ::GetDesktopWindow();
2267     // Get dimension of desktop in a rect
2268     ::GetWindowRect(hwndDeskTop, &rcDeskTop);
2269     // Get dimension of main window in a rect
2270     ::GetWindowRect(hwnd, &rcWnd);
2271     // Find center of desktop
2272 	x = (rcDeskTop.right - rcDeskTop.left)/2;
2273 	y = (rcDeskTop.bottom - rcDeskTop.top)/2;
2274     x -= (rcWnd.right - rcWnd.left)/2;
2275 	y -= (rcWnd.bottom - rcWnd.top)/2;
2276     // Set top and left to center main window on desktop
2277     ::SetWindowPos(hwnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
2278 //	::ShowWindow(hwnd, 1);
2279 }
2280 #endif
2281 
2282 /*
2283 void Core::adjustWindowPosition(int x, int y)
2284 {
2285 #ifdef BBGE_BUILD_WINDOWS
2286 	RECT rcWnd;
2287 	::GetWindowRect(hWnd, &rcWnd);
2288 	rcWnd.left += x;
2289 	rcWnd.top += y;
2290 	::SetWindowPos(hWnd, HWND_TOP, rcWnd.left, rcWnd.top, 0, 0, SWP_NOSIZE);
2291 #endif
2292 }
2293 */
2294 
createWindow(int width,int height,int bits,bool fullscreen,std::string windowTitle)2295 bool Core::createWindow(int width, int height, int bits, bool fullscreen, std::string windowTitle)
2296 {
2297 	this->width = width;
2298 	this->height = height;
2299 
2300 	redBits = greenBits = blueBits = alphaBits = 0;
2301 #ifdef BBGE_BUILD_SDL
2302 	return true;
2303 #endif
2304 
2305 #ifdef BBGE_BUILD_GLFW
2306 	int redbits, greenbits, bluebits, alphabits;
2307 	redbits = greenbits = bluebits = 8;
2308 	alphabits = 0;
2309 	switch(bits)
2310 	{
2311 	case 16:
2312 		redbits = 5;
2313 		greenbits = 6;
2314 		bluebits = 5;
2315 	break;
2316 	case 24:
2317 		redbits = 8;
2318 		bluebits = 8;
2319 		greenbits = 8;
2320 		alphabits = 0;
2321 	break;
2322 	case 32:
2323 		redbits = 8;
2324 		greenbits = 8;
2325 		bluebits = 8;
2326 		alphabits = 8;
2327 	break;
2328 	case 8:
2329 		redbits = 2;
2330 		greenbits = 2;
2331 		bluebits = 2;
2332 	break;
2333 	}
2334 	if (glfwOpenWindow(width, height, redbits, greenbits, bluebits, 0, 0, 0, fullscreen ? GLFW_FULLSCREEN : GLFW_WINDOW) == GL_TRUE)
2335 	{
2336 		glfwSetWindowTitle(windowTitle.c_str());
2337 		resize(width,height);
2338 
2339 
2340 #ifdef BBGE_BUILD_WINDOWS
2341 		this->hWnd = (HWND)glfwGetWindowHandle();
2342 
2343 		if (!fullscreen)	centerWindow(hWnd);
2344 #endif
2345 
2346 		glfwSetWindowSizeCallback(windowResize);
2347 
2348 		redBits = glfwGetWindowParam(GLFW_RED_BITS);
2349 		blueBits = glfwGetWindowParam(GLFW_BLUE_BITS);
2350 		greenBits = glfwGetWindowParam(GLFW_GREEN_BITS);
2351 		alphaBits = glfwGetWindowParam(GLFW_ALPHA_BITS);
2352 
2353 		if (redBits < 8 && (bits == 32 || bits == 24))
2354 		{
2355 			int sayBits = 32;
2356 			std::ostringstream os;
2357 			os << "(" << width << ", " << height << ") " << sayBits << "-bit mode could not be enabled. Please try setting your desktop to " << sayBits << "-bit color depth";
2358 			if (!fullscreen)
2359 				os << ", or try running in fullscreen.";
2360 			else
2361 				os << ".";
2362 			os << " This resolution may not be supported on your machine.";
2363 			errorLog(os.str());
2364 			exit(0); return false;
2365 		}
2366 		return true;
2367 	}
2368 	else
2369 		return false;
2370 #endif
2371 
2372 #ifdef BBGE_BUILD_DIRECTX
2373 	// Register the window class
2374     WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
2375                       GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
2376                       windowTitle.c_str(), NULL };
2377     RegisterClassEx( &wc );
2378 
2379 	this->hWnd = CreateWindow( windowTitle.c_str(), windowTitle.c_str(),
2380 							WS_OVERLAPPEDWINDOW, 100, 100, width, height+10,
2381 							GetDesktopWindow(), NULL, wc.hInstance, NULL );
2382 	return true;
2383 #endif
2384 }
2385 
2386 // No longer part of C/C++ standard
2387 #ifndef M_PI
2388 #define M_PI           3.14159265358979323846
2389 #endif
2390 
2391 static void
bbgePerspective(float fovy,float aspect,float zNear,float zFar)2392 bbgePerspective(float fovy, float aspect, float zNear, float zFar)
2393 {
2394     float sine, cotangent, deltaZ;
2395     float radians = fovy / 2.0f * M_PI / 180.0f;
2396 
2397     deltaZ = zFar - zNear;
2398     sine = sinf(radians);
2399     if ((deltaZ == 0.0f) || (sine == 0.0f) || (aspect == 0.0f)) {
2400         return;
2401     }
2402     cotangent = cosf(radians) / sine;
2403 
2404     GLfloat m[4][4] = {
2405         { 1.0f, 0.0f, 0.0f, 0.0f },
2406         { 0.0f, 1.0f, 0.0f, 0.0f },
2407         { 0.0f, 0.0f, 1.0f, 0.0f },
2408         { 0.0f, 0.0f, 0.0f, 1.0f }
2409     };
2410     m[0][0] = (GLfloat) (cotangent / aspect);
2411     m[1][1] = (GLfloat) cotangent;
2412     m[2][2] = (GLfloat) (-(zFar + zNear) / deltaZ);
2413     m[2][3] = -1.0f;
2414     m[3][2] = (GLfloat) (-2.0f * zNear * zFar / deltaZ);
2415     m[3][3] = 0.0f;
2416 
2417     glMultMatrixf(&m[0][0]);
2418 }
2419 
setPixelScale(int pixelScaleX,int pixelScaleY)2420 void Core::setPixelScale(int pixelScaleX, int pixelScaleY)
2421 {
2422 	/*
2423 	piScaleX = pixelScaleX;
2424 	piScaleY = pixelScaleY;
2425 	*/
2426 	virtualWidth = pixelScaleX;
2427 	//MAX(virtualWidth, 800);
2428 	virtualHeight = pixelScaleY;//int((pixelScale*aspectY)/aspectX);					//assumes 4:3 aspect ratio
2429 	this->baseCullRadius = 1.1f * sqrtf(sqr(getVirtualWidth()/2) + sqr(getVirtualHeight()/2));
2430 
2431 	std::ostringstream os;
2432 	os << "virtual(" << virtualWidth << ", " << virtualHeight << ")";
2433 	debugLog(os.str());
2434 
2435 	vw2 = virtualWidth/2;
2436 	vh2 = virtualHeight/2;
2437 
2438 	center = Vector(baseVirtualWidth/2, baseVirtualHeight/2);
2439 
2440 
2441 	virtualOffX = 0;
2442 	virtualOffY = 0;
2443 
2444 	int diff = 0;
2445 
2446 	diff = virtualWidth-baseVirtualWidth;
2447 	if (diff > 0)
2448 		virtualOffX = ((virtualWidth-baseVirtualWidth)/2);
2449 	else
2450 		virtualOffX = 0;
2451 
2452 
2453 	diff = virtualHeight-baseVirtualHeight;
2454 	if (diff > 0)
2455 		virtualOffY = ((virtualHeight-baseVirtualHeight)/2);
2456 	else
2457 		virtualOffY = 0;
2458 }
2459 
2460 // forcePixelScale used by Celu
2461 
enable2DWide(int rx,int ry)2462 void Core::enable2DWide(int rx, int ry)
2463 {
2464 	float aspect = float(rx) / float(ry);
2465 	if (aspect >= 1.3f)
2466 	{
2467 		int vw = int(float(baseVirtualHeight) * (float(rx)/float(ry)));
2468 		//vw = MAX(vw, baseVirtualWidth);
2469 		core->enable2D(vw, baseVirtualHeight, 1);
2470 	}
2471 	else
2472 	{
2473 		int vh = int(float(baseVirtualWidth) * (float(ry)/float(rx)));
2474 		//vh = MAX(vh, baseVirtualHeight);
2475 		core->enable2D(baseVirtualWidth, vh, 1);
2476 	}
2477 }
2478 
bbgeOrtho2D(float left,float right,float bottom,float top)2479 static void bbgeOrtho2D(float left, float right, float bottom, float top)
2480 {
2481     glOrtho(left, right, bottom, top, -1.0, 1.0);
2482 }
2483 
enable2D(int pixelScaleX,int pixelScaleY,bool forcePixelScale)2484 void Core::enable2D(int pixelScaleX, int pixelScaleY, bool forcePixelScale)
2485 {
2486 	// why do this again? don't really get it
2487 	/*
2488 	if (mode == MODE_2D)
2489 	{
2490 		if (forcePixelScale || (pixelScaleX!=0 && core->width!=pixelScaleX) || (pixelScaleY!=0 && core->height!=pixelScaleY))
2491 		{
2492 			float widthFactor = core->width/float(pixelScaleX);
2493 			float heightFactor = core->height/float(pixelScaleY);
2494 			core->globalResolutionScale = Vector(widthFactor,heightFactor,1.0f);
2495 			setPixelScale(pixelScaleX, pixelScaleY);
2496 
2497 			std::ostringstream os;
2498 			os << "top of call: ";
2499 			os << "widthFactor: " << widthFactor;
2500 			os << "heightFactor: " << heightFactor;
2501 			debugLog(os.str());
2502 		}
2503 		return;
2504 	}
2505 	*/
2506 
2507 #ifdef BBGE_BUILD_OPENGL
2508 
2509     GLint viewPort[4];
2510     glGetIntegerv(GL_VIEWPORT, viewPort);
2511 
2512     glMatrixMode(GL_PROJECTION);
2513     //glPushMatrix();
2514     glLoadIdentity();
2515 
2516 	float vw=0,vh=0;
2517 
2518 	viewOffX = viewOffY = 0;
2519 
2520 	float aspect = float(width)/float(height);
2521 
2522 	if (aspect >= 1.4f)
2523 	{
2524 		vw = float(baseVirtualWidth * viewPort[3]) / float(baseVirtualHeight);
2525 
2526 		viewOffX = (viewPort[2] - vw) * 0.5f;
2527 	}
2528 	else if (aspect < 1.3f)
2529 	{
2530 		vh = float(baseVirtualHeight * viewPort[2]) / float(baseVirtualWidth);
2531 
2532 		viewOffY = (viewPort[3] - vh) * 0.5f;
2533 	}
2534 
2535 
2536 
2537 	/*
2538 	vh = float(baseVirtualHeight * viewPort[2]) / float(baseVirtualWidth);
2539 
2540 	viewOffY = (viewPort[3] - vh) * 0.5f;
2541 	*/
2542 
2543 
2544 	/*
2545 	std::ostringstream os;
2546 	os << "vw: " << vw << " OFFX: " << viewOffX << " ";
2547 	os << "vh: " << vh << " OFFY: " << viewOffY;
2548 	debugLog(os.str());
2549 	*/
2550 
2551 
2552 	/*
2553 	float aspect = float(width) / float (height);
2554 
2555 	if (aspect < 1.3f)
2556 	{
2557 		viewOffX *= 0.5f;
2558 	}
2559 	*/
2560 
2561 
2562 //#else
2563 //	int offx=0,offy=0;
2564 //#endif
2565 
2566 	//+offx
2567 	//-offx
2568 	//glOrtho(0.0f,viewPort[2],viewPort[3],0.0f,-1000.0f,1000.0f);
2569 	//glOrtho(0.0f+offx,viewPort[2]+offx,viewPort[3]+offy,0.0f+offy,-1.0f,1.0f);
2570 	bbgeOrtho2D(0.0f-viewOffX,viewPort[2]-viewOffX,viewPort[3]-viewOffY,0.0f-viewOffY);
2571 	/*
2572 	static bool doOnce = false;
2573 	if (!doOnce)
2574 	{
2575 		glOrtho(0.0f,viewPort[2],viewPort[3],0.0f,-10.0f,10.0f);
2576 		doOnce = true;
2577 	}
2578 	*/
2579 	//glOrtho(-viewPort[2]/2,viewPort[2]/2,viewPort[3]/2,-viewPort[3]/2,-10.0f,10.0f);
2580     //glOrtho(0, viewPort[2], 0, viewPort[3], -100, 100);
2581 
2582     glMatrixMode(GL_MODELVIEW);
2583     //glPushMatrix();
2584     glLoadIdentity();
2585 
2586 	setupRenderPositionAndScale();
2587 #endif
2588 
2589 #ifdef BBGE_BUILD_DIRECTX
2590 	D3DXMATRIX matOrtho;
2591 	D3DXMATRIX matIdentity;
2592 
2593 	//Setup orthographic projection matrix
2594 
2595 	D3DXMatrixOrthoOffCenterLH(&matOrtho, 0, getWindowWidth(), getWindowHeight(), 0, 1, 10);
2596 	//D3DXMatrixOrthoLH (&matOrtho, getWindowWidth(), getWindowHeight(), 1.0f, 10.0f);
2597 	D3DXMatrixIdentity (&matIdentity);
2598 	g_pd3dDevice->SetTransform (D3DTS_PROJECTION, &matOrtho);
2599 	g_pd3dDevice->SetTransform (D3DTS_WORLD, &matIdentity);
2600 	g_pd3dDevice->SetTransform (D3DTS_VIEW, &matIdentity);
2601 	// For our world matrix, we will just leave it as the identity
2602 	/*
2603     D3DXMATRIXA16 matWorld;
2604     D3DXMatrixIdentity( &matWorld );
2605     //D3DXMatrixRotationX( &matWorld, 0/1000.0f );
2606     g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
2607 
2608     // Set up our view matrix. A view matrix can be defined given an eye point,
2609     // a point to lookat, and a direction for which way is up. Here, we set the
2610     // eye five units back along the z-axis and up three units, look at the
2611     // origin, and define "up" to be in the y-direction.
2612     D3DXVECTOR3 vEyePt( 0.0f, 0.0f,0.0f );
2613     D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
2614     D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
2615     D3DXMATRIXA16 matView;
2616     D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
2617     g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
2618 
2619     // For the projection matrix, we set up a perspective transform (which
2620     // transforms geometry from 3D view space to 2D viewport space, with
2621     // a perspective divide making objects smaller in the distance). To build
2622     // a perpsective transform, we need the field of view (1/4 pi is common),
2623     // the aspect ratio, and the near and far clipping planes (which define at
2624     // what distances geometry should be no longer be rendered).
2625 	///LPDIRECT3DVIEWPORT3 Viewport;
2626 
2627 	D3DVIEWPORT9 viewport;
2628 	viewport.Width = core->getWindowWidth();
2629 	viewport.Height = core->getWindowHeight();
2630 	viewport.MaxZ = 5;
2631 	viewport.MinZ = -5;
2632 	viewport.X = 0;
2633 	viewport.Y = 0;
2634 
2635 	g_pd3dDevice->SetViewport( &viewport );
2636 
2637 	D3DXMATRIXA16 matProj;
2638 	D3DXMatrixOrthoLH(&matProj, 800, 600, -5, 5);
2639 	g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
2640 	*/
2641 
2642 	// Create the viewport
2643 	/*
2644 	if (FAILED(g_pd3dDevice->CreateViewport(&Viewport,NULL)))
2645 	{ errorLog("Failed to create a viewport"); };
2646 	if (FAILED(g_pd3dDevice->AddViewport(Viewport)))
2647 	{ errorLog("Failed to add a viewport"); };
2648 	if (FAILED(g_pd3dDevice->SetViewport2(&Viewdata)))
2649 	{ errorLog("Failed to set Viewport data"); };
2650 	g_pd3dDevice->SetCurrentViewport(Viewport);
2651 	*/
2652 
2653 	/*
2654 	D3DXMATRIXA16 matProj;
2655 	D3DXMatrixOrthoLH(&matProj, 4, 3, -5, 5);
2656     g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
2657 	*/
2658 
2659 	/*
2660    D3DVIEWPORT9 viewport;
2661    g_pd3dDevice->GetViewport(&viewport);
2662    D3DXMATRIX matProj;
2663    D3DXMatrixOrthoLH(&matProj, viewport.Width, viewport.Height, -10, 10);
2664    g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
2665    */
2666 
2667 
2668 #endif
2669 
2670 	if (forcePixelScale || (pixelScaleX!=0 && core->width!=pixelScaleX) || (pixelScaleY!=0 && core->height!=pixelScaleY))
2671 	{
2672 		/*
2673 		float f = core->width/float(pixelScale);
2674 		core->globalResolutionScale = Vector(f,f,1.0f);
2675 		*/
2676 		//debugLog("HEEEREEE");
2677 		float widthFactor = core->width/float(pixelScaleX);
2678 		float heightFactor = core->height/float(pixelScaleY);
2679 		//float heightFactor =
2680 		core->globalResolutionScale = Vector(widthFactor,heightFactor,1.0f);
2681 		setPixelScale(pixelScaleX, pixelScaleY);
2682 
2683 		//core->globalResolutionScale = Vector(1.5,1.5,1);
2684 		/*
2685 		std::ostringstream os;
2686 		os << "bottom of call: ";
2687 		os << "widthFactor: " << widthFactor;
2688 		os << " heightFactor: " << heightFactor;
2689 		debugLog(os.str());
2690 		*/
2691 	}
2692 	setPixelScale(pixelScaleX, pixelScaleY);
2693 
2694 	//core->globalResolutionScale.x = 1.6;
2695 
2696 	//setupRenderPositionAndScale();
2697 
2698 
2699 }
2700 
quitNestedMain()2701 void Core::quitNestedMain()
2702 {
2703 	if (getNestedMains() > 1)
2704 	{
2705 		quitNestedMainFlag = true;
2706 	}
2707 }
2708 
resetTimer()2709 void Core::resetTimer()
2710 {
2711 #ifdef BBGE_BUILD_GLFW
2712 	glfwSetTime(0);
2713 #endif
2714 #ifdef BBGE_BUILD_SDL
2715 	nowTicks = thenTicks = SDL_GetTicks();
2716 #endif
2717 #ifdef BBGE_BUILD_DIRECTX
2718 	QueryPerformanceCounter((LARGE_INTEGER*)&timerEnd);
2719 	timerStart = timerEnd;
2720 #endif
2721 
2722 	for (int i = 0; i < avgFPS.size(); i++)
2723 	{
2724 		avgFPS[i] = 0;
2725 	}
2726 }
2727 
setDockIcon(const std::string & ident)2728 void Core::setDockIcon(const std::string &ident)
2729 {
2730 }
2731 
setMousePosition(const Vector & p)2732 void Core::setMousePosition(const Vector &p)
2733 {
2734 	Vector lp = core->mouse.position;
2735 
2736 	core->mouse.position = p;
2737 #if !defined(BBGE_BUILD_WINDOWS) && defined(BBGE_BUILD_GLFW)
2738 	glfwSetMousePos(p.x,p.y);
2739 #endif
2740 #ifdef BBGE_BUILD_SDL
2741 	float px = p.x + virtualOffX;
2742 	float py = p.y;// + virtualOffY;
2743 
2744 	#ifdef BBGE_BUILD_SDL2
2745 	SDL_WarpMouseInWindow(gScreen, px * (float(width)/float(virtualWidth)), py * (float(height)/float(virtualHeight)));
2746 	#else
2747 	SDL_WarpMouse( px * (float(width)/float(virtualWidth)), py * (float(height)/float(virtualHeight)));
2748 	#endif
2749 
2750 	/*
2751 	ignoreNextMouse = true;
2752 	unchange = core->mouse.position - lp;
2753 	*/
2754 #endif
2755 
2756 	/*
2757 	std::ostringstream os;
2758 	os << "setting position (" << p.x << ", " << p.y << ")";
2759 	debugLog(os.str());
2760 	*/
2761 }
2762 
2763 // used to update all render objects either uniformly or as part of a time sliced update process
updateRenderObjects(float dt)2764 void Core::updateRenderObjects(float dt)
2765 {
2766 	for (int c = 0; c < renderObjectLayers.size(); c++)
2767 	{
2768 
2769 		RenderObjectLayer *rl = &renderObjectLayers[c];
2770 
2771 		if (!rl->update)
2772 			continue;
2773 
2774 		for (RenderObject *r = rl->getFirst(); r; r = rl->getNext())
2775 		{
2776 			r->update(dt);
2777 		}
2778 	}
2779 
2780 	if (loopDone)
2781 		return;
2782 
2783 	if (clearedGarbageFlag)
2784 	{
2785 		clearedGarbageFlag = false;
2786 	}
2787 }
2788 
getEnqueuedJumpState()2789 std::string Core::getEnqueuedJumpState()
2790 {
2791 	return this->enqueuedJumpState;
2792 }
2793 
2794 int screenshotNum = 0;
getScreenshotFilename()2795 std::string getScreenshotFilename()
2796 {
2797 	while (true)
2798 	{
2799 		std::ostringstream os;
2800 		os << core->getUserDataFolder() << "/screenshots/screen" << screenshotNum << ".tga";
2801 		screenshotNum ++;
2802         std::string str(os.str());
2803 		if (!core->exists(str))  // keep going until we hit an unused filename.
2804 			return str;
2805 	}
2806 }
2807 
getTicks()2808 uint32 Core::getTicks()
2809 {
2810 #ifdef BBGE_BUILD_SDL
2811 	return SDL_GetTicks();
2812 #endif
2813 	return 0;
2814 }
2815 
stopWatch(int d)2816 float Core::stopWatch(int d)
2817 {
2818 	if (d)
2819 	{
2820 		stopWatchStartTime = getTicks()/1000.0f;
2821 		return stopWatchStartTime;
2822 	}
2823 	else
2824 	{
2825 		return (getTicks()/1000.0f) - stopWatchStartTime;
2826 	}
2827 
2828 	return 0;
2829 }
2830 
isWindowFocus()2831 bool Core::isWindowFocus()
2832 {
2833 #ifdef BBGE_BUILD_SDL
2834 	#ifdef BBGE_BUILD_SDL2
2835 	return ((SDL_GetWindowFlags(gScreen) & SDL_WINDOW_INPUT_FOCUS) != 0);
2836 	#else
2837 	return ((SDL_GetAppState() & SDL_APPINPUTFOCUS) != 0);
2838 	#endif
2839 #endif
2840 	return true;
2841 }
2842 
onBackgroundUpdate()2843 void Core::onBackgroundUpdate()
2844 {
2845 #if BBGE_BUILD_SDL
2846 	SDL_Delay(200);
2847 #endif
2848 }
2849 
main(float runTime)2850 void Core::main(float runTime)
2851 {
2852 	bool verbose = coreVerboseDebug;
2853 	if (verbose) debugLog("entered Core::main");
2854 	// cannot nest loops when the game is over
2855 	if (loopDone) return;
2856 
2857 	//QueryPerformanceCounter((LARGE_INTEGER*)&lastTime);
2858 	//QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
2859 	float dt;
2860 	float counter = 0;
2861 	int frames = 0;
2862 	float real_dt = 0;
2863 	//std::ofstream out("debug.log");
2864 
2865 #if (!defined(_DEBUG) || defined(BBGE_BUILD_UNIX)) && defined(BBGE_BUILD_SDL)
2866 	bool wasInactive = false;
2867 #endif
2868 
2869 #ifdef BBGE_BUILD_GLFW
2870 	if (runTime == -1)
2871 		glfwSetTime(0);
2872 #endif
2873 #ifdef BBGE_BUILD_DIRECTX
2874 	// HACK: find out how to use performance counter again Query
2875 
2876 
2877 	if (verbose) debugLog("Performance Counter");
2878 
2879 	if (!QueryPerformanceFrequency((LARGE_INTEGER*)&freq))
2880 	{
2881 		errorLog ("could not get clock freq");
2882 		return;
2883 	}
2884 	QueryPerformanceCounter((LARGE_INTEGER*)&timerStart);
2885 	/*
2886 	DWORD ticks = GetTickCount();
2887 	DWORD newTicks;
2888 	*/
2889 #endif
2890 
2891 #ifdef BBGE_BUILD_SDL
2892 	nowTicks = thenTicks = SDL_GetTicks();
2893 #endif
2894 
2895 	//int i;
2896 
2897 	nestedMains++;
2898 	// HACK: Why block this?
2899 	/*
2900 	if (nestedMains > 1 && runTime <= 0)
2901 		return;
2902 	*/
2903 
2904 #ifdef BBGE_BUILD_DIRECTX
2905 	MSG msg;
2906 	ZeroMemory( &msg, sizeof(msg) );
2907 #endif
2908 
2909 	while((runTime == -1 && !loopDone) || (runTime >0))									// Loop That Runs While done=FALSE
2910 	{
2911 		BBGE_PROF(Core_main);
2912 #ifdef BBGE_BUILD_DIRECTX
2913 		if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
2914 		{
2915 			TranslateMessage( &msg );
2916 			DispatchMessage( &msg );
2917 		}
2918 #endif
2919 
2920 
2921 #ifdef BBGE_BUILD_GLFW
2922 		if (verbose) debugLog("glfwSetTime");
2923 		dt = glfwGetTime();
2924 		glfwSetTime(0);
2925 #endif
2926 
2927 #ifdef BBGE_BUILD_DIRECTX
2928 		/*
2929 		newTicks = GetTickCount();
2930 		*/
2931 		QueryPerformanceCounter((LARGE_INTEGER*)&timerEnd);
2932 		dt = (float(timerEnd-timerStart)/float(freq));
2933 		timerStart = timerEnd;
2934 //		dt = float(newTicks)/1000.0f;
2935 		//dt = float(newTicks - ticks)/1000.0f;
2936 		//ticks = newTicks;
2937 #endif
2938 
2939 #ifdef BBGE_BUILD_SDL
2940 		if (timeUpdateType == TIMEUPDATE_DYNAMIC)
2941 		{
2942 			nowTicks = SDL_GetTicks();
2943 		}
2944 		/*
2945 		else
2946 		{
2947 			if (nowTicks == 0)
2948 			{
2949 				nowTicks = SDL_GetTicks();
2950 			}
2951 		}
2952 		*/
2953 		dt = (nowTicks-thenTicks)/1000.0;
2954 		thenTicks = nowTicks;
2955 		//thenTicks = SDL_GetTicks();
2956 #endif
2957 
2958 		if (verbose) debugLog("avgFPS");
2959 		if (!avgFPS.empty())
2960 		{
2961 			/*
2962 			if (avgFPS[0] <= 0)
2963 			{
2964 				for (int i = 0; i < avgFPS.size(); i++)
2965 					avgFPS[i] = dt;
2966 			}
2967 			*/
2968 			int i = 0;
2969 			for (i = avgFPS.size()-1; i > 0; i--)
2970 			{
2971 				avgFPS[i] = avgFPS[i-1];
2972 			}
2973 			avgFPS[0] = dt;
2974 
2975 			float c=0;
2976 			int n = 0;
2977 			for (i = 0; i < avgFPS.size(); i++)
2978 			{
2979 				if (avgFPS[i] > 0)
2980 				{
2981 					c += avgFPS[i];
2982 					n ++;
2983 				}
2984 			}
2985 			if (n > 0) // && n == avgFPS.size() ??
2986 			{
2987 				c /= n;
2988 				dt = c;
2989 			}
2990 			/*
2991 			std::ostringstream os;
2992 			os << dt;
2993 			debugLog(os.str());
2994 			*/
2995 		}
2996 
2997 #if !defined(_DEBUG) && defined(BBGE_BUILD_SDL)
2998 		if (verbose) debugLog("checking window active");
2999 
3000 		if (lib_graphics && (wasInactive || !settings.runInBackground))
3001 		{
3002 			if (isWindowFocus())
3003 			{
3004 				_hasFocus = true;
3005 				if (wasInactive)
3006 				{
3007 					debugLog("WINDOW ACTIVE");
3008 
3009 					setReentryInputGrab(1);
3010 
3011 					wasInactive = false;
3012 				}
3013 			}
3014 			else
3015 			{
3016 				if (_hasFocus)
3017 				{
3018 					if (!wasInactive)
3019 						debugLog("WINDOW INACTIVE");
3020 
3021 					wasInactive = true;
3022 					_hasFocus = false;
3023 
3024 					setReentryInputGrab(0);
3025 
3026 					sound->pause();
3027 
3028 					core->joystick.rumble(0,0,0);
3029 
3030 					while (!isWindowFocus())
3031 					{
3032 						pollEvents();
3033 						//debugLog("app not in input focus");
3034 						onBackgroundUpdate();
3035 
3036 						resetTimer();
3037 					}
3038 
3039 					debugLog("app back in focus, reset");
3040 
3041 					// Don't do this on Linux, it's not necessary and causes big stalls.
3042 					//  We don't actually _lose_ the device like Direct3D anyhow.
3043 					#ifndef BBGE_BUILD_UNIX
3044 					if (_fullscreen)
3045 					{
3046 						// calls reload device - reloadDevice()
3047 						resetGraphics(width, height);
3048 					}
3049 					#endif
3050 
3051 					resetTimer();
3052 
3053 					sound->resume();
3054 
3055 					resetTimer();
3056 
3057 					SDL_ShowCursor(SDL_DISABLE);
3058 
3059 					continue;
3060 				}
3061 			}
3062 		}
3063 #endif
3064 
3065 		if (timeUpdateType == TIMEUPDATE_FIXED)
3066 		{
3067 			real_dt = dt;
3068 			dt = 1.0f/float(fixedFPS);
3069 		}
3070 
3071 		old_dt = dt;
3072 
3073 		if (verbose) debugLog("modify dt");
3074 		modifyDt(dt);
3075 
3076 		current_dt = dt;
3077 
3078 		if (verbose) debugLog("check runtime/quit");
3079 
3080 		if (quitNestedMainFlag)
3081 		{
3082 			quitNestedMainFlag = false;
3083 			break;
3084 		}
3085 		if (runTime>0)
3086 		{
3087 			runTime -= dt;
3088 			if (runTime < 0)
3089 				runTime = 0;
3090 		}
3091 
3092 		// UPDATE
3093 		if (verbose) debugLog("post processing fx update");
3094 		postProcessingFx.update(dt);
3095 
3096 		if (verbose) debugLog("update eventQueue");
3097 		eventQueue.update(dt);
3098 
3099 		if (verbose) debugLog("Update render objects");
3100 
3101 		updateRenderObjects(dt);
3102 
3103 		if (verbose) debugLog("Update particle manager");
3104 
3105 		if (particleManager)
3106 			particleManager->update(dt);
3107 
3108 		if (verbose) debugLog("sound update");
3109 		sound->update(dt);
3110 
3111 		if (verbose) debugLog("onUpdate");
3112 		onUpdate(dt);
3113 
3114 		if (nestedMains == 1)
3115 			clearGarbage();
3116 
3117 		if (loopDone)
3118 			break;
3119 
3120 		updateCullData();
3121 
3122 		dbg_numRenderCalls = 0;
3123 
3124 		if (settings.renderOn)
3125 		{
3126 			if (verbose) debugLog("dark layer prerender");
3127 			if (darkLayer.isUsed())
3128 			{
3129 				darkLayer.preRender();
3130 			}
3131 
3132 			if (verbose) debugLog("render");
3133 			render();
3134 
3135 			if (verbose) debugLog("showBuffer");
3136 			showBuffer();
3137 
3138 			BBGE_PROF(STOP);
3139 
3140 			if (verbose) debugLog("clearGarbage");
3141 			if (nestedMains == 1)
3142 				clearGarbage();
3143 
3144 
3145 			if (verbose) debugLog("frame counter");
3146 			frames++;
3147 
3148 			counter += dt;
3149 			if (counter > 1)
3150 			{
3151 				fps = frames;
3152 				frames = counter = 0;
3153 			}
3154 		}
3155 
3156 		sound->setListenerPos(screenCenter.x, screenCenter.y);
3157 
3158 		if (doScreenshot)
3159 		{
3160 			if (verbose) debugLog("screenshot");
3161 
3162 			doScreenshot = false;
3163 
3164 			saveScreenshotTGA(getScreenshotFilename());
3165 			prepScreen(0);
3166 		}
3167 
3168 		// wait
3169 		if (timeUpdateType == TIMEUPDATE_FIXED)
3170 		{
3171 			static float avg_diff=0;
3172 			static int avg_diff_count=0;
3173 
3174 			float diff = (1.0f/float(fixedFPS)) - real_dt;
3175 
3176 			avg_diff_count++;
3177 			avg_diff += diff;
3178 
3179 			char buf[256];
3180 			sprintf(buf, "real_dt: %5.4f \n realFPS: %5.4f \n fixedFPS: %5.4f \n diff: %5.4f \n delay: %5.4f \n avgdiff: %5.8f", float(real_dt), float(real_dt>0?(1.0f/real_dt):0.0f), float(fixedFPS), float(diff), float(diff*1000), float(avg_diff/(float)avg_diff_count));
3181 			fpsDebugString = buf;
3182 
3183 			/*
3184 			std::ostringstream os;
3185 			os << "real_dt: " << real_dt << "\n realFPS: " << (1.0/real_dt) << "\n fixedFPS: " << fixedFPS << "\n diff: " << diff << "\n delay: " << diff*1000;
3186 			fpsDebugString = os.str();
3187 			*/
3188 
3189 #ifdef BBGE_BUILD_SDL
3190 			nowTicks = SDL_GetTicks();
3191 
3192 			if (diff > 0)
3193 			{
3194 				//Sleep(diff*1000);
3195 				//SDL_Delay(diff*1000);
3196 				while ((SDL_GetTicks() - nowTicks) < (diff*1000))
3197 				{
3198 					//wend, bitch
3199 				}
3200 			}
3201 
3202 			//nowTicks = SDL_GetTicks();
3203 #endif
3204 
3205 		}
3206 	}
3207 	if (verbose) debugLog("bottom of function");
3208 	quitNestedMainFlag = false;
3209 	if (nestedMains==1)
3210 		clearGarbage();
3211 	nestedMains--;
3212 	if (verbose) debugLog("exit Core::main");
3213 }
3214 
3215 // less than through pointer
RenderObject_lt(RenderObject * x,RenderObject * y)3216 bool RenderObject_lt(RenderObject* x, RenderObject* y)
3217 {
3218 	return x->getSortDepth() < y->getSortDepth();
3219 }
3220 
3221 // greater than through pointer
RenderObject_gt(RenderObject * x,RenderObject * y)3222 bool RenderObject_gt(RenderObject* x, RenderObject* y)
3223 {
3224 	return x->getSortDepth() > y->getSortDepth();
3225 }
3226 
sortLayer(int layer)3227 void Core::sortLayer(int layer)
3228 {
3229 	if (layer >= 0 && layer < renderObjectLayers.size())
3230 		renderObjectLayers[layer].sort();
3231 }
3232 
sort()3233 void Core::sort()
3234 {
3235 	/*
3236 	if (sortEnabled)
3237 		renderObjects.sort(RenderObject_lt);
3238 	*/
3239 	// sort layeres independantly
3240 
3241 	/*
3242 	for (int i = renderObjects.size()-1; i >= 0; i--)
3243 	{
3244 		bool flipped = false;
3245 		for (int j = 0; j < i; j++)
3246 		{
3247 			//position.z
3248 			//position.z
3249 			//!renderObjects[j]->parent && !renderObjects[j+1]->parent &&
3250 			if (renderObjects[j]->getSortDepth() > renderObjects[j+1]->getSortDepth())
3251 			{
3252 				RenderObject *temp;
3253 				temp = renderObjects[j];
3254 				renderObjects[j] = renderObjects[j+1];
3255 				renderObjects[j+1] = temp;
3256 				flipped = true;
3257 			}
3258 		}
3259 		if (!flipped) break;
3260 	}
3261 	*/
3262 
3263 }
3264 
clearBuffers()3265 void Core::clearBuffers()
3266 {
3267 	if (flags.get(CF_CLEARBUFFERS))
3268 	{
3269 #ifdef BBGE_BUILD_OPENGL
3270 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear The Screen And The Depth Buffer
3271 #endif
3272 #ifdef BBGE_BUILD_DIRECTX
3273 		g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(int(clearColor.x*255),int(clearColor.y*255),int(clearColor.z*255)), 1.0f, 0 );
3274 #endif
3275 	}
3276 }
3277 
setupRenderPositionAndScale()3278 void Core::setupRenderPositionAndScale()
3279 {
3280 #ifdef BBGE_BUILD_OPENGL
3281 	glScalef(globalScale.x*globalResolutionScale.x*screenCapScale.x, globalScale.y*globalResolutionScale.y*screenCapScale.y, globalScale.z*globalResolutionScale.z);
3282 	glTranslatef(-(cameraPos.x+cameraOffset.x), -(cameraPos.y+cameraOffset.y), -(cameraPos.z+cameraOffset.z));
3283 #endif
3284 }
3285 
setupGlobalResolutionScale()3286 void Core::setupGlobalResolutionScale()
3287 {
3288 	glScalef(globalResolutionScale.x, globalResolutionScale.y, globalResolutionScale.z);
3289 }
3290 
initFrameBuffer()3291 void Core::initFrameBuffer()
3292 {
3293 	frameBuffer.init(-1, -1, true);
3294 }
3295 
setMouseConstraint(bool on)3296 void Core::setMouseConstraint(bool on)
3297 {
3298 /*
3299 	if (mouseConstraint && !on)
3300 	{
3301 		setMousePosition(mouse.position);
3302 	}
3303 	*/
3304 	mouseConstraint = on;
3305 }
3306 
setMouseConstraintCircle(const Vector & pos,float circle)3307 void Core::setMouseConstraintCircle(const Vector& pos, float circle)
3308 {
3309 	mouseConstraint = true;
3310 	mouseCircle = circle;
3311 	mouseConstraintCenter = pos;
3312 	mouseConstraintCenter.z = 0;
3313 }
3314 
3315 /*
3316 void Core::clearKeys()
3317 {
3318 	for (int i = 0; i < KEY_MAXARRAY; i++)
3319 	{
3320 		keys[i] = 0;
3321 	}
3322 }
3323 */
3324 
getVirtualOffX()3325 int Core::getVirtualOffX()
3326 {
3327 	return virtualOffX;
3328 }
3329 
getVirtualOffY()3330 int Core::getVirtualOffY()
3331 {
3332 	return virtualOffY;
3333 }
3334 
centerMouse()3335 void Core::centerMouse()
3336 {
3337 	setMousePosition(Vector((virtualWidth/2) - core->getVirtualOffX(), virtualHeight/2));
3338 }
3339 
doMouseConstraint()3340 bool Core::doMouseConstraint()
3341 {
3342 	if (mouseConstraint)
3343 	{
3344 		//- core->getVirtualOffX()
3345 		//- virtualOffX
3346 		Vector h = mouseConstraintCenter;
3347 		Vector d = mouse.position - h;
3348 		if (!d.isLength2DIn(mouseCircle))
3349 		{
3350 			d.setLength2D(mouseCircle);
3351 			mouse.position = h+d;
3352 			//warpMouse = true;
3353 			return true;
3354 		}
3355 	}
3356 	return false;
3357 }
3358 
3359 #if defined(BBGE_BUILD_SDL)
3360 
3361 #if defined(BBGE_BUILD_SDL2)
3362 typedef std::map<SDL_Keycode,int> sdlKeyMap;
3363 #else
3364 typedef std::map<SDLKey,int> sdlKeyMap;
3365 #endif
3366 
initSDLKeymap(void)3367 static sdlKeyMap *initSDLKeymap(void)
3368 {
3369 	sdlKeyMap *_retval = new sdlKeyMap;
3370 	sdlKeyMap &retval = *_retval;
3371 
3372 	#define SETKEYMAP(gamekey,sdlkey) retval[sdlkey] = gamekey
3373 
3374 #ifdef BBGE_BUILD_SDL2
3375 	SETKEYMAP(KEY_LSUPER, SDLK_LGUI);
3376 	SETKEYMAP(KEY_RSUPER, SDLK_RGUI);
3377 	SETKEYMAP(KEY_LMETA, SDLK_LGUI);
3378 	SETKEYMAP(KEY_RMETA, SDLK_RGUI);
3379 	SETKEYMAP(KEY_PRINTSCREEN, SDLK_PRINTSCREEN);
3380 	SETKEYMAP(KEY_NUMPAD1, SDLK_KP_1);
3381 	SETKEYMAP(KEY_NUMPAD2, SDLK_KP_2);
3382 	SETKEYMAP(KEY_NUMPAD3, SDLK_KP_3);
3383 	SETKEYMAP(KEY_NUMPAD4, SDLK_KP_4);
3384 	SETKEYMAP(KEY_NUMPAD5, SDLK_KP_5);
3385 	SETKEYMAP(KEY_NUMPAD6, SDLK_KP_6);
3386 	SETKEYMAP(KEY_NUMPAD7, SDLK_KP_7);
3387 	SETKEYMAP(KEY_NUMPAD8, SDLK_KP_8);
3388 	SETKEYMAP(KEY_NUMPAD9, SDLK_KP_9);
3389 	SETKEYMAP(KEY_NUMPAD0, SDLK_KP_0);
3390 #else
3391 	SETKEYMAP(KEY_LSUPER, SDLK_LSUPER);
3392 	SETKEYMAP(KEY_RSUPER, SDLK_RSUPER);
3393 	SETKEYMAP(KEY_LMETA, SDLK_LMETA);
3394 	SETKEYMAP(KEY_RMETA, SDLK_RMETA);
3395 	SETKEYMAP(KEY_PRINTSCREEN, SDLK_PRINT);
3396 	SETKEYMAP(KEY_NUMPAD1, SDLK_KP1);
3397 	SETKEYMAP(KEY_NUMPAD2, SDLK_KP2);
3398 	SETKEYMAP(KEY_NUMPAD3, SDLK_KP3);
3399 	SETKEYMAP(KEY_NUMPAD4, SDLK_KP4);
3400 	SETKEYMAP(KEY_NUMPAD5, SDLK_KP5);
3401 	SETKEYMAP(KEY_NUMPAD6, SDLK_KP6);
3402 	SETKEYMAP(KEY_NUMPAD7, SDLK_KP7);
3403 	SETKEYMAP(KEY_NUMPAD8, SDLK_KP8);
3404 	SETKEYMAP(KEY_NUMPAD9, SDLK_KP9);
3405 	SETKEYMAP(KEY_NUMPAD0, SDLK_KP0);
3406 #endif
3407 
3408 	SETKEYMAP(KEY_BACKSPACE, SDLK_BACKSPACE);
3409 
3410 	//SETKEYMAP(KEY_CAPSLOCK, DIK_CAPSLOCK);
3411 	//SETKEYMAP(KEY_CIRCUMFLEX, DIK_CIRCUMFLEX);
3412 	SETKEYMAP(KEY_LALT, SDLK_LALT);
3413 	SETKEYMAP(KEY_RALT, SDLK_RALT);
3414 	SETKEYMAP(KEY_LSHIFT, SDLK_LSHIFT);
3415 	SETKEYMAP(KEY_RSHIFT, SDLK_RSHIFT);
3416 	SETKEYMAP(KEY_LCONTROL, SDLK_LCTRL);
3417 	SETKEYMAP(KEY_RCONTROL, SDLK_RCTRL);
3418 	SETKEYMAP(KEY_NUMPADMINUS, SDLK_KP_MINUS);
3419 	SETKEYMAP(KEY_NUMPADPERIOD, SDLK_KP_PERIOD);
3420 	SETKEYMAP(KEY_NUMPADPLUS, SDLK_KP_PLUS);
3421 	SETKEYMAP(KEY_NUMPADSLASH, SDLK_KP_DIVIDE);
3422 	SETKEYMAP(KEY_NUMPADSTAR, SDLK_KP_MULTIPLY);
3423 	SETKEYMAP(KEY_PGDN, SDLK_PAGEDOWN);
3424 	SETKEYMAP(KEY_PGUP, SDLK_PAGEUP);
3425 	SETKEYMAP(KEY_APOSTROPHE, SDLK_QUOTE);
3426 	SETKEYMAP(KEY_EQUALS, SDLK_EQUALS);
3427 	SETKEYMAP(KEY_SEMICOLON, SDLK_SEMICOLON);
3428 	SETKEYMAP(KEY_LBRACKET, SDLK_LEFTBRACKET);
3429 	SETKEYMAP(KEY_RBRACKET, SDLK_RIGHTBRACKET);
3430 	//SETKEYMAP(KEY_RALT, GLFW_SETKEYMAP(KEY_RALT);
3431 	SETKEYMAP(KEY_TILDE, SDLK_BACKQUOTE);
3432 	SETKEYMAP(KEY_0, SDLK_0);
3433 	SETKEYMAP(KEY_1, SDLK_1);
3434 	SETKEYMAP(KEY_2, SDLK_2);
3435 	SETKEYMAP(KEY_3, SDLK_3);
3436 	SETKEYMAP(KEY_4, SDLK_4);
3437 	SETKEYMAP(KEY_5, SDLK_5);
3438 	SETKEYMAP(KEY_6, SDLK_6);
3439 	SETKEYMAP(KEY_7, SDLK_7);
3440 	SETKEYMAP(KEY_8, SDLK_8);
3441 	SETKEYMAP(KEY_9, SDLK_9);
3442 	SETKEYMAP(KEY_A, SDLK_a);
3443 	SETKEYMAP(KEY_B, SDLK_b);
3444 	SETKEYMAP(KEY_C, SDLK_c);
3445 	SETKEYMAP(KEY_D, SDLK_d);
3446 	SETKEYMAP(KEY_E, SDLK_e);
3447 	SETKEYMAP(KEY_F, SDLK_f);
3448 	SETKEYMAP(KEY_G, SDLK_g);
3449 	SETKEYMAP(KEY_H, SDLK_h);
3450 	SETKEYMAP(KEY_I, SDLK_i);
3451 	SETKEYMAP(KEY_J, SDLK_j);
3452 	SETKEYMAP(KEY_K, SDLK_k);
3453 	SETKEYMAP(KEY_L, SDLK_l);
3454 	SETKEYMAP(KEY_M, SDLK_m);
3455 	SETKEYMAP(KEY_N, SDLK_n);
3456 	SETKEYMAP(KEY_O, SDLK_o);
3457 	SETKEYMAP(KEY_P, SDLK_p);
3458 	SETKEYMAP(KEY_Q, SDLK_q);
3459 	SETKEYMAP(KEY_R, SDLK_r);
3460 	SETKEYMAP(KEY_S, SDLK_s);
3461 	SETKEYMAP(KEY_T, SDLK_t);
3462 	SETKEYMAP(KEY_U, SDLK_u);
3463 	SETKEYMAP(KEY_V, SDLK_v);
3464 	SETKEYMAP(KEY_W, SDLK_w);
3465 	SETKEYMAP(KEY_X, SDLK_x);
3466 	SETKEYMAP(KEY_Y, SDLK_y);
3467 	SETKEYMAP(KEY_Z, SDLK_z);
3468 
3469 	SETKEYMAP(KEY_LEFT, SDLK_LEFT);
3470 	SETKEYMAP(KEY_RIGHT, SDLK_RIGHT);
3471 	SETKEYMAP(KEY_UP, SDLK_UP);
3472 	SETKEYMAP(KEY_DOWN, SDLK_DOWN);
3473 
3474 	SETKEYMAP(KEY_DELETE, SDLK_DELETE);
3475 	SETKEYMAP(KEY_SPACE, SDLK_SPACE);
3476 	SETKEYMAP(KEY_RETURN, SDLK_RETURN);
3477 	SETKEYMAP(KEY_PERIOD, SDLK_PERIOD);
3478 	SETKEYMAP(KEY_MINUS, SDLK_MINUS);
3479 	SETKEYMAP(KEY_CAPSLOCK, SDLK_CAPSLOCK);
3480 	SETKEYMAP(KEY_SYSRQ, SDLK_SYSREQ);
3481 	SETKEYMAP(KEY_TAB, SDLK_TAB);
3482 	SETKEYMAP(KEY_HOME, SDLK_HOME);
3483 	SETKEYMAP(KEY_END, SDLK_END);
3484 	SETKEYMAP(KEY_COMMA, SDLK_COMMA);
3485 	SETKEYMAP(KEY_SLASH, SDLK_SLASH);
3486 
3487 	SETKEYMAP(KEY_F1, SDLK_F1);
3488 	SETKEYMAP(KEY_F2, SDLK_F2);
3489 	SETKEYMAP(KEY_F3, SDLK_F3);
3490 	SETKEYMAP(KEY_F4, SDLK_F4);
3491 	SETKEYMAP(KEY_F5, SDLK_F5);
3492 	SETKEYMAP(KEY_F6, SDLK_F6);
3493 	SETKEYMAP(KEY_F7, SDLK_F7);
3494 	SETKEYMAP(KEY_F8, SDLK_F8);
3495 	SETKEYMAP(KEY_F9, SDLK_F9);
3496 	SETKEYMAP(KEY_F10, SDLK_F10);
3497 	SETKEYMAP(KEY_F11, SDLK_F11);
3498 	SETKEYMAP(KEY_F12, SDLK_F12);
3499 	SETKEYMAP(KEY_F13, SDLK_F13);
3500 	SETKEYMAP(KEY_F14, SDLK_F14);
3501 	SETKEYMAP(KEY_F15, SDLK_F15);
3502 
3503 	SETKEYMAP(KEY_ESCAPE, SDLK_ESCAPE);
3504 	//SETKEYMAP(KEY_ANYKEY, 4059);
3505 	//SETKEYMAP(KEY_MAXARRAY, SDLK_LAST+1
3506 
3507 	#undef SETKEYMAP
3508 
3509 	return _retval;
3510 }
3511 
3512 #if defined(BBGE_BUILD_SDL2)
mapSDLKeyToGameKey(const SDL_Keycode val)3513 static int mapSDLKeyToGameKey(const SDL_Keycode val)
3514 #else
3515 static int mapSDLKeyToGameKey(const SDLKey val)
3516 #endif
3517 {
3518 	static sdlKeyMap *keymap = NULL;
3519 	if (keymap == NULL)
3520 		keymap = initSDLKeymap();
3521 
3522 	return (*keymap)[val];
3523 }
3524 #endif
3525 
3526 
pollEvents()3527 void Core::pollEvents()
3528 {
3529 #if defined(BBGE_BUILD_SDL)
3530 	bool warpMouse=false;
3531 
3532 	/*
3533 	Uint8 *keystate = SDL_GetKeyState(NULL);
3534 	for (int i = 0; i < KEY_MAXARRAY; i++)
3535 	{
3536 		keys[i] = keystate[i];
3537 	}
3538 	*/
3539 
3540 	if (updateMouse)
3541 	{
3542 		int x, y;
3543 		Uint8 mousestate = SDL_GetMouseState(&x,&y);
3544 
3545 		if (mouse.buttonsEnabled)
3546 		{
3547 			mouse.buttons.left		= mousestate & SDL_BUTTON(1)?DOWN:UP;
3548 			mouse.buttons.right		= mousestate & SDL_BUTTON(3)?DOWN:UP;
3549 			mouse.buttons.middle	= mousestate & SDL_BUTTON(2)?DOWN:UP;
3550 
3551 			mouse.pure_buttons = mouse.buttons;
3552 
3553 			if (flipMouseButtons)
3554 			{
3555 				std::swap(mouse.buttons.left, mouse.buttons.right);
3556 			}
3557 		}
3558 		else
3559 		{
3560 			mouse.buttons.left = mouse.buttons.right = mouse.buttons.middle = UP;
3561 		}
3562 
3563 		mouse.scrollWheelChange = 0;
3564 		mouse.change = Vector(0,0);
3565 	}
3566 
3567 
3568 
3569 
3570 
3571 	SDL_Event event;
3572 
3573 
3574 
3575 	while ( SDL_PollEvent (&event) ) {
3576 		switch (event.type) {
3577 			case SDL_KEYDOWN:
3578 			{
3579 				#if __APPLE__
3580 					#if SDL_VERSION_ATLEAST(2, 0, 0)
3581 						if ((event.key.keysym.sym == SDLK_q) && (event.key.keysym.mod & KMOD_GUI))
3582 					#else
3583 						if ((event.key.keysym.sym == SDLK_q) && (event.key.keysym.mod & KMOD_META))
3584 					#endif
3585 				#else
3586 				if ((event.key.keysym.sym == SDLK_F4) && (event.key.keysym.mod & KMOD_ALT))
3587 				#endif
3588 				{
3589 					quitNestedMain();
3590 					quit();
3591 				}
3592 
3593 				if ((event.key.keysym.sym == SDLK_g) && (event.key.keysym.mod & KMOD_CTRL))
3594 				{
3595 					// toggle mouse grab with the magic hotkey.
3596 					grabInputOnReentry = (grabInputOnReentry)?0:-1;
3597 					setReentryInputGrab(1);
3598 				}
3599 				else if (_hasFocus)
3600 				{
3601 					keys[mapSDLKeyToGameKey(event.key.keysym.sym)] = 1;
3602 				}
3603 			}
3604 			break;
3605 
3606 			case SDL_KEYUP:
3607 			{
3608 				if (_hasFocus)
3609 				{
3610 					keys[mapSDLKeyToGameKey(event.key.keysym.sym)] = 0;
3611 				}
3612 			}
3613 			break;
3614 
3615 			case SDL_MOUSEMOTION:
3616 			{
3617 				if (_hasFocus && updateMouse)
3618 				{
3619 					mouse.lastPosition = mouse.position;
3620 
3621 					mouse.position.x = ((event.motion.x) * (float(virtualWidth)/float(getWindowWidth()))) - getVirtualOffX();
3622 					mouse.position.y = event.motion.y * (float(virtualHeight)/float(getWindowHeight()));
3623 
3624 					mouse.change = mouse.position - mouse.lastPosition;
3625 
3626 					if (doMouseConstraint()) warpMouse = true;
3627 				}
3628 			}
3629 			break;
3630 
3631 			#ifdef BBGE_BUILD_SDL2
3632 			case SDL_WINDOWEVENT:
3633 			{
3634 				if (event.window.event == SDL_WINDOWEVENT_CLOSE)
3635 				{
3636 					SDL_Quit();
3637 					_exit(0);
3638 					//loopDone = true;
3639 					//quit();
3640 				}
3641 			}
3642 			break;
3643 
3644 			case SDL_MOUSEWHEEL:
3645 			{
3646 				if (_hasFocus && updateMouse)
3647 				{
3648 					if (event.wheel.y > 0)
3649 						mouse.scrollWheelChange = 1;
3650 					else if (event.wheel.y < 0)
3651 						mouse.scrollWheelChange = -1;
3652 				}
3653 			}
3654 			break;
3655 			#else
3656 			case SDL_MOUSEBUTTONDOWN:
3657 			{
3658 				if (_hasFocus && updateMouse)
3659 				{
3660 					switch(event.button.button)
3661 					{
3662 					case 4:
3663 						mouse.scrollWheelChange = 1;
3664 					break;
3665 					case 5:
3666 						mouse.scrollWheelChange = -1;
3667 					break;
3668 					}
3669 				}
3670 			}
3671 			break;
3672 
3673 			case SDL_MOUSEBUTTONUP:
3674 			{
3675 				if (_hasFocus && updateMouse)
3676 				{
3677 					switch(event.button.button)
3678 					{
3679 					case 4:
3680 						mouse.scrollWheelChange = 1;
3681 					break;
3682 					case 5:
3683 						mouse.scrollWheelChange = -1;
3684 					break;
3685 					}
3686 				}
3687 			}
3688 			break;
3689 			#endif
3690 
3691 			case SDL_QUIT:
3692 				SDL_Quit();
3693 				_exit(0);
3694 				//loopDone = true;
3695 				//quit();
3696 			break;
3697 
3698 			case SDL_SYSWMEVENT:
3699 			{
3700 				/*
3701 				debugLog("SYSWM!");
3702 				if (event.syswm.type == WM_ACTIVATE)
3703 				{
3704 					debugLog("ACTIVE");
3705 					this->unloadDevice();
3706 					this->reloadDevice();
3707 				}
3708 				else
3709 				{
3710 					debugLog("NOT ACTIVE");
3711 					this->unloadDevice();
3712 				}
3713 				*/
3714 			}
3715 			break;
3716 
3717 			default:
3718 			break;
3719 		}
3720 	}
3721 
3722 	if (updateMouse)
3723 	{
3724 		mouse.scrollWheel += mouse.scrollWheelChange;
3725 
3726 		if (warpMouse)
3727 		{
3728 			setMousePosition(mouse.position);
3729 		}
3730 	}
3731 
3732 #endif
3733 }
3734 
3735 #define _VLN(x, y, x2, y2) glVertex2f(x, y); glVertex2f(x2, y2);
3736 
print(int x,int y,const char * str,float sz)3737 void Core::print(int x, int y, const char *str, float sz)
3738 {
3739 	//Prof(Core_print);
3740 	/*
3741 	glLoadIdentity();
3742 	core->setupRenderPositionAndScale();
3743 	*/
3744 	///glPushAttrib(GL_ALL_ATTRIB_BITS);
3745 
3746 #ifdef BBGE_BUILD_OPENGL
3747 	glBindTexture(GL_TEXTURE_2D, 0);
3748 
3749 	glPushMatrix();
3750 	//sz *= 8;
3751 	//float osz = sz;
3752 	float xx = x;
3753 	float yy = y;
3754 	glTranslatef(x, y-0.5f*sz, 0);
3755 	x = y = 0;
3756 	xx = 0; yy = 0;
3757 	bool isLower = false, wasLower = false;
3758 	int c=0;
3759 
3760 	/*
3761 	if (a == 1)
3762 		glDisable(GL_BLEND);
3763 	else
3764 		glEnable(GL_BLEND);
3765 	glColor4f(r,g,b,a);
3766 	*/
3767 	glLineWidth(1);
3768 	glScalef(sz*0.75f, sz, 1);
3769 
3770 	glBegin(GL_LINES);
3771 
3772 	while (str[c] != '\0')
3773 	{
3774 		if (str[c] <= 'z' && str[c] >= 'a')
3775 			isLower = true;
3776 		else
3777 			isLower = false;
3778 
3779 		/*
3780 		if (isLower)
3781 			glScalef(sz*0.5f, sz*0.5f, 1);
3782 		else if (wasLower)
3783 		{
3784 			glScalef(sz, sz, 1);
3785 			wasLower = false;
3786 		}
3787 		*/
3788 
3789 		switch(toupper(str[c]))
3790 		{
3791 		case '_':
3792 			_VLN(xx, y+1, xx+1, y+1)
3793 		break;
3794 		case '-':
3795 			_VLN(xx, y+0.5f, xx+1, y+0.5f)
3796 		break;
3797 		case '~':
3798 			_VLN(xx, y+0.5f, xx+0.25f, y+0.4f)
3799 			_VLN(xx+0.25f, y+0.4f, xx+0.75f, y+0.6f)
3800 			_VLN(xx+0.75f, y+0.6f, xx+1, y+0.5f)
3801 		break;
3802 		case 'A':
3803 			_VLN(xx, y, xx+1, y)
3804 			_VLN(xx+1, y, xx+1, y+1)
3805 			_VLN(xx, y, xx, y+1)
3806 			_VLN(xx, y+0.5f, xx+1, y+0.5f)
3807 		break;
3808 		case 'B':
3809 			_VLN(xx, y, xx+1, y)
3810 			_VLN(xx+1, y, xx+1, y+1)
3811 			_VLN(xx, y, xx, y+1)
3812 			_VLN(xx, y+0.5f, xx+1, y+0.5f)
3813 			_VLN(xx, y+1, xx+1, y+1)
3814 		break;
3815 		case 'C':
3816 			_VLN(xx, y, xx+1, y)
3817 			_VLN(xx, y, xx, y+1)
3818 			_VLN(xx, y+1, xx+1, y+1)
3819 		break;
3820 		case 'D':
3821 			_VLN(xx, y, xx+1, y+0.2f)
3822 			_VLN(xx, y, xx, y+1)
3823 			_VLN(xx, y+1, xx+1, y+1)
3824 			_VLN(xx+1, y+0.2f, xx+1, y+1)
3825 		break;
3826 		case 'E':
3827 			_VLN(xx, y, xx+1, y)
3828 			_VLN(xx, y, xx, y+1)
3829 			_VLN(xx, y+0.5f, xx+1, y+0.5f)
3830 			_VLN(xx, y+1, xx+1, y+1)
3831 		break;
3832 		case 'F':
3833 			_VLN(xx, y, xx+1, y)
3834 			_VLN(xx, y, xx, y+1)
3835 			_VLN(xx, y+0.5f, xx+1, y+0.5f)
3836 		break;
3837 		case 'G':
3838 			_VLN(xx, y, xx+1, y)
3839 			_VLN(xx, y, xx, y+1)
3840 			_VLN(xx, y+1, xx+1, y+1)
3841 			_VLN(xx+1, y+0.5f, xx+1, y+1)
3842 		break;
3843 		case 'H':
3844 			_VLN(xx, y, xx, y+1)
3845 			_VLN(xx, y+0.5f, xx+1, y+0.5f)
3846 			_VLN(xx+1, y, xx+1, y+1)
3847 		break;
3848 		case 'I':
3849 			_VLN(xx+0.5f, y, xx+0.5f, y+1)
3850 			_VLN(xx, y, xx+1, y)
3851 			_VLN(xx, y+1, xx+1, y+1)
3852 		break;
3853 		case 'J':
3854 			_VLN(xx+1, y, xx+1, y+1)
3855 			_VLN(xx, y, xx+1, y)
3856 			_VLN(xx, y+1, xx+1, y+1)
3857 			_VLN(xx, y+1, xx, y+0.75f)
3858 		break;
3859 		case 'K':
3860 			_VLN(xx, y, xx, y+1)
3861 			_VLN(xx, y+0.25f, xx+1, y)
3862 			_VLN(xx, y+0.25f, xx+1, y+1)
3863 		break;
3864 		case 'L':
3865 			_VLN(xx, y, xx, y+1)
3866 			_VLN(xx, y+1, xx+1, y+1)
3867 		break;
3868 		case 'M':
3869 			_VLN(xx, y, xx, y+1)
3870 			_VLN(xx+1, y, xx+1, y+1)
3871 			_VLN(xx, y, xx+0.5f, y+0.5f)
3872 			_VLN(xx+1, y, xx+0.5f, y+0.5f)
3873 		break;
3874 		case 'N':
3875 			_VLN(xx, y, xx, y+1)
3876 			_VLN(xx+1, y, xx+1, y+1)
3877 			_VLN(xx, y, xx+1, y+1)
3878 		break;
3879 		case 'O':
3880 			_VLN(xx, y, xx, y+1)
3881 			_VLN(xx+1, y, xx+1, y+1)
3882 			_VLN(xx, y+1, xx+1, y+1)
3883 			_VLN(xx, y, xx+1, y)
3884 		break;
3885 		case 'P':
3886 			_VLN(xx, y, xx+1, y)
3887 			_VLN(xx, y, xx, y+1)
3888 			_VLN(xx, y+0.5f, xx+1, y+0.5f)
3889 			_VLN(xx+1, y+0.5f, xx+1, y)
3890 		break;
3891 		case 'Q':
3892 			_VLN(xx, y, xx, y+1)
3893 			_VLN(xx+1, y, xx+1, y+1)
3894 			_VLN(xx, y+1, xx+1, y+1)
3895 			_VLN(xx, y, xx+1, y)
3896 			_VLN(xx, y+0.5f, xx+1.25f, y+1.25f)
3897 		break;
3898 		case 'R':
3899 			_VLN(xx, y, xx+1, y)
3900 			_VLN(xx, y, xx, y+1)
3901 			_VLN(xx, y+0.5f, xx+1, y+0.5f)
3902 			_VLN(xx+1, y+0.5f, xx+1, y)
3903 			_VLN(xx, y+0.5f, xx+1, y+1)
3904 		break;
3905 		case 'S':
3906 			_VLN(xx, y, xx+1, y)
3907 			_VLN(xx, y, xx, y+0.5f)
3908 			_VLN(xx, y+0.5f, xx+1, y+0.5f)
3909 			_VLN(xx+1, y+0.5f, xx+1, y+1)
3910 			_VLN(xx, y+1, xx+1, y+1)
3911 		break;
3912 		case 'T':
3913 			_VLN(xx, y, xx+1, y)
3914 			_VLN(xx+0.5f, y, xx+0.5f, y+1)
3915 		break;
3916 		case 'U':
3917 			_VLN(xx, y+1, xx+1, y+1)
3918 			_VLN(xx, y, xx, y+1)
3919 			_VLN(xx+1, y, xx+1, y+1)
3920 		break;
3921 		case 'V':
3922 			_VLN(xx, y, xx+0.5f, y+1)
3923 			_VLN(xx+1, y, xx+0.5f, y+1)
3924 		break;
3925 		case 'W':
3926 			_VLN(xx, y, xx+0.25f, y+1)
3927 			_VLN(xx+0.25f, y+1, xx+0.5f, y+0.5f)
3928 			_VLN(xx+0.5f, y+0.5f, xx+0.75f, y+1)
3929 			_VLN(xx+1, y, xx+0.75f, y+1)
3930 		break;
3931 		case 'X':
3932 			_VLN(xx, y, xx+1, y+1)
3933 			_VLN(xx+1, y, xx, y+1)
3934 		break;
3935 		case 'Y':
3936 			_VLN(xx, y, xx+0.5f, y+0.5f)
3937 			_VLN(xx+1, y, xx+0.5f, y+0.5f)
3938 			_VLN(xx+0.5f, y+0.5f, xx+0.5f, y+1)
3939 		break;
3940 		case 'Z':
3941 			_VLN(xx, y, xx+1, y)
3942 			_VLN(xx, y+1, xx+1, y)
3943 			_VLN(xx, y+1, xx+1, y+1)
3944 		break;
3945 
3946 		case '1':
3947 			_VLN(xx+0.5f, y, xx+0.5f, y+1)
3948 			_VLN(xx, y+1, xx+1, y+1)
3949 			_VLN(xx+0.5f, y, xx+0.25f, y+0.25f)
3950 		break;
3951 		case '2':
3952 			_VLN(xx, y, xx+1, y)
3953 			_VLN(xx+1, y, xx+1, y+0.5f)
3954 			_VLN(xx+1, y+0.5f, xx, y+0.5f)
3955 			_VLN(xx, y+0.5f, xx, y+1)
3956 			_VLN(xx, y+1, xx+1, y+1)
3957 		break;
3958 		case '3':
3959 			_VLN(xx, y, xx+1, y)
3960 			_VLN(xx, y+1, xx+1, y+1)
3961 			_VLN(xx, y+0.5f, xx+1, y+0.5f)
3962 			_VLN(xx+1, y, xx+1, y+1)
3963 		break;
3964 		case '4':
3965 			_VLN(xx+1, y, xx+1, y+1)
3966 			_VLN(xx+1, y, xx, y+0.5f)
3967 			_VLN(xx, y+0.5f, xx+1, y+0.5f)
3968 		break;
3969 		case '5':
3970 			_VLN(xx, y, xx+1, y)
3971 			_VLN(xx, y, xx, y+0.5f)
3972 			_VLN(xx+1, y+0.5f, xx, y+0.5f)
3973 			_VLN(xx+1, y+0.5f, xx+1, y+1)
3974 			_VLN(xx, y+1, xx+1, y+1)
3975 		break;
3976 		case '6':
3977 			_VLN(xx, y, xx+1, y)
3978 			_VLN(xx, y, xx, y+1)
3979 			_VLN(xx+1, y+0.5f, xx, y+0.5f)
3980 			_VLN(xx+1, y+0.5f, xx+1, y+1)
3981 			_VLN(xx, y+1, xx+1, y+1)
3982 		break;
3983 		case '7':
3984 			_VLN(xx+1, y, xx+0.5f, y+1)
3985 			_VLN(xx, y, xx+1, y)
3986 		break;
3987 		case '8':
3988 			_VLN(xx, y, xx+1, y)
3989 			_VLN(xx+1, y, xx+1, y+1)
3990 			_VLN(xx, y, xx, y+1)
3991 			_VLN(xx, y+0.5f, xx+1, y+0.5f)
3992 			_VLN(xx, y+1, xx+1, y+1)
3993 		break;
3994 		case '9':
3995 			_VLN(xx, y, xx+1, y)
3996 			_VLN(xx+1, y, xx+1, y+1)
3997 			_VLN(xx, y+0.5f, xx+1, y+0.5f)
3998 			_VLN(xx, y+0.5f, xx, y)
3999 		break;
4000 		case '0':
4001 			_VLN(xx, y, xx, y+1)
4002 			_VLN(xx+1, y, xx+1, y+1)
4003 			_VLN(xx, y+1, xx+1, y+1)
4004 			_VLN(xx, y, xx+1, y)
4005 			_VLN(xx, y, xx+1, y+1)
4006 		break;
4007 		case '.':
4008 			_VLN(xx+0.4f, y+1, xx+0.6f, y+1)
4009 		break;
4010 		case ',':
4011 			_VLN(xx+0.5f, y+0.75f, xx+0.5f, y+1.0f);
4012 			_VLN(xx+0.5f, y+1.0f, xx+0.2f, y+1.25f);
4013 		break;
4014 		case ' ':
4015 		break;
4016 		case '(':
4017 		case '[':
4018 			_VLN(xx, y, xx, y+1);
4019 			_VLN(xx, y, xx+0.25f, y);
4020 			_VLN(xx, y+1, xx+0.25f, y+1);
4021 		break;
4022 		case ')':
4023 		case ']':
4024 			_VLN(xx+1, y, xx+1, y+1);
4025 			_VLN(xx+1, y, xx+0.75f, y);
4026 			_VLN(xx+1, y+1, xx+0.75f, y+1);
4027 		break;
4028 		case ':':
4029 			_VLN(xx+0.5f, y, xx+0.5f, y+0.25f);
4030 			_VLN(xx+0.5f, y+0.75f, xx+0.5f, y+1);
4031 		break;
4032 		case '/':
4033 			_VLN(xx, y+1, xx+1, y);
4034 		break;
4035 		default:
4036 			/*
4037 			std::ostringstream os;
4038 			os << "Core::print doesn't know char: " << str[c];
4039 			debugLog(os.str());
4040 			*/
4041 		break;
4042 		}
4043 		if (isLower)
4044 		{
4045 			wasLower = true;
4046 
4047 		}
4048 		c++;
4049 		xx += 1.4f;
4050 	}
4051 	glEnd();
4052 
4053 	glPopMatrix();
4054 	//glPopAttrib();
4055 
4056 #endif
4057 }
4058 
cacheRender()4059 void Core::cacheRender()
4060 {
4061 	render();
4062 	// what if the screen was full white? then you wouldn't want to clear buffers
4063 	//clearBuffers();
4064 	showBuffer();
4065 	resetTimer();
4066 }
4067 
updateCullData()4068 void Core::updateCullData()
4069 {
4070 	cullRadius = baseCullRadius * invGlobalScale;
4071 	cullRadiusSqr = cullRadius * cullRadius;
4072 	screenCenter = cullCenter = cameraPos + Vector(400.0f*invGlobalScale,300.0f*invGlobalScale);
4073 }
4074 
render(int startLayer,int endLayer,bool useFrameBufferIfAvail)4075 void Core::render(int startLayer, int endLayer, bool useFrameBufferIfAvail)
4076 {
4077 
4078 	BBGE_PROF(Core_render);
4079 	//HWND hwnd = _glfwWin.Wnd;
4080 
4081 	if (startLayer == -1 && endLayer == -1 && overrideStartLayer != 0)
4082 	{
4083 		startLayer = overrideStartLayer;
4084 		endLayer = overrideEndLayer;
4085 	}
4086 
4087 	globalScaleChanged();
4088 
4089 	if (core->minimized) return;
4090 	onRender();
4091 
4092 	RenderObject::lastTextureApplied = 0;
4093 
4094 	updateCullData();
4095 
4096 
4097 
4098 	renderObjectCount = 0;
4099 	processedRenderObjectCount = 0;
4100 	totalRenderObjectCount = 0;
4101 
4102 
4103 #ifdef BBGE_BUILD_OPENGL
4104 	glBindTexture(GL_TEXTURE_2D, 0);
4105 	glLoadIdentity();									// Reset The View
4106 	clearBuffers();
4107 
4108 	if (afterEffectManager && frameBuffer.isInited() && useFrameBufferIfAvail)
4109 	{
4110 		frameBuffer.startCapture();
4111 	}
4112 
4113 	setupRenderPositionAndScale();
4114 #endif
4115 
4116 #ifdef BBGE_BUILD_DIRECTX
4117 	bool doRender = false;
4118 
4119 	core->getD3DMatrixStack()->LoadIdentity();
4120 
4121 
4122 	core->scaleMatrixStack(globalScale.x*globalResolutionScale.x, globalScale.y*globalResolutionScale.y);
4123 	core->translateMatrixStack(-(cameraPos.x+cameraOffset.x), -(cameraPos.y+cameraOffset.y));
4124 
4125 	clearBuffers();
4126 	if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
4127     {
4128 		doRender = true;
4129 		//d3dSprite->Begin(D3DXSPRITE_BILLBOARD | D3DXSPRITE_ALPHABLEND);
4130     }
4131 
4132 #endif
4133 
4134 
4135 	/*
4136 	//default
4137 	if (renderObjectLayerOrder.empty())
4138 	{
4139 		renderObjectLayerOrder.resize(renderObjectLayers.size());
4140 		for (int i = 0; i < renderObjectLayerOrder.size(); i++)
4141 		{
4142 			renderObjectLayerOrder[i] = i;
4143 		}
4144 	}
4145 	*/
4146 	RenderObject::rlayer = 0;
4147 
4148 	for (int c = 0; c < renderObjectLayerOrder.size(); c++)
4149 	//for (int i = 0; i < renderObjectLayers.size(); i++)
4150 	{
4151 		int i = renderObjectLayerOrder[c];
4152 		if (i == -1) continue;
4153 		if ((startLayer != -1 && endLayer != -1) && (i < startLayer || i > endLayer)) continue;
4154 
4155 		if (i == postProcessingFx.layer)
4156 		{
4157 			postProcessingFx.preRender();
4158 		}
4159 		if (i == postProcessingFx.renderLayer)
4160 		{
4161 			postProcessingFx.render();
4162 		}
4163 
4164 		if (darkLayer.isUsed() )
4165 		{
4166 			/*
4167 			if (i == darkLayer.getLayer())
4168 			{
4169 				darkLayer.preRender();
4170 			}
4171 			*/
4172 			if (i == darkLayer.getRenderLayer())
4173 			{
4174 				darkLayer.render();
4175 			}
4176 
4177 			if (i == darkLayer.getLayer() && startLayer != i)
4178 			{
4179 				continue;
4180 			}
4181 		}
4182 
4183 		if (afterEffectManager && afterEffectManager->active && i == afterEffectManagerLayer)
4184 		{
4185 			afterEffectManager->render();
4186 		}
4187 
4188 		RenderObjectLayer *r = &renderObjectLayers[i];
4189 		RenderObject::rlayer = r;
4190 		if (r->visible)
4191 		{
4192 			if (r->startPass == r->endPass)
4193 			{
4194 				r->renderPass(RenderObject::RENDER_ALL);
4195 			}
4196 			else
4197 			{
4198 				for (int pass = r->startPass; pass <= r->endPass; pass++)
4199 				{
4200 					r->renderPass(pass);
4201 				}
4202 			}
4203 		}
4204 	}
4205 
4206 #ifdef BBGE_BUILD_DIRECTX
4207 	if (doRender)
4208 	{
4209 		// End the scene
4210 		//d3dSprite->End();
4211 		//core->getD3DMatrixStack()->Pop();
4212 		g_pd3dDevice->EndScene();
4213 	}
4214 #endif
4215 
4216 }
4217 
showBuffer()4218 void Core::showBuffer()
4219 {
4220 	BBGE_PROF(Core_showBuffer);
4221 #ifdef BBGE_BUILD_SDL2
4222 	SDL_GL_SwapWindow(gScreen);
4223 #elif BBGE_BUILD_SDL
4224 	SDL_GL_SwapBuffers();
4225 	//glFlush();
4226 #endif
4227 
4228 #ifdef BBGE_BUILD_GLFW
4229 	glfwSwapBuffers();
4230 	//_glfwPlatSwapBuffers();
4231 #endif
4232 #ifdef BBGE_BUILD_DIRECTX
4233 	// Present the backbuffer contents to the display
4234     g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
4235 #endif
4236 }
4237 
4238 // WARNING: only for use during shutdown
4239 // otherwise, textures will try to remove themselves
4240 // when destroy is called on them
clearResources()4241 void Core::clearResources()
4242 {
4243 	if(resources.size())
4244 	{
4245 		debugLog("Warning: The following resources were not cleared:");
4246 		for(size_t i = 0; i < resources.size(); ++i)
4247 			debugLog(resources[i]->name);
4248 		resources.clear(); // nothing we can do; refcounting is messed up
4249 	}
4250 }
4251 
shutdownInputLibrary()4252 void Core::shutdownInputLibrary()
4253 {
4254 #if defined(BBGE_BUILD_WINDOWS) && !defined(BBGE_BUILD_SDL)
4255 	g_pKeyboard->Unacquire();
4256 	g_pKeyboard->Release();
4257 	g_pKeyboard = 0;
4258 	g_pMouse->Unacquire();
4259 	g_pMouse->Release();
4260 	g_pMouse = 0;
4261 #endif
4262 }
4263 
shutdownJoystickLibrary()4264 void Core::shutdownJoystickLibrary()
4265 {
4266 	if (joystickEnabled) {
4267 		joystick.shutdown();
4268 #ifdef BBGE_BUIDL_SDL
4269 		SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
4270 #endif
4271 		joystickEnabled = false;
4272 	}
4273 }
4274 
clearRenderObjects()4275 void Core::clearRenderObjects()
4276 {
4277 	for (int i = 0; i < renderObjectLayers.size(); i++)
4278 	{
4279 		/*
4280 		for (int j = 0; j < renderObjectLayers[i].renderObjects.size(); j++)
4281 		{
4282 			RenderObject *r = renderObjectLayers[i].renderObjects[j];
4283 		*/
4284 		RenderObject *r = renderObjectLayers[i].getFirst();
4285 		while (r)
4286 		{
4287 			if (r)
4288 			{
4289 				removeRenderObject(r, DESTROY_RENDER_OBJECT);
4290 			}
4291 			r = renderObjectLayers[i].getNext();
4292 		}
4293 	}
4294 }
4295 
shutdown()4296 void Core::shutdown()
4297 {
4298 	// pop all the states
4299 
4300 
4301 	debugLog("Core::shutdown");
4302 	shuttingDown = true;
4303 
4304 	debugLog("Shutdown Joystick Library...");
4305 		shutdownJoystickLibrary();
4306 	debugLog("OK");
4307 
4308 	debugLog("Shutdown Input Library...");
4309 		shutdownInputLibrary();
4310 	debugLog("OK");
4311 
4312 	debugLog("Shutdown All States...");
4313 		popAllStates();
4314 	debugLog("OK");
4315 
4316 	debugLog("Clear State Instances...");
4317 		clearStateInstances();
4318 	debugLog("OK");
4319 
4320 	debugLog("Clear All Remaining RenderObjects...");
4321 		clearRenderObjects();
4322 	debugLog("OK");
4323 
4324 	debugLog("Clear All Resources...");
4325 		clearResources();
4326 	debugLog("OK");
4327 
4328 
4329 	debugLog("Clear State Objects...");
4330 		clearStateObjects();
4331 	debugLog("OK");
4332 
4333 	if (afterEffectManager)
4334 	{
4335 		debugLog("Delete AEManager...");
4336 			delete afterEffectManager;
4337 			afterEffectManager = 0;
4338 		debugLog("OK");
4339 	}
4340 
4341 
4342 	if (sound)
4343 	{
4344 		debugLog("Shutdown Sound Library...");
4345 			sound->stopAll();
4346 			delete sound;
4347 			sound = 0;
4348 		debugLog("OK");
4349 	}
4350 
4351 	debugLog("Core's framebuffer...");
4352 		frameBuffer.unloadDevice();
4353 	debugLog("OK");
4354 
4355 	debugLog("Shutdown Graphics Library...");
4356 		shutdownGraphicsLibrary();
4357 	debugLog("OK");
4358 
4359 
4360 
4361 #ifdef BBGE_BUILD_GLFW
4362 	debugLog("Terminate GLFW...");
4363 		//killGlWindow();
4364 		glfwTerminate();
4365 	debugLog("OK");
4366 #endif
4367 
4368 #ifdef BBGE_BUILD_VFS
4369 	debugLog("Unload VFS...");
4370 		vfs.Clear();
4371 	debugLog("OK");
4372 #endif
4373 
4374 
4375 #ifdef BBGE_BUILD_SDL
4376 	debugLog("SDL Quit...");
4377 		SDL_Quit();
4378 	debugLog("OK");
4379 #endif
4380 }
4381 
4382 //util funcs
4383 
instantQuit()4384 void Core::instantQuit()
4385 {
4386 #ifdef BBGE_BUILD_SDL
4387     SDL_Event event;
4388     event.type = SDL_QUIT;
4389     SDL_PushEvent(&event);
4390 #endif
4391 }
4392 
exists(const std::string & filename)4393 bool Core::exists(const std::string &filename)
4394 {
4395 	return ::exists(filename, false); // defined in Base.cpp
4396 }
4397 
findTexture(const std::string & name)4398 CountedPtr<Texture> Core::findTexture(const std::string &name)
4399 {
4400 	//stringToUpper(name);
4401 	//std::ofstream out("texturefind.log");
4402 	int sz = resources.size();
4403 	for (int i = 0; i < sz; i++)
4404 	{
4405 		//out << resources[i]->name << " is " << name << " ?" << std::endl;
4406 		//NOTE: ensure all names are lowercase before this point
4407 		if (resources[i]->name == name)
4408 		{
4409 			return resources[i];
4410 		}
4411 	}
4412 	return 0;
4413 }
4414 
4415 // This handles unix/win32 relative paths: ./rel/path
4416 // Unix abs paths: /home/user/...
4417 // Win32 abs paths: C:/Stuff/.. and also C:\Stuff\...
4418 #define ISPATHROOT(x) (x[0] == '.' || x[0] == '/' || ((x).length() > 1 && x[1] == ':'))
4419 
getTextureLoadName(const std::string & texture)4420 std::string Core::getTextureLoadName(const std::string &texture)
4421 {
4422 	std::string loadName = texture;
4423 
4424 	if (texture.empty() || !ISPATHROOT(texture))
4425 	{
4426 		if (texture.find(baseTextureDirectory) == std::string::npos)
4427 			loadName = baseTextureDirectory + texture;
4428 	}
4429 	return loadName;
4430 }
4431 
doTextureAdd(const std::string & texture,const std::string & loadName,std::string internalTextureName)4432 std::pair<CountedPtr<Texture>, TextureLoadResult> Core::doTextureAdd(const std::string &texture, const std::string &loadName, std::string internalTextureName)
4433 {
4434 	if (texture.empty() || !ISPATHROOT(texture))
4435 	{
4436 		if (texture.find(baseTextureDirectory) != std::string::npos)
4437 			internalTextureName = internalTextureName.substr(baseTextureDirectory.size(), internalTextureName.size());
4438 	}
4439 
4440 	if (internalTextureName.size() > 4)
4441 	{
4442 		if (internalTextureName[internalTextureName.size()-4] == '.')
4443 		{
4444 			internalTextureName = internalTextureName.substr(0, internalTextureName.size()-4);
4445 		}
4446 	}
4447 
4448 	stringToLowerUserData(internalTextureName);
4449 	CountedPtr<Texture> t = core->findTexture(internalTextureName);
4450 	if (t)
4451 		return std::make_pair(t, TEX_SUCCESS);
4452 
4453 	t = new Texture;
4454 	t->name = internalTextureName;
4455 	unsigned res = TEX_FAILED;
4456 
4457 	if(t->load(loadName))
4458 		res |= (TEX_LOADED | TEX_SUCCESS);
4459 	else
4460 	{
4461 		t->width = 64;
4462 		t->height = 64;
4463 	}
4464 
4465 	return std::make_pair(t, (TextureLoadResult)res);
4466 }
4467 
addTexture(const std::string & textureName,TextureLoadResult * pLoadResult)4468 CountedPtr<Texture> Core::addTexture(const std::string &textureName, TextureLoadResult *pLoadResult /* = 0 */)
4469 {
4470 	BBGE_PROF(Core_addTexture);
4471 
4472 	if (textureName.empty())
4473 	{
4474 		if(pLoadResult)
4475 			*pLoadResult = TEX_FAILED;
4476 		return NULL;
4477 	}
4478 
4479 	std::pair<CountedPtr<Texture>, TextureLoadResult> texResult;
4480 	std::string texture = textureName;
4481 	stringToLowerUserData(texture);
4482 	std::string internalTextureName = texture;
4483 	std::string loadName = getTextureLoadName(texture);
4484 
4485 	if (!texture.empty() && texture[0] == '@')
4486 	{
4487 		texture = secondaryTexturePath + texture.substr(1, texture.size());
4488 		loadName = texture;
4489 	}
4490 	else if (!secondaryTexturePath.empty() && texture[0] != '.' && texture[0] != '/')
4491 	{
4492 		std::string t = texture;
4493 		std::string ln = loadName;
4494 		texture = secondaryTexturePath + texture;
4495 		loadName = texture;
4496 		texResult = doTextureAdd(texture, loadName, internalTextureName);
4497 		if (!texResult.second)
4498 			texResult = doTextureAdd(t, ln, internalTextureName);
4499 	}
4500 	else
4501 		texResult = doTextureAdd(texture, loadName, internalTextureName);
4502 
4503 	addTexture(texResult.first.content());
4504 
4505 	if(debugLogTextures)
4506 	{
4507 		if (texResult.second & TEX_LOADED)
4508 		{
4509 			std::ostringstream os;
4510 			os << "LOADED TEXTURE FROM DISK: [" << internalTextureName << "] idx: " << resources.size()-1;
4511 			debugLog(os.str());
4512 		}
4513 		else if(!(texResult.second & TEX_SUCCESS))
4514 		{
4515 			std::ostringstream os;
4516 			os << "FAILED TO LOAD TEXTURE: [" << internalTextureName << "] idx: " << resources.size()-1;
4517 			debugLog(os.str());
4518 		}
4519 	}
4520 	if(pLoadResult)
4521 		*pLoadResult = texResult.second;
4522 	return texResult.first;
4523 }
4524 
addRenderObject(RenderObject * o,int layer)4525 void Core::addRenderObject(RenderObject *o, int layer)
4526 {
4527 	if (!o) return;
4528 	o->layer = layer;
4529 	if (layer < 0 || layer >= renderObjectLayers.size())
4530 	{
4531 		std::ostringstream os;
4532 		os << "attempted to add render object to invalid layer [" << layer << "]";
4533 		errorLog(os.str());
4534 	}
4535 	renderObjectLayers[layer].add(o);
4536 }
4537 
switchRenderObjectLayer(RenderObject * o,int toLayer)4538 void Core::switchRenderObjectLayer(RenderObject *o, int toLayer)
4539 {
4540 	if (!o) return;
4541 	renderObjectLayers[o->layer].remove(o);
4542 	renderObjectLayers[toLayer].add(o);
4543 	o->layer = toLayer;
4544 }
4545 
unloadResources()4546 void Core::unloadResources()
4547 {
4548 	for (int i = 0; i < resources.size(); i++)
4549 	{
4550 		resources[i]->unload();
4551 	}
4552 }
4553 
onReloadResources()4554 void Core::onReloadResources()
4555 {
4556 }
4557 
reloadResources()4558 void Core::reloadResources()
4559 {
4560 	for (int i = 0; i < resources.size(); i++)
4561 	{
4562 		resources[i]->reload();
4563 	}
4564 	onReloadResources();
4565 }
4566 
addTexture(Texture * r)4567 void Core::addTexture(Texture *r)
4568 {
4569 	for(size_t i = 0; i < resources.size(); ++i)
4570 		if(resources[i] == r)
4571 			return;
4572 
4573 	resources.push_back(r);
4574 	if (r->name.empty())
4575 	{
4576 		debugLog("Empty name resource added");
4577 	}
4578 }
4579 
removeTexture(Texture * res)4580 void Core::removeTexture(Texture *res)
4581 {
4582 	std::vector<Texture*> copy;
4583 	copy.swap(resources);
4584 
4585 	for (size_t i = 0; i < copy.size(); ++i)
4586 	{
4587 		if (copy[i] == res)
4588 		{
4589 			copy[i]->destroy();
4590 			copy[i] = copy.back();
4591 			copy.pop_back();
4592 			break;
4593 		}
4594 	}
4595 
4596 	resources.swap(copy);
4597 }
4598 
deleteRenderObjectMemory(RenderObject * r)4599 void Core::deleteRenderObjectMemory(RenderObject *r)
4600 {
4601 	//if (!r->allocStatic)
4602 	delete r;
4603 }
4604 
removeRenderObject(RenderObject * r,RemoveRenderObjectFlag flag)4605 void Core::removeRenderObject(RenderObject *r, RemoveRenderObjectFlag flag)
4606 {
4607 	if (r)
4608 	{
4609 		if (r->layer != LR_NONE && !renderObjectLayers[r->layer].empty())
4610 		{
4611 			renderObjectLayers[r->layer].remove(r);
4612 		}
4613 		if (flag != DO_NOT_DESTROY_RENDER_OBJECT )
4614 		{
4615 			r->destroy();
4616 
4617 			deleteRenderObjectMemory(r);
4618 		}
4619 	}
4620 }
4621 
4622 
enqueueRenderObjectDeletion(RenderObject * object)4623 void Core::enqueueRenderObjectDeletion(RenderObject *object)
4624 {
4625 	if (!object->_dead) // && !object->staticallyAllocated)
4626 	{
4627 		garbage.push_back (object);
4628 		object->_dead = true;
4629 	}
4630 }
4631 
clearGarbage()4632 void Core::clearGarbage()
4633 {
4634 	BBGE_PROF(Core_clearGarbage);
4635 	// HACK: optimize this (use a list instead of a queue)
4636 
4637 	for (RenderObjectList::iterator i = garbage.begin(); i != garbage.end(); i++)
4638 	{
4639 		removeRenderObject(*i, DO_NOT_DESTROY_RENDER_OBJECT);
4640 
4641 		(*i)->destroy();
4642 	}
4643 
4644 	for (RenderObjectList::iterator i = garbage.begin(); i != garbage.end(); i++)
4645 	{
4646 		deleteRenderObjectMemory(*i);
4647 	}
4648 
4649 	garbage.clear();
4650 }
4651 
canChangeState()4652 bool Core::canChangeState()
4653 {
4654 	return (nestedMains<=1);
4655 }
4656 
4657 /*
4658 int Core::getVirtualWidth()
4659 {
4660 	return virtualWidth;
4661 }
4662 
4663 int Core::getVirtualHeight()
4664 {
4665 	return virtualHeight;
4666 }
4667 */
4668 
4669 // Take a screenshot of the specified region of the screen and store it
4670 // in a 32bpp pixel buffer.  delete[] the returned buffer when it's no
4671 // longer needed.
grabScreenshot(int x,int y,int w,int h)4672 unsigned char *Core::grabScreenshot(int x, int y, int w, int h)
4673 {
4674 #ifdef BBGE_BUILD_OPENGL
4675 
4676 	unsigned char *imageData;
4677 
4678 	unsigned int size = sizeof(unsigned char) * w * h * 4;
4679 	imageData = new unsigned char[size];
4680 
4681 	glPushAttrib(GL_ALL_ATTRIB_BITS);
4682 	glDisable(GL_BLEND);
4683 	glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND);
4684 	glDisable(GL_DEPTH_TEST); glDisable(GL_DITHER); glDisable(GL_FOG);
4685 	glDisable(GL_LIGHTING); glDisable(GL_LOGIC_OP);
4686 	glDisable(GL_STENCIL_TEST); glDisable(GL_TEXTURE_1D);
4687 	glDisable(GL_TEXTURE_2D); glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
4688 	glPixelTransferi(GL_RED_SCALE, 1); glPixelTransferi(GL_RED_BIAS, 0);
4689 	glPixelTransferi(GL_GREEN_SCALE, 1); glPixelTransferi(GL_GREEN_BIAS, 0);
4690 	glPixelTransferi(GL_BLUE_SCALE, 1); glPixelTransferi(GL_BLUE_BIAS, 0);
4691 	glPixelTransferi(GL_ALPHA_SCALE, 1); glPixelTransferi(GL_ALPHA_BIAS, 0);
4692 	glRasterPos2i(0, 0);
4693 	glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)imageData);
4694 	glPopAttrib();
4695 
4696 	// Force all alpha values to 255.
4697 	unsigned char *c = imageData;
4698 	for (int x = 0; x < w; x++)
4699 	{
4700 		for (int y = 0; y < h; y++, c += 4)
4701 		{
4702 			c[3] = 255;
4703 		}
4704 	}
4705 
4706 	return imageData;
4707 
4708 #else
4709 
4710 	#warning FIXME: Need to implement non-GL grabScreenshot().
4711 	// Avoid crashing, at least.
4712 	return new unsigned char[sizeof(unsigned char) * w * h * 4];
4713 
4714 #endif
4715 }
4716 
4717 // Like grabScreenshot(), but grab from the center of the screen.
grabCenteredScreenshot(int w,int h)4718 unsigned char *Core::grabCenteredScreenshot(int w, int h)
4719 {
4720 	return grabScreenshot(core->width/2 - w/2, core->height/2 - h/2, w, h);
4721 }
4722 
4723 // takes a screen shot and saves it to a TGA image
saveScreenshotTGA(const std::string & filename)4724 int Core::saveScreenshotTGA(const std::string &filename)
4725 {
4726 	int w = getWindowWidth(), h = getWindowHeight();
4727 	unsigned char *imageData = grabCenteredScreenshot(w, h);
4728 	return tgaSave(filename.c_str(),w,h,32,imageData);
4729 }
4730 
saveCenteredScreenshotTGA(const std::string & filename,int sz)4731 void Core::saveCenteredScreenshotTGA(const std::string &filename, int sz)
4732 {
4733 	int w=sz, h=sz;
4734 	int hsm = (w * 3.0f) / 4.0f;
4735 	unsigned char *imageData = grabCenteredScreenshot(w, hsm);
4736 
4737 	int imageDataSize = sizeof(unsigned char) * w * hsm * 4;
4738 	int tgaImageSize = sizeof(unsigned char) * w * h * 4;
4739 	unsigned char *tgaImage = new unsigned char[tgaImageSize];
4740 	memcpy(tgaImage, imageData, imageDataSize);
4741 	memset(tgaImage + imageDataSize, 0, tgaImageSize - imageDataSize);
4742 	delete[] imageData;
4743 
4744 	int savebits = 32;
4745 	tgaSave(filename.c_str(),w,h,savebits,tgaImage);
4746 }
4747 
saveSizedScreenshotTGA(const std::string & filename,int sz,int crop34)4748 void Core::saveSizedScreenshotTGA(const std::string &filename, int sz, int crop34)
4749 {
4750 	debugLog("saveSizedScreenshot");
4751 
4752 	int w, h;
4753 	unsigned char *imageData;
4754 	w = sz;
4755 	h = sz;
4756 	float fsz = (float)sz;
4757 
4758 	unsigned int size = sizeof(unsigned char) * w * h * 3;
4759 	imageData = (unsigned char *)malloc(size);
4760 
4761 	float wbit = fsz;//+1;
4762 	float hbit = ((fsz)*(3.0f/4.0f));
4763 
4764 	int width = core->width-1;
4765 	int height = core->height-1;
4766 	int diff = 0;
4767 
4768 	if (crop34)
4769 	{
4770 		width = int((core->height*4.0f)/3.0f);
4771 		diff = (core->width - width)/2;
4772 		width--;
4773 	}
4774 
4775 	float zx = wbit/(float)width;
4776 	float zy = hbit/(float)height;
4777 
4778 	float copyw = w*(1/zx);
4779 	float copyh = h*(1/zy);
4780 
4781 
4782 
4783 	std::ostringstream os;
4784 	os << "wbit: " << wbit << " hbit: " << hbit << std::endl;
4785 	os << "zx: " << zx << " zy: " << zy << std::endl;
4786 	os << "w: " << w << " h: " << h << std::endl;
4787 	os << "width: " << width << " height: " << height << std::endl;
4788 	os << "copyw: " << copyw << " copyh: " << copyh << std::endl;
4789 	debugLog(os.str());
4790 
4791 	glRasterPos2i(0, 0);
4792 
4793 	/*
4794 	glPushAttrib(GL_ALL_ATTRIB_BITS);
4795 
4796 	glDisable(GL_BLEND);
4797 
4798 	glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND);
4799 	glDisable(GL_DEPTH_TEST); glDisable(GL_DITHER); glDisable(GL_FOG);
4800 	glDisable(GL_LIGHTING); glDisable(GL_LOGIC_OP);
4801 	glDisable(GL_STENCIL_TEST); glDisable(GL_TEXTURE_1D);
4802 	glDisable(GL_TEXTURE_2D); glPixelTransferi(GL_MAP_COLOR,
4803 		GL_FALSE); glPixelTransferi(GL_RED_SCALE, 1);
4804 	glPixelTransferi(GL_RED_BIAS, 0); glPixelTransferi(GL_GREEN_SCALE, 1);
4805 	glPixelTransferi(GL_GREEN_BIAS, 0); glPixelTransferi(GL_BLUE_SCALE, 1);
4806 	glPixelTransferi(GL_BLUE_BIAS, 0); glPixelTransferi(GL_ALPHA_SCALE, 1);
4807 	glPixelTransferi(GL_ALPHA_BIAS, 0);
4808 	*/
4809 
4810 	//glPixelStorei(GL_PACK_ALIGNMENT, 1);
4811 
4812 	debugLog("pixel zoom");
4813 	glPixelZoom(zx,zy);
4814 	glFlush();
4815 
4816 	glPixelZoom(1,1);
4817 	debugLog("copy pixels");
4818 	glCopyPixels(diff, 0, width, height, GL_COLOR);
4819 	glFlush();
4820 
4821 	debugLog("read pixels");
4822 	glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)imageData);
4823 	glFlush();
4824 
4825 	int savebits = 24;
4826 	debugLog("saving bpp");
4827 	tgaSave(filename.c_str(),w,h,savebits,imageData);
4828 
4829 	debugLog("pop");
4830 	//glPopAttrib();
4831 
4832 	debugLog("done");
4833 }
4834 
save64x64ScreenshotTGA(const std::string & filename)4835 void Core::save64x64ScreenshotTGA(const std::string &filename)
4836 {
4837 #ifdef BBGE_BUILD_OPENGL
4838 	int w, h;
4839 	unsigned char *imageData;
4840 
4841 // compute width and heidth of the image
4842 	//w = xmax - xmin;
4843 	//h = ymax - ymin;
4844 	w = 64;
4845 	h = 64;
4846 
4847 // allocate memory for the pixels
4848 	imageData = (unsigned char *)malloc(sizeof(unsigned char) * w * h * 4);
4849 
4850 // read the pixels from the frame buffer
4851 
4852 	//glReadPixels(xmin,ymin,xmax,ymax,GL_RGBA,GL_UNSIGNED_BYTE, (GLvoid *)imageData);
4853 	glPixelZoom(64.0f/(float)getVirtualWidth(), 48.0f/(float)getVirtualHeight());
4854 	glCopyPixels(0, 0, getVirtualWidth(), getVirtualHeight(), GL_COLOR);
4855 
4856 	glReadPixels(0,0,64,64,GL_RGBA,GL_UNSIGNED_BYTE, (GLvoid *)imageData);
4857 
4858 
4859 	unsigned char *c = imageData;
4860 	for (int x=0; x < w; x++)
4861 	{
4862 		for (int y=0; y< h; y++)
4863 		{
4864 			c += 3;
4865 			(*c) = 255;
4866 			c ++;
4867 		}
4868 	}
4869 
4870 
4871 // save the image
4872 	tgaSave(filename.c_str(),64,64,32,imageData);
4873 	glPixelZoom(1,1);
4874 #endif
4875 
4876 	// do NOT free imageData here
4877 	// it IS freed in tgaSave
4878 	//free(imageData);
4879 }
4880 
4881 
4882 
4883 
4884 // saves an array of pixels as a TGA image (frees the image data passed in)
tgaSave(const char * filename,short int width,short int height,unsigned char pixelDepth,unsigned char * imageData)4885 int Core::tgaSave(	const char	*filename,
4886 		short int	width,
4887 		short int	height,
4888 		unsigned char	pixelDepth,
4889 		unsigned char	*imageData) {
4890 
4891 	unsigned char cGarbage = 0, type,mode,aux;
4892 	short int iGarbage = 0;
4893 	int i;
4894 	FILE *file;
4895 
4896 // open file and check for errors
4897 	file = fopen(adjustFilenameCase(filename).c_str(), "wb");
4898 	if (file == NULL) {
4899 		delete [] imageData;
4900 		return (int)false;
4901 	}
4902 
4903 // compute image type: 2 for RGB(A), 3 for greyscale
4904 	mode = pixelDepth / 8;
4905 	if ((pixelDepth == 24) || (pixelDepth == 32))
4906 		type = 2;
4907 	else
4908 		type = 3;
4909 
4910 // write the header
4911 	if (fwrite(&cGarbage, sizeof(unsigned char), 1, file) != 1
4912 		|| fwrite(&cGarbage, sizeof(unsigned char), 1, file) != 1
4913 		|| fwrite(&type, sizeof(unsigned char), 1, file) != 1
4914 		|| fwrite(&iGarbage, sizeof(short int), 1, file) != 1
4915 		|| fwrite(&iGarbage, sizeof(short int), 1, file) != 1
4916 		|| fwrite(&cGarbage, sizeof(unsigned char), 1, file) != 1
4917 		|| fwrite(&iGarbage, sizeof(short int), 1, file) != 1
4918 		|| fwrite(&iGarbage, sizeof(short int), 1, file) != 1
4919 		|| fwrite(&width, sizeof(short int), 1, file) != 1
4920 		|| fwrite(&height, sizeof(short int), 1, file) != 1
4921 		|| fwrite(&pixelDepth, sizeof(unsigned char), 1, file) != 1
4922 		|| fwrite(&cGarbage, sizeof(unsigned char), 1, file) != 1)
4923 	{
4924 		fclose(file);
4925 		delete [] imageData;
4926 		return (int)false;
4927 	}
4928 
4929 // convert the image data from RGB(A) to BGR(A)
4930 	if (mode >= 3)
4931 	for (i=0; i < width * height * mode ; i+= mode) {
4932 		aux = imageData[i];
4933 		imageData[i] = imageData[i+2];
4934 		imageData[i+2] = aux;
4935 	}
4936 
4937 // save the image data
4938 	if (fwrite(imageData, sizeof(unsigned char),
4939 			width * height * mode, file) != width * height * mode)
4940 	{
4941 		fclose(file);
4942 		delete [] imageData;
4943 		return (int)false;
4944 	}
4945 
4946 	fclose(file);
4947 	delete [] imageData;
4948 
4949 	return (int)true;
4950 }
4951 
4952 // saves a series of files with names "filenameX"
tgaSaveSeries(char * filename,short int width,short int height,unsigned char pixelDepth,unsigned char * imageData)4953 int Core::tgaSaveSeries(char		*filename,
4954 			 short int		width,
4955 			 short int		height,
4956 			 unsigned char	pixelDepth,
4957 			 unsigned char	*imageData) {
4958 
4959 	char *newFilename;
4960 	int status;
4961 
4962 // compute the new filename by adding the
4963 // series number and the extension
4964 	newFilename = (char *)malloc(sizeof(char) * strlen(filename)+8);
4965 
4966 	sprintf(newFilename,"%s%d",filename,numSavedScreenshots);
4967 
4968 // save the image
4969 	status = tgaSave(newFilename,width,height,pixelDepth,imageData);
4970 
4971 //increase the counter
4972 	if (status == (int)true)
4973 		numSavedScreenshots++;
4974 	free(newFilename);
4975 	return(status);
4976 }
4977 
screenshot()4978  void Core::screenshot()
4979  {
4980 	 doScreenshot = true;
4981 //	ilutGLScreenie();
4982  }
4983 
4984 
4985  #include "DeflateCompressor.h"
4986 
4987  // saves an array of pixels as a TGA image (frees the image data passed in)
zgaSave(const char * filename,short int w,short int h,unsigned char depth,unsigned char * imageData)4988 int Core::zgaSave(	const char	*filename,
4989 		short int	w,
4990 		short int	h,
4991 		unsigned char	depth,
4992 		unsigned char	*imageData) {
4993 
4994 	ByteBuffer::uint8 type,mode,aux, pixelDepth = depth;
4995 	ByteBuffer::uint8 cGarbage = 0;
4996 	ByteBuffer::uint16 iGarbage = 0;
4997 	ByteBuffer::uint16 width = w, height = h;
4998 
4999 // open file and check for errors
5000 	FILE *file = fopen(adjustFilenameCase(filename).c_str(), "wb");
5001 	if (file == NULL) {
5002 		delete [] imageData;
5003 		return (int)false;
5004 	}
5005 
5006 // compute image type: 2 for RGB(A), 3 for greyscale
5007 	mode = pixelDepth / 8;
5008 	if ((pixelDepth == 24) || (pixelDepth == 32))
5009 		type = 2;
5010 	else
5011 		type = 3;
5012 
5013 // convert the image data from RGB(A) to BGR(A)
5014 	if (mode >= 3)
5015 	for (int i=0; i < width * height * mode ; i+= mode) {
5016 		aux = imageData[i];
5017 		imageData[i] = imageData[i+2];
5018 		imageData[i+2] = aux;
5019 	}
5020 
5021 	ZlibCompressor z;
5022 	z.SetForceCompression(true);
5023 	z.reserve(width * height * mode + 30);
5024 	z	<< cGarbage
5025 		<< cGarbage
5026 		<< type
5027 		<< iGarbage
5028 		<< iGarbage
5029 		<< cGarbage
5030 		<< iGarbage
5031 		<< iGarbage
5032 		<< width
5033 		<< height
5034 		<< pixelDepth
5035 		<< cGarbage;
5036 
5037 	z.append(imageData, width * height * mode);
5038 	z.Compress(3);
5039 
5040 // save the image data
5041 	if (fwrite(z.contents(), 1, z.size(), file) != z.size())
5042 	{
5043 		fclose(file);
5044 		delete [] imageData;
5045 		return (int)false;
5046 	}
5047 
5048 	fclose(file);
5049 	delete [] imageData;
5050 
5051 	return (int)true;
5052 }
5053 
5054 
5055 
5056 #include "ttvfs_zip/VFSZipArchiveLoader.h"
5057 
setupFileAccess()5058 void Core::setupFileAccess()
5059 {
5060 #ifdef BBGE_BUILD_VFS
5061 	debugLog("Init VFS...");
5062 
5063 	if(!ttvfs::checkCompat())
5064 		exit_error("ttvfs not compatible");
5065 
5066 	ttvfs_setroot(&vfs);
5067 
5068 	vfs.AddLoader(new ttvfs::DiskLoader);
5069 	vfs.AddArchiveLoader(new ttvfs::VFSZipArchiveLoader);
5070 
5071 	vfs.Mount("override", "");
5072 
5073 	// If we ever want to read from a container...
5074 	//vfs.AddArchive("aqfiles.zip");
5075 
5076 	if(_extraDataDir.length())
5077 	{
5078 		debugLog("Mounting extra data dir: " + _extraDataDir);
5079 		vfs.Mount(_extraDataDir.c_str(), "");
5080 	}
5081 
5082 	debugLog("Done");
5083 #endif
5084 }
5085 
initLocalization()5086 void Core::initLocalization()
5087 {
5088 	InStream in(localisePath("data/localecase.txt"));
5089 	if(!in)
5090 	{
5091 		debugLog("data/localecase.txt does not exist, using internal locale data");
5092 		return;
5093 	}
5094 
5095 	std::string low, up;
5096 	std::map<unsigned char, unsigned char> trans;
5097 	while(in)
5098 	{
5099 		in >> low >> up;
5100 		trans[low[0]] = up[0];
5101 	}
5102 	initCharTranslationTables(trans);
5103 }
5104 
5105