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