00001
00002
00003
00004
00005 #include <stdio.h>
00006 #include "os.h"
00007 #include "resource.h"
00008 #include <GL/wglext.h>
00009
00010 static HINSTANCE g_hInstance;
00011 static HDC g_hDC;
00012 static OS_Event *g_eventHead = 0;
00013 static OS_Event **g_eventTail = &g_eventHead;
00014 static HWND g_hWnd;
00015 static int g_cursorVisible = 1;
00016
00017 int main(int argc, char** argv);
00018
00019 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
00020 {
00021 int argc;
00022 char** argv = (char**) CommandLineToArgvW((LPCWSTR) lpCmdLine, &argc);
00023 g_hInstance = hInstance;
00024 return main(argc, argv);
00025 }
00026
00027 void osWaitVsync(int interval)
00028 {
00029 PFNWGLSWAPINTERVALEXTPROC wglSwapInterval;
00030 wglSwapInterval = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT");
00031 if (wglSwapInterval)
00032 wglSwapInterval(interval);
00033 }
00034
00035 int osGetScreenWidth() { return GetSystemMetrics(SM_CXSCREEN); }
00036 int osGetScreenHeight() { return GetSystemMetrics(SM_CYSCREEN); }
00037
00038 #pragma warning(push)
00039 #pragma warning(disable:4996)
00040 void fatalf(const char *format, ...)
00041 {
00042 va_list args;
00043 int length;
00044 char *buffer;
00045
00046 va_start(args, format);
00047 length = _vscprintf(format, args);
00048 buffer = malloc(length + 1);
00049 vsprintf(buffer, format, args);
00050 OutputDebugString("\n\n");
00051 OutputDebugString(buffer);
00052 OutputDebugString("\n\n");
00053 free(buffer);
00054 exit(1);
00055 }
00056 void debugf(const char *format, ...)
00057 {
00058 va_list args;
00059 int length;
00060 char *buffer;
00061
00062 va_start(args, format);
00063 length = _vscprintf(format, args);
00064 buffer = malloc(length + 1);
00065 vsprintf(buffer, format, args);
00066 OutputDebugString(buffer);
00067 free(buffer);
00068 }
00069 #pragma warning(pop)
00070
00071 void osQuit(void)
00072 {
00073 timeEndPeriod(1);
00074
00075 if (g_hWnd)
00076 {
00077 DestroyWindow(g_hWnd);
00078 g_hWnd = 0;
00079 }
00080
00081 while (g_eventHead)
00082 {
00083 OS_Event *pending = g_eventHead;
00084 g_eventHead = pending->next;
00085 if (!g_eventHead)
00086 g_eventTail = &g_eventHead;
00087 free(pending);
00088 }
00089 }
00090
00091 static LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00092 {
00093 OS_Event e;
00094 e.type = 0;
00095
00096 switch (uMsg)
00097 {
00098 case WM_KEYDOWN:
00099 e.type = OS_KEYDOWN;
00100 e.key.key = (unsigned char) wParam;
00101 e.key.state = OSKS_DOWN;
00102 break;
00103
00104 case WM_KEYUP:
00105 e.type = OS_KEYUP;
00106 e.key.key = (unsigned char) wParam;
00107 e.key.state = OSKS_UP;
00108 break;
00109
00110 case WM_SIZE:
00111 e.type = OS_RESIZE;
00112 e.resize.width = LOWORD(lParam);
00113 e.resize.height = HIWORD(lParam);
00114 break;
00115
00116 case WM_PAINT:
00117 case WM_ERASEBKGND:
00118 break;
00119
00120 case WM_MOUSEMOVE:
00121 e.type = OS_MOUSEMOTION;
00122 e.mouse.button = 0;
00123 if (wParam & MK_LBUTTON) e.mouse.button |= OS_BUTTON_LEFT;
00124 if (wParam & MK_MBUTTON) e.mouse.button |= OS_BUTTON_MIDDLE;
00125 if (wParam & MK_RBUTTON) e.mouse.button |= OS_BUTTON_RIGHT;
00126 e.mouse.x = LOWORD(lParam);
00127 e.mouse.y = HIWORD(lParam);
00128 break;
00129
00130 case WM_LBUTTONDOWN:
00131 e.type = OS_MOUSEBUTTONDOWN;
00132 e.mouse.button = OS_BUTTON_LEFT;
00133 e.mouse.x = LOWORD(lParam);
00134 e.mouse.y = HIWORD(lParam);
00135 break;
00136
00137 case WM_LBUTTONUP:
00138 e.type = OS_MOUSEBUTTONUP;
00139 e.mouse.button = OS_BUTTON_LEFT;
00140 e.mouse.x = LOWORD(lParam);
00141 e.mouse.y = HIWORD(lParam);
00142 break;
00143
00144 case WM_CLOSE:
00145 case WM_QUIT:
00146 e.type = OS_QUIT;
00147 break;
00148 }
00149
00150 if (e.type)
00151 {
00152 e.next = 0;
00153 *g_eventTail = malloc(sizeof(OS_Event));
00154 memcpy(*g_eventTail, &e, sizeof(OS_Event));
00155 g_eventTail = &((*g_eventTail)->next);
00156 }
00157
00158 return DefWindowProc(hWnd, uMsg, wParam, lParam);
00159 }
00160
00161 void osInit(int width, int height, unsigned int flags, int *attribs)
00162 {
00163 HICON tiny, big;
00164 PIXELFORMATDESCRIPTOR pfd;
00165 LPCTSTR name = "Flatland Demo";
00166 int pixelFormat;
00167 HGLRC hRC;
00168 RECT rect;
00169 DWORD dwStyle, dwExStyle;
00170 int x, y;
00171
00172 WNDCLASS wndClass =
00173 {
00174 CS_OWNDC, WinProc, 0, 0,
00175 g_hInstance, 0, LoadCursor(0, IDC_ARROW), 0, 0, name
00176 };
00177
00178 atexit(osQuit);
00179 RegisterClass(&wndClass);
00180
00181 if (flags & OS_FULLSCREEN)
00182 {
00183 width = GetSystemMetrics(SM_CXSCREEN);
00184 height = GetSystemMetrics(SM_CYSCREEN);
00185 dwStyle = WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
00186 dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE | WS_EX_TOPMOST;
00187 x = y = 0;
00188 }
00189 else
00190 {
00191 dwStyle = WS_CAPTION | WS_SYSMENU | WS_VISIBLE | WS_MINIMIZEBOX;
00192 dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
00193 x = y = CW_USEDEFAULT;
00194 if (flags & OS_RESIZABLE)
00195 dwStyle |= WS_SIZEBOX | WS_MAXIMIZEBOX;
00196 }
00197
00198
00199 SetRect(&rect, 0, 0, width, height);
00200 AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);
00201 width = rect.right - rect.left;
00202 height = rect.bottom - rect.top;
00203 g_hWnd = CreateWindowEx(0, name, name, dwStyle, x, y, width, height, 0, 0, g_hInstance, 0);
00204
00205
00206 ZeroMemory(&pfd, sizeof(pfd));
00207 pfd.nSize = sizeof(pfd);
00208 pfd.nVersion = 1;
00209 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
00210 pfd.iPixelType = PFD_TYPE_RGBA;
00211 pfd.cColorBits = 24;
00212 pfd.cDepthBits = 0;
00213 pfd.cStencilBits = 0;
00214 pfd.iLayerType = PFD_MAIN_PLANE;
00215
00216 g_hDC = GetDC(g_hWnd);
00217 pixelFormat = ChoosePixelFormat(g_hDC, &pfd);
00218
00219 SetPixelFormat(g_hDC, pixelFormat, &pfd);
00220 hRC = wglCreateContext(g_hDC);
00221 wglMakeCurrent(g_hDC, hRC);
00222
00223 tiny = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_SMALL));
00224 SendMessage(g_hWnd, WM_SETICON, ICON_SMALL, (LPARAM) tiny);
00225
00226 big = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_BIG));
00227 SendMessage(g_hWnd, WM_SETICON, ICON_BIG, (LPARAM) big);
00228
00229 timeBeginPeriod(1);
00230 }
00231
00232 unsigned int osGetMilliseconds()
00233 {
00234 return timeGetTime();
00235 }
00236
00237 int osPollEvent(OS_Event *e)
00238 {
00239 MSG msg;
00240 msg.message = WM_NULL;
00241
00242 while (PeekMessage(&msg, g_hWnd, 0, 0, PM_REMOVE))
00243 {
00244 TranslateMessage(&msg);
00245 DispatchMessage(&msg);
00246
00247 if (msg.message == WM_QUIT || msg.message == WM_CLOSE)
00248 {
00249 e->type = OS_QUIT;
00250 return 1;
00251 }
00252 }
00253
00254 if (g_eventHead)
00255 {
00256 OS_Event *pending = g_eventHead;
00257 memcpy(e, pending, sizeof(OS_Event));
00258 g_eventHead = pending->next;
00259 if (!g_eventHead)
00260 g_eventTail = &g_eventHead;
00261 free(pending);
00262 return 1;
00263 }
00264
00265 e->type = 0;
00266 return 0;
00267 }
00268
00269 void osSwapBuffers()
00270 {
00271 SwapBuffers(g_hDC);
00272 }
00273
00274 int osIsKeyDown(int key)
00275 {
00276 int vKey;
00277 switch (key)
00278 {
00279 case OSK_ESCAPE: vKey = VK_ESCAPE; break;
00280 case OSK_LEFT: vKey = VK_LEFT; break;
00281 case OSK_RIGHT: vKey = VK_RIGHT; break;
00282 case OSK_UP: vKey = VK_UP; break;
00283 case OSK_DOWN: vKey = VK_DOWN; break;
00284 case OSK_SHIFT: vKey = VK_SHIFT; break;
00285 default: return 0;
00286 }
00287 return (GetAsyncKeyState(vKey) & 0x8000) == 0x8000;
00288 }
00289
00290 int osShowCursor(int toggle)
00291 {
00292 switch (toggle)
00293 {
00294 case OS_ENABLE:
00295 if (!g_cursorVisible)
00296 {
00297 ShowCursor(TRUE);
00298 g_cursorVisible = 1;
00299 }
00300 break;
00301
00302 case OS_DISABLE:
00303 if (g_cursorVisible)
00304 {
00305 ShowCursor(FALSE);
00306 g_cursorVisible = 0;
00307 }
00308 break;
00309
00310 case OS_QUERY:
00311 return g_cursorVisible;
00312 }
00313
00314 return g_cursorVisible;
00315 }