studies/game programming/Games-Code1/GLWindow.cpp
⇒
download file
1
2
3
4
5
6 #include "GLWindow.h"
7
8
9 #include <gl/gl.h>
10
11 #include <cstdio>
12
13 #include <cassert>
14
15
16
17
18 GLWindow* GLWindow::singleton = NULL;
19
20
21 unsigned int GLWindow::framesAtLastFPSUpdate = 0;
22
23
24
25
26 GLWindow::GLWindow(bool fullscreen_, const char* title_,
27 unsigned int width_, unsigned int height_,
28 bool doublebuffer_,
29 unsigned char colorbuffer_, unsigned char depthbuffer_,
30 unsigned char accumbuffer_)
31 : fullscreen(fullscreen_),
32 title(title_),
33 width(width_), height(height_),
34
35 doublebuffer(doublebuffer_),
36 accumbuffer(accumbuffer_),
37 colorbuffer(colorbuffer_),
38 depthbuffer(depthbuffer_),
39
40 active(true), timeInactive(0),
41 frames(0)
42 {
43
44 assert(singleton == NULL);
45 singleton = this;
46
47
48 hInstance = GetModuleHandle(NULL);
49
50
51 WNDCLASSEX window;
52 window.cbSize = sizeof(WNDCLASSEX);
53 window.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
54 window.lpfnWndProc = message;
55 window.cbClsExtra = 0;
56 window.cbWndExtra = 0;
57 window.hInstance = hInstance;
58 window.hIcon =
59 window.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
60 window.hCursor = LoadCursor(NULL, IDC_ARROW);
61 window.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
62 window.lpszMenuName = NULL;
63 window.lpszClassName = title;
64
65
66 bool registerClass = RegisterClassEx(&window) != 0;
67 assert(registerClass);
68
69
70 DWORD dwStyle = WS_OVERLAPPEDWINDOW;
71 DWORD dwExStyle = WS_EX_APPWINDOW;
72 if (fullscreen)
73 {
74 dwStyle = WS_POPUP | WS_MAXIMIZE;
75 dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
76 }
77
78
79 RECT size;
80 size.left = 0;
81 size.top = 0;
82 size.right = width;
83 size.bottom = height;
84 AdjustWindowRectEx(&size, dwStyle, FALSE, dwExStyle);
85
86
87 hWnd = CreateWindowEx(dwExStyle,
88 title, title,
89 dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
90 256,128,
91 size.right-size.left,
92 size.bottom-size.top,
93 NULL, NULL, hInstance, NULL);
94 assert(hWnd);
95
96
97
98 hDC = GetDC(hWnd);
99 assert(hDC);
100
101
102 PIXELFORMATDESCRIPTOR pfd;
103 ZeroMemory(&pfd, sizeof(pfd));
104 pfd.nSize = sizeof(pfd);
105 pfd.nVersion = 1;
106 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | (doublebuffer ? PFD_DOUBLEBUFFER : 0);
107 pfd.iPixelType = PFD_TYPE_RGBA;
108 pfd.cColorBits = colorbuffer;
109 pfd.cDepthBits = depthbuffer;
110 pfd.cAccumBits = accumbuffer;
111 pfd.iLayerType = PFD_MAIN_PLANE;
112
113
114 int format = ChoosePixelFormat(hDC, &pfd);
115 assert(format > 0);
116 bool setPixelFormat = SetPixelFormat(hDC, format, &pfd) != 0;
117 assert(setPixelFormat);
118
119
120 hRC = wglCreateContext(hDC);
121 assert(hRC);
122 wglMakeCurrent(hDC, hRC);
123
124
125 SetTimer(hWnd, FPS_TIMER_ID, FPS_TIMER_INTERVAL, 0);
126
127
128 if (fullscreen)
129 ShowCursor(FALSE);
130
131
132 AnimateWindow(hWnd, 200, AW_BLEND | AW_ACTIVATE);
133 SetForegroundWindow(hWnd);
134 SetFocus(hWnd);
135
136
137 typedef GLboolean (__stdcall * SwapProc) (GLint interval);
138 SwapProc wglSwapIntervalEXT =
139 (SwapProc) wglGetProcAddress("wglSwapIntervalEXT");
140 if (wglSwapIntervalEXT)
141 wglSwapIntervalEXT(0);
142
143
144
145 timeStarted = GetTickCount();
146 }
147
148
149
150 GLWindow::~GLWindow()
151 {
152
153
154
155 KillTimer(hWnd, FPS_TIMER_ID);
156
157
158 wglMakeCurrent(NULL, NULL);
159 wglDeleteContext(hRC);
160 ReleaseDC(hWnd, hDC);
161
162
163 if (fullscreen)
164 ShowCursor(TRUE);
165
166
167 AnimateWindow(hWnd, 500, AW_BLEND | AW_HIDE);
168 DestroyWindow(hWnd);
169 UnregisterClass(title, hInstance);
170 }
171
172
173
174 int GLWindow::run()
175 {
176
177 while (true)
178 {
179 MSG msg;
180
181 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
182 {
183
184 if (msg.message == WM_QUIT)
185 return (int)msg.wParam;
186
187
188 TranslateMessage(&msg);
189 DispatchMessage(&msg);
190 }
191
192
193 if (active)
194 paint();
195 else
196
197 WaitMessage();
198 }
199 }
200
201
202
203 void GLWindow::resize(int newWidth, int newHeight)
204 {
205
206 width = newWidth;
207 height = newHeight;
208
209
210 glViewport(0, 0, width, height);
211 }
212
213
214
215 void GLWindow::toggleFullscreen()
216 {
217
218 static int windowedWidth = 512;
219 static int windowedHeight = 512;
220
221
222 if (fullscreen)
223 {
224
225
226
227 SetWindowLong(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
228 SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_APPWINDOW);
229
230
231 ShowWindow(hWnd, SW_RESTORE);
232 UpdateWindow(hWnd);
233
234
235 width = windowedWidth;
236 height = windowedHeight;
237
238 RECT size;
239 size.left = 0;
240 size.top = 0;
241 size.right = width;
242 size.bottom = height;
243 AdjustWindowRectEx(&size, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, FALSE, WS_EX_APPWINDOW);
244
245
246 SetWindowPos(hWnd, HWND_TOP, 256,128,
247 size.right-size.left,
248 size.bottom-size.top,
249 SWP_SHOWWINDOW);
250
251
252 ShowCursor(TRUE);
253 }
254 else
255 {
256
257 windowedWidth = width;
258 windowedHeight = height;
259
260
261 SetWindowLong(hWnd, GWL_STYLE, WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
262 SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
263
264
265 ShowWindow(hWnd, SW_SHOWMAXIMIZED);
266 UpdateWindow(hWnd);
267
268
269 ShowCursor(FALSE);
270 }
271
272 fullscreen = !fullscreen;
273 }
274
275
276
277 void GLWindow::toggleActive()
278 {
279 setActive(!active);
280 }
281
282
283
284 void GLWindow::setActive(bool newState)
285 {
286
287 if (active == newState)
288
289 return;
290
291
292
293 active = newState;
294
295 if (!active)
296
297 inactiveSince = GetTickCount();
298 else
299
300 timeInactive += GetTickCount() - inactiveSince;
301 }
302
303
304
305 void GLWindow::paint()
306 {
307
308 redraw();
309
310 frames++;
311
312 if (doublebuffer)
313 SwapBuffers(hDC);
314 }
315
316
317
318 float GLWindow::seconds() const
319 {
320 if (active)
321 return (GetTickCount() - (timeStarted + timeInactive)) / 1000.0f;
322 else
323 return (inactiveSince - (timeStarted + timeInactive)) / 1000.0f;
324 }
325
326
327
328 LRESULT CALLBACK GLWindow::message(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
329 {
330 switch (uMsg)
331 {
332 case WM_SYSCOMMAND:
333 {
334 switch (wParam)
335 {
336
337
338 case SC_SCREENSAVE:
339 case SC_MONITORPOWER:
340 return 0;
341 }
342 break;
343 }
344
345
346
347
348
349
350
351
352 case WM_KEYDOWN:
353 {
354 switch (wParam)
355 {
356
357 case VK_ESCAPE:
358 PostMessage(hWnd, WM_CLOSE, 0, 0);
359 return 0;
360
361
362 case VK_F5:
363 singleton->toggleFullscreen();
364 return 0;
365
366
367 case VK_PAUSE:
368 case VK_SPACE:
369 singleton->toggleActive();
370 return 0;
371 }
372
373 break;
374 }
375
376
377 case WM_CLOSE:
378 {
379 PostQuitMessage(0);
380 return 0;
381 }
382
383
384 case WM_PAINT:
385 {
386 singleton->paint();
387
388
389 static PAINTSTRUCT ps;
390 BeginPaint(hWnd, &ps);
391 EndPaint(hWnd, &ps);
392 break;
393 }
394
395
396 case WM_SIZE:
397 {
398 singleton->resize(LOWORD(lParam), HIWORD(lParam));
399 PostMessage(hWnd, WM_PAINT, 0, 0);
400 return 0;
401 }
402
403
404 case WM_TIMER:
405
406 if(wParam == FPS_TIMER_ID)
407 {
408
409 float fps = (singleton->frames - framesAtLastFPSUpdate)
410 * (1000.0f / FPS_TIMER_INTERVAL);
411 framesAtLastFPSUpdate = singleton->frames;
412
413
414 static char newCaption[257];
415 sprintf(newCaption, "%s (%.0f fps)", singleton->title, fps);
416 SetWindowText(hWnd, newCaption);
417
418 return 0;
419 }
420 break;
421 }
422
423
424 return DefWindowProc(hWnd, uMsg, wParam, lParam);
425 }
426