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 WaitMessage();
197 }
198 }
199
200
201
202 void GLWindow::resize(int newWidth, int newHeight)
203 {
204
205 width = newWidth;
206 height = newHeight;
207
208
209 glViewport(0, 0, width, height);
210 }
211
212
213
214 void GLWindow::toggleFullscreen()
215 {
216
217 static int windowedWidth = 512;
218 static int windowedHeight = 512;
219
220
221 if (fullscreen)
222 {
223
224
225
226 SetWindowLong(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
227 SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_APPWINDOW);
228
229
230 ShowWindow(hWnd, SW_RESTORE);
231 UpdateWindow(hWnd);
232
233
234 width = windowedWidth;
235 height = windowedHeight;
236
237 RECT size;
238 size.left = 0;
239 size.top = 0;
240 size.right = width;
241 size.bottom = height;
242 AdjustWindowRectEx(&size, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, FALSE, WS_EX_APPWINDOW);
243
244
245 SetWindowPos(hWnd, HWND_TOP, 256,128,
246 size.right-size.left,
247 size.bottom-size.top,
248 SWP_SHOWWINDOW);
249
250
251 ShowCursor(TRUE);
252 }
253 else
{
254
255 windowedWidth = width;
256 windowedHeight = height;
257
258
259 SetWindowLong(hWnd, GWL_STYLE, WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
260 SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
261
262
263 ShowWindow(hWnd, SW_SHOWMAXIMIZED);
264 UpdateWindow(hWnd);
265
266
267 ShowCursor(FALSE);
268 }
269
270 fullscreen = !fullscreen;
271 }
272
273
274
275 void GLWindow::toggleActive()
276 {
277 setActive(!active);
278 }
279
280
281
282 void GLWindow::setActive(bool newState)
283 {
284
285 if (active == newState)
286
287 return;
288
289
290
291 active = newState;
292
293 if (!active)
294
295 inactiveSince = GetTickCount();
296 else
297 timeInactive += GetTickCount() - inactiveSince;
298 }
299
300
301
302 void GLWindow::paint()
303 {
304
305 redraw();
306
307 frames++;
308
309 if (doublebuffer)
310 SwapBuffers(hDC);
311 }
312
313
314
315 float GLWindow::seconds() const
{
316 if (active)
317 return (GetTickCount() - (timeStarted + timeInactive)) / 1000.0f;
318 else
return (inactiveSince - (timeStarted + timeInactive)) / 1000.0f;
319 }
320
321
322
323 LRESULT CALLBACK GLWindow::message(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
324 {
325 switch (uMsg)
326 {
327 case WM_SYSCOMMAND:
328 {
329 switch (wParam)
330 {
331
332
333 case SC_SCREENSAVE:
334 case SC_MONITORPOWER:
335 return 0;
336 }
337 break;
338 }
339
340
341
342
343
344
345
346
347 case WM_KEYDOWN:
348 {
349 switch (wParam)
350 {
351
352 case VK_ESCAPE:
353 PostMessage(hWnd, WM_CLOSE, 0, 0);
354 return 0;
355
356
357 case VK_F5:
358 singleton->toggleFullscreen();
359 return 0;
360
361
362 case VK_PAUSE:
363 case VK_SPACE:
364 singleton->toggleActive();
365 return 0;
366 }
367
368 break;
369 }
370
371
372 case WM_CLOSE:
373 {
374 PostQuitMessage(0);
375 return 0;
376 }
377
378
379 case WM_PAINT:
380 {
381 singleton->paint();
382
383
384 static PAINTSTRUCT ps;
385 BeginPaint(hWnd, &ps);
386 EndPaint(hWnd, &ps);
387 break;
388 }
389
390
391 case WM_SIZE:
392 {
393 singleton->resize(LOWORD(lParam), HIWORD(lParam));
394 PostMessage(hWnd, WM_PAINT, 0, 0);
395 return 0;
396 }
397
398
399 case WM_TIMER:
400
401 if(wParam == FPS_TIMER_ID)
402 {
403
404 float fps = (singleton->frames - framesAtLastFPSUpdate)
405 * (1000.0f / FPS_TIMER_INTERVAL);
406 framesAtLastFPSUpdate = singleton->frames;
407
408
409 static char newCaption[257];
410 sprintf(newCaption, "%s (%.0f fps)", singleton->title, fps);
411 SetWindowText(hWnd, newCaption);
412
413 return 0;
414 }
415 break;
416 }
417
418
419 return DefWindowProc(hWnd, uMsg, wParam, lParam);
420 }
421