]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CIrrDeviceWin32.h
Add back LightManager
[irrlicht.git] / source / Irrlicht / CIrrDeviceWin32.h
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #ifndef __C_IRR_DEVICE_WIN32_H_INCLUDED__\r
6 #define __C_IRR_DEVICE_WIN32_H_INCLUDED__\r
7 \r
8 #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_\r
9 \r
10 #include "CIrrDeviceStub.h"\r
11 #include "IrrlichtDevice.h"\r
12 \r
13 #define WIN32_LEAN_AND_MEAN\r
14 #include <windows.h>\r
15 #include <mmsystem.h> // For JOYCAPS\r
16 #include <windowsx.h>\r
17 #if !defined(GET_X_LPARAM)\r
18 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))\r
19 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))\r
20 #endif\r
21 \r
22 namespace irr\r
23 {\r
24         struct SJoystickWin32Control;\r
25 \r
26         class CIrrDeviceWin32 : public CIrrDeviceStub\r
27         {\r
28         friend struct SJoystickWin32Control;\r
29         public:\r
30 \r
31                 //! constructor\r
32                 CIrrDeviceWin32(const SIrrlichtCreationParameters& params);\r
33 \r
34                 //! destructor\r
35                 virtual ~CIrrDeviceWin32();\r
36 \r
37                 //! runs the device. Returns false if device wants to be deleted\r
38                 bool run() override;\r
39 \r
40                 //! Cause the device to temporarily pause execution and let other processes to run\r
41                 // This should bring down processor usage without major performance loss for Irrlicht\r
42                 void yield() override;\r
43 \r
44                 //! Pause execution and let other processes to run for a specified amount of time.\r
45                 void sleep(u32 timeMs, bool pauseTimer) override;\r
46 \r
47                 //! sets the caption of the window\r
48                 void setWindowCaption(const wchar_t* text) override;\r
49 \r
50                 //! returns if window is active. if not, nothing need to be drawn\r
51                 bool isWindowActive() const override;\r
52 \r
53                 //! returns if window has focus\r
54                 bool isWindowFocused() const override;\r
55 \r
56                 //! returns if window is minimized\r
57                 bool isWindowMinimized() const override;\r
58 \r
59                 //! returns last state from maximizeWindow() and restoreWindow()\r
60                 bool isWindowMaximized() const override;\r
61 \r
62                 //! notifies the device that it should close itself\r
63                 void closeDevice() override;\r
64 \r
65                 //! Notifies the device, that it has been resized\r
66                 /** Must be publis as it is called from free function (event handler) */\r
67                 void OnResized();\r
68 \r
69                 //! Sets if the window should be resizable in windowed mode.\r
70                 void setResizable(bool resize=false) override;\r
71 \r
72                 //! Resize the render window.\r
73                 void setWindowSize(const irr::core::dimension2d<u32>& size) override;\r
74 \r
75                 //! Minimizes the window.\r
76                 void minimizeWindow() override;\r
77 \r
78                 //! Maximizes the window.\r
79                 void maximizeWindow() override;\r
80 \r
81                 //! Restores the window size.\r
82                 void restoreWindow() override;\r
83 \r
84                 //! Get the position of the window on screen\r
85                 core::position2di getWindowPosition() override;\r
86 \r
87                 //! Activate any joysticks, and generate events for them.\r
88                 bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) override;\r
89 \r
90                 //! Remove all messages pending in the system message loop\r
91                 void clearSystemMessages() override;\r
92 \r
93                 //! Get the device type\r
94                 E_DEVICE_TYPE getType() const override\r
95                 {\r
96                         return EIDT_WIN32;\r
97                 }\r
98 \r
99                 //! Compares to the last call of this function to return double and triple clicks.\r
100                 //! \return Returns only 1,2 or 3. A 4th click will start with 1 again.\r
101                 u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent ) override\r
102                 {\r
103                         // we just have to make it public\r
104                         return CIrrDeviceStub::checkSuccessiveClicks(mouseX, mouseY, inputEvent );\r
105                 }\r
106 \r
107                 //! Switch to fullscreen\r
108                 bool switchToFullScreen();\r
109 \r
110                 // convert an Irrlicht texture to a windows cursor\r
111                 HCURSOR TextureToCursor(HWND hwnd, irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);\r
112 \r
113                 //! Implementation of the win32 cursor control\r
114                 class CCursorControl : public gui::ICursorControl\r
115                 {\r
116                 public:\r
117 \r
118                         CCursorControl(CIrrDeviceWin32* device, const core::dimension2d<u32>& wsize, HWND hwnd, bool fullscreen);\r
119                         ~CCursorControl();\r
120 \r
121                         //! Changes the visible state of the mouse cursor.\r
122                         void setVisible(bool visible) override\r
123                         {\r
124                                 CURSORINFO info;\r
125                                 info.cbSize = sizeof(CURSORINFO);\r
126                                 BOOL gotCursorInfo = GetCursorInfo(&info);\r
127                                 while ( gotCursorInfo )\r
128                                 {\r
129 #ifdef CURSOR_SUPPRESSED\r
130                                         // Since Windows 8 the cursor can be suppressed by a touch interface\r
131                                         if (visible && info.flags == CURSOR_SUPPRESSED)\r
132                                         {\r
133                                                 break;\r
134                                         }\r
135 #endif\r
136                                         if ( (visible && info.flags == CURSOR_SHOWING) || // visible\r
137                                                 (!visible && info.flags == 0 ) ) // hidden\r
138                                         {\r
139                                                 break;\r
140                                         }\r
141                                         // this only increases an internal\r
142                                         // display counter in windows, so it\r
143                                         // might have to be called some more\r
144                                         const int showResult = ShowCursor(visible);\r
145                                         // if result has correct sign we can\r
146                                         // stop here as well\r
147                                         if (( !visible && showResult < 0 ) ||\r
148                                                 (visible && showResult >= 0))\r
149                                                 break;\r
150                                         // yes, it really must be set each time\r
151                                         info.cbSize = sizeof(CURSORINFO);\r
152                                         gotCursorInfo = GetCursorInfo(&info);\r
153 \r
154 #ifdef CURSOR_SUPPRESSED\r
155                                         // Not sure if a cursor which we tried to hide still can be suppressed.\r
156                                         // I have no touch-display for testing this and MSDN doesn't describe it.\r
157                                         // But adding this check shouldn't hurt and might prevent an endless loop.\r
158                                         if (!visible && info.flags == CURSOR_SUPPRESSED)\r
159                                         {\r
160                                                 break;\r
161                                         }\r
162 #endif\r
163                                 }\r
164                                 IsVisible = visible;\r
165                         }\r
166 \r
167                         //! Returns if the cursor is currently visible.\r
168                         bool isVisible() const override\r
169                         {\r
170                                 return IsVisible;\r
171                         }\r
172 \r
173                         //! Sets the new position of the cursor.\r
174                         void setPosition(const core::position2d<f32> &pos) override\r
175                         {\r
176                                 setPosition(pos.X, pos.Y);\r
177                         }\r
178 \r
179                         //! Sets the new position of the cursor.\r
180                         void setPosition(f32 x, f32 y) override\r
181                         {\r
182                                 if (!UseReferenceRect)\r
183                                         setPosition(core::round32(x*WindowSize.Width), core::round32(y*WindowSize.Height));\r
184                                 else\r
185                                         setPosition(core::round32(x*ReferenceRect.getWidth()), core::round32(y*ReferenceRect.getHeight()));\r
186                         }\r
187 \r
188                         //! Sets the new position of the cursor.\r
189                         void setPosition(const core::position2d<s32> &pos) override\r
190                         {\r
191                                 setPosition(pos.X, pos.Y);\r
192                         }\r
193 \r
194                         //! Sets the new position of the cursor.\r
195                         void setPosition(s32 x, s32 y) override\r
196                         {\r
197                                 if (UseReferenceRect)\r
198                                 {\r
199                                         SetCursorPos(ReferenceRect.UpperLeftCorner.X + x,\r
200                                                                 ReferenceRect.UpperLeftCorner.Y + y);\r
201                                 }\r
202                                 else\r
203                                 {\r
204                                         RECT rect;\r
205                                         if (GetWindowRect(HWnd, &rect))\r
206                                                 SetCursorPos(x + rect.left + BorderX, y + rect.top + BorderY);\r
207                                 }\r
208 \r
209                                 CursorPos.X = x;\r
210                                 CursorPos.Y = y;\r
211                         }\r
212 \r
213                         //! Returns the current position of the mouse cursor.\r
214                         const core::position2d<s32>& getPosition(bool updateCursor) override\r
215                         {\r
216                                 if ( updateCursor )\r
217                                         updateInternalCursorPosition();\r
218                                 return CursorPos;\r
219                         }\r
220 \r
221                         //! Returns the current position of the mouse cursor.\r
222                         core::position2d<f32> getRelativePosition(bool updateCursor) override\r
223                         {\r
224                                 if ( updateCursor )\r
225                                         updateInternalCursorPosition();\r
226 \r
227                                 if (!UseReferenceRect)\r
228                                 {\r
229                                         return core::position2d<f32>(CursorPos.X * InvWindowSize.Width,\r
230                                                 CursorPos.Y * InvWindowSize.Height);\r
231                                 }\r
232 \r
233                                 return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),\r
234                                                 CursorPos.Y / (f32)ReferenceRect.getHeight());\r
235                         }\r
236 \r
237                         //! Sets an absolute reference rect for calculating the cursor position.\r
238                         void setReferenceRect(core::rect<s32>* rect=0) override\r
239                         {\r
240                                 if (rect)\r
241                                 {\r
242                                         ReferenceRect = *rect;\r
243                                         UseReferenceRect = true;\r
244 \r
245                                         // prevent division through zero and uneven sizes\r
246 \r
247                                         if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2)\r
248                                                 ReferenceRect.LowerRightCorner.Y += 1;\r
249 \r
250                                         if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2)\r
251                                                 ReferenceRect.LowerRightCorner.X += 1;\r
252                                 }\r
253                                 else\r
254                                         UseReferenceRect = false;\r
255                         }\r
256 \r
257                         /** Used to notify the cursor that the window was resized. */\r
258                         void OnResize(const core::dimension2d<u32>& size)\r
259                         {\r
260                                 WindowSize = size;\r
261                                 if (size.Width!=0)\r
262                                         InvWindowSize.Width = 1.0f / size.Width;\r
263                                 else\r
264                                         InvWindowSize.Width = 0.f;\r
265 \r
266                                 if (size.Height!=0)\r
267                                         InvWindowSize.Height = 1.0f / size.Height;\r
268                                 else\r
269                                         InvWindowSize.Height = 0.f;\r
270                         }\r
271 \r
272                         /** Used to notify the cursor that the window resizable settings changed. */\r
273                         void updateBorderSize(bool fullscreen, bool resizable)\r
274                         {\r
275                                 if (!fullscreen)\r
276                                 {\r
277                                         s32 paddingBorder = 0;\r
278                                         #ifdef SM_CXPADDEDBORDER\r
279                                                 paddingBorder = GetSystemMetrics(SM_CXPADDEDBORDER);\r
280                                         #endif\r
281 \r
282                                         if (resizable)\r
283                                         {\r
284                                                 BorderX = GetSystemMetrics(SM_CXSIZEFRAME) + paddingBorder;\r
285                                                 BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYSIZEFRAME) + paddingBorder;\r
286                                         }\r
287                                         else\r
288                                         {\r
289                                                 BorderX = GetSystemMetrics(SM_CXDLGFRAME) + paddingBorder;\r
290                                                 BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME) + paddingBorder;\r
291                                         }\r
292                                 }\r
293                                 else\r
294                                 {\r
295                                         BorderX = BorderY = 0;\r
296                                 }\r
297                         }\r
298 \r
299 \r
300                         //! Sets the active cursor icon\r
301                         void setActiveIcon(gui::ECURSOR_ICON iconId) override;\r
302 \r
303                         //! Gets the currently active icon\r
304                         gui::ECURSOR_ICON getActiveIcon() const override\r
305                         {\r
306                                 return ActiveIcon;\r
307                         }\r
308 \r
309                         //! Add a custom sprite as cursor icon.\r
310                         gui::ECURSOR_ICON addIcon(const gui::SCursorSprite& icon) override;\r
311 \r
312                         //! replace the given cursor icon.\r
313                         void changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite& icon) override;\r
314 \r
315                         //! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work.\r
316                         core::dimension2di getSupportedIconSize() const override;\r
317 \r
318                         void update();\r
319 \r
320                 private:\r
321 \r
322                         //! Updates the internal cursor position\r
323                         void updateInternalCursorPosition()\r
324                         {\r
325                                 POINT p;\r
326                                 if (!GetCursorPos(&p))\r
327                                 {\r
328                                         DWORD xy = GetMessagePos();\r
329                                         p.x = GET_X_LPARAM(xy);\r
330                                         p.y = GET_Y_LPARAM(xy);\r
331                                 }\r
332 \r
333                                 if (UseReferenceRect)\r
334                                 {\r
335                                         CursorPos.X = p.x - ReferenceRect.UpperLeftCorner.X;\r
336                                         CursorPos.Y = p.y - ReferenceRect.UpperLeftCorner.Y;\r
337                                 }\r
338                                 else\r
339                                 {\r
340                                         RECT rect;\r
341                                         if (GetWindowRect(HWnd, &rect))\r
342                                         {\r
343                                                 CursorPos.X = p.x-rect.left-BorderX;\r
344                                                 CursorPos.Y = p.y-rect.top-BorderY;\r
345                                         }\r
346                                         else\r
347                                         {\r
348                                                 // window seems not to be existent, so set cursor to\r
349                                                 // a negative value\r
350                                                 CursorPos.X = -1;\r
351                                                 CursorPos.Y = -1;\r
352                                         }\r
353                                 }\r
354                         }\r
355 \r
356                         CIrrDeviceWin32* Device;\r
357                         core::position2d<s32> CursorPos;\r
358                         core::dimension2d<u32> WindowSize;\r
359                         core::dimension2d<f32> InvWindowSize;\r
360                         HWND HWnd;\r
361 \r
362                         s32 BorderX, BorderY;\r
363                         core::rect<s32> ReferenceRect;\r
364                         bool UseReferenceRect;\r
365                         bool IsVisible;\r
366 \r
367 \r
368                         struct CursorFrameW32\r
369                         {\r
370                                 CursorFrameW32() : IconHW(0) {}\r
371                                 CursorFrameW32(HCURSOR icon) : IconHW(icon) {}\r
372 \r
373                                 HCURSOR IconHW; // hardware cursor\r
374                         };\r
375 \r
376                         struct CursorW32\r
377                         {\r
378                                 CursorW32() {}\r
379                                 explicit CursorW32(HCURSOR iconHw, u32 frameTime=0) : FrameTime(frameTime)\r
380                                 {\r
381                                         Frames.push_back( CursorFrameW32(iconHw) );\r
382                                 }\r
383                                 core::array<CursorFrameW32> Frames;\r
384                                 u32 FrameTime;\r
385                         };\r
386 \r
387                         core::array<CursorW32> Cursors;\r
388                         gui::ECURSOR_ICON ActiveIcon;\r
389                         u32 ActiveIconStartTime;\r
390 \r
391                         void initCursors();\r
392                 };\r
393 \r
394                 //! returns the win32 cursor control\r
395                 CCursorControl* getWin32CursorControl();\r
396 \r
397         private:\r
398 \r
399                 //! create the driver\r
400                 void createDriver();\r
401 \r
402                 //! Process system events\r
403                 void handleSystemMessages();\r
404 \r
405                 void getWindowsVersion(core::stringc& version);\r
406 \r
407                 void resizeIfNecessary();\r
408 \r
409                 DWORD getWindowStyle(bool fullscreen, bool resizable) const;\r
410 \r
411                 HWND HWnd;\r
412 \r
413                 bool Resized;\r
414                 bool ExternalWindow;\r
415                 CCursorControl* Win32CursorControl;\r
416 \r
417                 SJoystickWin32Control* JoyControl;\r
418 \r
419                 bool WindowMaximized;\r
420         };\r
421 \r
422 } // end namespace irr\r
423 \r
424 #endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_\r
425 #endif // __C_IRR_DEVICE_WIN32_H_INCLUDED__\r