|
14 | 14 | // |
15 | 15 | //********************************************************* |
16 | 16 | #include "pch.h" |
| 17 | +#include <windowsx.h> |
| 18 | +#include <shellapi.h> |
17 | 19 | #include <XrSceneLib/XrApp.h> |
| 20 | +#include "Resource.h" |
18 | 21 |
|
19 | 22 | std::unique_ptr<engine::Scene> TryCreateTitleScene(engine::Context& context); |
20 | 23 | std::unique_ptr<engine::Scene> TryCreateControllerModelScene(engine::Context& context); |
| 24 | +std::unique_ptr<engine::Scene> TryCreateControllerActionsScene(engine::Context& context); |
21 | 25 |
|
22 | | -int APIENTRY wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPWSTR, _In_ int) { |
23 | | - try { |
| 26 | +// Global Variables: |
| 27 | +std::thread sceneThread; |
| 28 | +std::unique_ptr<engine::XrApp> app; |
| 29 | + |
| 30 | +void EnterVR(); |
| 31 | +INT_PTR CALLBACK DialogWinProc(HWND, UINT, WPARAM, LPARAM); |
| 32 | + |
| 33 | +int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR, _In_ int) { |
| 34 | + int nArgs; |
| 35 | + LPWSTR* szArglist = ::CommandLineToArgvW(GetCommandLineW(), &nArgs); |
| 36 | + if (nArgs >= 2 && ::_wcsicmp(szArglist[1], L"-openxr") == 0) { |
| 37 | + EnterVR(); |
| 38 | + } |
| 39 | + |
| 40 | + DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOGBOX), NULL, DialogWinProc); |
| 41 | + return 0; |
| 42 | +} |
| 43 | + |
| 44 | +void EnterVR() { |
| 45 | + sceneThread = std::thread([] { |
24 | 46 | CHECK_HRCMD(::CoInitializeEx(nullptr, COINIT_MULTITHREADED)); |
25 | 47 | auto on_exit = MakeScopeGuard([] { ::CoUninitialize(); }); |
26 | 48 |
|
27 | 49 | engine::XrAppConfiguration appConfig({"SampleSceneWin32", 1}); |
28 | 50 | appConfig.RequestedExtensions.push_back(XR_MSFT_CONTROLLER_MODEL_EXTENSION_NAME); |
| 51 | + appConfig.RequestedExtensions.push_back(XR_MSFT_HAND_INTERACTION_EXTENSION_NAME); |
| 52 | + appConfig.RequestedExtensions.push_back(XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME); |
29 | 53 |
|
30 | | - auto app = engine::CreateXrApp(appConfig); |
| 54 | + app = engine::CreateXrApp(appConfig); |
31 | 55 | app->AddScene(TryCreateTitleScene(app->Context())); |
32 | 56 | app->AddScene(TryCreateControllerModelScene(app->Context())); |
| 57 | + app->AddScene(TryCreateControllerActionsScene(app->Context())); |
33 | 58 | app->Run(); |
34 | | - } catch (const std::exception& ex) { |
35 | | - sample::Trace("Unhandled Exception: {}", ex.what()); |
36 | | - return 1; |
37 | | - } catch (...) { |
38 | | - sample::Trace(L"Unhandled Exception"); |
39 | | - return 1; |
| 59 | + app = nullptr; |
| 60 | + }); |
| 61 | +} |
| 62 | + |
| 63 | +void ExitVR() { |
| 64 | + if (sceneThread.joinable()) { |
| 65 | + if (app) { |
| 66 | + app->Stop(); |
| 67 | + } |
| 68 | + sceneThread.join(); |
40 | 69 | } |
| 70 | +} |
41 | 71 |
|
42 | | - return 0; |
| 72 | +void TrapCursorIfMouseLeave(HWND hwnd) { |
| 73 | + RECT rc; |
| 74 | + ::GetWindowRect(hwnd, &rc); |
| 75 | + |
| 76 | + POINT pt; |
| 77 | + ::GetCursorPos(&pt); |
| 78 | + |
| 79 | + if (!::PtInRect(&rc, pt)) { |
| 80 | + ::SetCursorPos((rc.left + rc.right) / 2, (rc.top + rc.bottom) / 2); |
| 81 | + } |
| 82 | +} |
| 83 | + |
| 84 | +INT_PTR CALLBACK DialogWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { |
| 85 | + UNREFERENCED_PARAMETER(lParam); |
| 86 | + constexpr UINT_PTR IDT_MOUSETRAP = 1; |
| 87 | + |
| 88 | + switch (message) { |
| 89 | + case WM_INITDIALOG: |
| 90 | + // Setup a recurring timer to move mouse back when it moves out of this window. |
| 91 | + // It's a simple way to keep WM_MOUSEMOVE event to remain sending to this window. |
| 92 | + ::SetTimer(hwnd, IDT_MOUSETRAP, 100, NULL); |
| 93 | + return (INT_PTR)TRUE; |
| 94 | + |
| 95 | + case WM_COMMAND: |
| 96 | + if (LOWORD(wParam) == IDOK) { |
| 97 | + ExitVR(); |
| 98 | + EnterVR(); |
| 99 | + } else if (LOWORD(wParam) == IDCANCEL) { |
| 100 | + ::EndDialog(hwnd, 0); |
| 101 | + } |
| 102 | + break; |
| 103 | + |
| 104 | + case WM_TIMER: |
| 105 | + if (wParam == IDT_MOUSETRAP && hwnd == ::GetForegroundWindow()) { |
| 106 | + TrapCursorIfMouseLeave(hwnd); |
| 107 | + } |
| 108 | + break; |
| 109 | + |
| 110 | + case WM_MOUSEMOVE: |
| 111 | + ::SetWindowText(hwnd, fmt::format(L"Mouse pos: {}, {}", GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)).c_str()); |
| 112 | + break; |
| 113 | + |
| 114 | + case WM_DESTROY: |
| 115 | + ExitVR(); |
| 116 | + ::KillTimer(hwnd, IDT_MOUSETRAP); |
| 117 | + ::PostQuitMessage(0); |
| 118 | + break; |
| 119 | + } |
| 120 | + |
| 121 | + return (INT_PTR)FALSE; |
43 | 122 | } |
0 commit comments