1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
4 // This device code is based on the original SDL device implementation
5 // contributed by Shane Parker (sirshane).
6 
7 #ifndef __C_IRR_DEVICE_SDL_H_INCLUDED__
8 #define __C_IRR_DEVICE_SDL_H_INCLUDED__
9 
10 #include "IrrCompileConfig.h"
11 
12 #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
13 
14 #include "IrrlichtDevice.h"
15 #include "CIrrDeviceStub.h"
16 #include "IImagePresenter.h"
17 #include "ICursorControl.h"
18 
19 #include <SDL.h>
20 #include <SDL_syswm.h>
21 #include <map>
22 #include <set>
23 
24 namespace irr
25 {
26 
27 	class CIrrDeviceSDL : public CIrrDeviceStub, video::IImagePresenter
28 	{
29 	public:
30 
31 		//! constructor
32 		CIrrDeviceSDL(const SIrrlichtCreationParameters& param);
33 
34 		//! destructor
35 		virtual ~CIrrDeviceSDL();
36 
37 		//! runs the device. Returns false if device wants to be deleted
38 		virtual bool run();
39 
40 		//! pause execution temporarily
41 		virtual void yield();
42 
43 		//! pause execution for a specified time
44 		virtual void sleep(u32 timeMs, bool pauseTimer);
45 
46 		//! sets the caption of the window
47 		virtual void setWindowCaption(const wchar_t* text);
48 
49 		//! sets the class of the window
setWindowClass(const char * text)50 		virtual void setWindowClass(const char* text) {}
51 
52 		//! returns if window is active. if not, nothing need to be drawn
53 		virtual bool isWindowActive() const;
54 
55 		//! returns if window has focus.
56 		bool isWindowFocused() const;
57 
58 		//! returns if window is minimized.
59 		bool isWindowMinimized() const;
60 
61 		//! returns color format of the window.
62 		video::ECOLOR_FORMAT getColorFormat() const;
63 
64 		//! presents a surface in the client area
65 		virtual bool present(video::IImage* surface, void* windowId=0, core::rect<s32>* src=0);
66 
67 		//! notifies the device that it should close itself
68 		virtual void closeDevice();
69 
70 		//! \return Returns a pointer to a list with all video modes supported
71 		video::IVideoModeList* getVideoModeList();
72 
73 		//! Sets if the window should be resizable in windowed mode.
74 		virtual void setResizable(bool resize=false);
75 
76 		virtual bool isResizable() const;
77 
78 		//! Minimizes the window.
79 		virtual void minimizeWindow();
80 
81 		//! Maximizes the window.
82 		virtual void maximizeWindow();
83 
84 		//! Restores the window size.
85 		virtual void restoreWindow();
86 
87 		//! Move window to requested position
88 		virtual bool moveWindow(int x, int y);
89 
90 		//! Get current window position.
91 		virtual bool getWindowPosition(int* x, int* y);
92 
93 		//! Activate any joysticks, and generate events for them.
94 		virtual bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo);
95 
96 		//! Set the current Gamma Value for the Display
97 		virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast );
98 
99 		//! Get the current Gamma Value for the Display
100 		virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast );
101 
102 		virtual void setWindowMinimumSize(u32 width, u32 height);
103 
104 		virtual bool supportsTouchDevice() const;
105 
106 		//! Get the device type
getType()107 		virtual E_DEVICE_TYPE getType() const
108 		{
109 			return EIDT_SDL;
110 		}
111 
getWindow()112 		SDL_Window* getWindow() const { return Window; }
113 
getWMInfo()114 		const SDL_SysWMinfo& getWMInfo() const { return Info; }
115 
getTopPadding()116 		virtual s32 getTopPadding()
117 		{
118 			return TopPadding * getNativeScaleY();
119 		}
120 
getBottomPadding()121 		virtual s32 getBottomPadding()
122 		{
123 			return BottomPadding * getNativeScaleY();
124 		}
125 
getLeftPadding()126 		virtual s32 getLeftPadding()
127 		{
128 			return LeftPadding * getNativeScaleX();
129 		}
130 
getRightPadding()131 		virtual s32 getRightPadding()
132 		{
133 			return RightPadding * getNativeScaleX();
134 		}
135 
136 		virtual f32 getNativeScaleX() const;
137 		virtual f32 getNativeScaleY() const;
138 
139 		virtual bool hasOnScreenKeyboard() const;
140 
141 		virtual u32 getOnScreenKeyboardHeight() const;
142 
143 		virtual s32 getMovedHeight() const;
144 
145 		virtual bool activateAccelerometer(float updateInterval);
146 		virtual bool deactivateAccelerometer();
147 		virtual bool isAccelerometerActive();
148 		virtual bool isAccelerometerAvailable();
149 		virtual bool activateGyroscope(float updateInterval);
150 		virtual bool deactivateGyroscope();
151 		virtual bool isGyroscopeActive();
152 		virtual bool isGyroscopeAvailable();
153 
resetPaused()154 		virtual void resetPaused() { clearAllTouchIds(); }
155 
156 		//! Implementation of the linux cursor control
157 		class CCursorControl : public gui::ICursorControl
158 		{
159 		public:
160 
CCursorControl(CIrrDeviceSDL * dev)161 			CCursorControl(CIrrDeviceSDL* dev)
162 				: Device(dev), IsVisible(true)
163 			{
164 			}
165 
166 			//! Changes the visible state of the mouse cursor.
setVisible(bool visible)167 			virtual void setVisible(bool visible)
168 			{
169 				IsVisible = visible;
170 				if ( visible )
171 					SDL_ShowCursor( SDL_ENABLE );
172 				else
173 					SDL_ShowCursor( SDL_DISABLE );
174 			}
175 
176 			//! Returns if the cursor is currently visible.
isVisible()177 			virtual bool isVisible() const
178 			{
179 				return IsVisible;
180 			}
181 
182 			//! Sets the new position of the cursor.
setPosition(const core::position2d<f32> & pos)183 			virtual void setPosition(const core::position2d<f32> &pos)
184 			{
185 				setPosition(pos.X, pos.Y);
186 			}
187 
188 			//! Sets the new position of the cursor.
setPosition(f32 x,f32 y)189 			virtual void setPosition(f32 x, f32 y)
190 			{
191 				setPosition((s32)(x*Device->Width), (s32)(y*Device->Height));
192 			}
193 
194 			//! Sets the new position of the cursor.
setPosition(const core::position2d<s32> & pos)195 			virtual void setPosition(const core::position2d<s32> &pos)
196 			{
197 				setPosition(pos.X, pos.Y);
198 			}
199 
200 			//! Sets the new position of the cursor.
setPosition(s32 x,s32 y)201 			virtual void setPosition(s32 x, s32 y)
202 			{
203 				SDL_WarpMouseGlobal( x, y );
204 			}
205 
206 			//! Returns the current position of the mouse cursor.
getPosition()207 			virtual const core::position2d<s32>& getPosition()
208 			{
209 				updateCursorPos();
210 				return CursorPos;
211 			}
212 
213 			//! Returns the current position of the mouse cursor.
getRelativePosition()214 			virtual core::position2d<f32> getRelativePosition()
215 			{
216 				updateCursorPos();
217 				return core::position2d<f32>(CursorPos.X / (f32)Device->Width,
218 					CursorPos.Y / (f32)Device->Height);
219 			}
220 
221 			virtual void setReferenceRect(core::rect<s32>* rect=0)
222 			{
223 			}
224 
225 		private:
226 
updateCursorPos()227 			void updateCursorPos()
228 			{
229 				CursorPos.X = Device->MouseX;
230 				CursorPos.Y = Device->MouseY;
231 
232 				if (CursorPos.X < 0)
233 					CursorPos.X = 0;
234 				if (CursorPos.X > (s32)Device->Width)
235 					CursorPos.X = Device->Width;
236 				if (CursorPos.Y < 0)
237 					CursorPos.Y = 0;
238 				if (CursorPos.Y > (s32)Device->Height)
239 					CursorPos.Y = Device->Height;
240 			}
241 
242 			CIrrDeviceSDL* Device;
243 			core::position2d<s32> CursorPos;
244 			bool IsVisible;
245 		};
246 
247 	private:
248 
249 		//! create the driver
250 		void createDriver();
251 
252 		bool createWindow();
253 
254 		void createKeyMap();
255 
256 		SDL_Window* Window;
257 		SDL_GLContext Context;
258 
259 		s32 MouseX, MouseY;
260 		u32 MouseButtonStates;
261 
262 		u32 Width, Height;
263 		std::map<SDL_FingerID, size_t> TouchIDMap;
264 
265 		//! Get a unique touch id per touch, create one if it's a new touch
getTouchId(SDL_FingerID touch)266 		size_t getTouchId(SDL_FingerID touch)
267 		{
268 			auto it = TouchIDMap.find(touch);
269 			if (it == TouchIDMap.end())
270 			{
271 				std::set<size_t> ids;
272 				for (auto& p : TouchIDMap)
273 					ids.insert(p.second);
274 				size_t cur_id = 0;
275 				while (true)
276 				{
277 					if (ids.find(cur_id) == ids.end())
278 						break;
279 					 cur_id++;
280 				}
281 				TouchIDMap[touch] = cur_id;
282 				return cur_id;
283 			}
284 			return it->second;
285 		}
286 
287 		//! Remove a unique touch id, free it for future usage
removeTouchId(SDL_FingerID touch)288 		void removeTouchId(SDL_FingerID touch)
289 		{
290 			TouchIDMap.erase(touch);
291 		}
292 
293 		//! Clear all unique touch ids, used when the app out focused
clearAllTouchIds()294 		void clearAllTouchIds()
295 		{
296 			TouchIDMap.clear();
297 		}
298 
299 		f32 TopPadding;
300 		f32 BottomPadding;
301 		f32 LeftPadding;
302 		f32 RightPadding;
303 
304 		bool WindowHasFocus;
305 		bool WindowMinimized;
306 		bool Resizable;
307 
308 		s32 AccelerometerIndex;
309 		s32 AccelerometerInstance;
310 		s32 GyroscopeIndex;
311 		s32 GyroscopeInstance;
312 
313 		struct SKeyMap
314 		{
SKeyMapSKeyMap315 			SKeyMap() {}
SKeyMapSKeyMap316 			SKeyMap(s32 x11, s32 win32)
317 				: SDLKey(x11), Win32Key(win32)
318 			{
319 			}
320 
321 			s32 SDLKey;
322 			s32 Win32Key;
323 
324 			bool operator<(const SKeyMap& o) const
325 			{
326 				return SDLKey<o.SDLKey;
327 			}
328 		};
329 
330 		core::array<SKeyMap> KeyMap;
331 		std::map<SDL_Scancode, irr::EKEY_CODE> ScanCodeMap;
332 		SDL_SysWMinfo Info;
333 		void tryCreateOpenGLContext(u32 flags);
334 	};
335 
336 } // end namespace irr
337 
338 #endif // _IRR_COMPILE_WITH_SDL_DEVICE_
339 #endif // __C_IRR_DEVICE_SDL_H_INCLUDED__
340 
341