Input.cpp 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482
  1. //
  2. // Copyright (c) 2008-2014 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "Precompiled.h"
  23. #include "Context.h"
  24. #include "CoreEvents.h"
  25. #include "FileSystem.h"
  26. #include "Graphics.h"
  27. #include "GraphicsEvents.h"
  28. #include "GraphicsImpl.h"
  29. #include "Input.h"
  30. #include "Log.h"
  31. #include "Mutex.h"
  32. #include "ProcessUtils.h"
  33. #include "Profiler.h"
  34. #include "ResourceCache.h"
  35. #include "RWOpsWrapper.h"
  36. #include "StringUtils.h"
  37. #include "Text.h"
  38. #include "UI.h"
  39. #include <cstring>
  40. #include <SDL.h>
  41. #include "DebugNew.h"
  42. // Require a click inside window before re-hiding mouse cursor on OSX, otherwise dragging the window
  43. // can be incorrectly interpreted as mouse movement inside the window
  44. #if defined(__APPLE__) && !defined(IOS)
  45. #define REQUIRE_CLICK_TO_FOCUS
  46. #endif
  47. namespace Urho3D
  48. {
  49. const int SCREEN_JOYSTICK_START_INDEX = 1000;
  50. const ShortStringHash VAR_BUTTON_KEY_BINDING("VAR_BUTTON_KEY_BINDING");
  51. const ShortStringHash VAR_LAST_KEYSYM("VAR_LAST_KEYSYM");
  52. const ShortStringHash VAR_SCREEN_JOYSTICK_INDEX("VAR_SCREEN_JOYSTICK_INDEX");
  53. /// Convert SDL keycode if necessary.
  54. int ConvertSDLKeyCode(int keySym, int scanCode)
  55. {
  56. if (scanCode == SCANCODE_AC_BACK)
  57. return KEY_ESC;
  58. else
  59. return SDL_toupper(keySym);
  60. }
  61. Input::Input(Context* context) :
  62. Object(context),
  63. mouseButtonDown_(0),
  64. mouseButtonPress_(0),
  65. mouseMoveWheel_(0),
  66. windowID_(0),
  67. toggleFullscreen_(true),
  68. mouseVisible_(false),
  69. inputFocus_(false),
  70. minimized_(false),
  71. focusedThisFrame_(false),
  72. suppressNextMouseMove_(false),
  73. initialized_(false)
  74. {
  75. SubscribeToEvent(E_SCREENMODE, HANDLER(Input, HandleScreenMode));
  76. // Try to initialize right now, but skip if screen mode is not yet set
  77. Initialize();
  78. }
  79. Input::~Input()
  80. {
  81. }
  82. void Input::Update()
  83. {
  84. assert(initialized_);
  85. PROFILE(UpdateInput);
  86. // Reset input accumulation for this frame
  87. keyPress_.Clear();
  88. scancodePress_.Clear();
  89. mouseButtonPress_ = 0;
  90. mouseMove_ = IntVector2::ZERO;
  91. mouseMoveWheel_ = 0;
  92. for (HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
  93. {
  94. for (unsigned j = 0; j < i->second_.buttonPress_.Size(); ++j)
  95. i->second_.buttonPress_[j] = false;
  96. }
  97. // Reset touch delta movement
  98. for (HashMap<int, TouchState>::Iterator i = touches_.Begin(); i != touches_.End(); ++i)
  99. {
  100. TouchState& state = i->second_;
  101. state.lastPosition_ = state.position_;
  102. state.delta_ = IntVector2::ZERO;
  103. }
  104. // Check and handle SDL events
  105. SDL_PumpEvents();
  106. SDL_Event evt;
  107. while (SDL_PeepEvents(&evt, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) > 0)
  108. HandleSDLEvent(&evt);
  109. // Check for activation and inactivation from SDL window flags. Must nullcheck the window pointer because it may have
  110. // been closed due to input events
  111. SDL_Window* window = graphics_->GetImpl()->GetWindow();
  112. unsigned flags = window ? SDL_GetWindowFlags(window) & (SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS) : 0;
  113. if (window)
  114. {
  115. #ifdef REQUIRE_CLICK_TO_FOCUS
  116. if (!inputFocus_ && (graphics_->GetFullscreen() || mouseVisible_) && flags == (SDL_WINDOW_INPUT_FOCUS |
  117. SDL_WINDOW_MOUSE_FOCUS))
  118. #else
  119. if (!inputFocus_ && (flags & SDL_WINDOW_INPUT_FOCUS))
  120. #endif
  121. focusedThisFrame_ = true;
  122. if (focusedThisFrame_)
  123. GainFocus();
  124. if (inputFocus_ && (flags & SDL_WINDOW_INPUT_FOCUS) == 0)
  125. LoseFocus();
  126. }
  127. else
  128. return;
  129. // Check for relative mode mouse move
  130. if (graphics_->GetExternalWindow() || (!mouseVisible_ && inputFocus_ && (flags & SDL_WINDOW_MOUSE_FOCUS)))
  131. {
  132. IntVector2 mousePosition = GetMousePosition();
  133. mouseMove_ = mousePosition - lastMousePosition_;
  134. if (graphics_->GetExternalWindow())
  135. lastMousePosition_ = mousePosition;
  136. else
  137. {
  138. // Recenter the mouse cursor manually after move
  139. IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
  140. if (mousePosition != center)
  141. {
  142. SetMousePosition(center);
  143. lastMousePosition_ = center;
  144. }
  145. }
  146. // Send mouse move event if necessary
  147. if (mouseMove_ != IntVector2::ZERO)
  148. {
  149. if (suppressNextMouseMove_)
  150. {
  151. mouseMove_ = IntVector2::ZERO;
  152. suppressNextMouseMove_ = false;
  153. }
  154. else
  155. {
  156. using namespace MouseMove;
  157. VariantMap& eventData = GetEventDataMap();
  158. if (mouseVisible_)
  159. {
  160. eventData[P_X] = mousePosition.x_;
  161. eventData[P_Y] = mousePosition.y_;
  162. }
  163. eventData[P_DX] = mouseMove_.x_;
  164. eventData[P_DY] = mouseMove_.y_;
  165. eventData[P_BUTTONS] = mouseButtonDown_;
  166. eventData[P_QUALIFIERS] = GetQualifiers();
  167. SendEvent(E_MOUSEMOVE, eventData);
  168. }
  169. }
  170. }
  171. }
  172. void Input::SetMouseVisible(bool enable)
  173. {
  174. // SDL Raspberry Pi "video driver" does not have proper OS mouse support yet, so no-op for now
  175. #ifndef RASPI
  176. if (enable != mouseVisible_)
  177. {
  178. mouseVisible_ = enable;
  179. if (initialized_)
  180. {
  181. // External windows can only support visible mouse cursor
  182. if (graphics_->GetExternalWindow())
  183. {
  184. mouseVisible_ = true;
  185. return;
  186. }
  187. if (!mouseVisible_ && inputFocus_)
  188. {
  189. SDL_ShowCursor(SDL_FALSE);
  190. // Recenter the mouse cursor manually when hiding it to avoid erratic mouse move for one frame
  191. IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
  192. SetMousePosition(center);
  193. lastMousePosition_ = center;
  194. }
  195. else
  196. SDL_ShowCursor(SDL_TRUE);
  197. }
  198. using namespace MouseVisibleChanged;
  199. VariantMap& eventData = GetEventDataMap();
  200. eventData[P_VISIBLE] = mouseVisible_;
  201. SendEvent(E_MOUSEVISIBLECHANGED, eventData);
  202. }
  203. #endif
  204. }
  205. void Input::SetScreenJoystickVisible(SDL_JoystickID index, bool enable)
  206. {
  207. if(joysticks_.Contains(index))
  208. {
  209. JoystickState& state = joysticks_[index];
  210. if (state.screenJoystick_)
  211. state.screenJoystick_->SetVisible(enable);
  212. }
  213. }
  214. void Input::SetToggleFullscreen(bool enable)
  215. {
  216. toggleFullscreen_ = enable;
  217. }
  218. static void PopulateKeyBindingMap(HashMap<String, int>& keyBindingMap)
  219. {
  220. if (keyBindingMap.Empty())
  221. {
  222. keyBindingMap.Insert(MakePair<String, int>("SPACE", KEY_SPACE));
  223. keyBindingMap.Insert(MakePair<String, int>("LCTRL", KEY_LCTRL));
  224. keyBindingMap.Insert(MakePair<String, int>("RCTRL", KEY_RCTRL));
  225. keyBindingMap.Insert(MakePair<String, int>("LSHIFT", KEY_LSHIFT));
  226. keyBindingMap.Insert(MakePair<String, int>("RSHIFT", KEY_RSHIFT));
  227. keyBindingMap.Insert(MakePair<String, int>("LALT", KEY_LALT));
  228. keyBindingMap.Insert(MakePair<String, int>("RALT", KEY_RALT));
  229. keyBindingMap.Insert(MakePair<String, int>("LGUI", KEY_LGUI));
  230. keyBindingMap.Insert(MakePair<String, int>("RGUI", KEY_RGUI));
  231. keyBindingMap.Insert(MakePair<String, int>("TAB", KEY_TAB));
  232. keyBindingMap.Insert(MakePair<String, int>("RETURN", KEY_RETURN));
  233. keyBindingMap.Insert(MakePair<String, int>("RETURN2", KEY_RETURN2));
  234. keyBindingMap.Insert(MakePair<String, int>("ENTER", KEY_KP_ENTER));
  235. keyBindingMap.Insert(MakePair<String, int>("SELECT", KEY_SELECT));
  236. keyBindingMap.Insert(MakePair<String, int>("LEFT", KEY_LEFT));
  237. keyBindingMap.Insert(MakePair<String, int>("RIGHT", KEY_RIGHT));
  238. keyBindingMap.Insert(MakePair<String, int>("UP", KEY_UP));
  239. keyBindingMap.Insert(MakePair<String, int>("DOWN", KEY_DOWN));
  240. keyBindingMap.Insert(MakePair<String, int>("F1", KEY_F1));
  241. keyBindingMap.Insert(MakePair<String, int>("F2", KEY_F2));
  242. keyBindingMap.Insert(MakePair<String, int>("F3", KEY_F3));
  243. keyBindingMap.Insert(MakePair<String, int>("F4", KEY_F4));
  244. keyBindingMap.Insert(MakePair<String, int>("F5", KEY_F5));
  245. keyBindingMap.Insert(MakePair<String, int>("F6", KEY_F6));
  246. keyBindingMap.Insert(MakePair<String, int>("F7", KEY_F7));
  247. keyBindingMap.Insert(MakePair<String, int>("F8", KEY_F8));
  248. keyBindingMap.Insert(MakePair<String, int>("F9", KEY_F9));
  249. keyBindingMap.Insert(MakePair<String, int>("F10", KEY_F10));
  250. keyBindingMap.Insert(MakePair<String, int>("F11", KEY_F11));
  251. keyBindingMap.Insert(MakePair<String, int>("F12", KEY_F12));
  252. }
  253. }
  254. SDL_JoystickID Input::AddScreenJoystick(XMLFile* layoutFile, XMLFile* styleFile)
  255. {
  256. static HashMap<String, int> keyBindingMap;
  257. if (!graphics_)
  258. {
  259. LOGWARNING("Cannot add screen joystick in headless mode");
  260. return M_MAX_UNSIGNED;
  261. }
  262. // If layout file is not given, use the default screen joystick layout
  263. if (!layoutFile)
  264. {
  265. ResourceCache* cache = GetSubsystem<ResourceCache>();
  266. layoutFile = cache->GetResource<XMLFile>("UI/ScreenJoystick.xml");
  267. if (!layoutFile) // Error is already logged
  268. return M_MAX_UNSIGNED;
  269. }
  270. UI* ui = GetSubsystem<UI>();
  271. SharedPtr<UIElement> screenJoystick = ui->LoadLayout(layoutFile, styleFile);
  272. if (!screenJoystick) // Error is already logged
  273. return M_MAX_UNSIGNED;
  274. screenJoystick->SetSize(ui->GetRoot()->GetSize());
  275. screenJoystick->SetVisible(false); // Set to visible when it is opened later
  276. ui->GetRoot()->AddChild(screenJoystick);
  277. SDL_JoystickID instanceID = SCREEN_JOYSTICK_START_INDEX + joysticks_.Size();
  278. JoystickState& state = joysticks_[instanceID];
  279. state.name_ = screenJoystick->GetName();
  280. state.screenJoystick_ = screenJoystick;
  281. unsigned numButtons = 0;
  282. unsigned numAxes = 0;
  283. unsigned numHats = 0;
  284. const Vector<SharedPtr<UIElement> >& children = state.screenJoystick_->GetChildren();
  285. for (Vector<SharedPtr<UIElement> >::ConstIterator iter = children.Begin(); iter != children.End(); ++iter)
  286. {
  287. UIElement* element = iter->Get();
  288. String name = element->GetName();
  289. if (name.StartsWith("Button"))
  290. {
  291. ++numButtons;
  292. // Check whether the button has key binding
  293. Text* text = dynamic_cast<Text*>(element->GetChild("KeyBinding", false));
  294. if (text)
  295. {
  296. text->SetVisible(false);
  297. const String& key = text->GetText();
  298. int keyBinding;
  299. if (key.Length() == 1)
  300. keyBinding = key[0];
  301. else
  302. {
  303. PopulateKeyBindingMap(keyBindingMap);
  304. HashMap<String, int>::Iterator i = keyBindingMap.Find(key);
  305. if (i != keyBindingMap.End())
  306. keyBinding = i->second_;
  307. else
  308. {
  309. LOGERRORF("Unsupported key binding: %s", key.CString());
  310. keyBinding = M_MAX_INT;
  311. }
  312. }
  313. if (keyBinding != M_MAX_INT)
  314. element->SetVar(VAR_BUTTON_KEY_BINDING, keyBinding);
  315. }
  316. }
  317. else if (name.StartsWith("Axis"))
  318. {
  319. ++numAxes;
  320. ///\todo Axis emulation for screen joystick is not fully supported yet.
  321. LOGWARNING("Axis emulation for screen joystick is not fully supported yet");
  322. }
  323. else if (name.StartsWith("Hat"))
  324. {
  325. ++numHats;
  326. Text* text = dynamic_cast<Text*>(element->GetChild("KeyBinding", false));
  327. if (text)
  328. {
  329. text->SetVisible(false);
  330. String keyBinding = text->GetText();
  331. if (keyBinding.Contains(' ')) // e.g.: "UP DOWN LEFT RIGHT"
  332. {
  333. // Attempt to split the text using ' ' as separator
  334. Vector<String>keyBindings(keyBinding.Split(' '));
  335. String mappedKeyBinding;
  336. if (keyBindings.Size() == 4)
  337. {
  338. PopulateKeyBindingMap(keyBindingMap);
  339. for (unsigned j = 0; j < 4; ++j)
  340. {
  341. if (keyBindings[j].Length() == 1)
  342. mappedKeyBinding.Append(keyBindings[j][0]);
  343. else
  344. {
  345. HashMap<String, int>::Iterator i = keyBindingMap.Find(keyBindings[j]);
  346. if (i != keyBindingMap.End())
  347. mappedKeyBinding.Append(i->second_);
  348. else
  349. break;
  350. }
  351. }
  352. }
  353. if (mappedKeyBinding.Length() != 4)
  354. {
  355. LOGERRORF("%s has invalid key binding %s, fallback to WSAD", name.CString(), keyBinding.CString());
  356. keyBinding = "WSAD";
  357. }
  358. else
  359. keyBinding = mappedKeyBinding;
  360. }
  361. else if (keyBinding.Length() != 4)
  362. {
  363. LOGERRORF("%s has invalid key binding %s, fallback to WSAD", name.CString(), keyBinding.CString());
  364. keyBinding = "WSAD";
  365. }
  366. element->SetVar(VAR_BUTTON_KEY_BINDING, keyBinding);
  367. }
  368. }
  369. element->SetVar(VAR_SCREEN_JOYSTICK_INDEX, instanceID);
  370. }
  371. // Make sure all the children are non-focusable so they do not mistakenly to be considered as active UI input controls by application
  372. PODVector<UIElement*> allChildren;
  373. state.screenJoystick_->GetChildren(allChildren, true);
  374. for (PODVector<UIElement*>::Iterator iter = allChildren.Begin(); iter != allChildren.End(); ++iter)
  375. (*iter)->SetFocusMode(FM_NOTFOCUSABLE);
  376. state.buttons_.Resize(numButtons);
  377. state.buttonPress_.Resize(numButtons);
  378. state.axes_.Resize(numAxes);
  379. state.hats_.Resize(numHats);
  380. // There could be potentially more than one screen joystick, however they all will be handled by a same handler method
  381. // So there is no harm to replace the old handler with the new handler in each call to SubscribeToEvent()
  382. SubscribeToEvent(E_TOUCHBEGIN, HANDLER(Input, HandleScreenJoystickTouch));
  383. SubscribeToEvent(E_TOUCHMOVE, HANDLER(Input, HandleScreenJoystickTouch));
  384. SubscribeToEvent(E_TOUCHEND, HANDLER(Input, HandleScreenJoystickTouch));
  385. return instanceID;
  386. }
  387. bool Input::RemoveScreenJoystick(unsigned index)
  388. {
  389. if (index >= joysticks_.Size())
  390. {
  391. LOGERRORF("Joystick index #%d is out of bounds", index);
  392. return false;
  393. }
  394. JoystickState& state = joysticks_[index];
  395. if (!state.screenJoystick_)
  396. {
  397. LOGERRORF("Failed to remove joystick at index #%d which is not a screen joystick", index);
  398. return false;
  399. }
  400. state.screenJoystick_->Remove();
  401. joysticks_.Erase(index);
  402. return true;
  403. }
  404. void Input::SetScreenKeyboardVisible(bool enable)
  405. {
  406. if (!graphics_)
  407. return;
  408. if (enable != IsScreenKeyboardVisible())
  409. {
  410. if (enable)
  411. SDL_StartTextInput();
  412. else
  413. SDL_StopTextInput();
  414. }
  415. }
  416. bool Input::RecordGesture()
  417. {
  418. // If have no touch devices, fail
  419. if (!SDL_GetNumTouchDevices())
  420. {
  421. LOGERROR("Can not record gesture: no touch devices");
  422. return false;
  423. }
  424. return SDL_RecordGesture(-1);
  425. }
  426. bool Input::SaveGestures(Serializer& dest)
  427. {
  428. RWOpsWrapper<Serializer> wrapper(dest);
  429. return SDL_SaveAllDollarTemplates(wrapper.GetRWOps());
  430. }
  431. bool Input::SaveGesture(Serializer& dest, unsigned gestureID)
  432. {
  433. RWOpsWrapper<Serializer> wrapper(dest);
  434. return SDL_SaveDollarTemplate(gestureID, wrapper.GetRWOps());
  435. }
  436. unsigned Input::LoadGestures(Deserializer& source)
  437. {
  438. // If have no touch devices, fail
  439. if (!SDL_GetNumTouchDevices())
  440. {
  441. LOGERROR("Can not load gestures: no touch devices");
  442. return 0;
  443. }
  444. RWOpsWrapper<Deserializer> wrapper(source);
  445. return SDL_LoadDollarTemplates(-1, wrapper.GetRWOps());
  446. }
  447. SDL_JoystickID Input::OpenJoystick(unsigned index)
  448. {
  449. SDL_Joystick* joystick = SDL_JoystickOpen(index);
  450. if (!joystick)
  451. {
  452. LOGERRORF("Cannot open joystick #%d", index);
  453. return -1;
  454. }
  455. // Map SDL joystick index to internal index (which starts at 0)
  456. int sdl_joy_instance_id = SDL_JoystickInstanceID(joystick);
  457. JoystickState& state = joysticks_[sdl_joy_instance_id];
  458. state.joystick_ = joystick;
  459. if (SDL_IsGameController(index))
  460. state.controller_ = SDL_GameControllerOpen(index);
  461. state.buttons_.Resize(SDL_JoystickNumButtons(joystick));
  462. state.buttonPress_.Resize(state.buttons_.Size());
  463. state.axes_.Resize(SDL_JoystickNumAxes(joystick));
  464. state.hats_.Resize(SDL_JoystickNumHats(joystick));
  465. for (unsigned i = 0; i < state.buttons_.Size(); ++i)
  466. {
  467. state.buttons_[i] = false;
  468. state.buttonPress_[i] = false;
  469. }
  470. for (unsigned i = 0; i < state.axes_.Size(); ++i)
  471. state.axes_[i] = 0.0f;
  472. for (unsigned i = 0; i < state.hats_.Size(); ++i)
  473. state.hats_[i] = HAT_CENTER;
  474. return sdl_joy_instance_id;
  475. }
  476. int Input::GetKeyFromName(const String& name) const
  477. {
  478. return SDL_GetKeyFromName(name.CString());
  479. }
  480. int Input::GetKeyFromScancode(int scancode) const
  481. {
  482. return SDL_GetKeyFromScancode((SDL_Scancode)scancode);
  483. }
  484. String Input::GetKeyName(int key) const
  485. {
  486. return String(SDL_GetKeyName(key));
  487. }
  488. int Input::GetScancodeFromKey(int key) const
  489. {
  490. return SDL_GetScancodeFromKey(key);
  491. }
  492. int Input::GetScancodeFromName(const String& name) const
  493. {
  494. return SDL_GetScancodeFromName(name.CString());
  495. }
  496. String Input::GetScancodeName(int scancode) const
  497. {
  498. return SDL_GetScancodeName((SDL_Scancode)scancode);
  499. }
  500. bool Input::GetKeyDown(int key) const
  501. {
  502. return keyDown_.Contains(SDL_toupper(key));
  503. }
  504. bool Input::GetKeyPress(int key) const
  505. {
  506. return keyPress_.Contains(SDL_toupper(key));
  507. }
  508. bool Input::GetScancodeDown(int scancode) const
  509. {
  510. return scancodeDown_.Contains(scancode);
  511. }
  512. bool Input::GetScancodePress(int scancode) const
  513. {
  514. return scancodePress_.Contains(scancode);
  515. }
  516. bool Input::GetMouseButtonDown(int button) const
  517. {
  518. return (mouseButtonDown_ & button) != 0;
  519. }
  520. bool Input::GetMouseButtonPress(int button) const
  521. {
  522. return (mouseButtonPress_ & button) != 0;
  523. }
  524. bool Input::GetQualifierDown(int qualifier) const
  525. {
  526. if (qualifier == QUAL_SHIFT)
  527. return GetKeyDown(KEY_LSHIFT) || GetKeyDown(KEY_RSHIFT);
  528. if (qualifier == QUAL_CTRL)
  529. return GetKeyDown(KEY_LCTRL) || GetKeyDown(KEY_RCTRL);
  530. if (qualifier == QUAL_ALT)
  531. return GetKeyDown(KEY_LALT) || GetKeyDown(KEY_RALT);
  532. return false;
  533. }
  534. bool Input::GetQualifierPress(int qualifier) const
  535. {
  536. if (qualifier == QUAL_SHIFT)
  537. return GetKeyPress(KEY_LSHIFT) || GetKeyPress(KEY_RSHIFT);
  538. if (qualifier == QUAL_CTRL)
  539. return GetKeyPress(KEY_LCTRL) || GetKeyPress(KEY_RCTRL);
  540. if (qualifier == QUAL_ALT)
  541. return GetKeyPress(KEY_LALT) || GetKeyPress(KEY_RALT);
  542. return false;
  543. }
  544. int Input::GetQualifiers() const
  545. {
  546. int ret = 0;
  547. if (GetQualifierDown(QUAL_SHIFT))
  548. ret |= QUAL_SHIFT;
  549. if (GetQualifierDown(QUAL_CTRL))
  550. ret |= QUAL_CTRL;
  551. if (GetQualifierDown(QUAL_ALT))
  552. ret |= QUAL_ALT;
  553. return ret;
  554. }
  555. IntVector2 Input::GetMousePosition() const
  556. {
  557. IntVector2 ret = IntVector2::ZERO;
  558. if (!initialized_)
  559. return ret;
  560. SDL_GetMouseState(&ret.x_, &ret.y_);
  561. return ret;
  562. }
  563. TouchState* Input::GetTouch(unsigned index) const
  564. {
  565. if (index >= touches_.Size())
  566. return 0;
  567. HashMap<int, TouchState>::ConstIterator i = touches_.Begin();
  568. while (index--)
  569. ++i;
  570. return const_cast<TouchState*>(&i->second_);
  571. }
  572. const String& Input::GetJoystickName(SDL_JoystickID index) const
  573. {
  574. HashMap<SDL_JoystickID, JoystickState>::ConstIterator itr = joysticks_.Find(index);
  575. if(itr != joysticks_.End())
  576. return itr->second_.name_;
  577. else
  578. return String::EMPTY;
  579. }
  580. JoystickState* Input::GetJoystick(SDL_JoystickID index)
  581. {
  582. if (joysticks_.Contains(index))
  583. {
  584. JoystickState& state = joysticks_[index];
  585. // If necessary, automatically open the joystick first
  586. if ((!state.joystick_ && !state.screenJoystick_) || (state.screenJoystick_ && !state.screenJoystick_->IsVisible()))
  587. OpenJoystick(index);
  588. return const_cast<JoystickState*>(&state);
  589. }
  590. else
  591. return 0;
  592. }
  593. bool Input::GetScreenKeyboardSupport() const
  594. {
  595. return graphics_ ? SDL_HasScreenKeyboardSupport() : false;
  596. }
  597. bool Input::IsScreenKeyboardVisible() const
  598. {
  599. if (graphics_)
  600. {
  601. SDL_Window* window = graphics_->GetImpl()->GetWindow();
  602. return SDL_IsScreenKeyboardShown(window);
  603. }
  604. else
  605. return false;
  606. }
  607. bool Input::IsMinimized() const
  608. {
  609. // Return minimized state also when unfocused in fullscreen
  610. if (!inputFocus_ && graphics_ && graphics_->GetFullscreen())
  611. return true;
  612. else
  613. return minimized_;
  614. }
  615. void Input::Initialize()
  616. {
  617. Graphics* graphics = GetSubsystem<Graphics>();
  618. if (!graphics || !graphics->IsInitialized())
  619. return;
  620. graphics_ = graphics;
  621. // In external window mode only visible mouse is supported
  622. if (graphics_->GetExternalWindow())
  623. mouseVisible_ = true;
  624. // Set the initial activation
  625. focusedThisFrame_ = true;
  626. initialized_ = true;
  627. ResetJoysticks();
  628. ResetState();
  629. SubscribeToEvent(E_BEGINFRAME, HANDLER(Input, HandleBeginFrame));
  630. LOGINFO("Initialized input");
  631. }
  632. void Input::ResetJoysticks()
  633. {
  634. joysticks_.Clear();
  635. int size = SDL_NumJoysticks();
  636. for (unsigned i = 0; i < size; ++i)
  637. {
  638. OpenJoystick(i);
  639. }
  640. }
  641. void Input::GainFocus()
  642. {
  643. ResetState();
  644. inputFocus_ = true;
  645. focusedThisFrame_ = false;
  646. // Re-establish mouse cursor hiding as necessary
  647. if (!mouseVisible_)
  648. {
  649. SDL_ShowCursor(SDL_FALSE);
  650. suppressNextMouseMove_ = true;
  651. }
  652. else
  653. lastMousePosition_ = GetMousePosition();
  654. SendInputFocusEvent();
  655. }
  656. void Input::LoseFocus()
  657. {
  658. ResetState();
  659. inputFocus_ = false;
  660. focusedThisFrame_ = false;
  661. // Show the mouse cursor when inactive
  662. SDL_ShowCursor(SDL_TRUE);
  663. SendInputFocusEvent();
  664. }
  665. void Input::ResetState()
  666. {
  667. keyDown_.Clear();
  668. keyPress_.Clear();
  669. scancodeDown_.Clear();
  670. scancodePress_.Clear();
  671. /// \todo Check if this is necessary
  672. for (HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
  673. {
  674. for (unsigned j = 0; j < i->second_.buttons_.Size(); ++j)
  675. i->second_.buttons_[j] = false;
  676. for (unsigned j = 0; j < i->second_.hats_.Size(); ++j)
  677. i->second_.hats_[j] = HAT_CENTER;
  678. }
  679. // When clearing touch states, send the corresponding touch end events
  680. for (HashMap<int, TouchState>::Iterator i = touches_.Begin(); i != touches_.End(); ++i)
  681. {
  682. TouchState& state = i->second_;
  683. using namespace TouchEnd;
  684. VariantMap& eventData = GetEventDataMap();
  685. eventData[P_TOUCHID] = state.touchID_;
  686. eventData[P_X] = state.position_.x_;
  687. eventData[P_Y] = state.position_.y_;
  688. SendEvent(E_TOUCHEND, eventData);
  689. }
  690. // Use SetMouseButton() to reset the state so that mouse events will be sent properly
  691. SetMouseButton(MOUSEB_LEFT, false);
  692. SetMouseButton(MOUSEB_RIGHT, false);
  693. SetMouseButton(MOUSEB_MIDDLE, false);
  694. mouseMove_ = IntVector2::ZERO;
  695. mouseMoveWheel_ = 0;
  696. mouseButtonPress_ = 0;
  697. }
  698. void Input::SendInputFocusEvent()
  699. {
  700. using namespace InputFocus;
  701. VariantMap& eventData = GetEventDataMap();
  702. eventData[P_FOCUS] = HasFocus();
  703. eventData[P_MINIMIZED] = IsMinimized();
  704. SendEvent(E_INPUTFOCUS, eventData);
  705. }
  706. void Input::SetMouseButton(int button, bool newState)
  707. {
  708. #ifdef REQUIRE_CLICK_TO_FOCUS
  709. if (!mouseVisible_ && !graphics_->GetFullscreen())
  710. {
  711. if (!inputFocus_ && newState && button == MOUSEB_LEFT)
  712. focusedThisFrame_ = true;
  713. }
  714. #endif
  715. // If we do not have focus yet, do not react to the mouse button down
  716. if (!graphics_->GetExternalWindow() && newState && !inputFocus_)
  717. return;
  718. if (newState)
  719. {
  720. if (!(mouseButtonDown_ & button))
  721. mouseButtonPress_ |= button;
  722. mouseButtonDown_ |= button;
  723. }
  724. else
  725. {
  726. if (!(mouseButtonDown_ & button))
  727. return;
  728. mouseButtonDown_ &= ~button;
  729. }
  730. using namespace MouseButtonDown;
  731. VariantMap& eventData = GetEventDataMap();
  732. eventData[P_BUTTON] = button;
  733. eventData[P_BUTTONS] = mouseButtonDown_;
  734. eventData[P_QUALIFIERS] = GetQualifiers();
  735. SendEvent(newState ? E_MOUSEBUTTONDOWN : E_MOUSEBUTTONUP, eventData);
  736. }
  737. void Input::SetKey(int key, int scancode, unsigned raw, bool newState)
  738. {
  739. // If we do not have focus yet, do not react to the key down
  740. if (!graphics_->GetExternalWindow() && newState && !inputFocus_)
  741. return;
  742. bool repeat = false;
  743. if (newState)
  744. {
  745. scancodeDown_.Insert(scancode);
  746. scancodePress_.Insert(scancode);
  747. if (!keyDown_.Contains(key))
  748. {
  749. keyDown_.Insert(key);
  750. keyPress_.Insert(key);
  751. }
  752. else
  753. repeat = true;
  754. }
  755. else
  756. {
  757. scancodeDown_.Erase(scancode);
  758. if (!keyDown_.Erase(key))
  759. return;
  760. }
  761. using namespace KeyDown;
  762. VariantMap& eventData = GetEventDataMap();
  763. eventData[P_KEY] = key;
  764. eventData[P_SCANCODE] = scancode;
  765. eventData[P_RAW] = raw;
  766. eventData[P_BUTTONS] = mouseButtonDown_;
  767. eventData[P_QUALIFIERS] = GetQualifiers();
  768. if (newState)
  769. eventData[P_REPEAT] = repeat;
  770. SendEvent(newState ? E_KEYDOWN : E_KEYUP, eventData);
  771. if ((key == KEY_RETURN || key == KEY_RETURN2 || key == KEY_KP_ENTER) && newState && !repeat && toggleFullscreen_ &&
  772. (GetKeyDown(KEY_LALT) || GetKeyDown(KEY_RALT)))
  773. graphics_->ToggleFullscreen();
  774. }
  775. void Input::SetMouseWheel(int delta)
  776. {
  777. // If we do not have focus yet, do not react to the wheel
  778. if (!graphics_->GetExternalWindow() && !inputFocus_)
  779. return;
  780. if (delta)
  781. {
  782. mouseMoveWheel_ += delta;
  783. using namespace MouseWheel;
  784. VariantMap& eventData = GetEventDataMap();
  785. eventData[P_WHEEL] = delta;
  786. eventData[P_BUTTONS] = mouseButtonDown_;
  787. eventData[P_QUALIFIERS] = GetQualifiers();
  788. SendEvent(E_MOUSEWHEEL, eventData);
  789. }
  790. }
  791. void Input::SetMousePosition(const IntVector2& position)
  792. {
  793. if (!graphics_)
  794. return;
  795. SDL_WarpMouseInWindow(graphics_->GetImpl()->GetWindow(), position.x_, position.y_);
  796. }
  797. void Input::HandleSDLEvent(void* sdlEvent)
  798. {
  799. SDL_Event& evt = *static_cast<SDL_Event*>(sdlEvent);
  800. switch (evt.type)
  801. {
  802. case SDL_KEYDOWN:
  803. // Convert to uppercase to match Win32 virtual key codes
  804. SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, evt.key.keysym.raw, true);
  805. break;
  806. case SDL_KEYUP:
  807. SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, evt.key.keysym.raw, false);
  808. break;
  809. case SDL_TEXTINPUT:
  810. {
  811. textInput_ = &evt.text.text[0];
  812. unsigned unicode = textInput_.AtUTF8(0);
  813. if (unicode)
  814. {
  815. using namespace TextInput;
  816. VariantMap textInputEventData;
  817. textInputEventData[P_TEXT] = textInput_;
  818. textInputEventData[P_BUTTONS] = mouseButtonDown_;
  819. textInputEventData[P_QUALIFIERS] = GetQualifiers();
  820. SendEvent(E_TEXTINPUT, textInputEventData);
  821. }
  822. }
  823. break;
  824. case SDL_MOUSEBUTTONDOWN:
  825. SetMouseButton(1 << (evt.button.button - 1), true);
  826. break;
  827. case SDL_MOUSEBUTTONUP:
  828. SetMouseButton(1 << (evt.button.button - 1), false);
  829. break;
  830. case SDL_MOUSEMOTION:
  831. if (mouseVisible_)
  832. {
  833. mouseMove_.x_ += evt.motion.xrel;
  834. mouseMove_.y_ += evt.motion.yrel;
  835. using namespace MouseMove;
  836. VariantMap& eventData = GetEventDataMap();
  837. if (mouseVisible_)
  838. {
  839. eventData[P_X] = evt.motion.x;
  840. eventData[P_Y] = evt.motion.y;
  841. }
  842. eventData[P_DX] = evt.motion.xrel;
  843. eventData[P_DY] = evt.motion.yrel;
  844. eventData[P_BUTTONS] = mouseButtonDown_;
  845. eventData[P_QUALIFIERS] = GetQualifiers();
  846. SendEvent(E_MOUSEMOVE, eventData);
  847. }
  848. break;
  849. case SDL_MOUSEWHEEL:
  850. SetMouseWheel(evt.wheel.y);
  851. break;
  852. case SDL_FINGERDOWN:
  853. if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
  854. {
  855. int touchID = evt.tfinger.fingerId & 0x7ffffff;
  856. TouchState& state = touches_[touchID];
  857. state.touchID_ = touchID;
  858. state.lastPosition_ = state.position_ = IntVector2((int)(evt.tfinger.x * graphics_->GetWidth()),
  859. (int)(evt.tfinger.y * graphics_->GetHeight()));
  860. state.delta_ = IntVector2::ZERO;
  861. state.pressure_ = evt.tfinger.pressure;
  862. using namespace TouchBegin;
  863. VariantMap& eventData = GetEventDataMap();
  864. eventData[P_TOUCHID] = touchID;
  865. eventData[P_X] = state.position_.x_;
  866. eventData[P_Y] = state.position_.y_;
  867. eventData[P_PRESSURE] = state.pressure_;
  868. SendEvent(E_TOUCHBEGIN, eventData);
  869. }
  870. break;
  871. case SDL_FINGERUP:
  872. if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
  873. {
  874. int touchID = evt.tfinger.fingerId & 0x7ffffff;
  875. TouchState& state = touches_[touchID];
  876. using namespace TouchEnd;
  877. VariantMap& eventData = GetEventDataMap();
  878. // Do not trust the position in the finger up event. Instead use the last position stored in the
  879. // touch structure
  880. eventData[P_TOUCHID] = touchID;
  881. eventData[P_X] = state.position_.x_;
  882. eventData[P_Y] = state.position_.y_;
  883. SendEvent(E_TOUCHEND, eventData);
  884. touches_.Erase(touchID);
  885. }
  886. break;
  887. case SDL_FINGERMOTION:
  888. if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
  889. {
  890. int touchID = evt.tfinger.fingerId & 0x7ffffff;
  891. TouchState& state = touches_[touchID];
  892. state.touchID_ = touchID;
  893. state.position_ = IntVector2((int)(evt.tfinger.x * graphics_->GetWidth()),
  894. (int)(evt.tfinger.y * graphics_->GetHeight()));
  895. state.delta_ = state.position_ - state.lastPosition_;
  896. state.pressure_ = evt.tfinger.pressure;
  897. using namespace TouchMove;
  898. VariantMap& eventData = GetEventDataMap();
  899. eventData[P_TOUCHID] = touchID;
  900. eventData[P_X] = state.position_.x_;
  901. eventData[P_Y] = state.position_.y_;
  902. eventData[P_DX] = (int)(evt.tfinger.dx * graphics_->GetWidth());
  903. eventData[P_DY] = (int)(evt.tfinger.dy * graphics_->GetHeight());
  904. eventData[P_PRESSURE] = state.pressure_;
  905. SendEvent(E_TOUCHMOVE, eventData);
  906. }
  907. break;
  908. case SDL_DOLLARRECORD:
  909. {
  910. using namespace GestureRecorded;
  911. VariantMap& eventData = GetEventDataMap();
  912. eventData[P_GESTUREID] = (int)evt.dgesture.gestureId;
  913. SendEvent(E_GESTURERECORDED, eventData);
  914. }
  915. break;
  916. case SDL_DOLLARGESTURE:
  917. {
  918. using namespace GestureInput;
  919. VariantMap& eventData = GetEventDataMap();
  920. eventData[P_GESTUREID] = (int)evt.dgesture.gestureId;
  921. eventData[P_CENTERX] = (int)(evt.dgesture.x * graphics_->GetWidth());
  922. eventData[P_CENTERY] = (int)(evt.dgesture.y * graphics_->GetHeight());
  923. eventData[P_NUMFINGERS] = (int)evt.dgesture.numFingers;
  924. eventData[P_ERROR] = evt.dgesture.error;
  925. SendEvent(E_GESTUREINPUT, eventData);
  926. }
  927. break;
  928. case SDL_MULTIGESTURE:
  929. {
  930. using namespace MultiGesture;
  931. VariantMap& eventData = GetEventDataMap();
  932. eventData[P_CENTERX] = (int)(evt.mgesture.x * graphics_->GetWidth());
  933. eventData[P_CENTERY] = (int)(evt.mgesture.y * graphics_->GetHeight());
  934. eventData[P_NUMFINGERS] = (int)evt.mgesture.numFingers;
  935. eventData[P_DTHETA] = M_RADTODEG * evt.mgesture.dTheta;
  936. eventData[P_DDIST] = evt.mgesture.dDist;
  937. SendEvent(E_MULTIGESTURE, eventData);
  938. }
  939. break;
  940. case SDL_JOYDEVICEADDED:
  941. {
  942. using namespace JoystickConnected;
  943. SDL_JoystickID joyID = OpenJoystick(evt.jdevice.which);
  944. VariantMap& eventData = GetEventDataMap();
  945. eventData[P_JOYSTICK] = joyID;
  946. SendEvent(E_JOYSTICKCONNECTED, eventData);
  947. }
  948. break;
  949. case SDL_JOYDEVICEREMOVED:
  950. {
  951. using namespace JoystickDisconnected;
  952. joysticks_.Erase(evt.jdevice.which);
  953. VariantMap& eventData = GetEventDataMap();
  954. eventData[P_JOYSTICK] = evt.jdevice.which;
  955. SendEvent(E_JOYSTICKDISCONNECTED, eventData);
  956. }
  957. break;
  958. case SDL_JOYBUTTONDOWN:
  959. {
  960. using namespace JoystickButtonDown;
  961. unsigned button = evt.jbutton.button;
  962. SDL_JoystickID joystickIndex = evt.jbutton.which;
  963. VariantMap& eventData = GetEventDataMap();
  964. eventData[P_JOYSTICK] = joystickIndex;
  965. eventData[P_BUTTON] = button;
  966. if (button < joysticks_[joystickIndex].buttons_.Size()) {
  967. joysticks_[joystickIndex].buttons_[button] = true;
  968. joysticks_[joystickIndex].buttonPress_[button] = true;
  969. SendEvent(E_JOYSTICKBUTTONDOWN, eventData);
  970. }
  971. }
  972. break;
  973. case SDL_JOYBUTTONUP:
  974. {
  975. using namespace JoystickButtonUp;
  976. unsigned button = evt.jbutton.button;
  977. SDL_JoystickID joystickIndex = evt.jbutton.which;
  978. VariantMap& eventData = GetEventDataMap();
  979. eventData[P_JOYSTICK] = joystickIndex;
  980. eventData[P_BUTTON] = button;
  981. if (button < joysticks_[joystickIndex].buttons_.Size()) {
  982. joysticks_[joystickIndex].buttons_[button] = false;
  983. SendEvent(E_JOYSTICKBUTTONUP, eventData);
  984. }
  985. }
  986. break;
  987. case SDL_JOYAXISMOTION:
  988. {
  989. using namespace JoystickAxisMove;
  990. SDL_JoystickID joystickIndex = evt.jaxis.which;
  991. VariantMap& eventData = GetEventDataMap();
  992. eventData[P_JOYSTICK] = joystickIndex;
  993. eventData[P_AXIS] = evt.jaxis.axis;
  994. eventData[P_POSITION] = Clamp((float)evt.jaxis.value / 32767.0f, -1.0f, 1.0f);
  995. if (evt.jaxis.axis < joysticks_[joystickIndex].axes_.Size())
  996. {
  997. joysticks_[joystickIndex].axes_[evt.jaxis.axis] = eventData[P_POSITION].GetFloat();
  998. SendEvent(E_JOYSTICKAXISMOVE, eventData);
  999. }
  1000. }
  1001. break;
  1002. case SDL_JOYHATMOTION:
  1003. {
  1004. using namespace JoystickHatMove;
  1005. SDL_JoystickID joystickIndex = evt.jaxis.which;
  1006. VariantMap& eventData = GetEventDataMap();
  1007. eventData[P_JOYSTICK] = joystickIndex;
  1008. eventData[P_HAT] = evt.jhat.hat;
  1009. eventData[P_POSITION] = evt.jhat.value;
  1010. if (evt.jhat.hat < joysticks_[joystickIndex].hats_.Size())
  1011. {
  1012. joysticks_[joystickIndex].hats_[evt.jhat.hat] = evt.jhat.value;
  1013. SendEvent(E_JOYSTICKHATMOVE, eventData);
  1014. }
  1015. }
  1016. break;
  1017. case SDL_CONTROLLERBUTTONDOWN:
  1018. {
  1019. using namespace ControllerButtonDown;
  1020. unsigned button = evt.cbutton.button;
  1021. SDL_JoystickID joystickIndex = evt.cbutton.which;
  1022. VariantMap& eventData = GetEventDataMap();
  1023. eventData[P_JOYSTICK] = joystickIndex;
  1024. eventData[P_BUTTON] = button;
  1025. if (button < joysticks_[joystickIndex].buttons_.Size()) {
  1026. joysticks_[joystickIndex].buttons_[button] = true;
  1027. joysticks_[joystickIndex].buttonPress_[button] = true;
  1028. SendEvent(E_CONTROLLERBUTTONDOWN, eventData);
  1029. }
  1030. }
  1031. break;
  1032. case SDL_CONTROLLERBUTTONUP:
  1033. {
  1034. using namespace ControllerButtonUp;
  1035. unsigned button = evt.cbutton.button;
  1036. SDL_JoystickID joystickIndex = evt.cbutton.which;
  1037. VariantMap& eventData = GetEventDataMap();
  1038. eventData[P_JOYSTICK] = joystickIndex;
  1039. eventData[P_BUTTON] = button;
  1040. if (button < joysticks_[joystickIndex].buttons_.Size()) {
  1041. joysticks_[joystickIndex].buttons_[button] = false;
  1042. SendEvent(E_CONTROLLERBUTTONUP, eventData);
  1043. }
  1044. }
  1045. break;
  1046. case SDL_CONTROLLERAXISMOTION:
  1047. {
  1048. using namespace ControllerAxisMove;
  1049. SDL_JoystickID joystickIndex = evt.caxis.which;
  1050. VariantMap& eventData = GetEventDataMap();
  1051. eventData[P_JOYSTICK] = joystickIndex;
  1052. eventData[P_AXIS] = evt.caxis.axis;
  1053. eventData[P_POSITION] = Clamp((float)evt.caxis.value / 32767.0f, -1.0f, 1.0f);
  1054. if (evt.caxis.axis < joysticks_[joystickIndex].axes_.Size())
  1055. {
  1056. joysticks_[joystickIndex].axes_[evt.caxis.axis] = eventData[P_POSITION].GetFloat();
  1057. SendEvent(E_CONTROLLERAXISMOVE, eventData);
  1058. }
  1059. }
  1060. break;
  1061. case SDL_WINDOWEVENT:
  1062. {
  1063. switch (evt.window.event)
  1064. {
  1065. case SDL_WINDOWEVENT_MINIMIZED:
  1066. minimized_ = true;
  1067. SendInputFocusEvent();
  1068. break;
  1069. case SDL_WINDOWEVENT_MAXIMIZED:
  1070. case SDL_WINDOWEVENT_RESTORED:
  1071. minimized_ = false;
  1072. SendInputFocusEvent();
  1073. #ifdef IOS
  1074. // On iOS we never lose the GL context, but may have done GPU object changes that could not be applied yet.
  1075. // Apply them now
  1076. graphics_->Restore();
  1077. #endif
  1078. break;
  1079. #ifdef ANDROID
  1080. case SDL_WINDOWEVENT_FOCUS_GAINED:
  1081. // Restore GPU objects to the new GL context
  1082. graphics_->Restore();
  1083. break;
  1084. #endif
  1085. case SDL_WINDOWEVENT_RESIZED:
  1086. graphics_->WindowResized();
  1087. break;
  1088. }
  1089. }
  1090. break;
  1091. case SDL_DROPFILE:
  1092. {
  1093. using namespace DropFile;
  1094. VariantMap& eventData = GetEventDataMap();
  1095. eventData[P_FILENAME] = GetInternalPath(String(evt.drop.file));
  1096. SDL_free(evt.drop.file);
  1097. SendEvent(E_DROPFILE, eventData);
  1098. }
  1099. break;
  1100. case SDL_QUIT:
  1101. SendEvent(E_EXITREQUESTED);
  1102. break;
  1103. }
  1104. }
  1105. void Input::HandleScreenMode(StringHash eventType, VariantMap& eventData)
  1106. {
  1107. // Reset input state on subsequent initializations
  1108. if (!initialized_)
  1109. Initialize();
  1110. else
  1111. ResetState();
  1112. // Re-enable cursor clipping, and re-center the cursor (if needed) to the new screen size, so that there is no erroneous
  1113. // mouse move event. Also get new window ID if it changed
  1114. SDL_Window* window = graphics_->GetImpl()->GetWindow();
  1115. windowID_ = SDL_GetWindowID(window);
  1116. if (!mouseVisible_)
  1117. {
  1118. IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
  1119. SetMousePosition(center);
  1120. lastMousePosition_ = center;
  1121. }
  1122. focusedThisFrame_ = true;
  1123. // After setting a new screen mode we should not be minimized
  1124. minimized_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) != 0;
  1125. }
  1126. void Input::HandleBeginFrame(StringHash eventType, VariantMap& eventData)
  1127. {
  1128. // Update input right at the beginning of the frame
  1129. Update();
  1130. }
  1131. void Input::HandleScreenJoystickTouch(StringHash eventType, VariantMap& eventData)
  1132. {
  1133. using namespace TouchBegin;
  1134. // Only interested in events from screen joystick(s)
  1135. TouchState& state = touches_[eventData[P_TOUCHID].GetInt()];
  1136. IntVector2 position(state.position_.x_, state.position_.y_);
  1137. UIElement* element = eventType == E_TOUCHBEGIN ? GetSubsystem<UI>()->GetElementAt(position) : state.touchedElement_;
  1138. if (!element)
  1139. return;
  1140. Variant variant = element->GetVar(VAR_SCREEN_JOYSTICK_INDEX);
  1141. if (variant.IsEmpty())
  1142. return;
  1143. unsigned index = variant.GetUInt();
  1144. if (eventType == E_TOUCHEND)
  1145. state.touchedElement_.Reset();
  1146. else
  1147. state.touchedElement_ = element;
  1148. // Prepare a fake SDL event
  1149. SDL_Event evt;
  1150. const String& name = element->GetName();
  1151. if (name.StartsWith("Button"))
  1152. {
  1153. if (eventType == E_TOUCHMOVE)
  1154. return;
  1155. // Determine whether to inject a joystick event or keyboard event
  1156. Variant variant = element->GetVar(VAR_BUTTON_KEY_BINDING);
  1157. if (variant.IsEmpty())
  1158. {
  1159. evt.type = eventType == E_TOUCHBEGIN ? SDL_JOYBUTTONDOWN : SDL_JOYBUTTONUP;
  1160. evt.jbutton.which = SCREEN_JOYSTICK_START_INDEX + index;
  1161. evt.jbutton.button = ToUInt(name.Substring(6));
  1162. }
  1163. else
  1164. {
  1165. evt.type = eventType == E_TOUCHBEGIN ? SDL_KEYDOWN : SDL_KEYUP;
  1166. evt.key.keysym.sym = variant.GetInt();
  1167. evt.key.keysym.scancode = SDL_SCANCODE_UNKNOWN;
  1168. }
  1169. }
  1170. else if (name.StartsWith("Hat"))
  1171. {
  1172. Variant variant = element->GetVar(VAR_BUTTON_KEY_BINDING);
  1173. if (variant.IsEmpty())
  1174. {
  1175. evt.type = SDL_JOYHATMOTION;
  1176. evt.jaxis.which = SCREEN_JOYSTICK_START_INDEX + index;
  1177. evt.jhat.hat = ToUInt(name.Substring(3));
  1178. evt.jhat.value = HAT_CENTER;
  1179. if (eventType != E_TOUCHEND)
  1180. {
  1181. IntVector2 relPosition = position - element->GetScreenPosition() - element->GetSize() / 2;
  1182. if (relPosition.y_ < 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  1183. evt.jhat.value |= HAT_UP;
  1184. if (relPosition.y_ > 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  1185. evt.jhat.value |= HAT_DOWN;
  1186. if (relPosition.x_ < 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  1187. evt.jhat.value |= HAT_LEFT;
  1188. if (relPosition.x_ > 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  1189. evt.jhat.value |= HAT_RIGHT;
  1190. }
  1191. }
  1192. else
  1193. {
  1194. // Hat is binded by 4 keys, like 'WASD'
  1195. String keyBinding = variant.GetString();
  1196. if (eventType == E_TOUCHEND)
  1197. {
  1198. evt.type = SDL_KEYUP;
  1199. evt.key.keysym.sym = element->GetVar(VAR_LAST_KEYSYM).GetInt();
  1200. if (!evt.key.keysym.sym)
  1201. return;
  1202. element->SetVar(VAR_LAST_KEYSYM, 0);
  1203. }
  1204. else
  1205. {
  1206. evt.type = SDL_KEYDOWN;
  1207. IntVector2 relPosition = position - element->GetScreenPosition() - element->GetSize() / 2;
  1208. if (relPosition.y_ < 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  1209. evt.key.keysym.sym = keyBinding[0];
  1210. else if (relPosition.y_ > 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  1211. evt.key.keysym.sym = keyBinding[1];
  1212. else if (relPosition.x_ < 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  1213. evt.key.keysym.sym = keyBinding[2];
  1214. else if (relPosition.x_ > 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  1215. evt.key.keysym.sym = keyBinding[3];
  1216. else
  1217. return;
  1218. if (eventType == E_TOUCHMOVE && evt.key.keysym.sym != element->GetVar(VAR_LAST_KEYSYM).GetInt())
  1219. {
  1220. // Dragging past the directional boundary will cause an additional key up event for previous key symbol
  1221. SDL_Event evt;
  1222. evt.type = SDL_KEYUP;
  1223. evt.key.keysym.sym = element->GetVar(VAR_LAST_KEYSYM).GetInt();
  1224. if (evt.key.keysym.sym)
  1225. {
  1226. evt.key.keysym.scancode = SDL_SCANCODE_UNKNOWN;
  1227. HandleSDLEvent(&evt);
  1228. }
  1229. element->SetVar(VAR_LAST_KEYSYM, 0);
  1230. }
  1231. evt.key.keysym.scancode = SDL_SCANCODE_UNKNOWN;
  1232. element->SetVar(VAR_LAST_KEYSYM, evt.key.keysym.sym);
  1233. }
  1234. }
  1235. }
  1236. else
  1237. return;
  1238. // Handle the fake SDL event to turn it into Urho3D genuine event
  1239. HandleSDLEvent(&evt);
  1240. }
  1241. }