]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CIrrDeviceSDL.h
7657718fcbbda3f506c2e3c85f29a1471d1556b4
[irrlicht.git] / source / Irrlicht / CIrrDeviceSDL.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 // This device code is based on the original SDL device implementation\r
5 // contributed by Shane Parker (sirshane).\r
6 \r
7 #ifndef __C_IRR_DEVICE_SDL_H_INCLUDED__\r
8 #define __C_IRR_DEVICE_SDL_H_INCLUDED__\r
9 \r
10 #include "IrrCompileConfig.h"\r
11 \r
12 #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_\r
13 \r
14 #include "IrrlichtDevice.h"\r
15 #include "CIrrDeviceStub.h"\r
16 #include "ICursorControl.h"\r
17 \r
18 #ifdef _IRR_EMSCRIPTEN_PLATFORM_\r
19 #include <emscripten/html5.h>\r
20 #endif\r
21 \r
22 #include <SDL.h>\r
23 #include <SDL_syswm.h>\r
24 \r
25 #include <memory>\r
26 \r
27 namespace irr\r
28 {\r
29 \r
30         class CIrrDeviceSDL : public CIrrDeviceStub\r
31         {\r
32         public:\r
33 \r
34                 //! constructor\r
35                 CIrrDeviceSDL(const SIrrlichtCreationParameters& param);\r
36 \r
37                 //! destructor\r
38                 virtual ~CIrrDeviceSDL();\r
39 \r
40                 //! runs the device. Returns false if device wants to be deleted\r
41                 bool run() override;\r
42 \r
43                 //! pause execution temporarily\r
44                 void yield() override;\r
45 \r
46                 //! pause execution for a specified time\r
47                 void sleep(u32 timeMs, bool pauseTimer) override;\r
48 \r
49                 //! sets the caption of the window\r
50                 void setWindowCaption(const wchar_t* text) override;\r
51 \r
52                 //! returns if window is active. if not, nothing need to be drawn\r
53                 bool isWindowActive() const override;\r
54 \r
55                 //! returns if window has focus.\r
56                 bool isWindowFocused() const override;\r
57 \r
58                 //! returns if window is minimized.\r
59                 bool isWindowMinimized() const override;\r
60 \r
61                 //! returns color format of the window.\r
62                 video::ECOLOR_FORMAT getColorFormat() const override;\r
63 \r
64                 //! notifies the device that it should close itself\r
65                 void closeDevice() override;\r
66 \r
67                 //! Sets if the window should be resizable in windowed mode.\r
68                 void setResizable(bool resize=false) override;\r
69 \r
70                 //! Minimizes the window.\r
71                 void minimizeWindow() override;\r
72 \r
73                 //! Maximizes the window.\r
74                 void maximizeWindow() override;\r
75 \r
76                 //! Restores the window size.\r
77                 void restoreWindow() override;\r
78 \r
79                 //! Checks if the window is maximized.\r
80                 bool isWindowMaximized() const override;\r
81 \r
82                 //! Checks if the Irrlicht window is running in fullscreen mode\r
83                 /** \return True if window is fullscreen. */\r
84                 bool isFullscreen() const override;\r
85 \r
86                 //! Get the position of this window on screen\r
87                 core::position2di getWindowPosition() override;\r
88 \r
89                 //! Activate any joysticks, and generate events for them.\r
90                 bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) override;\r
91 \r
92                 //! Get the device type\r
93                 E_DEVICE_TYPE getType() const override\r
94                 {\r
95                         return EIDT_SDL;\r
96                 }\r
97 \r
98                 void SwapWindow();\r
99 \r
100                 //! Implementation of the linux cursor control\r
101                 class CCursorControl : public gui::ICursorControl\r
102                 {\r
103                 public:\r
104 \r
105                         CCursorControl(CIrrDeviceSDL* dev)\r
106                                 : Device(dev), IsVisible(true)\r
107                         {\r
108                                 initCursors();\r
109                         }\r
110 \r
111                         //! Changes the visible state of the mouse cursor.\r
112                         void setVisible(bool visible) override\r
113                         {\r
114                                 IsVisible = visible;\r
115                                 if ( visible )\r
116                                         SDL_ShowCursor( SDL_ENABLE );\r
117                                 else\r
118                                 {\r
119                                         SDL_ShowCursor( SDL_DISABLE );\r
120                                 }\r
121                         }\r
122 \r
123                         //! Returns if the cursor is currently visible.\r
124                         bool isVisible() const override\r
125                         {\r
126                                 return IsVisible;\r
127                         }\r
128 \r
129                         //! Sets the new position of the cursor.\r
130                         void setPosition(const core::position2d<f32> &pos) override\r
131                         {\r
132                                 setPosition(pos.X, pos.Y);\r
133                         }\r
134 \r
135                         //! Sets the new position of the cursor.\r
136                         void setPosition(f32 x, f32 y) override\r
137                         {\r
138                                 setPosition((s32)(x*Device->Width), (s32)(y*Device->Height));\r
139                         }\r
140 \r
141                         //! Sets the new position of the cursor.\r
142                         void setPosition(const core::position2d<s32> &pos) override\r
143                         {\r
144                                 setPosition(pos.X, pos.Y);\r
145                         }\r
146 \r
147                         //! Sets the new position of the cursor.\r
148                         void setPosition(s32 x, s32 y) override\r
149                         {\r
150                                 SDL_WarpMouseInWindow(Device->Window, x, y);\r
151 \r
152                                 if (SDL_GetRelativeMouseMode()) {\r
153                                         // There won't be an event for this warp (details on libsdl-org/SDL/issues/6034)\r
154                                         Device->MouseX = x;\r
155                                         Device->MouseY = y;\r
156                                 }\r
157                         }\r
158 \r
159                         //! Returns the current position of the mouse cursor.\r
160                         const core::position2d<s32>& getPosition(bool updateCursor) override\r
161                         {\r
162                                 if ( updateCursor )\r
163                                         updateCursorPos();\r
164                                 return CursorPos;\r
165                         }\r
166 \r
167                         //! Returns the current position of the mouse cursor.\r
168                         core::position2d<f32> getRelativePosition(bool updateCursor) override\r
169                         {\r
170                                 if ( updateCursor )\r
171                                         updateCursorPos();\r
172                                 return core::position2d<f32>(CursorPos.X / (f32)Device->Width,\r
173                                         CursorPos.Y / (f32)Device->Height);\r
174                         }\r
175 \r
176                         void setReferenceRect(core::rect<s32>* rect=0) override\r
177                         {\r
178                         }\r
179 \r
180                         virtual void setRelativeMode(bool relative) _IRR_OVERRIDE_\r
181                         {\r
182                                 // Only change it when necessary, as it flushes mouse motion when enabled\r
183                                 if ( relative != SDL_GetRelativeMouseMode()) {\r
184                                         if ( relative )\r
185                                                 SDL_SetRelativeMouseMode( SDL_TRUE );\r
186                                         else\r
187                                                 SDL_SetRelativeMouseMode( SDL_FALSE );\r
188                                 }\r
189                         }\r
190 \r
191                         void setActiveIcon(gui::ECURSOR_ICON iconId) override\r
192                         {\r
193                                 ActiveIcon = iconId;\r
194                                 if (iconId > Cursors.size() || !Cursors[iconId]) {\r
195                                         iconId = gui::ECI_NORMAL;\r
196                                         if (iconId > Cursors.size() || !Cursors[iconId])\r
197                                                 return;\r
198                                 }\r
199                                 SDL_SetCursor(Cursors[iconId].get());\r
200                         }\r
201 \r
202                         gui::ECURSOR_ICON getActiveIcon() const override\r
203                         {\r
204                                 return ActiveIcon;\r
205                         }\r
206 \r
207                 private:\r
208 \r
209                         void updateCursorPos()\r
210                         {\r
211 #ifdef _IRR_EMSCRIPTEN_PLATFORM_\r
212                                 EmscriptenPointerlockChangeEvent pointerlockStatus; // let's hope that test is not expensive ...\r
213                                 if ( emscripten_get_pointerlock_status(&pointerlockStatus) == EMSCRIPTEN_RESULT_SUCCESS )\r
214                                 {\r
215                                         if ( pointerlockStatus.isActive )\r
216                                         {\r
217                                                 CursorPos.X += Device->MouseXRel;\r
218                                                 CursorPos.Y += Device->MouseYRel;\r
219                                                 Device->MouseXRel = 0;\r
220                                                 Device->MouseYRel = 0;\r
221                                         }\r
222                                         else\r
223                                         {\r
224                                                 CursorPos.X = Device->MouseX;\r
225                                                 CursorPos.Y = Device->MouseY;\r
226                                         }\r
227                                 }\r
228 #else\r
229                                 CursorPos.X = Device->MouseX;\r
230                                 CursorPos.Y = Device->MouseY;\r
231 \r
232                                 if (CursorPos.X < 0)\r
233                                         CursorPos.X = 0;\r
234                                 if (CursorPos.X > (s32)Device->Width)\r
235                                         CursorPos.X = Device->Width;\r
236                                 if (CursorPos.Y < 0)\r
237                                         CursorPos.Y = 0;\r
238                                 if (CursorPos.Y > (s32)Device->Height)\r
239                                         CursorPos.Y = Device->Height;\r
240 #endif\r
241                         }\r
242 \r
243                         void initCursors();\r
244 \r
245                         CIrrDeviceSDL* Device;\r
246                         core::position2d<s32> CursorPos;\r
247                         bool IsVisible;\r
248 \r
249                         struct CursorDeleter {\r
250                                 void operator()(SDL_Cursor *ptr) {\r
251                                         if (ptr)\r
252                                                 SDL_FreeCursor(ptr);\r
253                                 }\r
254                         };\r
255                         std::vector<std::unique_ptr<SDL_Cursor, CursorDeleter>> Cursors;\r
256                         gui::ECURSOR_ICON ActiveIcon;\r
257                 };\r
258 \r
259         private:\r
260 \r
261 #ifdef _IRR_EMSCRIPTEN_PLATFORM_\r
262         static EM_BOOL MouseUpDownCallback(int eventType, const EmscriptenMouseEvent * event, void* userData);\r
263         static EM_BOOL MouseEnterCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);\r
264         static EM_BOOL MouseLeaveCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);\r
265 \r
266 #endif\r
267                 // Check if a key is a known special character with no side effects on text boxes.\r
268                 static bool keyIsKnownSpecial(EKEY_CODE key);\r
269 \r
270                 // Return the Char that should be sent to Irrlicht for the given key (either the one passed in or 0).\r
271                 static int findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key);\r
272 \r
273                 // Check if a text box is in focus. Enable or disable SDL_TEXTINPUT events only if in focus.\r
274                 void resetReceiveTextInputEvents();\r
275 \r
276                 //! create the driver\r
277                 void createDriver();\r
278 \r
279                 bool createWindow();\r
280 \r
281                 void createKeyMap();\r
282 \r
283                 void logAttributes();\r
284                 SDL_GLContext Context;\r
285                 SDL_Window *Window;\r
286                 int SDL_Flags;\r
287 #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)\r
288                 core::array<SDL_Joystick*> Joysticks;\r
289 #endif\r
290 \r
291                 s32 MouseX, MouseY;\r
292                 s32 MouseXRel, MouseYRel;\r
293                 u32 MouseButtonStates;\r
294 \r
295                 u32 Width, Height;\r
296 \r
297                 bool Resizable;\r
298 \r
299                 struct SKeyMap\r
300                 {\r
301                         SKeyMap() {}\r
302                         SKeyMap(s32 x11, s32 win32)\r
303                                 : SDLKey(x11), Win32Key(win32)\r
304                         {\r
305                         }\r
306 \r
307                         s32 SDLKey;\r
308                         s32 Win32Key;\r
309 \r
310                         bool operator<(const SKeyMap& o) const\r
311                         {\r
312                                 return SDLKey<o.SDLKey;\r
313                         }\r
314                 };\r
315 \r
316                 core::array<SKeyMap> KeyMap;\r
317                 SDL_SysWMinfo Info;\r
318         };\r
319 \r
320 } // end namespace irr\r
321 \r
322 #endif // _IRR_COMPILE_WITH_SDL_DEVICE_\r
323 #endif // __C_IRR_DEVICE_SDL_H_INCLUDED__\r
324 \r