00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "Kernel/OVR_System.h"
00025 #include "Kernel/OVR_Array.h"
00026 #include "Kernel/OVR_String.h"
00027
00028 #include "Win32_Platform.h"
00029 #include "Win32_Gamepad.h"
00030 #include "../Render/Render_Device.h"
00031
00032 namespace OVR { namespace Platform { namespace Win32 {
00033
00034
00035 PlatformCore::PlatformCore(Application* app, HINSTANCE hinst)
00036 : Platform::PlatformCore(app), hWnd(NULL), hInstance(hinst), Quit(0), MMode(Mouse_Normal),
00037 Cursor(0), Modifiers(0), WindowTitle("App")
00038 {
00039 pGamepadManager = *new Win32::GamepadManager();
00040 }
00041
00042 PlatformCore::~PlatformCore()
00043 {
00044 }
00045
00046 bool PlatformCore::SetupWindow(int w, int h)
00047 {
00048 WNDCLASS wc;
00049 memset(&wc, 0, sizeof(wc));
00050 wc.lpszClassName = L"OVRAppWindow";
00051 wc.style = CS_OWNDC;
00052 wc.lpfnWndProc = systemWindowProc;
00053 wc.cbWndExtra = sizeof(PlatformCore*);
00054
00055 RegisterClass(&wc);
00056
00057 Width = w;
00058 Height = h;
00059 RECT winSize;
00060 winSize.left = winSize.top = 0;
00061 winSize.right = Width;
00062 winSize.bottom = Height;
00063 AdjustWindowRect(&winSize, WS_OVERLAPPEDWINDOW, false);
00064 hWnd = CreateWindowA("OVRAppWindow", WindowTitle.ToCStr(), WS_OVERLAPPEDWINDOW,
00065 CW_USEDEFAULT, CW_USEDEFAULT,
00066
00067 winSize.right-winSize.left, winSize.bottom-winSize.top,
00068 NULL, NULL, hInstance, (LPVOID)this);
00069 Modifiers = 0;
00070
00071 Cursor = LoadCursor(NULL, IDC_CROSS);
00072
00073
00074 POINT center = { Width / 2, Height / 2 };
00075 ::ClientToScreen(hWnd, ¢er);
00076 WindowCenter = center;
00077
00078 if (MMode == Mouse_Relative)
00079 {
00080 ::SetCursorPos(WindowCenter.x, WindowCenter.y);
00081 ShowCursor(FALSE);
00082 }
00083 ::SetFocus(hWnd);
00084
00085 return (hWnd != NULL);
00086 }
00087
00088 void PlatformCore::DestroyWindow()
00089 {
00090
00091 pRender.Clear();
00092
00093
00094 pGamepadManager.Clear();
00095
00096
00097 ::DestroyWindow(hWnd);
00098 UnregisterClass(L"OVRAppWindow", hInstance);
00099 hWnd = 0;
00100 Width = Height = 0;
00101
00102
00103 Cursor = 0;
00104 }
00105
00106 void PlatformCore::ShowWindow(bool visible)
00107 {
00108 ::ShowWindow(hWnd, visible ? SW_SHOW : SW_HIDE);
00109 }
00110
00111 void PlatformCore::SetMouseMode(MouseMode mm)
00112 {
00113 if (mm == MMode)
00114 return;
00115
00116 if (hWnd)
00117 {
00118 if (mm == Mouse_Relative)
00119 {
00120 ShowCursor(FALSE);
00121 ::SetCursorPos(WindowCenter.x, WindowCenter.y);
00122 }
00123 else
00124 {
00125 if (MMode == Mouse_Relative)
00126 ShowCursor(TRUE);
00127 }
00128 }
00129 MMode = mm;
00130 }
00131
00132 void PlatformCore::GetWindowSize(int* w, int* h) const
00133 {
00134 *w = Width;
00135 *h = Height;
00136 }
00137
00138
00139 void PlatformCore::SetWindowTitle(const char* title)
00140 {
00141 WindowTitle = title;
00142 if (hWnd)
00143 ::SetWindowTextA(hWnd, title);
00144 }
00145
00146 static UByte KeyMap[][2] =
00147 {
00148 { VK_BACK, Key_Backspace },
00149 { VK_TAB, Key_Tab },
00150 { VK_CLEAR, Key_Clear },
00151 { VK_RETURN, Key_Return },
00152 { VK_SHIFT, Key_Shift },
00153 { VK_CONTROL, Key_Control },
00154 { VK_MENU, Key_Alt },
00155 { VK_PAUSE, Key_Pause },
00156 { VK_CAPITAL, Key_CapsLock },
00157 { VK_ESCAPE, Key_Escape },
00158 { VK_SPACE, Key_Space },
00159 { VK_PRIOR, Key_PageUp },
00160 { VK_NEXT, Key_PageDown },
00161 { VK_END, Key_End },
00162 { VK_HOME, Key_Home },
00163 { VK_LEFT, Key_Left },
00164 { VK_UP, Key_Up },
00165 { VK_RIGHT, Key_Right },
00166 { VK_DOWN, Key_Down },
00167 { VK_INSERT, Key_Insert },
00168 { VK_DELETE, Key_Delete },
00169 { VK_HELP, Key_Help },
00170
00171 { VK_NUMLOCK, Key_NumLock },
00172 { VK_SCROLL, Key_ScrollLock },
00173
00174 { VK_OEM_1, Key_Semicolon },
00175 { VK_OEM_PLUS, Key_Equal },
00176 { VK_OEM_COMMA, Key_Comma },
00177 { VK_OEM_MINUS, Key_Minus },
00178 { VK_OEM_PERIOD,Key_Period },
00179 { VK_OEM_2, Key_Slash },
00180 { VK_OEM_3, Key_Bar },
00181 { VK_OEM_4, Key_BracketLeft },
00182 { VK_OEM_5, Key_Backslash },
00183 { VK_OEM_6, Key_BracketRight },
00184 { VK_OEM_7, Key_Quote },
00185
00186 { VK_OEM_AX, Key_OEM_AX },
00187 { VK_OEM_102, Key_OEM_102 },
00188 { VK_ICO_HELP, Key_ICO_HELP },
00189 { VK_ICO_00, Key_ICO_00 }
00190 };
00191
00192
00193 KeyCode MapVKToKeyCode(unsigned vk)
00194 {
00195 unsigned key = Key_None;
00196
00197 if ((vk >= '0') && (vk <= '9'))
00198 {
00199 key = vk - '0' + Key_Num0;
00200 }
00201 else if ((vk >= 'A') && (vk <= 'Z'))
00202 {
00203 key = vk - 'A' + Key_A;
00204 }
00205 else if ((vk >= VK_NUMPAD0) && (vk <= VK_DIVIDE))
00206 {
00207 key = vk - VK_NUMPAD0 + Key_KP_0;
00208 }
00209 else if ((vk >= VK_F1) && (vk <= VK_F15))
00210 {
00211 key = vk - VK_F1 + Key_F1;
00212 }
00213 else
00214 {
00215 for (unsigned i = 0; i< (sizeof(KeyMap) / sizeof(KeyMap[1])); i++)
00216 {
00217 if (vk == KeyMap[i][0])
00218 {
00219 key = KeyMap[i][1];
00220 break;
00221 }
00222 }
00223 }
00224
00225 return (KeyCode)key;
00226 }
00227
00228
00229
00230 LRESULT CALLBACK PlatformCore::systemWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
00231 {
00232 PlatformCore* self;
00233
00234
00235 if (msg == WM_NCCREATE)
00236 {
00237 self = static_cast<PlatformCore*>(((LPCREATESTRUCT)lp)->lpCreateParams);
00238
00239 if (self)
00240 {
00241 SetWindowLongPtr(hwnd, 0, (LONG_PTR)self);
00242 self->hWnd = hwnd;
00243 }
00244 }
00245 else
00246 {
00247 self = (PlatformCore*)(UPInt)GetWindowLongPtr(hwnd, 0);
00248 }
00249
00250 return self ? self->WindowProc(msg, wp, lp) :
00251 DefWindowProc(hwnd, msg, wp, lp);
00252 }
00253
00254
00255 LRESULT PlatformCore::WindowProc(UINT msg, WPARAM wp, LPARAM lp)
00256 {
00257 KeyCode keyCode;
00258
00259 switch (msg)
00260 {
00261 case WM_PAINT:
00262 {
00263 PAINTSTRUCT ps;
00264 BeginPaint(hWnd, &ps);
00265 EndPaint(hWnd, &ps);
00266 }
00267 return 0;
00268
00269 case WM_SETCURSOR:
00270 ::SetCursor(Cursor);
00271 return 0;
00272
00273 case WM_MOUSEMOVE:
00274 if (MMode == Mouse_Relative)
00275 {
00276 POINT newPos = { LOWORD(lp), HIWORD(lp) };
00277 ::ClientToScreen(hWnd, &newPos);
00278 if ((newPos.x == WindowCenter.x) && (newPos.y == WindowCenter.y))
00279 break;
00280 ::SetCursorPos(WindowCenter.x, WindowCenter.y);
00281
00282 LONG dx = newPos.x - WindowCenter.x;
00283 LONG dy = newPos.y - WindowCenter.y;
00284
00285 pApp->OnMouseMove(dx, dy, Mod_MouseRelative);
00286 }
00287 else
00288 {
00289 pApp->OnMouseMove(LOWORD(lp), HIWORD(lp), 0);
00290 }
00291 break;
00292
00293 case WM_MOVE:
00294 {
00295 RECT r;
00296 GetClientRect(hWnd, &r);
00297 WindowCenter.x = r.right/2;
00298 WindowCenter.y = r.bottom/2;
00299 ::ClientToScreen(hWnd, &WindowCenter);
00300 }
00301 break;
00302
00303 case WM_KEYDOWN:
00304 switch (wp)
00305 {
00306 case VK_CONTROL: Modifiers |= Mod_Control; break;
00307 case VK_MENU: Modifiers |= Mod_Alt; break;
00308 case VK_SHIFT: Modifiers |= Mod_Shift; break;
00309 case VK_LWIN:
00310 case VK_RWIN: Modifiers |= Mod_Meta; break;
00311 }
00312 if ((keyCode = MapVKToKeyCode((unsigned)wp)) != Key_None)
00313 pApp->OnKey(keyCode, 0, true, Modifiers);
00314
00315 if (keyCode == Key_Escape && MMode == Mouse_Relative)
00316 {
00317 MMode = Mouse_RelativeEscaped;
00318 ShowCursor(TRUE);
00319 }
00320 break;
00321
00322 case WM_KEYUP:
00323 if ((keyCode = MapVKToKeyCode((unsigned)wp)) != Key_None)
00324 pApp->OnKey(keyCode, 0, false, Modifiers);
00325 switch (wp)
00326 {
00327 case VK_CONTROL: Modifiers &= ~Mod_Control; break;
00328 case VK_MENU: Modifiers &= ~Mod_Alt; break;
00329 case VK_SHIFT: Modifiers &= ~Mod_Shift; break;
00330 case VK_LWIN:
00331 case VK_RWIN: Modifiers &= ~Mod_Meta; break;
00332 }
00333 break;
00334
00335 case WM_LBUTTONDOWN:
00336
00337
00338 ::SetCapture(hWnd);
00339
00340 if (MMode == Mouse_RelativeEscaped)
00341 {
00342 ::SetCursorPos(WindowCenter.x, WindowCenter.y);
00343 ::ShowCursor(FALSE);
00344 MMode = Mouse_Relative;
00345 }
00346 break;
00347
00348 case WM_LBUTTONUP:
00349 ReleaseCapture();
00350 break;
00351
00352 case WM_SETFOCUS:
00353
00354
00355
00356 break;
00357
00358 case WM_KILLFOCUS:
00359 if (MMode == Mouse_Relative)
00360 {
00361 MMode = Mouse_RelativeEscaped;
00362 ShowCursor(TRUE);
00363 }
00364 break;
00365
00366 case WM_SIZE:
00367
00368 if (wp != SIZE_MINIMIZED)
00369 {
00370 Width = LOWORD(lp);
00371 Height = HIWORD(lp);
00372 if (pRender)
00373 pRender->SetWindowSize(Width, Height);
00374 pApp->OnResize(Width,Height);
00375 }
00376 break;
00377
00378 case WM_STYLECHANGING:
00379
00380
00381 {
00382 STYLESTRUCT* pss = (STYLESTRUCT*)lp;
00383 RECT winSize;
00384 winSize.left = winSize.top = 0;
00385 winSize.right = Width;
00386 winSize.bottom = Height;
00387 int w = winSize.right-winSize.left;
00388 int h = winSize.bottom-winSize.top;
00389 AdjustWindowRect(&winSize, pss->styleNew, false);
00390 ::SetWindowPos(hWnd, NULL, 0, 0, w, h, SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
00391 }
00392 break;
00393
00394 case WM_QUIT:
00395 case WM_CLOSE:
00396 pApp->OnQuitRequest();
00397 return false;
00398 }
00399
00400 return DefWindowProc(hWnd, msg, wp, lp);
00401 }
00402
00403 int PlatformCore::Run()
00404 {
00405 while (!Quit)
00406 {
00407 MSG msg;
00408 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
00409 {
00410 TranslateMessage(&msg);
00411 DispatchMessage(&msg);
00412 }
00413 else
00414 {
00415 pApp->OnIdle();
00416
00417
00418 if (IsIconic(hWnd))
00419 {
00420 Sleep(10);
00421 }
00422 }
00423 }
00424
00425 return ExitCode;
00426 }
00427
00428
00429 RenderDevice* PlatformCore::SetupGraphics(const SetupGraphicsDeviceSet& setupGraphicsDesc,
00430 const char* type, const Render::RendererParams& rp)
00431 {
00432 const SetupGraphicsDeviceSet* setupDesc = setupGraphicsDesc.PickSetupDevice(type);
00433 OVR_ASSERT(setupDesc);
00434
00435 pRender = *setupDesc->pCreateDevice(rp, (void*)hWnd);
00436 if (pRender)
00437 pRender->SetWindowSize(Width, Height);
00438
00439 ::ShowWindow(hWnd, SW_RESTORE);
00440 return pRender.GetPtr();
00441 }
00442
00443
00444 void PlatformCore::PlayMusicFile(const char *fileName)
00445 {
00446 PlaySoundA(fileName, NULL, SND_FILENAME | SND_LOOP | SND_ASYNC);
00447 }
00448
00449
00450
00451
00452
00453 struct MonitorSet
00454 {
00455 enum { MaxMonitors = 8 };
00456 HMONITOR Monitors[MaxMonitors];
00457 int MonitorCount;
00458 int PrimaryCount;
00459 };
00460
00461
00462 BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData)
00463 {
00464 MonitorSet* monitorSet = (MonitorSet*)dwData;
00465 if (monitorSet->MonitorCount > MonitorSet::MaxMonitors)
00466 return FALSE;
00467
00468 monitorSet->Monitors[monitorSet->MonitorCount] = hMonitor;
00469 monitorSet->MonitorCount++;
00470 return TRUE;
00471 };
00472
00473
00474
00475 int PlatformCore::GetDisplayCount()
00476 {
00477
00478 MonitorSet monitors;
00479 monitors.MonitorCount = 0;
00480 EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&monitors);
00481
00482
00483 int primary = 0;
00484 MONITORINFOEX info;
00485 for (int m=0; m < monitors.MonitorCount; m++)
00486 {
00487 info.cbSize = sizeof(MONITORINFOEX);
00488 GetMonitorInfo(monitors.Monitors[m], &info);
00489
00490 if (info.dwFlags & MONITORINFOF_PRIMARY)
00491 primary++;
00492 }
00493
00494 if (primary > 1)
00495 return 1;
00496 else
00497 return monitors.MonitorCount;
00498 }
00499
00500
00501
00502
00503 Render::DisplayId PlatformCore::GetDisplay(int screen)
00504 {
00505
00506 MonitorSet monitors;
00507 monitors.MonitorCount = 0;
00508 EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&monitors);
00509
00510 String screen_name;
00511
00512
00513
00514 int non_primary_count = 0;
00515 MONITORINFOEX info;
00516 for (int m=0; m < monitors.MonitorCount; m++)
00517 {
00518 info.cbSize = sizeof(MONITORINFOEX);
00519 GetMonitorInfo(monitors.Monitors[m], &info);
00520
00521 if (info.dwFlags & MONITORINFOF_PRIMARY)
00522 {
00523 if (screen == 0)
00524 {
00525 screen_name = info.szDevice;
00526 break;
00527 }
00528 }
00529 else
00530 {
00531 non_primary_count++;
00532 if (screen == non_primary_count)
00533 {
00534 screen_name = info.szDevice;
00535 break;
00536 }
00537 }
00538 }
00539
00540 return screen_name;
00541 }
00542
00543
00544 }}}
00545
00546
00547 int WINAPI WinMain(HINSTANCE hinst, HINSTANCE prevInst, LPSTR inArgs, int show)
00548 {
00549 using namespace OVR;
00550 using namespace OVR::Platform;
00551
00552 OVR_UNUSED2(prevInst, show);
00553
00554
00555 Application* app = Application::CreateApplication();
00556 Win32::PlatformCore* platform = new Win32::PlatformCore(app, hinst);
00557
00558 app->SetPlatformCore(platform);
00559
00560 int exitCode = 0;
00561
00562
00563 {
00564 Array<String> args;
00565 Array<const char*> argv;
00566 argv.PushBack("app");
00567
00568 const char* p = inArgs;
00569 const char* pstart = inArgs;
00570 while (*p)
00571 {
00572 if (*p == ' ')
00573 {
00574 args.PushBack(String(pstart, p - pstart));
00575 while (*p == ' ')
00576 p++;
00577 pstart = p;
00578 }
00579 else
00580 {
00581 p++;
00582 }
00583 }
00584 if (p != pstart)
00585 args.PushBack(String(pstart, p - pstart));
00586 for (UPInt i = 0; i < args.GetSize(); i++)
00587 argv.PushBack(args[i].ToCStr());
00588
00589 exitCode = app->OnStartup((int)argv.GetSize(), &argv[0]);
00590 if (!exitCode)
00591 exitCode = platform->Run();
00592 }
00593
00594
00595 Application::DestroyApplication(app);
00596 app = 0;
00597
00598 OVR_DEBUG_STATEMENT(_CrtDumpMemoryLeaks());
00599 return exitCode;
00600 }