diff options
Diffstat (limited to 'Samples/CommonSrc/Platform/Win32_Platform.cpp')
-rw-r--r-- | Samples/CommonSrc/Platform/Win32_Platform.cpp | 1200 |
1 files changed, 600 insertions, 600 deletions
diff --git a/Samples/CommonSrc/Platform/Win32_Platform.cpp b/Samples/CommonSrc/Platform/Win32_Platform.cpp index cdd1e1f..9be7196 100644 --- a/Samples/CommonSrc/Platform/Win32_Platform.cpp +++ b/Samples/CommonSrc/Platform/Win32_Platform.cpp @@ -1,600 +1,600 @@ -/************************************************************************************
-
-Filename : Win32_Platform.cpp
-Content : Win32 implementation of Platform app infrastructure
-Created : September 6, 2012
-Authors : Andrew Reisse
-
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-************************************************************************************/
-
-#include "Kernel/OVR_System.h"
-#include "Kernel/OVR_Array.h"
-#include "Kernel/OVR_String.h"
-
-#include "Win32_Platform.h"
-#include "Win32_Gamepad.h"
-#include "../Render/Render_Device.h"
-
-namespace OVR { namespace Platform { namespace Win32 {
-
-
-PlatformCore::PlatformCore(Application* app, HINSTANCE hinst)
- : Platform::PlatformCore(app), hWnd(NULL), hInstance(hinst), Quit(0), MMode(Mouse_Normal),
- Cursor(0), Modifiers(0), WindowTitle("App")
-{
- pGamepadManager = *new Win32::GamepadManager();
-}
-
-PlatformCore::~PlatformCore()
-{
-}
-
-bool PlatformCore::SetupWindow(int w, int h)
-{
- WNDCLASS wc;
- memset(&wc, 0, sizeof(wc));
- wc.lpszClassName = L"OVRAppWindow";
- wc.style = CS_OWNDC;
- wc.lpfnWndProc = systemWindowProc;
- wc.cbWndExtra = sizeof(PlatformCore*);
-
- RegisterClass(&wc);
-
- Width = w;
- Height = h;
- RECT winSize;
- winSize.left = winSize.top = 0;
- winSize.right = Width;
- winSize.bottom = Height;
- AdjustWindowRect(&winSize, WS_OVERLAPPEDWINDOW, false);
- hWnd = CreateWindowA("OVRAppWindow", WindowTitle.ToCStr(), WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT,
- // 1950, 10,
- winSize.right-winSize.left, winSize.bottom-winSize.top,
- NULL, NULL, hInstance, (LPVOID)this);
- Modifiers = 0;
-
- Cursor = LoadCursor(NULL, IDC_CROSS);
-
- // Initialize Window center in screen coordinates
- POINT center = { Width / 2, Height / 2 };
- ::ClientToScreen(hWnd, ¢er);
- WindowCenter = center;
-
- if (MMode == Mouse_Relative)
- {
- ::SetCursorPos(WindowCenter.x, WindowCenter.y);
- ShowCursor(FALSE);
- }
- ::SetFocus(hWnd);
-
- return (hWnd != NULL);
-}
-
-void PlatformCore::DestroyWindow()
-{
- // Release renderer.
- pRender.Clear();
-
- // Release gamepad.
- pGamepadManager.Clear();
-
- // Release window resources.
- ::DestroyWindow(hWnd);
- UnregisterClass(L"OVRAppWindow", hInstance);
- hWnd = 0;
- Width = Height = 0;
-
- //DestroyCursor(Cursor);
- Cursor = 0;
-}
-
-void PlatformCore::ShowWindow(bool visible)
-{
- ::ShowWindow(hWnd, visible ? SW_SHOW : SW_HIDE);
-}
-
-void PlatformCore::SetMouseMode(MouseMode mm)
-{
- if (mm == MMode)
- return;
-
- if (hWnd)
- {
- if (mm == Mouse_Relative)
- {
- ShowCursor(FALSE);
- ::SetCursorPos(WindowCenter.x, WindowCenter.y);
- }
- else
- {
- if (MMode == Mouse_Relative)
- ShowCursor(TRUE);
- }
- }
- MMode = mm;
-}
-
-void PlatformCore::GetWindowSize(int* w, int* h) const
-{
- *w = Width;
- *h = Height;
-}
-
-
-void PlatformCore::SetWindowTitle(const char* title)
-{
- WindowTitle = title;
- if (hWnd)
- ::SetWindowTextA(hWnd, title);
-}
-
-static UByte KeyMap[][2] =
-{
- { VK_BACK, Key_Backspace },
- { VK_TAB, Key_Tab },
- { VK_CLEAR, Key_Clear },
- { VK_RETURN, Key_Return },
- { VK_SHIFT, Key_Shift },
- { VK_CONTROL, Key_Control },
- { VK_MENU, Key_Alt },
- { VK_PAUSE, Key_Pause },
- { VK_CAPITAL, Key_CapsLock },
- { VK_ESCAPE, Key_Escape },
- { VK_SPACE, Key_Space },
- { VK_PRIOR, Key_PageUp },
- { VK_NEXT, Key_PageDown },
- { VK_END, Key_End },
- { VK_HOME, Key_Home },
- { VK_LEFT, Key_Left },
- { VK_UP, Key_Up },
- { VK_RIGHT, Key_Right },
- { VK_DOWN, Key_Down },
- { VK_INSERT, Key_Insert },
- { VK_DELETE, Key_Delete },
- { VK_HELP, Key_Help },
-
- { VK_NUMLOCK, Key_NumLock },
- { VK_SCROLL, Key_ScrollLock },
-
- { VK_OEM_1, Key_Semicolon },
- { VK_OEM_PLUS, Key_Equal },
- { VK_OEM_COMMA, Key_Comma },
- { VK_OEM_MINUS, Key_Minus },
- { VK_OEM_PERIOD,Key_Period },
- { VK_OEM_2, Key_Slash },
- { VK_OEM_3, Key_Bar },
- { VK_OEM_4, Key_BracketLeft },
- { VK_OEM_5, Key_Backslash },
- { VK_OEM_6, Key_BracketRight },
- { VK_OEM_7, Key_Quote },
-
- { VK_OEM_AX, Key_OEM_AX }, // 'AX' key on Japanese AX keyboard.
- { VK_OEM_102, Key_OEM_102 }, // "<>" or "\|" on RT 102-key keyboard.
- { VK_ICO_HELP, Key_ICO_HELP },
- { VK_ICO_00, Key_ICO_00 }
-};
-
-
-KeyCode MapVKToKeyCode(unsigned vk)
-{
- unsigned key = Key_None;
-
- if ((vk >= '0') && (vk <= '9'))
- {
- key = vk - '0' + Key_Num0;
- }
- else if ((vk >= 'A') && (vk <= 'Z'))
- {
- key = vk - 'A' + Key_A;
- }
- else if ((vk >= VK_NUMPAD0) && (vk <= VK_DIVIDE))
- {
- key = vk - VK_NUMPAD0 + Key_KP_0;
- }
- else if ((vk >= VK_F1) && (vk <= VK_F15))
- {
- key = vk - VK_F1 + Key_F1;
- }
- else
- {
- for (unsigned i = 0; i< (sizeof(KeyMap) / sizeof(KeyMap[1])); i++)
- {
- if (vk == KeyMap[i][0])
- {
- key = KeyMap[i][1];
- break;
- }
- }
- }
-
- return (KeyCode)key;
-}
-
-
-
-LRESULT CALLBACK PlatformCore::systemWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
-{
- PlatformCore* self;
-
- // WM_NCCREATE should be the first message to come it; use it to set class pointer.
- if (msg == WM_NCCREATE)
- {
- self = static_cast<PlatformCore*>(((LPCREATESTRUCT)lp)->lpCreateParams);
-
- if (self)
- {
- SetWindowLongPtr(hwnd, 0, (LONG_PTR)self);
- self->hWnd = hwnd;
- }
- }
- else
- {
- self = (PlatformCore*)(UPInt)GetWindowLongPtr(hwnd, 0);
- }
-
- return self ? self->WindowProc(msg, wp, lp) :
- DefWindowProc(hwnd, msg, wp, lp);
-}
-
-
-LRESULT PlatformCore::WindowProc(UINT msg, WPARAM wp, LPARAM lp)
-{
- KeyCode keyCode;
-
- switch (msg)
- {
- case WM_PAINT:
- {
- PAINTSTRUCT ps;
- BeginPaint(hWnd, &ps);
- EndPaint(hWnd, &ps);
- }
- return 0;
-
- case WM_SETCURSOR:
- ::SetCursor(Cursor);
- return 0;
-
- case WM_MOUSEMOVE:
- if (MMode == Mouse_Relative)
- {
- POINT newPos = { LOWORD(lp), HIWORD(lp) };
- ::ClientToScreen(hWnd, &newPos);
- if ((newPos.x == WindowCenter.x) && (newPos.y == WindowCenter.y))
- break;
- ::SetCursorPos(WindowCenter.x, WindowCenter.y);
-
- LONG dx = newPos.x - WindowCenter.x;
- LONG dy = newPos.y - WindowCenter.y;
-
- pApp->OnMouseMove(dx, dy, Mod_MouseRelative);
- }
- else
- {
- pApp->OnMouseMove(LOWORD(lp), HIWORD(lp), 0);
- }
- break;
-
- case WM_MOVE:
- {
- RECT r;
- GetClientRect(hWnd, &r);
- WindowCenter.x = r.right/2;
- WindowCenter.y = r.bottom/2;
- ::ClientToScreen(hWnd, &WindowCenter);
- }
- break;
-
- case WM_KEYDOWN:
- switch (wp)
- {
- case VK_CONTROL: Modifiers |= Mod_Control; break;
- case VK_MENU: Modifiers |= Mod_Alt; break;
- case VK_SHIFT: Modifiers |= Mod_Shift; break;
- case VK_LWIN:
- case VK_RWIN: Modifiers |= Mod_Meta; break;
- }
- if ((keyCode = MapVKToKeyCode((unsigned)wp)) != Key_None)
- pApp->OnKey(keyCode, 0, true, Modifiers);
-
- if (keyCode == Key_Escape && MMode == Mouse_Relative)
- {
- MMode = Mouse_RelativeEscaped;
- ShowCursor(TRUE);
- }
- break;
-
- case WM_KEYUP:
- if ((keyCode = MapVKToKeyCode((unsigned)wp)) != Key_None)
- pApp->OnKey(keyCode, 0, false, Modifiers);
- switch (wp)
- {
- case VK_CONTROL: Modifiers &= ~Mod_Control; break;
- case VK_MENU: Modifiers &= ~Mod_Alt; break;
- case VK_SHIFT: Modifiers &= ~Mod_Shift; break;
- case VK_LWIN:
- case VK_RWIN: Modifiers &= ~Mod_Meta; break;
- }
- break;
-
- case WM_LBUTTONDOWN:
- //App->OnMouseButton(0,
-
- ::SetCapture(hWnd);
-
- if (MMode == Mouse_RelativeEscaped)
- {
- ::SetCursorPos(WindowCenter.x, WindowCenter.y);
- ::ShowCursor(FALSE);
- MMode = Mouse_Relative;
- }
- break;
-
- case WM_LBUTTONUP:
- ReleaseCapture();
- break;
-
- case WM_SETFOCUS:
- // Do NOT restore the Relative mode here, since calling SetCursorPos
- // would screw up titlebar window dragging.
- // Let users click in the center instead to resume.
- break;
-
- case WM_KILLFOCUS:
- if (MMode == Mouse_Relative)
- {
- MMode = Mouse_RelativeEscaped;
- ShowCursor(TRUE);
- }
- break;
-
- case WM_SIZE:
- // Change window size as long as we're not being minimized.
- if (wp != SIZE_MINIMIZED)
- {
- Width = LOWORD(lp);
- Height = HIWORD(lp);
- if (pRender)
- pRender->SetWindowSize(Width, Height);
- pApp->OnResize(Width,Height);
- }
- break;
-
- case WM_STYLECHANGING:
- // Resize the window. This is needed because the size includes any present system controls, and
- // windows does not adjust it when changing to fullscreen.
- {
- STYLESTRUCT* pss = (STYLESTRUCT*)lp;
- RECT winSize;
- winSize.left = winSize.top = 0;
- winSize.right = Width;
- winSize.bottom = Height;
- int w = winSize.right-winSize.left;
- int h = winSize.bottom-winSize.top;
- AdjustWindowRect(&winSize, pss->styleNew, false);
- ::SetWindowPos(hWnd, NULL, 0, 0, w, h, SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
- }
- break;
-
- case WM_QUIT:
- case WM_CLOSE:
- pApp->OnQuitRequest();
- return false;
- }
-
- return DefWindowProc(hWnd, msg, wp, lp);
-}
-
-int PlatformCore::Run()
-{
- while (!Quit)
- {
- MSG msg;
- if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- else
- {
- pApp->OnIdle();
-
- // Keep sleeping when we're minimized.
- if (IsIconic(hWnd))
- {
- Sleep(10);
- }
- }
- }
-
- return ExitCode;
-}
-
-
-RenderDevice* PlatformCore::SetupGraphics(const SetupGraphicsDeviceSet& setupGraphicsDesc,
- const char* type, const Render::RendererParams& rp)
-{
- const SetupGraphicsDeviceSet* setupDesc = setupGraphicsDesc.PickSetupDevice(type);
- OVR_ASSERT(setupDesc);
-
- pRender = *setupDesc->pCreateDevice(rp, (void*)hWnd);
- if (pRender)
- pRender->SetWindowSize(Width, Height);
-
- ::ShowWindow(hWnd, SW_RESTORE);
- return pRender.GetPtr();
-}
-
-
-void PlatformCore::PlayMusicFile(const char *fileName)
-{
- PlaySoundA(fileName, NULL, SND_FILENAME | SND_LOOP | SND_ASYNC);
-}
-
-
-//-----------------------------------------------------------------------------
-
-// Used to capture all the active monitor handles
-struct MonitorSet
-{
- enum { MaxMonitors = 8 };
- HMONITOR Monitors[MaxMonitors];
- int MonitorCount;
- int PrimaryCount;
-};
-
-
-BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData)
-{
- MonitorSet* monitorSet = (MonitorSet*)dwData;
- if (monitorSet->MonitorCount > MonitorSet::MaxMonitors)
- return FALSE;
-
- monitorSet->Monitors[monitorSet->MonitorCount] = hMonitor;
- monitorSet->MonitorCount++;
- return TRUE;
-};
-
-
-// Returns the number of active screens for extended displays and 1 for mirrored display
-int PlatformCore::GetDisplayCount()
-{
- // Get all the monitor handles
- MonitorSet monitors;
- monitors.MonitorCount = 0;
- EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&monitors);
-
- // Count the primary monitors
- int primary = 0;
- MONITORINFOEX info;
- for (int m=0; m < monitors.MonitorCount; m++)
- {
- info.cbSize = sizeof(MONITORINFOEX);
- GetMonitorInfo(monitors.Monitors[m], &info);
-
- if (info.dwFlags & MONITORINFOF_PRIMARY)
- primary++;
- }
-
- if (primary > 1)
- return 1; // Regard mirrored displays as a single screen
- else
- return monitors.MonitorCount; // Return all extended displays
-}
-
-//-----------------------------------------------------------------------------
-// Returns the device name for the given screen index or empty string for invalid index
-// The zero index will always return the primary screen name
-Render::DisplayId PlatformCore::GetDisplay(int screen)
-{
- // Get all the monitor handles
- MonitorSet monitors;
- monitors.MonitorCount = 0;
- EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&monitors);
-
- String screen_name;
-
- // Get the name of the suppled screen index with the requirement
- // that screen 0 is the primary monitor
- int non_primary_count = 0;
- MONITORINFOEX info;
- for (int m=0; m < monitors.MonitorCount; m++)
- {
- info.cbSize = sizeof(MONITORINFOEX);
- GetMonitorInfo(monitors.Monitors[m], &info);
-
- if (info.dwFlags & MONITORINFOF_PRIMARY)
- {
- if (screen == 0)
- {
- screen_name = info.szDevice;
- break;
- }
- }
- else
- {
- non_primary_count++;
- if (screen == non_primary_count)
- {
- screen_name = info.szDevice;
- break;
- }
- }
- }
-
- return screen_name;
-}
-
-
-}}}
-
-
-int WINAPI WinMain(HINSTANCE hinst, HINSTANCE prevInst, LPSTR inArgs, int show)
-{
- using namespace OVR;
- using namespace OVR::Platform;
-
- OVR_UNUSED2(prevInst, show);
-
- // CreateApplication must be the first call since it does OVR::System::Initialize.
- Application* app = Application::CreateApplication();
- Win32::PlatformCore* platform = new Win32::PlatformCore(app, hinst);
- // The platform attached to an app will be deleted by DestroyApplication.
- app->SetPlatformCore(platform);
-
- int exitCode = 0;
-
- // Nested scope for container destructors to shutdown before DestroyApplication.
- {
- Array<String> args;
- Array<const char*> argv;
- argv.PushBack("app");
-
- const char* p = inArgs;
- const char* pstart = inArgs;
- while (*p)
- {
- if (*p == ' ')
- {
- args.PushBack(String(pstart, p - pstart));
- while (*p == ' ')
- p++;
- pstart = p;
- }
- else
- {
- p++;
- }
- }
- if (p != pstart)
- args.PushBack(String(pstart, p - pstart));
- for (UPInt i = 0; i < args.GetSize(); i++)
- argv.PushBack(args[i].ToCStr());
-
- exitCode = app->OnStartup((int)argv.GetSize(), &argv[0]);
- if (!exitCode)
- exitCode = platform->Run();
- }
-
- // No OVR functions involving memory are allowed after this.
- Application::DestroyApplication(app);
- app = 0;
-
- OVR_DEBUG_STATEMENT(_CrtDumpMemoryLeaks());
- return exitCode;
-}
+/************************************************************************************ + +Filename : Win32_Platform.cpp +Content : Win32 implementation of Platform app infrastructure +Created : September 6, 2012 +Authors : Andrew Reisse + +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#include "Kernel/OVR_System.h" +#include "Kernel/OVR_Array.h" +#include "Kernel/OVR_String.h" + +#include "Win32_Platform.h" +#include "Win32_Gamepad.h" +#include "../Render/Render_Device.h" + +namespace OVR { namespace Platform { namespace Win32 { + + +PlatformCore::PlatformCore(Application* app, HINSTANCE hinst) + : Platform::PlatformCore(app), hWnd(NULL), hInstance(hinst), Quit(0), MMode(Mouse_Normal), + Cursor(0), Modifiers(0), WindowTitle("App") +{ + pGamepadManager = *new Win32::GamepadManager(); +} + +PlatformCore::~PlatformCore() +{ +} + +bool PlatformCore::SetupWindow(int w, int h) +{ + WNDCLASS wc; + memset(&wc, 0, sizeof(wc)); + wc.lpszClassName = L"OVRAppWindow"; + wc.style = CS_OWNDC; + wc.lpfnWndProc = systemWindowProc; + wc.cbWndExtra = sizeof(PlatformCore*); + + RegisterClass(&wc); + + Width = w; + Height = h; + RECT winSize; + winSize.left = winSize.top = 0; + winSize.right = Width; + winSize.bottom = Height; + AdjustWindowRect(&winSize, WS_OVERLAPPEDWINDOW, false); + hWnd = CreateWindowA("OVRAppWindow", WindowTitle.ToCStr(), WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, + // 1950, 10, + winSize.right-winSize.left, winSize.bottom-winSize.top, + NULL, NULL, hInstance, (LPVOID)this); + Modifiers = 0; + + Cursor = LoadCursor(NULL, IDC_CROSS); + + // Initialize Window center in screen coordinates + POINT center = { Width / 2, Height / 2 }; + ::ClientToScreen(hWnd, ¢er); + WindowCenter = center; + + if (MMode == Mouse_Relative) + { + ::SetCursorPos(WindowCenter.x, WindowCenter.y); + ShowCursor(FALSE); + } + ::SetFocus(hWnd); + + return (hWnd != NULL); +} + +void PlatformCore::DestroyWindow() +{ + // Release renderer. + pRender.Clear(); + + // Release gamepad. + pGamepadManager.Clear(); + + // Release window resources. + ::DestroyWindow(hWnd); + UnregisterClass(L"OVRAppWindow", hInstance); + hWnd = 0; + Width = Height = 0; + + //DestroyCursor(Cursor); + Cursor = 0; +} + +void PlatformCore::ShowWindow(bool visible) +{ + ::ShowWindow(hWnd, visible ? SW_SHOW : SW_HIDE); +} + +void PlatformCore::SetMouseMode(MouseMode mm) +{ + if (mm == MMode) + return; + + if (hWnd) + { + if (mm == Mouse_Relative) + { + ShowCursor(FALSE); + ::SetCursorPos(WindowCenter.x, WindowCenter.y); + } + else + { + if (MMode == Mouse_Relative) + ShowCursor(TRUE); + } + } + MMode = mm; +} + +void PlatformCore::GetWindowSize(int* w, int* h) const +{ + *w = Width; + *h = Height; +} + + +void PlatformCore::SetWindowTitle(const char* title) +{ + WindowTitle = title; + if (hWnd) + ::SetWindowTextA(hWnd, title); +} + +static UByte KeyMap[][2] = +{ + { VK_BACK, Key_Backspace }, + { VK_TAB, Key_Tab }, + { VK_CLEAR, Key_Clear }, + { VK_RETURN, Key_Return }, + { VK_SHIFT, Key_Shift }, + { VK_CONTROL, Key_Control }, + { VK_MENU, Key_Alt }, + { VK_PAUSE, Key_Pause }, + { VK_CAPITAL, Key_CapsLock }, + { VK_ESCAPE, Key_Escape }, + { VK_SPACE, Key_Space }, + { VK_PRIOR, Key_PageUp }, + { VK_NEXT, Key_PageDown }, + { VK_END, Key_End }, + { VK_HOME, Key_Home }, + { VK_LEFT, Key_Left }, + { VK_UP, Key_Up }, + { VK_RIGHT, Key_Right }, + { VK_DOWN, Key_Down }, + { VK_INSERT, Key_Insert }, + { VK_DELETE, Key_Delete }, + { VK_HELP, Key_Help }, + + { VK_NUMLOCK, Key_NumLock }, + { VK_SCROLL, Key_ScrollLock }, + + { VK_OEM_1, Key_Semicolon }, + { VK_OEM_PLUS, Key_Equal }, + { VK_OEM_COMMA, Key_Comma }, + { VK_OEM_MINUS, Key_Minus }, + { VK_OEM_PERIOD,Key_Period }, + { VK_OEM_2, Key_Slash }, + { VK_OEM_3, Key_Bar }, + { VK_OEM_4, Key_BracketLeft }, + { VK_OEM_5, Key_Backslash }, + { VK_OEM_6, Key_BracketRight }, + { VK_OEM_7, Key_Quote }, + + { VK_OEM_AX, Key_OEM_AX }, // 'AX' key on Japanese AX keyboard. + { VK_OEM_102, Key_OEM_102 }, // "<>" or "\|" on RT 102-key keyboard. + { VK_ICO_HELP, Key_ICO_HELP }, + { VK_ICO_00, Key_ICO_00 } +}; + + +KeyCode MapVKToKeyCode(unsigned vk) +{ + unsigned key = Key_None; + + if ((vk >= '0') && (vk <= '9')) + { + key = vk - '0' + Key_Num0; + } + else if ((vk >= 'A') && (vk <= 'Z')) + { + key = vk - 'A' + Key_A; + } + else if ((vk >= VK_NUMPAD0) && (vk <= VK_DIVIDE)) + { + key = vk - VK_NUMPAD0 + Key_KP_0; + } + else if ((vk >= VK_F1) && (vk <= VK_F15)) + { + key = vk - VK_F1 + Key_F1; + } + else + { + for (unsigned i = 0; i< (sizeof(KeyMap) / sizeof(KeyMap[1])); i++) + { + if (vk == KeyMap[i][0]) + { + key = KeyMap[i][1]; + break; + } + } + } + + return (KeyCode)key; +} + + + +LRESULT CALLBACK PlatformCore::systemWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) +{ + PlatformCore* self; + + // WM_NCCREATE should be the first message to come it; use it to set class pointer. + if (msg == WM_NCCREATE) + { + self = static_cast<PlatformCore*>(((LPCREATESTRUCT)lp)->lpCreateParams); + + if (self) + { + SetWindowLongPtr(hwnd, 0, (LONG_PTR)self); + self->hWnd = hwnd; + } + } + else + { + self = (PlatformCore*)(UPInt)GetWindowLongPtr(hwnd, 0); + } + + return self ? self->WindowProc(msg, wp, lp) : + DefWindowProc(hwnd, msg, wp, lp); +} + + +LRESULT PlatformCore::WindowProc(UINT msg, WPARAM wp, LPARAM lp) +{ + KeyCode keyCode; + + switch (msg) + { + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint(hWnd, &ps); + EndPaint(hWnd, &ps); + } + return 0; + + case WM_SETCURSOR: + ::SetCursor(Cursor); + return 0; + + case WM_MOUSEMOVE: + if (MMode == Mouse_Relative) + { + POINT newPos = { LOWORD(lp), HIWORD(lp) }; + ::ClientToScreen(hWnd, &newPos); + if ((newPos.x == WindowCenter.x) && (newPos.y == WindowCenter.y)) + break; + ::SetCursorPos(WindowCenter.x, WindowCenter.y); + + LONG dx = newPos.x - WindowCenter.x; + LONG dy = newPos.y - WindowCenter.y; + + pApp->OnMouseMove(dx, dy, Mod_MouseRelative); + } + else + { + pApp->OnMouseMove(LOWORD(lp), HIWORD(lp), 0); + } + break; + + case WM_MOVE: + { + RECT r; + GetClientRect(hWnd, &r); + WindowCenter.x = r.right/2; + WindowCenter.y = r.bottom/2; + ::ClientToScreen(hWnd, &WindowCenter); + } + break; + + case WM_KEYDOWN: + switch (wp) + { + case VK_CONTROL: Modifiers |= Mod_Control; break; + case VK_MENU: Modifiers |= Mod_Alt; break; + case VK_SHIFT: Modifiers |= Mod_Shift; break; + case VK_LWIN: + case VK_RWIN: Modifiers |= Mod_Meta; break; + } + if ((keyCode = MapVKToKeyCode((unsigned)wp)) != Key_None) + pApp->OnKey(keyCode, 0, true, Modifiers); + + if (keyCode == Key_Escape && MMode == Mouse_Relative) + { + MMode = Mouse_RelativeEscaped; + ShowCursor(TRUE); + } + break; + + case WM_KEYUP: + if ((keyCode = MapVKToKeyCode((unsigned)wp)) != Key_None) + pApp->OnKey(keyCode, 0, false, Modifiers); + switch (wp) + { + case VK_CONTROL: Modifiers &= ~Mod_Control; break; + case VK_MENU: Modifiers &= ~Mod_Alt; break; + case VK_SHIFT: Modifiers &= ~Mod_Shift; break; + case VK_LWIN: + case VK_RWIN: Modifiers &= ~Mod_Meta; break; + } + break; + + case WM_LBUTTONDOWN: + //App->OnMouseButton(0, + + ::SetCapture(hWnd); + + if (MMode == Mouse_RelativeEscaped) + { + ::SetCursorPos(WindowCenter.x, WindowCenter.y); + ::ShowCursor(FALSE); + MMode = Mouse_Relative; + } + break; + + case WM_LBUTTONUP: + ReleaseCapture(); + break; + + case WM_SETFOCUS: + // Do NOT restore the Relative mode here, since calling SetCursorPos + // would screw up titlebar window dragging. + // Let users click in the center instead to resume. + break; + + case WM_KILLFOCUS: + if (MMode == Mouse_Relative) + { + MMode = Mouse_RelativeEscaped; + ShowCursor(TRUE); + } + break; + + case WM_SIZE: + // Change window size as long as we're not being minimized. + if (wp != SIZE_MINIMIZED) + { + Width = LOWORD(lp); + Height = HIWORD(lp); + if (pRender) + pRender->SetWindowSize(Width, Height); + pApp->OnResize(Width,Height); + } + break; + + case WM_STYLECHANGING: + // Resize the window. This is needed because the size includes any present system controls, and + // windows does not adjust it when changing to fullscreen. + { + STYLESTRUCT* pss = (STYLESTRUCT*)lp; + RECT winSize; + winSize.left = winSize.top = 0; + winSize.right = Width; + winSize.bottom = Height; + int w = winSize.right-winSize.left; + int h = winSize.bottom-winSize.top; + AdjustWindowRect(&winSize, pss->styleNew, false); + ::SetWindowPos(hWnd, NULL, 0, 0, w, h, SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); + } + break; + + case WM_QUIT: + case WM_CLOSE: + pApp->OnQuitRequest(); + return false; + } + + return DefWindowProc(hWnd, msg, wp, lp); +} + +int PlatformCore::Run() +{ + while (!Quit) + { + MSG msg; + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + else + { + pApp->OnIdle(); + + // Keep sleeping when we're minimized. + if (IsIconic(hWnd)) + { + Sleep(10); + } + } + } + + return ExitCode; +} + + +RenderDevice* PlatformCore::SetupGraphics(const SetupGraphicsDeviceSet& setupGraphicsDesc, + const char* type, const Render::RendererParams& rp) +{ + const SetupGraphicsDeviceSet* setupDesc = setupGraphicsDesc.PickSetupDevice(type); + OVR_ASSERT(setupDesc); + + pRender = *setupDesc->pCreateDevice(rp, (void*)hWnd); + if (pRender) + pRender->SetWindowSize(Width, Height); + + ::ShowWindow(hWnd, SW_RESTORE); + return pRender.GetPtr(); +} + + +void PlatformCore::PlayMusicFile(const char *fileName) +{ + PlaySoundA(fileName, NULL, SND_FILENAME | SND_LOOP | SND_ASYNC); +} + + +//----------------------------------------------------------------------------- + +// Used to capture all the active monitor handles +struct MonitorSet +{ + enum { MaxMonitors = 8 }; + HMONITOR Monitors[MaxMonitors]; + int MonitorCount; + int PrimaryCount; +}; + + +BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData) +{ + MonitorSet* monitorSet = (MonitorSet*)dwData; + if (monitorSet->MonitorCount > MonitorSet::MaxMonitors) + return FALSE; + + monitorSet->Monitors[monitorSet->MonitorCount] = hMonitor; + monitorSet->MonitorCount++; + return TRUE; +}; + + +// Returns the number of active screens for extended displays and 1 for mirrored display +int PlatformCore::GetDisplayCount() +{ + // Get all the monitor handles + MonitorSet monitors; + monitors.MonitorCount = 0; + EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&monitors); + + // Count the primary monitors + int primary = 0; + MONITORINFOEX info; + for (int m=0; m < monitors.MonitorCount; m++) + { + info.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(monitors.Monitors[m], &info); + + if (info.dwFlags & MONITORINFOF_PRIMARY) + primary++; + } + + if (primary > 1) + return 1; // Regard mirrored displays as a single screen + else + return monitors.MonitorCount; // Return all extended displays +} + +//----------------------------------------------------------------------------- +// Returns the device name for the given screen index or empty string for invalid index +// The zero index will always return the primary screen name +Render::DisplayId PlatformCore::GetDisplay(int screen) +{ + // Get all the monitor handles + MonitorSet monitors; + monitors.MonitorCount = 0; + EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&monitors); + + String screen_name; + + // Get the name of the suppled screen index with the requirement + // that screen 0 is the primary monitor + int non_primary_count = 0; + MONITORINFOEX info; + for (int m=0; m < monitors.MonitorCount; m++) + { + info.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(monitors.Monitors[m], &info); + + if (info.dwFlags & MONITORINFOF_PRIMARY) + { + if (screen == 0) + { + screen_name = info.szDevice; + break; + } + } + else + { + non_primary_count++; + if (screen == non_primary_count) + { + screen_name = info.szDevice; + break; + } + } + } + + return screen_name; +} + + +}}} + + +int WINAPI WinMain(HINSTANCE hinst, HINSTANCE prevInst, LPSTR inArgs, int show) +{ + using namespace OVR; + using namespace OVR::Platform; + + OVR_UNUSED2(prevInst, show); + + // CreateApplication must be the first call since it does OVR::System::Initialize. + Application* app = Application::CreateApplication(); + Win32::PlatformCore* platform = new Win32::PlatformCore(app, hinst); + // The platform attached to an app will be deleted by DestroyApplication. + app->SetPlatformCore(platform); + + int exitCode = 0; + + // Nested scope for container destructors to shutdown before DestroyApplication. + { + Array<String> args; + Array<const char*> argv; + argv.PushBack("app"); + + const char* p = inArgs; + const char* pstart = inArgs; + while (*p) + { + if (*p == ' ') + { + args.PushBack(String(pstart, p - pstart)); + while (*p == ' ') + p++; + pstart = p; + } + else + { + p++; + } + } + if (p != pstart) + args.PushBack(String(pstart, p - pstart)); + for (UPInt i = 0; i < args.GetSize(); i++) + argv.PushBack(args[i].ToCStr()); + + exitCode = app->OnStartup((int)argv.GetSize(), &argv[0]); + if (!exitCode) + exitCode = platform->Run(); + } + + // No OVR functions involving memory are allowed after this. + Application::DestroyApplication(app); + app = 0; + + OVR_DEBUG_STATEMENT(_CrtDumpMemoryLeaks()); + return exitCode; +} |