forked from IntelRealSense/hand_tracking_samples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmswin.h
234 lines (209 loc) · 7.51 KB
/
mswin.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
//
// mswin.h
//
// Create and setup of a Window for a typical MS Windows application intended for user interaction.
// This file contains the OS specific common window setup and callback functionality.
// This file does not include any of the opengl or directx graphics library setup, just the win32 parts.
// see glwin.h or dxwin.h for subclasses that do this.
//
//
#ifndef SANDBOX_MSWIN_H
#define SANDBOX_MSWIN_H
#include <assert.h>
#include <functional>
#include <vector>
#include <string>
#define NOMINMAX
#include <windows.h>
#include <cstring>
#include <cstdarg> // For va_list, va_start, ...
#include <cstdio> // For vsnprintf
#include "geometric.h"
#define VERIFY (assert(0),throw(std::exception((std::string(__FILE__) + ":" + std::to_string(__LINE__)).c_str())),1)
class MSWin // parent class for DXWin and GLWin, abstract class for the common 3D usages and win32 gui calls support(separated from any dx or opengl)
{
public:
HWND hWnd;
int2 res;
int mousewheel; // if and how much its been rolled up/down this frame
int2 mousepos;
int2 mousepos_previous;
int2 mousepos_lastup;
float2 dmouse = { 0,0 };
float3 MouseVector; // 3D direction mouse points
float3 OldMouseVector;
int MouseState; // true iff left button down
float ViewAngle;
bool downevent;
bool centermouse = false;
bool centered_last_frame = false;
bool focus = true;
bool window_should_stay_open = true;
RECT window_inset; // the extra pixels windows needs for its borders on windowed windows.
std::function<void(int, int, int)> keyboardfunc; // for WM_CHAR events
std::function<void(int)> keydownfunc = [](int) {}; // because windows
std::function<void()> preshutdown = []() {};
std::function<void(int,int)> reshape = [](int,int) {};
float aspect_ratio() { return (float)res.x / (float)res.y; }
void ComputeMouseVector()
{
OldMouseVector = MouseVector;
float spread = (float)tan(ViewAngle / 2 * 3.14 / 180);
float y = spread * ((res.y - mousepos.y) - res.y / 2.0f) / (res.y / 2.0f);
float x = spread * (mousepos.x - res.x / 2.0f) / (res.y / 2.0f);
MouseVector = normalize(float3(x, y, -1));
}
MSWin(const char *title, int2 res) :res(res), mousepos(0, 0), MouseState(0),
mousewheel(0), ViewAngle(60.0f), window_should_stay_open(true),
reshape([this](int x, int y) {this->res = { x,y }; })
{
}
// virtual LONG WINAPI MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) = 0; // since we override
void CreateMSWindow(const char* title, int2 res, int2 win_position = { 5,25 })
{
WNDCLASSA wc; // force non-unicode16 version using 'A' suffix
wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)MsgProcG; // the global winproc
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandleA(NULL); // hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "SANDBOX";
if (!RegisterClassA(&wc))
throw("RegisterClassA() failed: Cannot register window class."); // supposedly should only register the window class once
SetRect(&window_inset, 0, 0, 0, 0);
AdjustWindowRect(&window_inset, WS_OVERLAPPEDWINDOW, 0);
this->hWnd = CreateWindowA("SANDBOX", title, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
//rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
win_position.x + window_inset.left, win_position.y + window_inset.top, res.x + window_inset.right - window_inset.left, res.y + window_inset.bottom - window_inset.top,
NULL, NULL, wc.hInstance, this); // force non-unicode16 non-wchar version of Windows's CreateWindow
if (hWnd == NULL)
throw("CreateWindow() failed: Cannot create a window.");
}
static LRESULT WINAPI MsgProcG(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_NCCREATE)
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)(reinterpret_cast<CREATESTRUCT *>(lParam)->lpCreateParams)); // grab my pointer passed into createwindow
auto w = reinterpret_cast<MSWin *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
return (w) ? w->MsgProc(hWnd, msg, wParam, lParam) : DefWindowProc(hWnd, msg, wParam, lParam);
}
LRESULT WINAPI MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
auto fixnbits = [](int d) { return (d & 1 << 15) ? d - (1 << 16) : d; };
auto take_mouse_position_from_lparam = [lParam, fixnbits]() ->int2 { return int2(fixnbits(LOWORD(lParam)), fixnbits(HIWORD(lParam))); };
switch (uMsg) {
case WM_CHAR:
switch (wParam) {
case 27: /* ESC key */
if (preshutdown)
preshutdown();
PostQuitMessage(0);
break;
}
if (keyboardfunc)
keyboardfunc((int)wParam, mousepos.x, mousepos.y); // to match glut's api, add the x and y.
return 0;
case WM_KEYDOWN:
keydownfunc((int)wParam);
return 0;
case WM_LBUTTONDOWN:
SetCapture(hWnd); // set the capture to get mouse moves outside window
mousepos_lastup = mousepos_previous = mousepos = take_mouse_position_from_lparam();
ComputeMouseVector();
OldMouseVector = MouseVector; // for touch devices to avoid unwanted snappings
downevent = 1;
MouseState = 1;
return 0;
case WM_LBUTTONUP:
mousepos = take_mouse_position_from_lparam();
ComputeMouseVector();
MouseState = 0;
ReleaseCapture();
return 0;
case WM_MOUSEMOVE:
mousepos = take_mouse_position_from_lparam();
ComputeMouseVector();
return 0;
case WM_MOUSEWHEEL:
//shiftdown = (wParam&MK_SHIFT) ? 1 : 0; ctrldown = (wParam&MK_CONTROL) ? 1 : 0;
mousewheel += GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;
return 0;
case WM_SIZE:
if(reshape)
reshape(LOWORD(lParam), HIWORD(lParam));
PostMessage(hWnd, WM_PAINT, 0, 0);
return 0;
case WM_SETFOCUS:
focus = 1;
break;
case WM_KILLFOCUS:
focus = 0;
break;
case WM_CLOSE:
if (preshutdown)
preshutdown();
PostQuitMessage(0);
window_should_stay_open = false;
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
bool WindowUp()
{
dmouse = { 0,0 }; // only used if mouse is being centered each frame
downevent = 0;
mousewheel = 0; // reset to 0 each frame
mousepos_previous = mousepos;
if (!MouseState)
mousepos_lastup = mousepos;
OldMouseVector = MouseVector;
MSG msg; // Windows message
while (PeekMessage(&msg, hWnd, 0, 0, PM_NOREMOVE)) {
if (GetMessage(&msg, hWnd, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
if (preshutdown)
preshutdown();
window_should_stay_open = false;
return false;
}
}
if (centermouse && focus) {
RECT rect;
RECT crect;
POINT pt;
GetWindowRect(hWnd, &rect);
GetClientRect(hWnd, &crect);
GetCursorPos(&pt);
if (1) // (windowed)
{
rect.left -= window_inset.left; // todo: look into the function: ScreenToClient(hwnd,point)
rect.top -= window_inset.top;
}
if (centered_last_frame)
{
dmouse.x = (float)(pt.x - rect.left - (res.x / 2)) / (res.x / 2.0f);
dmouse.y = -(float)(pt.y - rect.top - (res.y / 2)) / (res.y / 2.0f);
}
else
dmouse = { 0,0 };
SetCursorPos(res.x / 2 + rect.left, res.y / 2 + rect.top);
MouseVector = float3(0, 0, -1);
centered_last_frame = 1;
}
else
{
centered_last_frame = 0;
}
return window_should_stay_open;
}
};
// see dxwin.h for usage such as:
// class DXWin : public MSWin
#endif //SANDBOX_MSWIN_H