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
5 #include "IrrCompileConfig.h"
6
7 #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
8
9 #include "CIrrDeviceSDL.h"
10 #include "IEventReceiver.h"
11 #include "irrList.h"
12 #include "os.h"
13 #include "CTimer.h"
14 #include "irrString.h"
15 #include "Keycodes.h"
16 #include "COSOperator.h"
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include "SIrrCreationParameters.h"
20 #include "COpenGLExtensionHandler.h"
21
22 #include "guiengine/engine.hpp"
23
24 extern bool GLContextDebugBit;
25
26 namespace irr
27 {
28 namespace video
29 {
30 extern bool useCoreContext;
31 IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params,
32 io::IFileSystem* io, CIrrDeviceSDL* device);
33 IVideoDriver* createOGLES2Driver(const SIrrlichtCreationParameters& params,
34 io::IFileSystem* io, CIrrDeviceSDL* device, u32 default_fb);
35
36 } // end namespace video
37
38 } // end namespace irr
39
40 extern "C" void init_objc(SDL_SysWMinfo* info, float* top, float* bottom, float* left, float* right);
41 extern "C" int handle_app_event(void* userdata, SDL_Event* event);
42
43 namespace irr
44 {
45
46 float g_native_scale_x = 1.0f;
47 float g_native_scale_y = 1.0f;
48
49 //! constructor
CIrrDeviceSDL(const SIrrlichtCreationParameters & param)50 CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param)
51 : CIrrDeviceStub(param),
52 Window(0), Context(0),
53 MouseX(0), MouseY(0), MouseButtonStates(0),
54 Width(param.WindowSize.Width), Height(param.WindowSize.Height),
55 TopPadding(0), BottomPadding(0), LeftPadding(0), RightPadding(0),
56 WindowHasFocus(false), WindowMinimized(false), Resizable(false),
57 AccelerometerIndex(-1), AccelerometerInstance(-1),
58 GyroscopeIndex(-1), GyroscopeInstance(-1)
59 {
60 #ifdef _DEBUG
61 setDebugName("CIrrDeviceSDL");
62 #endif
63
64 Operator = 0;
65 // Initialize SDL... Timer for sleep, video for the obvious, and
66 // noparachute prevents SDL from catching fatal errors.
67 SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1");
68 SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
69 u32 init_flags = SDL_INIT_TIMER | SDL_INIT_VIDEO;
70 if (SDL_Init(init_flags) < 0)
71 {
72 os::Printer::log("Unable to initialize SDL!", SDL_GetError());
73 Close = true;
74 }
75
76 #if SDL_VERSION_ATLEAST(2, 0, 9)
77 // Don't exit if failed to init sensor (doesn't work in wine)
78 if (SDL_InitSubSystem(SDL_INIT_SENSOR) < 0)
79 {
80 os::Printer::log("Failed to init SDL sensor!", SDL_GetError());
81 }
82 #endif
83
84 // create keymap
85 createKeyMap();
86
87 // create window
88 if (CreationParams.DriverType != video::EDT_NULL)
89 {
90 // create the window, only if we do not use the null device
91 if (!Close && createWindow())
92 {
93 SDL_VERSION(&Info.version);
94
95 if (!SDL_GetWindowWMInfo(Window, &Info))
96 return;
97 #ifdef IOS_STK
98 init_objc(&Info, &TopPadding, &BottomPadding, &LeftPadding, &RightPadding);
99 #endif
100 core::stringc sdlversion = "SDL Version ";
101 sdlversion += Info.version.major;
102 sdlversion += ".";
103 sdlversion += Info.version.minor;
104 sdlversion += ".";
105 sdlversion += Info.version.patch;
106
107 Operator = new COSOperator(sdlversion);
108 os::Printer::log(sdlversion.c_str(), ELL_INFORMATION);
109 #if SDL_VERSION_ATLEAST(2, 0, 9)
110 for (int i = 0; i < SDL_NumSensors(); i++)
111 {
112 if (SDL_SensorGetDeviceType(i) == SDL_SENSOR_ACCEL)
113 AccelerometerIndex = i;
114 else if (SDL_SensorGetDeviceType(i) == SDL_SENSOR_GYRO)
115 GyroscopeIndex = i;
116 }
117 #endif
118 }
119 else
120 return;
121 }
122 #ifndef ANDROID
123 else if (!GUIEngine::isNoGraphics())
124 {
125 // Get highdpi native scale using renderer so it will work with any
126 // backend later (opengl or vulkan)
127 // Android doesn't use high dpi
128 SDL_Window* window = NULL;
129 SDL_Renderer* renderer = NULL;
130 if (SDL_CreateWindowAndRenderer(640, 480,
131 SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN,
132 &window, &renderer) == 0)
133 {
134 int w, h, rw, rh;
135 w = h = rw = rh = 0;
136 SDL_GetWindowSize(window, &w, &h);
137 SDL_GetRendererOutputSize(renderer, &rw, &rh);
138 if (w != 0 && h != 0 && rw != 0 && rh != 0)
139 {
140 g_native_scale_x = (float)rw / (float)w;
141 g_native_scale_y = (float)rh / (float)h;
142 }
143 SDL_DestroyRenderer(renderer);
144 SDL_DestroyWindow(window);
145 }
146 }
147 #endif
148
149 // create cursor control
150 CursorControl = new CCursorControl(this);
151
152 // create driver
153 createDriver();
154
155 if (VideoDriver)
156 createGUIAndScene();
157 #ifdef IOS_STK
158 SDL_SetEventFilter(handle_app_event, NULL);
159 #endif
160 }
161
162
163 //! destructor
~CIrrDeviceSDL()164 CIrrDeviceSDL::~CIrrDeviceSDL()
165 {
166 if (VideoDriver)
167 {
168 VideoDriver->drop();
169 VideoDriver = NULL;
170 }
171 if (Context)
172 SDL_GL_DeleteContext(Context);
173 if (Window)
174 SDL_DestroyWindow(Window);
175 SDL_Quit();
176 }
177
178
activateAccelerometer(float updateInterval)179 bool CIrrDeviceSDL::activateAccelerometer(float updateInterval)
180 {
181 #if SDL_VERSION_ATLEAST(2, 0, 9)
182 if (AccelerometerInstance == -1 && AccelerometerIndex != -1)
183 {
184 SDL_Sensor* accel = SDL_SensorOpen(AccelerometerIndex);
185 if (accel)
186 AccelerometerInstance = SDL_SensorGetInstanceID(accel);
187 }
188 #endif
189 return AccelerometerInstance != -1;
190 }
191
192
deactivateAccelerometer()193 bool CIrrDeviceSDL::deactivateAccelerometer()
194 {
195 #if SDL_VERSION_ATLEAST(2, 0, 9)
196 if (AccelerometerInstance == -1)
197 return false;
198 SDL_Sensor* accel = SDL_SensorFromInstanceID(AccelerometerInstance);
199 if (!accel)
200 return false;
201 SDL_SensorClose(accel);
202 AccelerometerInstance = -1;
203 #endif
204 return true;
205 }
206
207
isAccelerometerActive()208 bool CIrrDeviceSDL::isAccelerometerActive()
209 {
210 return AccelerometerInstance != -1;
211 }
212
213
isAccelerometerAvailable()214 bool CIrrDeviceSDL::isAccelerometerAvailable()
215 {
216 return AccelerometerIndex != -1;
217 }
218
219
activateGyroscope(float updateInterval)220 bool CIrrDeviceSDL::activateGyroscope(float updateInterval)
221 {
222 #if SDL_VERSION_ATLEAST(2, 0, 9)
223 if (GyroscopeInstance == -1 && GyroscopeIndex != -1)
224 {
225 SDL_Sensor* gyro = SDL_SensorOpen(GyroscopeIndex);
226 if (gyro)
227 GyroscopeInstance = SDL_SensorGetInstanceID(gyro);
228 }
229 #endif
230 return GyroscopeInstance != -1;
231 }
232
233
deactivateGyroscope()234 bool CIrrDeviceSDL::deactivateGyroscope()
235 {
236 #if SDL_VERSION_ATLEAST(2, 0, 9)
237 if (GyroscopeInstance == -1)
238 return false;
239 SDL_Sensor* gyro = SDL_SensorFromInstanceID(GyroscopeInstance);
240 if (!gyro)
241 return false;
242 SDL_SensorClose(gyro);
243 GyroscopeInstance = -1;
244 #endif
245 return true;
246 }
247
248
isGyroscopeActive()249 bool CIrrDeviceSDL::isGyroscopeActive()
250 {
251 return GyroscopeInstance != -1;
252 }
253
254
isGyroscopeAvailable()255 bool CIrrDeviceSDL::isGyroscopeAvailable()
256 {
257 return GyroscopeIndex != -1;
258 }
259
260
versionCorrect(int major,int minor)261 bool versionCorrect(int major, int minor)
262 {
263 #ifdef _IRR_COMPILE_WITH_OGLES2_
264 return true;
265 #else
266 int created_major = 2;
267 int created_minor = 0;
268 glGetIntegerv(GL_MAJOR_VERSION, &created_major);
269 glGetIntegerv(GL_MINOR_VERSION, &created_minor);
270 if (created_major > major ||
271 (created_major == major && created_minor >= minor))
272 return true;
273 return false;
274 #endif
275 }
276
277
278 // Used in OptionsScreenVideo for live updating vertical sync config
update_swap_interval(int swap_interval)279 extern "C" void update_swap_interval(int swap_interval)
280 {
281 #ifndef IOS_STK
282 // iOS always use vertical sync
283 if (swap_interval > 1)
284 swap_interval = 1;
285
286 // Try adaptive vsync first if support
287 if (swap_interval > 0)
288 {
289 int ret = SDL_GL_SetSwapInterval(-1);
290 if (ret == 0)
291 return;
292 }
293 SDL_GL_SetSwapInterval(swap_interval);
294 #endif
295 }
296
297
createWindow()298 bool CIrrDeviceSDL::createWindow()
299 {
300 // Ignore alpha size here, this follow irr_driver.cpp:450
301 // Try 32 and, upon failure, 24 then 16 bit per pixels
302 if (CreationParams.Bits == 32)
303 {
304 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
305 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
306 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
307 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
308 }
309 else if (CreationParams.Bits == 24)
310 {
311 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
312 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
313 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
314 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
315 }
316 else
317 {
318 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 3);
319 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 3);
320 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 2);
321 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
322 }
323
324 u32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI;
325 if (CreationParams.Fullscreen)
326 flags |= SDL_WINDOW_FULLSCREEN;
327
328 if (CreationParams.DriverType == video::EDT_OPENGL ||
329 CreationParams.DriverType == video::EDT_OGLES2)
330 flags |= SDL_WINDOW_OPENGL;
331
332 #ifdef MOBILE_STK
333 flags |= SDL_WINDOW_BORDERLESS | SDL_WINDOW_MAXIMIZED;
334 #endif
335
336 tryCreateOpenGLContext(flags);
337 if (!Window || !Context)
338 {
339 os::Printer::log( "Could not initialize display!" );
340 return false;
341 }
342
343 update_swap_interval(CreationParams.SwapInterval);
344 return true;
345 }
346
347
tryCreateOpenGLContext(u32 flags)348 void CIrrDeviceSDL::tryCreateOpenGLContext(u32 flags)
349 {
350 start:
351 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, CreationParams.Doublebuffer);
352 irr::video::useCoreContext = true;
353
354 if (GLContextDebugBit)
355 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
356
357 if (CreationParams.DriverType == video::EDT_OGLES2)
358 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
359 else
360 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
361
362 if (CreationParams.ForceLegacyDevice)
363 goto legacy;
364
365 #ifdef _IRR_COMPILE_WITH_OGLES2_
366 if (Context)
367 {
368 SDL_GL_DeleteContext(Context);
369 Context = NULL;
370 }
371 if (Window)
372 {
373 SDL_DestroyWindow(Window);
374 Window = NULL;
375 }
376
377 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
378 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
379 Window = SDL_CreateWindow("",
380 (float)CreationParams.WindowPosition.X / g_native_scale_x,
381 (float)CreationParams.WindowPosition.Y / g_native_scale_y,
382 (float)CreationParams.WindowSize.Width / g_native_scale_x,
383 (float)CreationParams.WindowSize.Height / g_native_scale_y, flags);
384 if (Window)
385 {
386 Context = SDL_GL_CreateContext(Window);
387 if (Context && versionCorrect(3, 0)) return;
388 }
389
390 #else
391 if (Context)
392 {
393 SDL_GL_DeleteContext(Context);
394 Context = NULL;
395 }
396 if (Window)
397 {
398 SDL_DestroyWindow(Window);
399 Window = NULL;
400 }
401
402 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
403 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
404 Window = SDL_CreateWindow("",
405 (float)CreationParams.WindowPosition.X / g_native_scale_x,
406 (float)CreationParams.WindowPosition.Y / g_native_scale_y,
407 (float)CreationParams.WindowSize.Width / g_native_scale_x,
408 (float)CreationParams.WindowSize.Height / g_native_scale_y, flags);
409 if (Window)
410 {
411 Context = SDL_GL_CreateContext(Window);
412 if (Context && versionCorrect(4, 3)) return;
413 }
414
415 if (Context)
416 {
417 SDL_GL_DeleteContext(Context);
418 Context = NULL;
419 }
420 if (Window)
421 {
422 SDL_DestroyWindow(Window);
423 Window = NULL;
424 }
425
426 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
427 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
428 Window = SDL_CreateWindow("",
429 (float)CreationParams.WindowPosition.X / g_native_scale_x,
430 (float)CreationParams.WindowPosition.Y / g_native_scale_y,
431 (float)CreationParams.WindowSize.Width / g_native_scale_x,
432 (float)CreationParams.WindowSize.Height / g_native_scale_y, flags);
433 if (Window)
434 {
435 Context = SDL_GL_CreateContext(Window);
436 if (Context && versionCorrect(3, 3)) return;
437 }
438
439 if (Context)
440 {
441 SDL_GL_DeleteContext(Context);
442 Context = NULL;
443 }
444 if (Window)
445 {
446 SDL_DestroyWindow(Window);
447 Window = NULL;
448 }
449
450 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
451 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
452 Window = SDL_CreateWindow("",
453 (float)CreationParams.WindowPosition.X / g_native_scale_x,
454 (float)CreationParams.WindowPosition.Y / g_native_scale_y,
455 (float)CreationParams.WindowSize.Width / g_native_scale_x,
456 (float)CreationParams.WindowSize.Height / g_native_scale_y, flags);
457 if (Window)
458 {
459 Context = SDL_GL_CreateContext(Window);
460 if (Context && versionCorrect(3, 1)) return;
461 }
462 #endif
463
464 legacy:
465 irr::video::useCoreContext = false;
466 if (Context)
467 {
468 SDL_GL_DeleteContext(Context);
469 Context = NULL;
470 }
471 if (Window)
472 {
473 SDL_DestroyWindow(Window);
474 Window = NULL;
475 }
476
477 #ifdef _IRR_COMPILE_WITH_OGLES2_
478 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
479 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
480 #else
481 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
482 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
483 #endif
484 if (CreationParams.DriverType == video::EDT_OGLES2)
485 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
486 else
487 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
488 Window = SDL_CreateWindow("",
489 (float)CreationParams.WindowPosition.X / g_native_scale_x,
490 (float)CreationParams.WindowPosition.Y / g_native_scale_y,
491 (float)CreationParams.WindowSize.Width / g_native_scale_x,
492 (float)CreationParams.WindowSize.Height / g_native_scale_y, flags);
493 if (Window)
494 {
495 Context = SDL_GL_CreateContext(Window);
496 if (Context) return;
497 }
498
499 if (CreationParams.Doublebuffer)
500 {
501 CreationParams.Doublebuffer = false;
502 goto start;
503 }
504 }
505
506 //! create the driver
createDriver()507 void CIrrDeviceSDL::createDriver()
508 {
509 switch(CreationParams.DriverType)
510 {
511 case video::EDT_OPENGL:
512 #ifdef _IRR_COMPILE_WITH_OPENGL_
513 VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem, this);
514 #else
515 os::Printer::log("No OpenGL support compiled in.", ELL_ERROR);
516 #endif
517 break;
518
519 case video::EDT_OGLES2:
520 {
521 #ifdef _IRR_COMPILE_WITH_OGLES2_
522 u32 default_fb = 0;
523 #ifdef IOS_STK
524 default_fb = Info.info.uikit.framebuffer;
525 #endif
526 VideoDriver = video::createOGLES2Driver(CreationParams, FileSystem, this, default_fb);
527 #else
528 os::Printer::log("No OpenGL ES 2.0 support compiled in.", ELL_ERROR);
529 #endif
530 break;
531 }
532
533 case video::EDT_NULL:
534 VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize);
535 break;
536
537 default:
538 os::Printer::log("Unable to create video driver of unknown type.", ELL_ERROR);
539 break;
540 }
541 }
542
543 // In input_manager.cpp
544 extern "C" void handle_joystick(SDL_Event& event);
545 // In main_loop.cpp
546 extern "C" void pause_mainloop();
547 extern "C" void resume_mainloop();
548 //! runs the device. Returns false if device wants to be deleted
run()549 bool CIrrDeviceSDL::run()
550 {
551 os::Timer::tick();
552
553 SEvent irrevent;
554 SDL_Event SDL_event;
555
556 while ( !Close && SDL_PollEvent( &SDL_event ) )
557 {
558 switch ( SDL_event.type )
559 {
560 #if defined(MOBILE_STK) && !defined(IOS_STK)
561 case SDL_APP_WILLENTERBACKGROUND:
562 pause_mainloop();
563 break;
564 case SDL_APP_DIDENTERFOREGROUND:
565 resume_mainloop();
566 break;
567 #endif
568 #if SDL_VERSION_ATLEAST(2, 0, 9)
569 case SDL_SENSORUPDATE:
570 if (SDL_event.sensor.which == AccelerometerInstance)
571 {
572 SDL_DisplayOrientation o = SDL_GetDisplayOrientation(0);
573 irrevent.EventType = irr::EET_ACCELEROMETER_EVENT;
574 if (o == SDL_ORIENTATION_LANDSCAPE ||
575 o == SDL_ORIENTATION_LANDSCAPE_FLIPPED)
576 {
577 irrevent.AccelerometerEvent.X = SDL_event.sensor.data[0];
578 irrevent.AccelerometerEvent.Y = SDL_event.sensor.data[1];
579 }
580 else
581 {
582 // For android multi-window mode vertically
583 irrevent.AccelerometerEvent.X = -SDL_event.sensor.data[1];
584 irrevent.AccelerometerEvent.Y = -SDL_event.sensor.data[0];
585 }
586 irrevent.AccelerometerEvent.Z = SDL_event.sensor.data[2];
587 // Mobile STK specific
588 if (irrevent.AccelerometerEvent.X < 0.0)
589 irrevent.AccelerometerEvent.X *= -1.0;
590 #ifdef IOS_STK
591 if (o == SDL_ORIENTATION_LANDSCAPE)
592 irrevent.AccelerometerEvent.Y *= -1.0;
593 #else
594 if (o == SDL_ORIENTATION_LANDSCAPE_FLIPPED ||
595 o == SDL_ORIENTATION_PORTRAIT_FLIPPED)
596 irrevent.AccelerometerEvent.Y *= -1.0;
597 #endif
598 postEventFromUser(irrevent);
599 }
600 else if (SDL_event.sensor.which == GyroscopeInstance)
601 {
602 irrevent.EventType = irr::EET_GYROSCOPE_EVENT;
603 irrevent.GyroscopeEvent.X = SDL_event.sensor.data[0];
604 irrevent.GyroscopeEvent.Y = SDL_event.sensor.data[1];
605 irrevent.GyroscopeEvent.Z = SDL_event.sensor.data[2];
606 postEventFromUser(irrevent);
607 }
608 break;
609 #endif
610 case SDL_FINGERMOTION:
611 case SDL_FINGERDOWN:
612 case SDL_FINGERUP:
613 irrevent.EventType = irr::EET_TOUCH_INPUT_EVENT;
614 irrevent.TouchInput.Event = SDL_event.type == SDL_FINGERMOTION ? irr::ETIE_MOVED :
615 SDL_event.type == SDL_FINGERDOWN ? irr::ETIE_PRESSED_DOWN : irr::ETIE_LEFT_UP;
616 irrevent.TouchInput.ID = getTouchId(SDL_event.tfinger.fingerId);
617 if (SDL_event.type == SDL_FINGERUP)
618 removeTouchId(SDL_event.tfinger.fingerId);
619 irrevent.TouchInput.X = SDL_event.tfinger.x * Width;
620 irrevent.TouchInput.Y = SDL_event.tfinger.y * Height;
621 postEventFromUser(irrevent);
622 break;
623
624 case SDL_MOUSEWHEEL:
625 if (SDL_event.wheel.x > 0 || SDL_event.wheel.x < 0)
626 break;
627 irrevent.EventType = irr::EET_MOUSE_INPUT_EVENT;
628 irrevent.MouseInput.Event = irr::EMIE_MOUSE_WHEEL;
629 irrevent.MouseInput.X = MouseX;
630 irrevent.MouseInput.Y = MouseY;
631 irrevent.MouseInput.ButtonStates = MouseButtonStates;
632 irrevent.MouseInput.Wheel = SDL_event.wheel.y > 0 ? 1.0f : -1.0f;
633 postEventFromUser(irrevent);
634 break;
635
636 case SDL_MOUSEMOTION:
637 irrevent.EventType = irr::EET_MOUSE_INPUT_EVENT;
638 irrevent.MouseInput.Event = irr::EMIE_MOUSE_MOVED;
639 MouseX = irrevent.MouseInput.X = SDL_event.motion.x * g_native_scale_x;
640 MouseY = irrevent.MouseInput.Y = SDL_event.motion.y * g_native_scale_y;
641 irrevent.MouseInput.ButtonStates = MouseButtonStates;
642
643 postEventFromUser(irrevent);
644 break;
645
646 case SDL_MOUSEBUTTONDOWN:
647 case SDL_MOUSEBUTTONUP:
648
649 irrevent.EventType = irr::EET_MOUSE_INPUT_EVENT;
650 irrevent.MouseInput.X = SDL_event.button.x * g_native_scale_x;
651 irrevent.MouseInput.Y = SDL_event.button.y * g_native_scale_y;
652
653 irrevent.MouseInput.Event = irr::EMIE_MOUSE_MOVED;
654
655 switch(SDL_event.button.button)
656 {
657 case SDL_BUTTON_LEFT:
658 if (SDL_event.type == SDL_MOUSEBUTTONDOWN)
659 {
660 irrevent.MouseInput.Event = irr::EMIE_LMOUSE_PRESSED_DOWN;
661 MouseButtonStates |= irr::EMBSM_LEFT;
662 }
663 else
664 {
665 irrevent.MouseInput.Event = irr::EMIE_LMOUSE_LEFT_UP;
666 MouseButtonStates &= ~irr::EMBSM_LEFT;
667 }
668 break;
669
670 case SDL_BUTTON_RIGHT:
671 if (SDL_event.type == SDL_MOUSEBUTTONDOWN)
672 {
673 irrevent.MouseInput.Event = irr::EMIE_RMOUSE_PRESSED_DOWN;
674 MouseButtonStates |= irr::EMBSM_RIGHT;
675 }
676 else
677 {
678 irrevent.MouseInput.Event = irr::EMIE_RMOUSE_LEFT_UP;
679 MouseButtonStates &= ~irr::EMBSM_RIGHT;
680 }
681 break;
682
683 case SDL_BUTTON_MIDDLE:
684 if (SDL_event.type == SDL_MOUSEBUTTONDOWN)
685 {
686 irrevent.MouseInput.Event = irr::EMIE_MMOUSE_PRESSED_DOWN;
687 MouseButtonStates |= irr::EMBSM_MIDDLE;
688 }
689 else
690 {
691 irrevent.MouseInput.Event = irr::EMIE_MMOUSE_LEFT_UP;
692 MouseButtonStates &= ~irr::EMBSM_MIDDLE;
693 }
694 break;
695 }
696
697 irrevent.MouseInput.ButtonStates = MouseButtonStates;
698
699 if (irrevent.MouseInput.Event != irr::EMIE_MOUSE_MOVED)
700 {
701 postEventFromUser(irrevent);
702
703 if ( irrevent.MouseInput.Event >= EMIE_LMOUSE_PRESSED_DOWN && irrevent.MouseInput.Event <= EMIE_MMOUSE_PRESSED_DOWN )
704 {
705 u32 clicks = checkSuccessiveClicks(irrevent.MouseInput.X, irrevent.MouseInput.Y, irrevent.MouseInput.Event);
706 if ( clicks == 2 )
707 {
708 irrevent.MouseInput.Event = (EMOUSE_INPUT_EVENT)(EMIE_LMOUSE_DOUBLE_CLICK + irrevent.MouseInput.Event-EMIE_LMOUSE_PRESSED_DOWN);
709 postEventFromUser(irrevent);
710 }
711 else if ( clicks == 3 )
712 {
713 irrevent.MouseInput.Event = (EMOUSE_INPUT_EVENT)(EMIE_LMOUSE_TRIPLE_CLICK + irrevent.MouseInput.Event-EMIE_LMOUSE_PRESSED_DOWN);
714 postEventFromUser(irrevent);
715 }
716 }
717 }
718 break;
719
720 case SDL_KEYDOWN:
721 case SDL_KEYUP:
722 {
723 SKeyMap mp;
724 mp.SDLKey = SDL_event.key.keysym.sym;
725 s32 idx = KeyMap.binary_search(mp);
726
727 EKEY_CODE key;
728 if (idx == -1)
729 {
730 // Fallback to use scancode directly if not found, happens in
731 // belarusian keyboard layout for example
732 auto it = ScanCodeMap.find(SDL_event.key.keysym.scancode);
733 if (it != ScanCodeMap.end())
734 key = it->second;
735 else
736 key = (EKEY_CODE)0;
737 }
738 else
739 key = (EKEY_CODE)KeyMap[idx].Win32Key;
740
741 irrevent.EventType = irr::EET_KEY_INPUT_EVENT;
742 irrevent.KeyInput.Char = 0;
743 irrevent.KeyInput.Key = key;
744 irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN);
745 irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0;
746 irrevent.KeyInput.Control = (SDL_event.key.keysym.mod & KMOD_CTRL ) != 0;
747 postEventFromUser(irrevent);
748 }
749 break;
750
751 case SDL_QUIT:
752 Close = true;
753 break;
754
755 case SDL_WINDOWEVENT:
756 {
757 u32 new_width = SDL_event.window.data1 * g_native_scale_x;
758 u32 new_height = SDL_event.window.data2 * g_native_scale_y;
759 if (SDL_event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED &&
760 ((new_width != Width) || (new_height != Height)))
761 {
762 Width = new_width;
763 Height = new_height;
764 if (VideoDriver)
765 VideoDriver->OnResize(core::dimension2d<u32>(Width, Height));
766 }
767 else if (SDL_event.window.event == SDL_WINDOWEVENT_MINIMIZED)
768 {
769 WindowMinimized = true;
770 }
771 else if (SDL_event.window.event == SDL_WINDOWEVENT_MAXIMIZED)
772 {
773 WindowMinimized = false;
774 }
775 else if (SDL_event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
776 {
777 WindowHasFocus = true;
778 }
779 else if (SDL_event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
780 {
781 WindowHasFocus = false;
782 }
783 }
784 break;
785 case SDL_TEXTEDITING:
786 {
787 irrevent.EventType = irr::EET_SDL_TEXT_EVENT;
788 irrevent.SDLTextEvent.Type = SDL_event.type;
789 const size_t size = sizeof(irrevent.SDLTextEvent.Text);
790 const size_t other_size = sizeof(SDL_event.edit.text);
791 static_assert(sizeof(size) == sizeof(other_size), "Wrong size");
792 memcpy(irrevent.SDLTextEvent.Text, SDL_event.edit.text, size);
793 irrevent.SDLTextEvent.Start = SDL_event.edit.start;
794 irrevent.SDLTextEvent.Length = SDL_event.edit.length;
795 postEventFromUser(irrevent);
796 }
797 break;
798 case SDL_TEXTINPUT:
799 {
800 irrevent.EventType = irr::EET_SDL_TEXT_EVENT;
801 irrevent.SDLTextEvent.Type = SDL_event.type;
802 const size_t size = sizeof(irrevent.SDLTextEvent.Text);
803 const size_t other_size = sizeof(SDL_event.text.text);
804 static_assert(sizeof(size) == sizeof(other_size), "Wrong size");
805 memcpy(irrevent.SDLTextEvent.Text, SDL_event.text.text, size);
806 irrevent.SDLTextEvent.Start = 0;
807 irrevent.SDLTextEvent.Length = 0;
808 postEventFromUser(irrevent);
809 }
810 break;
811 default:
812 handle_joystick(SDL_event);
813 break;
814 } // end switch
815
816 } // end while
817
818 return !Close;
819 }
820
821 //! Activate any joysticks, and generate events for them.
activateJoysticks(core::array<SJoystickInfo> & joystickInfo)822 bool CIrrDeviceSDL::activateJoysticks(core::array<SJoystickInfo> & joystickInfo)
823 {
824 return false;
825 }
826
827
828
829 //! pause execution temporarily
yield()830 void CIrrDeviceSDL::yield()
831 {
832 SDL_Delay(0);
833 }
834
835
836 //! pause execution for a specified time
sleep(u32 timeMs,bool pauseTimer)837 void CIrrDeviceSDL::sleep(u32 timeMs, bool pauseTimer)
838 {
839 const bool wasStopped = Timer ? Timer->isStopped() : true;
840 if (pauseTimer && !wasStopped)
841 Timer->stop();
842
843 SDL_Delay(timeMs);
844
845 if (pauseTimer && !wasStopped)
846 Timer->start();
847 }
848
849
850 //! sets the caption of the window
setWindowCaption(const wchar_t * text)851 void CIrrDeviceSDL::setWindowCaption(const wchar_t* text)
852 {
853 core::stringc textc = text;
854 SDL_SetWindowTitle(Window, textc.c_str());
855 }
856
857
858 //! presents a surface in the client area
present(video::IImage * surface,void * windowId,core::rect<s32> * srcClip)859 bool CIrrDeviceSDL::present(video::IImage* surface, void* windowId, core::rect<s32>* srcClip)
860 {
861 return false;
862 }
863
864
865 //! notifies the device that it should close itself
closeDevice()866 void CIrrDeviceSDL::closeDevice()
867 {
868 Close = true;
869 }
870
871
872 //! \return Pointer to a list with all video modes supported
getVideoModeList()873 video::IVideoModeList* CIrrDeviceSDL::getVideoModeList()
874 {
875 if (!VideoModeList.getVideoModeCount())
876 {
877 // enumerate video modes.
878 int display_count = 0;
879 if ((display_count = SDL_GetNumVideoDisplays()) < 1)
880 {
881 os::Printer::log("No display created: ", SDL_GetError(), ELL_ERROR);
882 return &VideoModeList;
883 }
884
885 int mode_count = 0;
886 if ((mode_count = SDL_GetNumDisplayModes(0)) < 1)
887 {
888 os::Printer::log("No display modes available: ", SDL_GetError(), ELL_ERROR);
889 return &VideoModeList;
890 }
891
892 SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 };
893 if (SDL_GetDesktopDisplayMode(0, &mode) == 0)
894 {
895 VideoModeList.setDesktop(SDL_BITSPERPIXEL(mode.format),
896 core::dimension2d<u32>(mode.w * g_native_scale_x, mode.h * g_native_scale_y));
897 }
898
899 #ifdef MOBILE_STK
900 // SDL2 will return w,h and h,w for mobile STK, as we only use landscape
901 // so we just use desktop resolution for now
902 VideoModeList.addMode(core::dimension2d<u32>(mode.w * g_native_scale_x, mode.h * g_native_scale_y),
903 SDL_BITSPERPIXEL(mode.format));
904 #else
905 for (int i = 0; i < mode_count; i++)
906 {
907 if (SDL_GetDisplayMode(0, i, &mode) == 0)
908 {
909 VideoModeList.addMode(core::dimension2d<u32>(mode.w * g_native_scale_x, mode.h * g_native_scale_y),
910 SDL_BITSPERPIXEL(mode.format));
911 }
912 }
913 #endif
914 }
915
916 return &VideoModeList;
917 }
918
919
920 //! Sets if the window should be resizable in windowed mode.
setResizable(bool resize)921 void CIrrDeviceSDL::setResizable(bool resize)
922 {
923 #if SDL_VERSION_ATLEAST(2, 0, 5)
924 if (CreationParams.Fullscreen)
925 return;
926 SDL_SetWindowResizable(Window, resize ? SDL_TRUE : SDL_FALSE);
927 Resizable = resize;
928 #endif
929 }
930
931
isResizable() const932 bool CIrrDeviceSDL::isResizable() const
933 {
934 if (CreationParams.Fullscreen)
935 return false;
936 return Resizable;
937 }
938
939
940 //! Minimizes window if possible
minimizeWindow()941 void CIrrDeviceSDL::minimizeWindow()
942 {
943 // do nothing
944 }
945
946
947 //! Maximize window
maximizeWindow()948 void CIrrDeviceSDL::maximizeWindow()
949 {
950 // do nothing
951 }
952
953
954 //! Restore original window size
restoreWindow()955 void CIrrDeviceSDL::restoreWindow()
956 {
957 // do nothing
958 }
959
960
961 //! Move window to requested position
moveWindow(int x,int y)962 bool CIrrDeviceSDL::moveWindow(int x, int y)
963 {
964 if (Window)
965 {
966 SDL_SetWindowPosition(Window, x, y);
967 return true;
968 }
969 return false;
970 }
971
972
973 //! Get current window position.
getWindowPosition(int * x,int * y)974 bool CIrrDeviceSDL::getWindowPosition(int* x, int* y)
975 {
976 if (Window)
977 {
978 SDL_GetWindowPosition(Window, x, y);
979 return true;
980 }
981 return false;
982 }
983
984
985 //! returns if window is active. if not, nothing need to be drawn
isWindowActive() const986 bool CIrrDeviceSDL::isWindowActive() const
987 {
988 return (WindowHasFocus && !WindowMinimized);
989 }
990
991
992 //! returns if window has focus.
isWindowFocused() const993 bool CIrrDeviceSDL::isWindowFocused() const
994 {
995 return WindowHasFocus;
996 }
997
998
999 //! returns if window is minimized.
isWindowMinimized() const1000 bool CIrrDeviceSDL::isWindowMinimized() const
1001 {
1002 return WindowMinimized;
1003 }
1004
1005
1006 //! Set the current Gamma Value for the Display
setGammaRamp(f32 red,f32 green,f32 blue,f32 brightness,f32 contrast)1007 bool CIrrDeviceSDL::setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast )
1008 {
1009 /*
1010 // todo: Gamma in SDL takes ints, what does Irrlicht use?
1011 return (SDL_SetGamma(red, green, blue) != -1);
1012 */
1013 return false;
1014 }
1015
1016 //! Get the current Gamma Value for the Display
getGammaRamp(f32 & red,f32 & green,f32 & blue,f32 & brightness,f32 & contrast)1017 bool CIrrDeviceSDL::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast )
1018 {
1019 /* brightness = 0.f;
1020 contrast = 0.f;
1021 return (SDL_GetGamma(&red, &green, &blue) != -1);*/
1022 return false;
1023 }
1024
setWindowMinimumSize(u32 width,u32 height)1025 void CIrrDeviceSDL::setWindowMinimumSize(u32 width, u32 height)
1026 {
1027 if (Window)
1028 SDL_SetWindowMinimumSize(Window, width, height);
1029 }
1030
1031 //! returns color format of the window.
getColorFormat() const1032 video::ECOLOR_FORMAT CIrrDeviceSDL::getColorFormat() const
1033 {
1034 if (Window)
1035 {
1036 u32 pixel_format = SDL_GetWindowPixelFormat(Window);
1037 if (SDL_BITSPERPIXEL(pixel_format) == 16)
1038 {
1039 if (SDL_ISPIXELFORMAT_ALPHA(pixel_format))
1040 return video::ECF_A1R5G5B5;
1041 else
1042 return video::ECF_R5G6B5;
1043 }
1044 else
1045 {
1046 if (SDL_ISPIXELFORMAT_ALPHA(pixel_format))
1047 return video::ECF_A8R8G8B8;
1048 else
1049 return video::ECF_R8G8B8;
1050 }
1051 }
1052 else
1053 return CIrrDeviceStub::getColorFormat();
1054 }
1055
1056
createKeyMap()1057 void CIrrDeviceSDL::createKeyMap()
1058 {
1059 // I don't know if this is the best method to create
1060 // the lookuptable, but I'll leave it like that until
1061 // I find a better version.
1062
1063 KeyMap.reallocate(105);
1064
1065 // buttons missing
1066
1067 KeyMap.push_back(SKeyMap(SDLK_BACKSPACE, IRR_KEY_BACK));
1068 KeyMap.push_back(SKeyMap(SDLK_TAB, IRR_KEY_TAB));
1069 KeyMap.push_back(SKeyMap(SDLK_CLEAR, IRR_KEY_CLEAR));
1070 KeyMap.push_back(SKeyMap(SDLK_RETURN, IRR_KEY_RETURN));
1071
1072 // combined modifiers missing
1073
1074 KeyMap.push_back(SKeyMap(SDLK_PAUSE, IRR_KEY_PAUSE));
1075 KeyMap.push_back(SKeyMap(SDLK_CAPSLOCK, IRR_KEY_CAPITAL));
1076
1077 // asian letter keys missing
1078
1079 KeyMap.push_back(SKeyMap(SDLK_ESCAPE, IRR_KEY_ESCAPE));
1080
1081 // asian letter keys missing
1082
1083 KeyMap.push_back(SKeyMap(SDLK_SPACE, IRR_KEY_SPACE));
1084 KeyMap.push_back(SKeyMap(SDLK_PAGEUP, IRR_KEY_PRIOR));
1085 KeyMap.push_back(SKeyMap(SDLK_PAGEDOWN, IRR_KEY_NEXT));
1086 KeyMap.push_back(SKeyMap(SDLK_END, IRR_KEY_END));
1087 KeyMap.push_back(SKeyMap(SDLK_HOME, IRR_KEY_HOME));
1088 KeyMap.push_back(SKeyMap(SDLK_LEFT, IRR_KEY_LEFT));
1089 KeyMap.push_back(SKeyMap(SDLK_UP, IRR_KEY_UP));
1090 KeyMap.push_back(SKeyMap(SDLK_RIGHT, IRR_KEY_RIGHT));
1091 KeyMap.push_back(SKeyMap(SDLK_DOWN, IRR_KEY_DOWN));
1092
1093 // select missing
1094 KeyMap.push_back(SKeyMap(SDLK_PRINTSCREEN, IRR_KEY_PRINT));
1095 // execute missing
1096 KeyMap.push_back(SKeyMap(SDLK_PRINTSCREEN, IRR_KEY_SNAPSHOT));
1097
1098 KeyMap.push_back(SKeyMap(SDLK_INSERT, IRR_KEY_INSERT));
1099 KeyMap.push_back(SKeyMap(SDLK_DELETE, IRR_KEY_DELETE));
1100 KeyMap.push_back(SKeyMap(SDLK_HELP, IRR_KEY_HELP));
1101
1102 KeyMap.push_back(SKeyMap(SDLK_0, IRR_KEY_0));
1103 KeyMap.push_back(SKeyMap(SDLK_1, IRR_KEY_1));
1104 KeyMap.push_back(SKeyMap(SDLK_2, IRR_KEY_2));
1105 KeyMap.push_back(SKeyMap(SDLK_3, IRR_KEY_3));
1106 KeyMap.push_back(SKeyMap(SDLK_4, IRR_KEY_4));
1107 KeyMap.push_back(SKeyMap(SDLK_5, IRR_KEY_5));
1108 KeyMap.push_back(SKeyMap(SDLK_6, IRR_KEY_6));
1109 KeyMap.push_back(SKeyMap(SDLK_7, IRR_KEY_7));
1110 KeyMap.push_back(SKeyMap(SDLK_8, IRR_KEY_8));
1111 KeyMap.push_back(SKeyMap(SDLK_9, IRR_KEY_9));
1112
1113 KeyMap.push_back(SKeyMap(SDLK_a, IRR_KEY_A));
1114 KeyMap.push_back(SKeyMap(SDLK_b, IRR_KEY_B));
1115 KeyMap.push_back(SKeyMap(SDLK_c, IRR_KEY_C));
1116 KeyMap.push_back(SKeyMap(SDLK_d, IRR_KEY_D));
1117 KeyMap.push_back(SKeyMap(SDLK_e, IRR_KEY_E));
1118 KeyMap.push_back(SKeyMap(SDLK_f, IRR_KEY_F));
1119 KeyMap.push_back(SKeyMap(SDLK_g, IRR_KEY_G));
1120 KeyMap.push_back(SKeyMap(SDLK_h, IRR_KEY_H));
1121 KeyMap.push_back(SKeyMap(SDLK_i, IRR_KEY_I));
1122 KeyMap.push_back(SKeyMap(SDLK_j, IRR_KEY_J));
1123 KeyMap.push_back(SKeyMap(SDLK_k, IRR_KEY_K));
1124 KeyMap.push_back(SKeyMap(SDLK_l, IRR_KEY_L));
1125 KeyMap.push_back(SKeyMap(SDLK_m, IRR_KEY_M));
1126 KeyMap.push_back(SKeyMap(SDLK_n, IRR_KEY_N));
1127 KeyMap.push_back(SKeyMap(SDLK_o, IRR_KEY_O));
1128 KeyMap.push_back(SKeyMap(SDLK_p, IRR_KEY_P));
1129 KeyMap.push_back(SKeyMap(SDLK_q, IRR_KEY_Q));
1130 KeyMap.push_back(SKeyMap(SDLK_r, IRR_KEY_R));
1131 KeyMap.push_back(SKeyMap(SDLK_s, IRR_KEY_S));
1132 KeyMap.push_back(SKeyMap(SDLK_t, IRR_KEY_T));
1133 KeyMap.push_back(SKeyMap(SDLK_u, IRR_KEY_U));
1134 KeyMap.push_back(SKeyMap(SDLK_v, IRR_KEY_V));
1135 KeyMap.push_back(SKeyMap(SDLK_w, IRR_KEY_W));
1136 KeyMap.push_back(SKeyMap(SDLK_x, IRR_KEY_X));
1137 KeyMap.push_back(SKeyMap(SDLK_y, IRR_KEY_Y));
1138 KeyMap.push_back(SKeyMap(SDLK_z, IRR_KEY_Z));
1139
1140 KeyMap.push_back(SKeyMap(SDLK_LGUI, IRR_KEY_LWIN));
1141 KeyMap.push_back(SKeyMap(SDLK_RGUI, IRR_KEY_RWIN));
1142 KeyMap.push_back(SKeyMap(SDLK_APPLICATION, IRR_KEY_APPS));
1143 KeyMap.push_back(SKeyMap(SDLK_POWER, IRR_KEY_SLEEP)); //??
1144
1145 KeyMap.push_back(SKeyMap(SDLK_KP_0, IRR_KEY_NUMPAD0));
1146 KeyMap.push_back(SKeyMap(SDLK_KP_1, IRR_KEY_NUMPAD1));
1147 KeyMap.push_back(SKeyMap(SDLK_KP_2, IRR_KEY_NUMPAD2));
1148 KeyMap.push_back(SKeyMap(SDLK_KP_3, IRR_KEY_NUMPAD3));
1149 KeyMap.push_back(SKeyMap(SDLK_KP_4, IRR_KEY_NUMPAD4));
1150 KeyMap.push_back(SKeyMap(SDLK_KP_5, IRR_KEY_NUMPAD5));
1151 KeyMap.push_back(SKeyMap(SDLK_KP_6, IRR_KEY_NUMPAD6));
1152 KeyMap.push_back(SKeyMap(SDLK_KP_7, IRR_KEY_NUMPAD7));
1153 KeyMap.push_back(SKeyMap(SDLK_KP_8, IRR_KEY_NUMPAD8));
1154 KeyMap.push_back(SKeyMap(SDLK_KP_9, IRR_KEY_NUMPAD9));
1155 KeyMap.push_back(SKeyMap(SDLK_KP_MULTIPLY, IRR_KEY_MULTIPLY));
1156 KeyMap.push_back(SKeyMap(SDLK_KP_PLUS, IRR_KEY_ADD));
1157 KeyMap.push_back(SKeyMap(SDLK_SEPARATOR, IRR_KEY_SEPARATOR));
1158 KeyMap.push_back(SKeyMap(SDLK_KP_MINUS, IRR_KEY_SUBTRACT));
1159 KeyMap.push_back(SKeyMap(SDLK_KP_PERIOD, IRR_KEY_DECIMAL));
1160 KeyMap.push_back(SKeyMap(SDLK_KP_DIVIDE, IRR_KEY_DIVIDE));
1161
1162 KeyMap.push_back(SKeyMap(SDLK_F1, IRR_KEY_F1));
1163 KeyMap.push_back(SKeyMap(SDLK_F2, IRR_KEY_F2));
1164 KeyMap.push_back(SKeyMap(SDLK_F3, IRR_KEY_F3));
1165 KeyMap.push_back(SKeyMap(SDLK_F4, IRR_KEY_F4));
1166 KeyMap.push_back(SKeyMap(SDLK_F5, IRR_KEY_F5));
1167 KeyMap.push_back(SKeyMap(SDLK_F6, IRR_KEY_F6));
1168 KeyMap.push_back(SKeyMap(SDLK_F7, IRR_KEY_F7));
1169 KeyMap.push_back(SKeyMap(SDLK_F8, IRR_KEY_F8));
1170 KeyMap.push_back(SKeyMap(SDLK_F9, IRR_KEY_F9));
1171 KeyMap.push_back(SKeyMap(SDLK_F10, IRR_KEY_F10));
1172 KeyMap.push_back(SKeyMap(SDLK_F11, IRR_KEY_F11));
1173 KeyMap.push_back(SKeyMap(SDLK_F12, IRR_KEY_F12));
1174 KeyMap.push_back(SKeyMap(SDLK_F13, IRR_KEY_F13));
1175 KeyMap.push_back(SKeyMap(SDLK_F14, IRR_KEY_F14));
1176 KeyMap.push_back(SKeyMap(SDLK_F15, IRR_KEY_F15));
1177 // no higher F-keys
1178
1179 KeyMap.push_back(SKeyMap(SDLK_NUMLOCKCLEAR, IRR_KEY_NUMLOCK));
1180 KeyMap.push_back(SKeyMap(SDLK_SCROLLLOCK, IRR_KEY_SCROLL));
1181 KeyMap.push_back(SKeyMap(SDLK_LSHIFT, IRR_KEY_LSHIFT));
1182 KeyMap.push_back(SKeyMap(SDLK_RSHIFT, IRR_KEY_RSHIFT));
1183 KeyMap.push_back(SKeyMap(SDLK_LCTRL, IRR_KEY_LCONTROL));
1184 KeyMap.push_back(SKeyMap(SDLK_RCTRL, IRR_KEY_RCONTROL));
1185 KeyMap.push_back(SKeyMap(SDLK_LALT, IRR_KEY_LMENU));
1186 KeyMap.push_back(SKeyMap(SDLK_RALT, IRR_KEY_RMENU));
1187 KeyMap.push_back(SKeyMap(SDLK_MENU, IRR_KEY_MENU));
1188
1189 KeyMap.push_back(SKeyMap(SDLK_PLUS, IRR_KEY_PLUS));
1190 KeyMap.push_back(SKeyMap(SDLK_COMMA, IRR_KEY_COMMA));
1191 KeyMap.push_back(SKeyMap(SDLK_MINUS, IRR_KEY_MINUS));
1192 KeyMap.push_back(SKeyMap(SDLK_PERIOD, IRR_KEY_PERIOD));
1193 KeyMap.push_back(SKeyMap(SDLK_AC_BACK, IRR_KEY_ESCAPE));
1194
1195 KeyMap.push_back(SKeyMap(SDLK_EQUALS, IRR_KEY_PLUS));
1196 KeyMap.push_back(SKeyMap(SDLK_LEFTBRACKET, IRR_KEY_OEM_4));
1197 KeyMap.push_back(SKeyMap(SDLK_RIGHTBRACKET, IRR_KEY_OEM_6));
1198 KeyMap.push_back(SKeyMap(SDLK_BACKSLASH, IRR_KEY_OEM_5));
1199 KeyMap.push_back(SKeyMap(SDLK_SEMICOLON, IRR_KEY_OEM_1));
1200 KeyMap.push_back(SKeyMap(SDLK_SLASH, IRR_KEY_OEM_2));
1201 KeyMap.push_back(SKeyMap(SDLK_MODE, IRR_KEY_BUTTON_MODE));
1202
1203 // some special keys missing
1204
1205 KeyMap.sort();
1206
1207 ScanCodeMap[SDL_SCANCODE_A] = IRR_KEY_A;
1208 ScanCodeMap[SDL_SCANCODE_B] = IRR_KEY_B;
1209 ScanCodeMap[SDL_SCANCODE_C] = IRR_KEY_C;
1210 ScanCodeMap[SDL_SCANCODE_D] = IRR_KEY_D;
1211 ScanCodeMap[SDL_SCANCODE_E] = IRR_KEY_E;
1212 ScanCodeMap[SDL_SCANCODE_F] = IRR_KEY_F;
1213 ScanCodeMap[SDL_SCANCODE_G] = IRR_KEY_G;
1214 ScanCodeMap[SDL_SCANCODE_H] = IRR_KEY_H;
1215 ScanCodeMap[SDL_SCANCODE_I] = IRR_KEY_I;
1216 ScanCodeMap[SDL_SCANCODE_J] = IRR_KEY_J;
1217 ScanCodeMap[SDL_SCANCODE_K] = IRR_KEY_K;
1218 ScanCodeMap[SDL_SCANCODE_L] = IRR_KEY_L;
1219 ScanCodeMap[SDL_SCANCODE_M] = IRR_KEY_M;
1220 ScanCodeMap[SDL_SCANCODE_N] = IRR_KEY_N;
1221 ScanCodeMap[SDL_SCANCODE_O] = IRR_KEY_O;
1222 ScanCodeMap[SDL_SCANCODE_P] = IRR_KEY_P;
1223 ScanCodeMap[SDL_SCANCODE_Q] = IRR_KEY_Q;
1224 ScanCodeMap[SDL_SCANCODE_R] = IRR_KEY_R;
1225 ScanCodeMap[SDL_SCANCODE_S] = IRR_KEY_S;
1226 ScanCodeMap[SDL_SCANCODE_T] = IRR_KEY_T;
1227 ScanCodeMap[SDL_SCANCODE_U] = IRR_KEY_U;
1228 ScanCodeMap[SDL_SCANCODE_V] = IRR_KEY_V;
1229 ScanCodeMap[SDL_SCANCODE_W] = IRR_KEY_W;
1230 ScanCodeMap[SDL_SCANCODE_X] = IRR_KEY_X;
1231 ScanCodeMap[SDL_SCANCODE_Y] = IRR_KEY_Y;
1232 ScanCodeMap[SDL_SCANCODE_Z] = IRR_KEY_Z;
1233 ScanCodeMap[SDL_SCANCODE_1] = IRR_KEY_1;
1234 ScanCodeMap[SDL_SCANCODE_2] = IRR_KEY_2;
1235 ScanCodeMap[SDL_SCANCODE_3] = IRR_KEY_3;
1236 ScanCodeMap[SDL_SCANCODE_4] = IRR_KEY_4;
1237 ScanCodeMap[SDL_SCANCODE_5] = IRR_KEY_5;
1238 ScanCodeMap[SDL_SCANCODE_6] = IRR_KEY_6;
1239 ScanCodeMap[SDL_SCANCODE_7] = IRR_KEY_7;
1240 ScanCodeMap[SDL_SCANCODE_8] = IRR_KEY_8;
1241 ScanCodeMap[SDL_SCANCODE_9] = IRR_KEY_9;
1242 ScanCodeMap[SDL_SCANCODE_0] = IRR_KEY_0;
1243 ScanCodeMap[SDL_SCANCODE_RETURN] = IRR_KEY_RETURN;
1244 ScanCodeMap[SDL_SCANCODE_ESCAPE] = IRR_KEY_ESCAPE;
1245 ScanCodeMap[SDL_SCANCODE_BACKSPACE] = IRR_KEY_BACK;
1246 ScanCodeMap[SDL_SCANCODE_TAB] = IRR_KEY_TAB;
1247 ScanCodeMap[SDL_SCANCODE_SPACE] = IRR_KEY_SPACE;
1248 ScanCodeMap[SDL_SCANCODE_MINUS] = IRR_KEY_MINUS;
1249 ScanCodeMap[SDL_SCANCODE_EQUALS] = IRR_KEY_PLUS;
1250 ScanCodeMap[SDL_SCANCODE_LEFTBRACKET] = IRR_KEY_OEM_4;
1251 ScanCodeMap[SDL_SCANCODE_RIGHTBRACKET] = IRR_KEY_OEM_6;
1252 ScanCodeMap[SDL_SCANCODE_BACKSLASH] = IRR_KEY_OEM_5;
1253 ScanCodeMap[SDL_SCANCODE_SEMICOLON] = IRR_KEY_OEM_1;
1254 ScanCodeMap[SDL_SCANCODE_APOSTROPHE] = IRR_KEY_OEM_7;
1255 ScanCodeMap[SDL_SCANCODE_GRAVE] = IRR_KEY_OEM_3;
1256 ScanCodeMap[SDL_SCANCODE_COMMA] = IRR_KEY_COMMA;
1257 ScanCodeMap[SDL_SCANCODE_PERIOD] = IRR_KEY_PERIOD;
1258 ScanCodeMap[SDL_SCANCODE_SLASH] = IRR_KEY_OEM_2;
1259 ScanCodeMap[SDL_SCANCODE_CAPSLOCK] = IRR_KEY_CAPITAL;
1260 ScanCodeMap[SDL_SCANCODE_F1] = IRR_KEY_F1;
1261 ScanCodeMap[SDL_SCANCODE_F2] = IRR_KEY_F2;
1262 ScanCodeMap[SDL_SCANCODE_F3] = IRR_KEY_F3;
1263 ScanCodeMap[SDL_SCANCODE_F4] = IRR_KEY_F4;
1264 ScanCodeMap[SDL_SCANCODE_F5] = IRR_KEY_F5;
1265 ScanCodeMap[SDL_SCANCODE_F6] = IRR_KEY_F6;
1266 ScanCodeMap[SDL_SCANCODE_F7] = IRR_KEY_F7;
1267 ScanCodeMap[SDL_SCANCODE_F8] = IRR_KEY_F8;
1268 ScanCodeMap[SDL_SCANCODE_F9] = IRR_KEY_F9;
1269 ScanCodeMap[SDL_SCANCODE_F10] = IRR_KEY_F10;
1270 ScanCodeMap[SDL_SCANCODE_F11] = IRR_KEY_F11;
1271 ScanCodeMap[SDL_SCANCODE_F12] = IRR_KEY_F12;
1272 ScanCodeMap[SDL_SCANCODE_PRINTSCREEN] = IRR_KEY_PRINT;
1273 ScanCodeMap[SDL_SCANCODE_SCROLLLOCK] = IRR_KEY_SCROLL;
1274 ScanCodeMap[SDL_SCANCODE_PAUSE] = IRR_KEY_PAUSE;
1275 ScanCodeMap[SDL_SCANCODE_INSERT] = IRR_KEY_INSERT;
1276 ScanCodeMap[SDL_SCANCODE_HOME] = IRR_KEY_HOME;
1277 ScanCodeMap[SDL_SCANCODE_PAGEUP] = IRR_KEY_PRIOR;
1278 ScanCodeMap[SDL_SCANCODE_DELETE] = IRR_KEY_DELETE;
1279 ScanCodeMap[SDL_SCANCODE_END] = IRR_KEY_END;
1280 ScanCodeMap[SDL_SCANCODE_PAGEDOWN] = IRR_KEY_NEXT;
1281 ScanCodeMap[SDL_SCANCODE_RIGHT] = IRR_KEY_RIGHT;
1282 ScanCodeMap[SDL_SCANCODE_LEFT] = IRR_KEY_LEFT;
1283 ScanCodeMap[SDL_SCANCODE_DOWN] = IRR_KEY_DOWN;
1284 ScanCodeMap[SDL_SCANCODE_UP] = IRR_KEY_UP;
1285 ScanCodeMap[SDL_SCANCODE_NUMLOCKCLEAR] = IRR_KEY_NUMLOCK;
1286 ScanCodeMap[SDL_SCANCODE_KP_DIVIDE] = IRR_KEY_DIVIDE;
1287 ScanCodeMap[SDL_SCANCODE_KP_MULTIPLY] = IRR_KEY_MULTIPLY;
1288 ScanCodeMap[SDL_SCANCODE_KP_MINUS] = IRR_KEY_MINUS;
1289 ScanCodeMap[SDL_SCANCODE_KP_PLUS] = IRR_KEY_PLUS;
1290 ScanCodeMap[SDL_SCANCODE_SEPARATOR] = IRR_KEY_SEPARATOR;
1291 ScanCodeMap[SDL_SCANCODE_KP_ENTER] = IRR_KEY_RETURN;
1292 ScanCodeMap[SDL_SCANCODE_KP_1] = IRR_KEY_NUMPAD1;
1293 ScanCodeMap[SDL_SCANCODE_KP_2] = IRR_KEY_NUMPAD2;
1294 ScanCodeMap[SDL_SCANCODE_KP_3] = IRR_KEY_NUMPAD3;
1295 ScanCodeMap[SDL_SCANCODE_KP_4] = IRR_KEY_NUMPAD4;
1296 ScanCodeMap[SDL_SCANCODE_KP_5] = IRR_KEY_NUMPAD5;
1297 ScanCodeMap[SDL_SCANCODE_KP_6] = IRR_KEY_NUMPAD6;
1298 ScanCodeMap[SDL_SCANCODE_KP_7] = IRR_KEY_NUMPAD7;
1299 ScanCodeMap[SDL_SCANCODE_KP_8] = IRR_KEY_NUMPAD8;
1300 ScanCodeMap[SDL_SCANCODE_KP_9] = IRR_KEY_NUMPAD9;
1301 ScanCodeMap[SDL_SCANCODE_KP_0] = IRR_KEY_NUMPAD0;
1302 ScanCodeMap[SDL_SCANCODE_LCTRL] = IRR_KEY_LCONTROL;
1303 ScanCodeMap[SDL_SCANCODE_LSHIFT] = IRR_KEY_LSHIFT;
1304 ScanCodeMap[SDL_SCANCODE_LALT] = IRR_KEY_LMENU;
1305 ScanCodeMap[SDL_SCANCODE_LGUI] = IRR_KEY_LWIN;
1306 ScanCodeMap[SDL_SCANCODE_RCTRL] = IRR_KEY_RCONTROL;
1307 ScanCodeMap[SDL_SCANCODE_RSHIFT] = IRR_KEY_RSHIFT;
1308 ScanCodeMap[SDL_SCANCODE_RALT] = IRR_KEY_RMENU;
1309 ScanCodeMap[SDL_SCANCODE_RGUI] = IRR_KEY_RWIN;
1310 ScanCodeMap[SDL_SCANCODE_APPLICATION] = IRR_KEY_APPS;
1311 ScanCodeMap[SDL_SCANCODE_MODE] = IRR_KEY_BUTTON_MODE;
1312 ScanCodeMap[SDL_SCANCODE_MENU] = IRR_KEY_MENU;
1313 }
1314
1315
supportsTouchDevice() const1316 bool CIrrDeviceSDL::supportsTouchDevice() const
1317 {
1318 return SDL_GetNumTouchDevices() > 0;
1319 }
1320
1321
hasOnScreenKeyboard() const1322 bool CIrrDeviceSDL::hasOnScreenKeyboard() const
1323 {
1324 return SDL_HasScreenKeyboardSupport() == SDL_TRUE;
1325 }
1326
1327
1328 extern "C" int Android_getMovedHeight();
getMovedHeight() const1329 s32 CIrrDeviceSDL::getMovedHeight() const
1330 {
1331 #if defined(IOS_STK)
1332 return SDL_GetMovedHeightByScreenKeyboard() * g_native_scale_y;
1333 #elif defined(ANDROID)
1334 return Android_getMovedHeight();
1335 #else
1336 return 0;
1337 #endif
1338 }
1339
1340
1341 extern "C" int Android_getKeyboardHeight();
getOnScreenKeyboardHeight() const1342 u32 CIrrDeviceSDL::getOnScreenKeyboardHeight() const
1343 {
1344 #if defined(IOS_STK)
1345 return SDL_GetScreenKeyboardHeight() * g_native_scale_y;
1346 #elif defined(ANDROID)
1347 return Android_getKeyboardHeight();
1348 #else
1349 return 0;
1350 #endif
1351 }
1352
1353
getNativeScaleX() const1354 f32 CIrrDeviceSDL::getNativeScaleX() const
1355 {
1356 return g_native_scale_x;
1357 }
1358
1359
getNativeScaleY() const1360 f32 CIrrDeviceSDL::getNativeScaleY() const
1361 {
1362 return g_native_scale_y;
1363 }
1364
1365 } // end namespace irr
1366
1367 #endif // _IRR_COMPILE_WITH_SDL_DEVICE_
1368
1369