Merge branch 'reduce-cpu'
[hex-a-hop.git] / gfx.cpp
blob503a72aa0e01fd4b458fd70983f680fd68962faa
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
17 */
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 #ifndef DATA_DIR
32 #define DATA_DIR "."
33 #endif
35 StateMakerBase* StateMakerBase::first = 0;
36 State* StateMakerBase::current = 0;
38 int SDL_focus = SDL_APPACTIVE | SDL_APPINPUTFOCUS; // Initial focus state
40 #ifdef WIN32
41 #include <windows.h>
42 #include <winuser.h>
43 #include <commdlg.h>
44 #include <direct.h>
46 bool tablet_system = false;
48 char* LoadSaveDialog(bool save, bool levels, const char * title)
50 OPENFILENAME f;
51 static char filename[1025] = "";
52 static char path[1025] = "C:\\WINDOWS\\Desktop\\New Folder\\Foo\\Levels";
53 char backupPath[1025];
54 _getcwd(backupPath, sizeof(backupPath)/sizeof(backupPath[0])-1);
56 memset(&f, 0, sizeof(f));
58 #define FILTER(desc, f) desc " (" f ")\0" f "\0"
59 f.lpstrFilter = FILTER("All known files","*.lev;*.sol")
60 FILTER("Level files","*.lev")
61 FILTER("Solution files","*.sol")
62 FILTER("All files","*.*");
63 #undef FILTER
65 f.lStructSize = sizeof(f);
66 f.lpstrFile = filename;
67 f.nMaxFile = sizeof(filename);
68 f.lpstrInitialDir = path;
69 f.lpstrTitle = title;
71 if (GetSaveFileName(&f)==TRUE)
73 // Remember user's choice of path!
74 _getcwd(path, sizeof(path)/sizeof(path[0])-1);
76 if (save)
78 int i = strlen(filename)-1;
79 while (i>0 && filename[i]!='.' && filename[i]!='\\' && filename[i]!='/') i--;
80 if (filename[i]!='.' && levels)
81 strcat(filename, ".lev");
82 if (filename[i]!='.' && !levels)
83 strcat(filename, ".sol");
85 _chdir(backupPath);
86 return filename;
89 _chdir(backupPath);
90 return 0;
92 #else
93 char* LoadSaveDialog(bool /*save*/, bool /*levels*/, const char * /*title*/)
95 return 0;
97 #endif
99 extern void test();
101 int mouse_buttons = 0;
102 int mousex= 10, mousey = 10;
103 int noMouse = 0;
104 int quitting = 0;
106 double stylusx= 0, stylusy= 0;
107 int stylusok= 0;
108 float styluspressure = 0;
109 SDL_Surface * screen = 0;
110 SDL_Surface * realScreen = 0;
112 extern State* MakeWorld();
114 bool fullscreen = false;
116 void InitScreen()
118 #ifdef USE_OPENGL
119 SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
120 SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
121 SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
122 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
123 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
125 // printf("SDL_SetVideoMode (OpenGL)\n");
126 realScreen = SDL_SetVideoMode(
127 SCREEN_W, SCREEN_H, // Width, Height
128 0, // Current BPP
129 SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0) );
130 #else
131 // printf("SDL_SetVideoMode (non-OpenGL)\n");
132 realScreen = SDL_SetVideoMode(
133 SCREEN_W, SCREEN_H, // Width, Height
134 0, // Current BPP
135 SDL_SWSURFACE | SDL_DOUBLEBUF | (fullscreen ? SDL_FULLSCREEN : 0) );
136 #endif
138 if (screen)
139 SDL_FreeSurface(screen);
141 SDL_Surface* tempscreen = SDL_CreateRGBSurface(
142 SDL_SWSURFACE,
143 SCREEN_W, SCREEN_H,
144 16, 0xf800, 0x07e0, 0x001f, 0);
146 screen = SDL_DisplayFormat(tempscreen);
147 SDL_FreeSurface(tempscreen);
150 void ToggleFullscreen()
152 fullscreen = !fullscreen;
153 InitScreen();
154 StateMakerBase::current->ScreenModeChanged();
156 String base_path;
158 int TickTimer()
160 static int time = SDL_GetTicks();
161 int cap=40;
163 int x = SDL_GetTicks() - time;
164 time += x;
165 if (x<0) x = 0, time = SDL_GetTicks();
166 if (x>cap) x = cap;
168 return x;
171 int main(int /*argc*/, char * /*argv*/[])
173 base_path = DATA_DIR "/";
174 for (int i=strlen(base_path)-1; i>=0; i--)
175 if (base_path[i]=='/' || base_path[i]=='\\')
177 base_path.truncate(i+1);
178 break;
180 // Check the path ends with a directory seperator
181 if (strlen(base_path)>0)
183 char last = base_path[strlen(base_path)-1];
184 if (last!='/' && last!='\\')
185 base_path = "";
187 #ifdef WIN32
188 if (strstr(base_path, "\\foo2___Win32_Debug\\"))
189 strstr(base_path, "\\foo2___Win32_Debug\\")[1] = '\0';
190 if (strstr(base_path, "\\Release\\"))
191 strstr(base_path, "\\Release\\")[1] = '\0';
192 #endif
193 // printf("SDL_Init\n");
196 // Experimental - create a splash screen window whilst loading
197 SDL_Init(SDL_INIT_VIDEO);
198 screen = SDL_SetVideoMode( 200,200,0,SDL_NOFRAME );
199 SDL_Rect r = {0,0,200,200};
200 SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 0, 0, 50));
201 SDL_Flip(screen);
204 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE);
206 SDL_Surface* icon = SDL_LoadBMP("graphics/icon.bmp");
207 if (icon)
209 static unsigned int mask[32] = {
210 0x00001fc0,
211 0x00003fe0,
212 0x00007ff0,
213 0x00007df8,
214 0x0000f0f8,
215 0x0000f07c,
216 0x0005f87c,
217 0x0fbfff3c,
219 0x1ffffffe,
220 0x3ffffffe,
221 0x3ffffffe,
222 0x7ffffffe,
223 0x7ffffffe,
224 0x7ffffffe,
225 0x7ffffffe,
226 0xefffffff,
228 0x1fffffff,
229 0x3fffffff,
230 0x3fffffff,
231 0x3fffffff,
232 0x3fffffff,
233 0x3fffffff,
234 0x3fffffff,
235 0x3ffffffe,
237 0x3ffffff8,
238 0x3ffffff0,
239 0x3ffffff0,
240 0x3ffffff0,
241 0x3fffffe0,
242 0x3fffffe0,
243 0x1ffffff0,
244 0x1ffffff1,
246 for (int i=0; i<32; i++)
247 mask[i] = mask[i]>>24 | (mask[i]>>8)&0xff00 | (mask[i]<<8)&0xff0000 | (mask[i]<<24)&0xff000000;
248 SDL_WM_SetIcon(icon, (unsigned char*) mask);
249 SDL_FreeSurface(icon);
252 InitScreen();
254 SDL_WarpMouse(SCREEN_W/2, SCREEN_H/2);
256 int videoExposed = 1;
258 #ifdef WIN32
259 HWND hwnd = 0;
260 #endif
261 #ifdef USE_BBTABLET
262 bbTabletDevice &td = bbTabletDevice::getInstance( );
263 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
264 #endif
266 // printf("Main loop...\n");
268 StateMakerBase::GetNew();
270 while(!quitting)
272 SDL_Event e;
273 while(!SDL_PollEvent(&e) && !quitting)
275 int x = 0;
277 if ((SDL_focus & 6)==6)
279 videoExposed = 1;
281 x = TickTimer();
283 while (x<10)
285 SDL_Delay(10-x);
286 x += TickTimer();
289 StateMakerBase::current->Update(x / 1000.0);
291 else
293 // Not focussed. Try not to eat too much CPU!
294 SDL_Delay(150);
297 // experimental...
298 if (!noMouse)
299 StateMakerBase::current->Mouse(mousex, mousey, 0, 0, 0, 0, mouse_buttons);
301 if (videoExposed)
303 StateMakerBase::current->Render();
305 #ifdef USE_OPENGL
306 SDL_GL_SwapBuffers();
307 #else
308 if (screen && realScreen!=screen)
310 SDL_Rect r = {0,0,SCREEN_W,SCREEN_H};
311 SDL_BlitSurface(screen, &r, realScreen, &r);
313 SDL_Flip(realScreen);
314 #endif
315 videoExposed = 0;
318 SDL_Delay(10);
320 #ifdef USE_BBTABLET
321 // Tablet ////////////////////////
322 bbTabletEvent evt;
323 while(hwnd!=NULL && td.getNextEvent(evt))
325 stylusok = 1;
326 RECT r;
327 if (tablet_system)
329 GetWindowRect(hwnd, &r);
330 stylusx = evt.x * GetSystemMetrics(SM_CXSCREEN);
331 stylusy = (1.0 - evt.y) * GetSystemMetrics(SM_CYSCREEN);
332 stylusx -= (r.left + GetSystemMetrics(SM_CXFIXEDFRAME));
333 stylusy -= (r.top + GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION));;
335 else
337 GetClientRect(hwnd, &r);
338 stylusx = evt.x * r.right;
339 stylusy = (1.0 - evt.y) * r.bottom;
341 styluspressure = (evt.buttons & 1) ? evt.pressure : 0;
344 printf("id=%d csrtype=%d b=%x (%0.3f, %0.3f, %0.3f) p=%0.3f tp=%0.3f\n",
345 evt.id,
346 evt.type,
347 evt.buttons,
348 evt.x,
349 evt.y,
350 evt.z,
351 evt.pressure,
352 evt.tpressure
357 #endif
360 switch (e.type)
362 case SDL_VIDEOEXPOSE:
363 videoExposed = 1;
364 break;
366 #ifdef WIN32
367 case SDL_SYSWMEVENT:
369 SDL_SysWMmsg* m = e.syswm.msg;
370 hwnd = m->hwnd;
371 static bool init=false;
372 if (!init)
374 init = true;
375 DragAcceptFiles(hwnd, TRUE);
376 #ifdef USE_BBTABLET
377 td.initTablet(hwnd, tablet_system ? bbTabletDevice::SYSTEM_POINTER : bbTabletDevice::SEPARATE_POINTER );
378 if (!td.isValid())
379 printf("No tablet/driver found\n");
380 #endif
382 if (m->msg == WM_DROPFILES)
384 HDROP h = (HDROP)m->wParam;
386 char name[512];
387 if (DragQueryFile(h, 0xffffffff, 0, 0) == 1)
389 DragQueryFile(h, 0, name, sizeof(name)/sizeof(name[0]));
391 StateMakerBase::current->FileDrop(name);
394 DragFinish(h);
397 break;
399 #endif
401 case SDL_ACTIVEEVENT:
403 int gain = e.active.gain ? e.active.state : 0;
404 int loss = e.active.gain ? 0 : e.active.state;
405 SDL_focus = (SDL_focus | gain) & ~loss;
406 if (gain & SDL_APPACTIVE)
407 StateMakerBase::current->ScreenModeChanged();
408 if (loss & SDL_APPMOUSEFOCUS)
409 noMouse = 1;
410 else if (gain & SDL_APPMOUSEFOCUS)
411 noMouse = 0;
413 break;
416 case SDL_MOUSEMOTION:
417 noMouse = false;
418 StateMakerBase::current->Mouse(e.motion.x, e.motion.y, e.motion.x-mousex, e.motion.y-mousey, 0, 0, mouse_buttons);
419 mousex = e.motion.x; mousey = e.motion.y;
420 break;
421 case SDL_MOUSEBUTTONUP:
422 noMouse = false;
423 mouse_buttons &= ~(1<<(e.button.button-1));
424 StateMakerBase::current->Mouse(e.button.x, e.button.y, e.button.x-mousex, e.button.y-mousey,
425 0, 1<<(e.button.button-1), mouse_buttons);
426 mousex = e.button.x; mousey = e.button.y ;
427 break;
428 case SDL_MOUSEBUTTONDOWN:
429 noMouse = false;
430 mouse_buttons |= 1<<(e.button.button-1);
431 StateMakerBase::current->Mouse(e.button.x, e.button.y, e.button.x-mousex, e.button.y-mousey,
432 1<<(e.button.button-1), 0, mouse_buttons);
433 mousex = e.button.x; mousey = e.button.y ;
434 break;
436 case SDL_KEYUP:
437 StateMakerBase::current->KeyReleased(e.key.keysym.sym);
438 break;
440 case SDL_KEYDOWN:
442 SDL_KeyboardEvent & k = e.key;
444 if (k.keysym.sym==SDLK_F4 && (k.keysym.mod & KMOD_ALT))
446 quitting = 1;
448 else if (k.keysym.sym==SDLK_F12)
450 // Toggle system pointer controlled by tablet or not
451 #ifdef USE_BBTABLET
452 if (td.isValid())
454 tablet_system = !tablet_system;
455 td.setPointerMode(tablet_system ? bbTabletDevice::SYSTEM_POINTER : bbTabletDevice::SEPARATE_POINTER);
457 #endif
459 else if (k.keysym.sym==SDLK_RETURN && (k.keysym.mod & KMOD_ALT) && !(k.keysym.mod & KMOD_CTRL))
461 ToggleFullscreen();
463 else if (StateMakerBase::current->KeyPressed(k.keysym.sym, k.keysym.mod))
466 else if ((k.keysym.mod & (KMOD_ALT | KMOD_CTRL))==0)
468 StateMakerBase::GetNew(k.keysym.sym);
471 break;
473 case SDL_QUIT:
474 quitting = 1;
475 break;
479 SDL_Quit();
480 return 0;