Reduce CPU usage
[hex-a-hop.git] / gfx.cpp
blob1533d395fd6dcfa0f5213999a508b354384fe339
1 /*
2 Copyright (C) 2005-2007 Tom Beaumont
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "state.h"
21 #ifdef WIN32
22 #include <SDL_syswm.h>
23 #include <shellapi.h> // Windows header for drag & drop
24 #ifdef USE_BBTABLET
25 #include "bbtablet/bbtablet.h"
26 #endif
27 #else
28 #undef USE_BBTABLET
29 #endif
31 StateMakerBase* StateMakerBase::first = 0;
32 State* StateMakerBase::current = 0;
34 int SDL_focus = SDL_APPACTIVE | SDL_APPINPUTFOCUS; // Initial focus state
36 #ifdef WIN32
37 #include <windows.h>
38 #include <winuser.h>
39 #include <commdlg.h>
40 #include <direct.h>
42 bool tablet_system = false;
44 char* LoadSaveDialog(bool save, bool levels, const char * title)
46 OPENFILENAME f;
47 static char filename[1025] = "";
48 static char path[1025] = "C:\\WINDOWS\\Desktop\\New Folder\\Foo\\Levels";
49 char backupPath[1025];
50 _getcwd(backupPath, sizeof(backupPath)/sizeof(backupPath[0])-1);
52 memset(&f, 0, sizeof(f));
54 #define FILTER(desc, f) desc " (" f ")\0" f "\0"
55 f.lpstrFilter = FILTER("All known files","*.lev;*.sol")
56 FILTER("Level files","*.lev")
57 FILTER("Solution files","*.sol")
58 FILTER("All files","*.*");
59 #undef FILTER
61 f.lStructSize = sizeof(f);
62 f.lpstrFile = filename;
63 f.nMaxFile = sizeof(filename);
64 f.lpstrInitialDir = path;
65 f.lpstrTitle = title;
67 if (GetSaveFileName(&f)==TRUE)
69 // Remember user's choice of path!
70 _getcwd(path, sizeof(path)/sizeof(path[0])-1);
72 if (save)
74 int i = strlen(filename)-1;
75 while (i>0 && filename[i]!='.' && filename[i]!='\\' && filename[i]!='/') i--;
76 if (filename[i]!='.' && levels)
77 strcat(filename, ".lev");
78 if (filename[i]!='.' && !levels)
79 strcat(filename, ".sol");
81 _chdir(backupPath);
82 return filename;
85 _chdir(backupPath);
86 return 0;
88 #else
89 char* LoadSaveDialog(bool save, bool levels, const char * title)
91 return 0;
93 #endif
95 extern void test();
97 int mouse_buttons = 0;
98 int mousex= 10, mousey = 10;
99 int noMouse = 0;
100 int quitting = 0;
102 double stylusx= 0, stylusy= 0;
103 int stylusok= 0;
104 float styluspressure = 0;
105 SDL_Surface * screen = 0;
106 SDL_Surface * realScreen = 0;
108 extern State* MakeWorld();
110 bool fullscreen = false;
112 void InitScreen()
114 #ifdef USE_OPENGL
115 SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
116 SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
117 SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
118 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
119 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
121 // printf("SDL_SetVideoMode (OpenGL)\n");
122 realScreen = SDL_SetVideoMode(
123 SCREEN_W, SCREEN_H, // Width, Height
124 0, // Current BPP
125 SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0) );
126 #else
127 // printf("SDL_SetVideoMode (non-OpenGL)\n");
128 realScreen = SDL_SetVideoMode(
129 SCREEN_W, SCREEN_H, // Width, Height
130 0, // Current BPP
131 SDL_SWSURFACE | SDL_DOUBLEBUF | (fullscreen ? SDL_FULLSCREEN : 0) );
132 #endif
134 if (screen)
135 SDL_FreeSurface(screen);
137 SDL_Surface* tempscreen = SDL_CreateRGBSurface(
138 SDL_SWSURFACE,
139 SCREEN_W, SCREEN_H,
140 16, 0xf800, 0x07e0, 0x001f, 0);
142 screen = SDL_DisplayFormat(tempscreen);
143 SDL_FreeSurface(tempscreen);
146 void ToggleFullscreen()
148 fullscreen = !fullscreen;
149 InitScreen();
150 StateMakerBase::current->ScreenModeChanged();
152 String base_path;
154 int TickTimer()
156 static int time = SDL_GetTicks();
157 int cap=40;
159 int x = SDL_GetTicks() - time;
160 time += x;
161 if (x<0) x = 0, time = SDL_GetTicks();
162 if (x>cap) x = cap;
164 return x;
167 int main(int argc, char * argv[])
169 base_path = argv[0];
170 for (int i=strlen(base_path)-1; i>=0; i--)
171 if (base_path[i]=='/' || base_path[i]=='\\')
173 base_path.truncate(i+1);
174 break;
176 // Check the path ends with a directory seperator
177 if (strlen(base_path)>0)
179 char last = base_path[strlen(base_path)-1];
180 if (last!='/' && last!='\\')
181 base_path = "";
183 #ifdef WIN32
184 if (strstr(base_path, "\\foo2___Win32_Debug\\"))
185 strstr(base_path, "\\foo2___Win32_Debug\\")[1] = '\0';
186 if (strstr(base_path, "\\Release\\"))
187 strstr(base_path, "\\Release\\")[1] = '\0';
188 #endif
189 // printf("SDL_Init\n");
192 // Experimental - create a splash screen window whilst loading
193 SDL_Init(SDL_INIT_VIDEO);
194 screen = SDL_SetVideoMode( 200,200,0,SDL_NOFRAME );
195 SDL_Rect r = {0,0,200,200};
196 SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 0, 0, 50));
197 SDL_Flip(screen);
200 SDL_Init(SDL_INIT_EVERYTHING | SDL_INIT_NOPARACHUTE);
202 SDL_Surface* icon = SDL_LoadBMP("graphics/icon.bmp");
203 if (icon)
205 static unsigned int mask[32] = {
206 0x00001fc0,
207 0x00003fe0,
208 0x00007ff0,
209 0x00007df8,
210 0x0000f0f8,
211 0x0000f07c,
212 0x0005f87c,
213 0x0fbfff3c,
215 0x1ffffffe,
216 0x3ffffffe,
217 0x3ffffffe,
218 0x7ffffffe,
219 0x7ffffffe,
220 0x7ffffffe,
221 0x7ffffffe,
222 0xefffffff,
224 0x1fffffff,
225 0x3fffffff,
226 0x3fffffff,
227 0x3fffffff,
228 0x3fffffff,
229 0x3fffffff,
230 0x3fffffff,
231 0x3ffffffe,
233 0x3ffffff8,
234 0x3ffffff0,
235 0x3ffffff0,
236 0x3ffffff0,
237 0x3fffffe0,
238 0x3fffffe0,
239 0x1ffffff0,
240 0x1ffffff1,
242 for (int i=0; i<32; i++)
243 mask[i] = mask[i]>>24 | (mask[i]>>8)&0xff00 | (mask[i]<<8)&0xff0000 | (mask[i]<<24)&0xff000000;
244 SDL_WM_SetIcon(icon, (unsigned char*) mask);
245 SDL_FreeSurface(icon);
248 InitScreen();
250 SDL_WarpMouse(SCREEN_W/2, SCREEN_H/2);
252 int videoExposed = 1;
254 #ifdef WIN32
255 HWND hwnd = 0;
256 #endif
257 #ifdef USE_BBTABLET
258 bbTabletDevice &td = bbTabletDevice::getInstance( );
259 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
260 #endif
262 // printf("Main loop...\n");
264 StateMakerBase::GetNew();
265 int time = SDL_GetTicks();
267 while(!quitting)
269 SDL_Event e;
270 while(!SDL_PollEvent(&e) && !quitting)
272 int x = 0;
274 if ((SDL_focus & 6)==6)
276 videoExposed = 1;
278 x = TickTimer();
280 while (x<10)
282 SDL_Delay(10-x);
283 x += TickTimer();
286 StateMakerBase::current->Update(x / 1000.0);
288 else
290 // Not focussed. Try not to eat too much CPU!
291 SDL_Delay(150);
294 // experimental...
295 if (!noMouse)
296 StateMakerBase::current->Mouse(mousex, mousey, 0, 0, 0, 0, mouse_buttons);
298 if (videoExposed)
300 StateMakerBase::current->Render();
302 #ifdef USE_OPENGL
303 SDL_GL_SwapBuffers();
304 #else
305 if (screen && realScreen!=screen)
307 SDL_Rect r = {0,0,SCREEN_W,SCREEN_H};
308 SDL_BlitSurface(screen, &r, realScreen, &r);
310 SDL_Flip(realScreen);
311 #endif
312 videoExposed = 0;
315 SDL_Delay(10);
317 #ifdef USE_BBTABLET
318 // Tablet ////////////////////////
319 bbTabletEvent evt;
320 while(hwnd!=NULL && td.getNextEvent(evt))
322 stylusok = 1;
323 RECT r;
324 if (tablet_system)
326 GetWindowRect(hwnd, &r);
327 stylusx = evt.x * GetSystemMetrics(SM_CXSCREEN);
328 stylusy = (1.0 - evt.y) * GetSystemMetrics(SM_CYSCREEN);
329 stylusx -= (r.left + GetSystemMetrics(SM_CXFIXEDFRAME));
330 stylusy -= (r.top + GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION));;
332 else
334 GetClientRect(hwnd, &r);
335 stylusx = evt.x * r.right;
336 stylusy = (1.0 - evt.y) * r.bottom;
338 styluspressure = (evt.buttons & 1) ? evt.pressure : 0;
341 printf("id=%d csrtype=%d b=%x (%0.3f, %0.3f, %0.3f) p=%0.3f tp=%0.3f\n",
342 evt.id,
343 evt.type,
344 evt.buttons,
345 evt.x,
346 evt.y,
347 evt.z,
348 evt.pressure,
349 evt.tpressure
354 #endif
357 switch (e.type)
359 case SDL_VIDEOEXPOSE:
360 videoExposed = 1;
361 break;
363 #ifdef WIN32
364 case SDL_SYSWMEVENT:
366 SDL_SysWMmsg* m = e.syswm.msg;
367 hwnd = m->hwnd;
368 static bool init=false;
369 if (!init)
371 init = true;
372 DragAcceptFiles(hwnd, TRUE);
373 #ifdef USE_BBTABLET
374 td.initTablet(hwnd, tablet_system ? bbTabletDevice::SYSTEM_POINTER : bbTabletDevice::SEPARATE_POINTER );
375 if (!td.isValid())
376 printf("No tablet/driver found\n");
377 #endif
379 if (m->msg == WM_DROPFILES)
381 HDROP h = (HDROP)m->wParam;
383 char name[512];
384 if (DragQueryFile(h, 0xffffffff, 0, 0) == 1)
386 DragQueryFile(h, 0, name, sizeof(name)/sizeof(name[0]));
388 StateMakerBase::current->FileDrop(name);
391 DragFinish(h);
394 break;
396 #endif
398 case SDL_ACTIVEEVENT:
400 int gain = e.active.gain ? e.active.state : 0;
401 int loss = e.active.gain ? 0 : e.active.state;
402 SDL_focus = (SDL_focus | gain) & ~loss;
403 if (gain & SDL_APPACTIVE)
404 StateMakerBase::current->ScreenModeChanged();
405 if (loss & SDL_APPMOUSEFOCUS)
406 noMouse = 1;
407 else if (gain & SDL_APPMOUSEFOCUS)
408 noMouse = 0;
410 break;
413 case SDL_MOUSEMOTION:
414 noMouse = false;
415 StateMakerBase::current->Mouse(e.motion.x, e.motion.y, e.motion.x-mousex, e.motion.y-mousey, 0, 0, mouse_buttons);
416 mousex = e.motion.x; mousey = e.motion.y;
417 break;
418 case SDL_MOUSEBUTTONUP:
419 noMouse = false;
420 mouse_buttons &= ~(1<<(e.button.button-1));
421 StateMakerBase::current->Mouse(e.button.x, e.button.y, e.button.x-mousex, e.button.y-mousey,
422 0, 1<<(e.button.button-1), mouse_buttons);
423 mousex = e.button.x; mousey = e.button.y ;
424 break;
425 case SDL_MOUSEBUTTONDOWN:
426 noMouse = false;
427 mouse_buttons |= 1<<(e.button.button-1);
428 StateMakerBase::current->Mouse(e.button.x, e.button.y, e.button.x-mousex, e.button.y-mousey,
429 1<<(e.button.button-1), 0, mouse_buttons);
430 mousex = e.button.x; mousey = e.button.y ;
431 break;
433 case SDL_KEYUP:
434 StateMakerBase::current->KeyReleased(e.key.keysym.sym);
435 break;
437 case SDL_KEYDOWN:
439 SDL_KeyboardEvent & k = e.key;
441 if (k.keysym.sym==SDLK_F4 && (k.keysym.mod & KMOD_ALT))
443 quitting = 1;
445 else if (k.keysym.sym==SDLK_F12)
447 // Toggle system pointer controlled by tablet or not
448 #ifdef USE_BBTABLET
449 if (td.isValid())
451 tablet_system = !tablet_system;
452 td.setPointerMode(tablet_system ? bbTabletDevice::SYSTEM_POINTER : bbTabletDevice::SEPARATE_POINTER);
454 #endif
456 else if (k.keysym.sym==SDLK_RETURN && (k.keysym.mod & KMOD_ALT) && !(k.keysym.mod & KMOD_CTRL))
458 ToggleFullscreen();
460 else if (StateMakerBase::current->KeyPressed(k.keysym.sym, k.keysym.mod))
463 else if ((k.keysym.mod & (KMOD_ALT | KMOD_CTRL))==0)
465 StateMakerBase::GetNew(k.keysym.sym);
468 break;
470 case SDL_QUIT:
471 quitting = 1;
472 break;
476 SDL_Quit();
477 return 0;