Input.cpp 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518
  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_ID = 0x40000000;
  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_ID("VAR_SCREEN_JOYSTICK_ID");
  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::SetToggleFullscreen(bool enable)
  206. {
  207. toggleFullscreen_ = enable;
  208. }
  209. static void PopulateKeyBindingMap(HashMap<String, int>& keyBindingMap)
  210. {
  211. if (keyBindingMap.Empty())
  212. {
  213. keyBindingMap.Insert(MakePair<String, int>("SPACE", KEY_SPACE));
  214. keyBindingMap.Insert(MakePair<String, int>("LCTRL", KEY_LCTRL));
  215. keyBindingMap.Insert(MakePair<String, int>("RCTRL", KEY_RCTRL));
  216. keyBindingMap.Insert(MakePair<String, int>("LSHIFT", KEY_LSHIFT));
  217. keyBindingMap.Insert(MakePair<String, int>("RSHIFT", KEY_RSHIFT));
  218. keyBindingMap.Insert(MakePair<String, int>("LALT", KEY_LALT));
  219. keyBindingMap.Insert(MakePair<String, int>("RALT", KEY_RALT));
  220. keyBindingMap.Insert(MakePair<String, int>("LGUI", KEY_LGUI));
  221. keyBindingMap.Insert(MakePair<String, int>("RGUI", KEY_RGUI));
  222. keyBindingMap.Insert(MakePair<String, int>("TAB", KEY_TAB));
  223. keyBindingMap.Insert(MakePair<String, int>("RETURN", KEY_RETURN));
  224. keyBindingMap.Insert(MakePair<String, int>("RETURN2", KEY_RETURN2));
  225. keyBindingMap.Insert(MakePair<String, int>("ENTER", KEY_KP_ENTER));
  226. keyBindingMap.Insert(MakePair<String, int>("SELECT", KEY_SELECT));
  227. keyBindingMap.Insert(MakePair<String, int>("LEFT", KEY_LEFT));
  228. keyBindingMap.Insert(MakePair<String, int>("RIGHT", KEY_RIGHT));
  229. keyBindingMap.Insert(MakePair<String, int>("UP", KEY_UP));
  230. keyBindingMap.Insert(MakePair<String, int>("DOWN", KEY_DOWN));
  231. keyBindingMap.Insert(MakePair<String, int>("F1", KEY_F1));
  232. keyBindingMap.Insert(MakePair<String, int>("F2", KEY_F2));
  233. keyBindingMap.Insert(MakePair<String, int>("F3", KEY_F3));
  234. keyBindingMap.Insert(MakePair<String, int>("F4", KEY_F4));
  235. keyBindingMap.Insert(MakePair<String, int>("F5", KEY_F5));
  236. keyBindingMap.Insert(MakePair<String, int>("F6", KEY_F6));
  237. keyBindingMap.Insert(MakePair<String, int>("F7", KEY_F7));
  238. keyBindingMap.Insert(MakePair<String, int>("F8", KEY_F8));
  239. keyBindingMap.Insert(MakePair<String, int>("F9", KEY_F9));
  240. keyBindingMap.Insert(MakePair<String, int>("F10", KEY_F10));
  241. keyBindingMap.Insert(MakePair<String, int>("F11", KEY_F11));
  242. keyBindingMap.Insert(MakePair<String, int>("F12", KEY_F12));
  243. }
  244. }
  245. SDL_JoystickID Input::AddScreenJoystick(XMLFile* layoutFile, XMLFile* styleFile)
  246. {
  247. static HashMap<String, int> keyBindingMap;
  248. if (!graphics_)
  249. {
  250. LOGWARNING("Cannot add screen joystick in headless mode");
  251. return -1;
  252. }
  253. // If layout file is not given, use the default screen joystick layout
  254. if (!layoutFile)
  255. {
  256. ResourceCache* cache = GetSubsystem<ResourceCache>();
  257. layoutFile = cache->GetResource<XMLFile>("UI/ScreenJoystick.xml");
  258. if (!layoutFile) // Error is already logged
  259. return -1;
  260. }
  261. UI* ui = GetSubsystem<UI>();
  262. SharedPtr<UIElement> screenJoystick = ui->LoadLayout(layoutFile, styleFile);
  263. if (!screenJoystick) // Error is already logged
  264. return -1;
  265. screenJoystick->SetSize(ui->GetRoot()->GetSize());
  266. ui->GetRoot()->AddChild(screenJoystick);
  267. // Get an unused ID for the screen joystick
  268. /// \todo After a real joystick has been plugged in 1073741824 times, the ranges will overlap
  269. SDL_JoystickID joystickID = SCREEN_JOYSTICK_START_ID;
  270. while (joysticks_.Contains(joystickID))
  271. ++joystickID;
  272. JoystickState& state = joysticks_[joystickID];
  273. state.joystickID_ = joystickID;
  274. state.name_ = screenJoystick->GetName();
  275. state.screenJoystick_ = screenJoystick;
  276. unsigned numButtons = 0;
  277. unsigned numAxes = 0;
  278. unsigned numHats = 0;
  279. const Vector<SharedPtr<UIElement> >& children = state.screenJoystick_->GetChildren();
  280. for (Vector<SharedPtr<UIElement> >::ConstIterator iter = children.Begin(); iter != children.End(); ++iter)
  281. {
  282. UIElement* element = iter->Get();
  283. String name = element->GetName();
  284. if (name.StartsWith("Button"))
  285. {
  286. ++numButtons;
  287. // Check whether the button has key binding
  288. Text* text = dynamic_cast<Text*>(element->GetChild("KeyBinding", false));
  289. if (text)
  290. {
  291. text->SetVisible(false);
  292. const String& key = text->GetText();
  293. int keyBinding;
  294. if (key.Length() == 1)
  295. keyBinding = key[0];
  296. else
  297. {
  298. PopulateKeyBindingMap(keyBindingMap);
  299. HashMap<String, int>::Iterator i = keyBindingMap.Find(key);
  300. if (i != keyBindingMap.End())
  301. keyBinding = i->second_;
  302. else
  303. {
  304. LOGERRORF("Unsupported key binding: %s", key.CString());
  305. keyBinding = M_MAX_INT;
  306. }
  307. }
  308. if (keyBinding != M_MAX_INT)
  309. element->SetVar(VAR_BUTTON_KEY_BINDING, keyBinding);
  310. }
  311. }
  312. else if (name.StartsWith("Axis"))
  313. {
  314. ++numAxes;
  315. ///\todo Axis emulation for screen joystick is not fully supported yet.
  316. LOGWARNING("Axis emulation for screen joystick is not fully supported yet");
  317. }
  318. else if (name.StartsWith("Hat"))
  319. {
  320. ++numHats;
  321. Text* text = dynamic_cast<Text*>(element->GetChild("KeyBinding", false));
  322. if (text)
  323. {
  324. text->SetVisible(false);
  325. String keyBinding = text->GetText();
  326. if (keyBinding.Contains(' ')) // e.g.: "UP DOWN LEFT RIGHT"
  327. {
  328. // Attempt to split the text using ' ' as separator
  329. Vector<String>keyBindings(keyBinding.Split(' '));
  330. String mappedKeyBinding;
  331. if (keyBindings.Size() == 4)
  332. {
  333. PopulateKeyBindingMap(keyBindingMap);
  334. for (unsigned j = 0; j < 4; ++j)
  335. {
  336. if (keyBindings[j].Length() == 1)
  337. mappedKeyBinding.Append(keyBindings[j][0]);
  338. else
  339. {
  340. HashMap<String, int>::Iterator i = keyBindingMap.Find(keyBindings[j]);
  341. if (i != keyBindingMap.End())
  342. mappedKeyBinding.Append(i->second_);
  343. else
  344. break;
  345. }
  346. }
  347. }
  348. if (mappedKeyBinding.Length() != 4)
  349. {
  350. LOGERRORF("%s has invalid key binding %s, fallback to WSAD", name.CString(), keyBinding.CString());
  351. keyBinding = "WSAD";
  352. }
  353. else
  354. keyBinding = mappedKeyBinding;
  355. }
  356. else if (keyBinding.Length() != 4)
  357. {
  358. LOGERRORF("%s has invalid key binding %s, fallback to WSAD", name.CString(), keyBinding.CString());
  359. keyBinding = "WSAD";
  360. }
  361. element->SetVar(VAR_BUTTON_KEY_BINDING, keyBinding);
  362. }
  363. }
  364. element->SetVar(VAR_SCREEN_JOYSTICK_ID, joystickID);
  365. }
  366. // Make sure all the children are non-focusable so they do not mistakenly to be considered as active UI input controls by application
  367. PODVector<UIElement*> allChildren;
  368. state.screenJoystick_->GetChildren(allChildren, true);
  369. for (PODVector<UIElement*>::Iterator iter = allChildren.Begin(); iter != allChildren.End(); ++iter)
  370. (*iter)->SetFocusMode(FM_NOTFOCUSABLE);
  371. state.buttons_.Resize(numButtons);
  372. state.buttonPress_.Resize(numButtons);
  373. state.axes_.Resize(numAxes);
  374. state.hats_.Resize(numHats);
  375. // There could be potentially more than one screen joystick, however they all will be handled by a same handler method
  376. // So there is no harm to replace the old handler with the new handler in each call to SubscribeToEvent()
  377. SubscribeToEvent(E_TOUCHBEGIN, HANDLER(Input, HandleScreenJoystickTouch));
  378. SubscribeToEvent(E_TOUCHMOVE, HANDLER(Input, HandleScreenJoystickTouch));
  379. SubscribeToEvent(E_TOUCHEND, HANDLER(Input, HandleScreenJoystickTouch));
  380. return joystickID;
  381. }
  382. bool Input::RemoveScreenJoystick(SDL_JoystickID id)
  383. {
  384. if (!joysticks_.Contains(id))
  385. {
  386. LOGERRORF("Failed to remove non-existing screen joystick ID #%d", id);
  387. return false;
  388. }
  389. JoystickState& state = joysticks_[id];
  390. if (!state.screenJoystick_)
  391. {
  392. LOGERRORF("Failed to remove joystick with ID #%d which is not a screen joystick", id);
  393. return false;
  394. }
  395. state.screenJoystick_->Remove();
  396. joysticks_.Erase(id);
  397. return true;
  398. }
  399. void Input::SetScreenJoystickVisible(SDL_JoystickID id, bool enable)
  400. {
  401. if (joysticks_.Contains(id))
  402. {
  403. JoystickState& state = joysticks_[id];
  404. if (state.screenJoystick_)
  405. state.screenJoystick_->SetVisible(enable);
  406. }
  407. }
  408. void Input::SetScreenKeyboardVisible(bool enable)
  409. {
  410. if (!graphics_)
  411. return;
  412. if (enable != IsScreenKeyboardVisible())
  413. {
  414. if (enable)
  415. SDL_StartTextInput();
  416. else
  417. SDL_StopTextInput();
  418. }
  419. }
  420. bool Input::RecordGesture()
  421. {
  422. // If have no touch devices, fail
  423. if (!SDL_GetNumTouchDevices())
  424. {
  425. LOGERROR("Can not record gesture: no touch devices");
  426. return false;
  427. }
  428. return SDL_RecordGesture(-1);
  429. }
  430. bool Input::SaveGestures(Serializer& dest)
  431. {
  432. RWOpsWrapper<Serializer> wrapper(dest);
  433. return SDL_SaveAllDollarTemplates(wrapper.GetRWOps());
  434. }
  435. bool Input::SaveGesture(Serializer& dest, unsigned gestureID)
  436. {
  437. RWOpsWrapper<Serializer> wrapper(dest);
  438. return SDL_SaveDollarTemplate(gestureID, wrapper.GetRWOps());
  439. }
  440. unsigned Input::LoadGestures(Deserializer& source)
  441. {
  442. // If have no touch devices, fail
  443. if (!SDL_GetNumTouchDevices())
  444. {
  445. LOGERROR("Can not load gestures: no touch devices");
  446. return 0;
  447. }
  448. RWOpsWrapper<Deserializer> wrapper(source);
  449. return SDL_LoadDollarTemplates(-1, wrapper.GetRWOps());
  450. }
  451. SDL_JoystickID Input::OpenJoystick(unsigned index)
  452. {
  453. SDL_Joystick* joystick = SDL_JoystickOpen(index);
  454. if (!joystick)
  455. {
  456. LOGERRORF("Cannot open joystick #%d", index);
  457. return -1;
  458. }
  459. // Create joystick state for the new joystick
  460. int joystickID = SDL_JoystickInstanceID(joystick);
  461. JoystickState& state = joysticks_[joystickID];
  462. state.joystick_ = joystick;
  463. state.joystickID_ = joystickID;
  464. state.name_ = SDL_JoystickName(joystick);
  465. if (SDL_IsGameController(index))
  466. state.controller_ = SDL_GameControllerOpen(index);
  467. state.buttons_.Resize(SDL_JoystickNumButtons(joystick));
  468. state.axes_.Resize(SDL_JoystickNumAxes(joystick));
  469. // When the joystick is a controller, make sure there's enough axes & buttons for the standard controller mappings
  470. if (state.controller_)
  471. {
  472. if (state.buttons_.Size() < SDL_CONTROLLER_BUTTON_MAX)
  473. state.buttons_.Resize(SDL_CONTROLLER_BUTTON_MAX);
  474. if (state.axes_.Size() < SDL_CONTROLLER_AXIS_MAX)
  475. state.axes_.Resize(SDL_CONTROLLER_AXIS_MAX);
  476. }
  477. state.buttonPress_.Resize(state.buttons_.Size());
  478. state.hats_.Resize(SDL_JoystickNumHats(joystick));
  479. for (unsigned i = 0; i < state.buttons_.Size(); ++i)
  480. {
  481. state.buttons_[i] = false;
  482. state.buttonPress_[i] = false;
  483. }
  484. for (unsigned i = 0; i < state.axes_.Size(); ++i)
  485. state.axes_[i] = 0.0f;
  486. for (unsigned i = 0; i < state.hats_.Size(); ++i)
  487. state.hats_[i] = HAT_CENTER;
  488. return joystickID;
  489. }
  490. int Input::GetKeyFromName(const String& name) const
  491. {
  492. return SDL_GetKeyFromName(name.CString());
  493. }
  494. int Input::GetKeyFromScancode(int scancode) const
  495. {
  496. return SDL_GetKeyFromScancode((SDL_Scancode)scancode);
  497. }
  498. String Input::GetKeyName(int key) const
  499. {
  500. return String(SDL_GetKeyName(key));
  501. }
  502. int Input::GetScancodeFromKey(int key) const
  503. {
  504. return SDL_GetScancodeFromKey(key);
  505. }
  506. int Input::GetScancodeFromName(const String& name) const
  507. {
  508. return SDL_GetScancodeFromName(name.CString());
  509. }
  510. String Input::GetScancodeName(int scancode) const
  511. {
  512. return SDL_GetScancodeName((SDL_Scancode)scancode);
  513. }
  514. bool Input::GetKeyDown(int key) const
  515. {
  516. return keyDown_.Contains(SDL_toupper(key));
  517. }
  518. bool Input::GetKeyPress(int key) const
  519. {
  520. return keyPress_.Contains(SDL_toupper(key));
  521. }
  522. bool Input::GetScancodeDown(int scancode) const
  523. {
  524. return scancodeDown_.Contains(scancode);
  525. }
  526. bool Input::GetScancodePress(int scancode) const
  527. {
  528. return scancodePress_.Contains(scancode);
  529. }
  530. bool Input::GetMouseButtonDown(int button) const
  531. {
  532. return (mouseButtonDown_ & button) != 0;
  533. }
  534. bool Input::GetMouseButtonPress(int button) const
  535. {
  536. return (mouseButtonPress_ & button) != 0;
  537. }
  538. bool Input::GetQualifierDown(int qualifier) const
  539. {
  540. if (qualifier == QUAL_SHIFT)
  541. return GetKeyDown(KEY_LSHIFT) || GetKeyDown(KEY_RSHIFT);
  542. if (qualifier == QUAL_CTRL)
  543. return GetKeyDown(KEY_LCTRL) || GetKeyDown(KEY_RCTRL);
  544. if (qualifier == QUAL_ALT)
  545. return GetKeyDown(KEY_LALT) || GetKeyDown(KEY_RALT);
  546. return false;
  547. }
  548. bool Input::GetQualifierPress(int qualifier) const
  549. {
  550. if (qualifier == QUAL_SHIFT)
  551. return GetKeyPress(KEY_LSHIFT) || GetKeyPress(KEY_RSHIFT);
  552. if (qualifier == QUAL_CTRL)
  553. return GetKeyPress(KEY_LCTRL) || GetKeyPress(KEY_RCTRL);
  554. if (qualifier == QUAL_ALT)
  555. return GetKeyPress(KEY_LALT) || GetKeyPress(KEY_RALT);
  556. return false;
  557. }
  558. int Input::GetQualifiers() const
  559. {
  560. int ret = 0;
  561. if (GetQualifierDown(QUAL_SHIFT))
  562. ret |= QUAL_SHIFT;
  563. if (GetQualifierDown(QUAL_CTRL))
  564. ret |= QUAL_CTRL;
  565. if (GetQualifierDown(QUAL_ALT))
  566. ret |= QUAL_ALT;
  567. return ret;
  568. }
  569. IntVector2 Input::GetMousePosition() const
  570. {
  571. IntVector2 ret = IntVector2::ZERO;
  572. if (!initialized_)
  573. return ret;
  574. SDL_GetMouseState(&ret.x_, &ret.y_);
  575. return ret;
  576. }
  577. TouchState* Input::GetTouch(unsigned index) const
  578. {
  579. if (index >= touches_.Size())
  580. return 0;
  581. HashMap<int, TouchState>::ConstIterator i = touches_.Begin();
  582. while (index--)
  583. ++i;
  584. return const_cast<TouchState*>(&i->second_);
  585. }
  586. JoystickState* Input::GetJoystickByIndex(unsigned index)
  587. {
  588. unsigned compare = 0;
  589. for (HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
  590. {
  591. if (compare++ == index)
  592. return &(i->second_);
  593. }
  594. return 0;
  595. }
  596. JoystickState* Input::GetJoystick(SDL_JoystickID id)
  597. {
  598. HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Find(id);
  599. return i != joysticks_.End() ? &(i->second_) : 0;
  600. }
  601. bool Input::IsScreenJoystickVisible(SDL_JoystickID id) const
  602. {
  603. HashMap<SDL_JoystickID, JoystickState>::ConstIterator i = joysticks_.Find(id);
  604. return i != joysticks_.End() && i->second_.screenJoystick_ && i->second_.screenJoystick_->IsVisible();
  605. }
  606. bool Input::GetScreenKeyboardSupport() const
  607. {
  608. return graphics_ ? SDL_HasScreenKeyboardSupport() : false;
  609. }
  610. bool Input::IsScreenKeyboardVisible() const
  611. {
  612. if (graphics_)
  613. {
  614. SDL_Window* window = graphics_->GetImpl()->GetWindow();
  615. return SDL_IsScreenKeyboardShown(window);
  616. }
  617. else
  618. return false;
  619. }
  620. bool Input::IsMinimized() const
  621. {
  622. // Return minimized state also when unfocused in fullscreen
  623. if (!inputFocus_ && graphics_ && graphics_->GetFullscreen())
  624. return true;
  625. else
  626. return minimized_;
  627. }
  628. void Input::Initialize()
  629. {
  630. Graphics* graphics = GetSubsystem<Graphics>();
  631. if (!graphics || !graphics->IsInitialized())
  632. return;
  633. graphics_ = graphics;
  634. // In external window mode only visible mouse is supported
  635. if (graphics_->GetExternalWindow())
  636. mouseVisible_ = true;
  637. // Set the initial activation
  638. focusedThisFrame_ = true;
  639. initialized_ = true;
  640. ResetJoysticks();
  641. ResetState();
  642. SubscribeToEvent(E_BEGINFRAME, HANDLER(Input, HandleBeginFrame));
  643. LOGINFO("Initialized input");
  644. }
  645. void Input::ResetJoysticks()
  646. {
  647. joysticks_.Clear();
  648. // Open each detected joystick automatically on startup
  649. int size = SDL_NumJoysticks();
  650. for (int i = 0; i < size; ++i)
  651. OpenJoystick(i);
  652. }
  653. void Input::GainFocus()
  654. {
  655. ResetState();
  656. inputFocus_ = true;
  657. focusedThisFrame_ = false;
  658. // Re-establish mouse cursor hiding as necessary
  659. if (!mouseVisible_)
  660. {
  661. SDL_ShowCursor(SDL_FALSE);
  662. suppressNextMouseMove_ = true;
  663. }
  664. else
  665. lastMousePosition_ = GetMousePosition();
  666. SendInputFocusEvent();
  667. }
  668. void Input::LoseFocus()
  669. {
  670. ResetState();
  671. inputFocus_ = false;
  672. focusedThisFrame_ = false;
  673. // Show the mouse cursor when inactive
  674. SDL_ShowCursor(SDL_TRUE);
  675. SendInputFocusEvent();
  676. }
  677. void Input::ResetState()
  678. {
  679. keyDown_.Clear();
  680. keyPress_.Clear();
  681. scancodeDown_.Clear();
  682. scancodePress_.Clear();
  683. /// \todo Check if this is necessary
  684. for (HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
  685. {
  686. for (unsigned j = 0; j < i->second_.buttons_.Size(); ++j)
  687. i->second_.buttons_[j] = false;
  688. for (unsigned j = 0; j < i->second_.hats_.Size(); ++j)
  689. i->second_.hats_[j] = HAT_CENTER;
  690. }
  691. // When clearing touch states, send the corresponding touch end events
  692. for (HashMap<int, TouchState>::Iterator i = touches_.Begin(); i != touches_.End(); ++i)
  693. {
  694. TouchState& state = i->second_;
  695. using namespace TouchEnd;
  696. VariantMap& eventData = GetEventDataMap();
  697. eventData[P_TOUCHID] = state.touchID_;
  698. eventData[P_X] = state.position_.x_;
  699. eventData[P_Y] = state.position_.y_;
  700. SendEvent(E_TOUCHEND, eventData);
  701. }
  702. // Use SetMouseButton() to reset the state so that mouse events will be sent properly
  703. SetMouseButton(MOUSEB_LEFT, false);
  704. SetMouseButton(MOUSEB_RIGHT, false);
  705. SetMouseButton(MOUSEB_MIDDLE, false);
  706. mouseMove_ = IntVector2::ZERO;
  707. mouseMoveWheel_ = 0;
  708. mouseButtonPress_ = 0;
  709. }
  710. void Input::SendInputFocusEvent()
  711. {
  712. using namespace InputFocus;
  713. VariantMap& eventData = GetEventDataMap();
  714. eventData[P_FOCUS] = HasFocus();
  715. eventData[P_MINIMIZED] = IsMinimized();
  716. SendEvent(E_INPUTFOCUS, eventData);
  717. }
  718. void Input::SetMouseButton(int button, bool newState)
  719. {
  720. #ifdef REQUIRE_CLICK_TO_FOCUS
  721. if (!mouseVisible_ && !graphics_->GetFullscreen())
  722. {
  723. if (!inputFocus_ && newState && button == MOUSEB_LEFT)
  724. focusedThisFrame_ = true;
  725. }
  726. #endif
  727. // If we do not have focus yet, do not react to the mouse button down
  728. if (!graphics_->GetExternalWindow() && newState && !inputFocus_)
  729. return;
  730. if (newState)
  731. {
  732. if (!(mouseButtonDown_ & button))
  733. mouseButtonPress_ |= button;
  734. mouseButtonDown_ |= button;
  735. }
  736. else
  737. {
  738. if (!(mouseButtonDown_ & button))
  739. return;
  740. mouseButtonDown_ &= ~button;
  741. }
  742. using namespace MouseButtonDown;
  743. VariantMap& eventData = GetEventDataMap();
  744. eventData[P_BUTTON] = button;
  745. eventData[P_BUTTONS] = mouseButtonDown_;
  746. eventData[P_QUALIFIERS] = GetQualifiers();
  747. SendEvent(newState ? E_MOUSEBUTTONDOWN : E_MOUSEBUTTONUP, eventData);
  748. }
  749. void Input::SetKey(int key, int scancode, unsigned raw, bool newState)
  750. {
  751. // If we do not have focus yet, do not react to the key down
  752. if (!graphics_->GetExternalWindow() && newState && !inputFocus_)
  753. return;
  754. bool repeat = false;
  755. if (newState)
  756. {
  757. scancodeDown_.Insert(scancode);
  758. scancodePress_.Insert(scancode);
  759. if (!keyDown_.Contains(key))
  760. {
  761. keyDown_.Insert(key);
  762. keyPress_.Insert(key);
  763. }
  764. else
  765. repeat = true;
  766. }
  767. else
  768. {
  769. scancodeDown_.Erase(scancode);
  770. if (!keyDown_.Erase(key))
  771. return;
  772. }
  773. using namespace KeyDown;
  774. VariantMap& eventData = GetEventDataMap();
  775. eventData[P_KEY] = key;
  776. eventData[P_SCANCODE] = scancode;
  777. eventData[P_RAW] = raw;
  778. eventData[P_BUTTONS] = mouseButtonDown_;
  779. eventData[P_QUALIFIERS] = GetQualifiers();
  780. if (newState)
  781. eventData[P_REPEAT] = repeat;
  782. SendEvent(newState ? E_KEYDOWN : E_KEYUP, eventData);
  783. if ((key == KEY_RETURN || key == KEY_RETURN2 || key == KEY_KP_ENTER) && newState && !repeat && toggleFullscreen_ &&
  784. (GetKeyDown(KEY_LALT) || GetKeyDown(KEY_RALT)))
  785. graphics_->ToggleFullscreen();
  786. }
  787. void Input::SetMouseWheel(int delta)
  788. {
  789. // If we do not have focus yet, do not react to the wheel
  790. if (!graphics_->GetExternalWindow() && !inputFocus_)
  791. return;
  792. if (delta)
  793. {
  794. mouseMoveWheel_ += delta;
  795. using namespace MouseWheel;
  796. VariantMap& eventData = GetEventDataMap();
  797. eventData[P_WHEEL] = delta;
  798. eventData[P_BUTTONS] = mouseButtonDown_;
  799. eventData[P_QUALIFIERS] = GetQualifiers();
  800. SendEvent(E_MOUSEWHEEL, eventData);
  801. }
  802. }
  803. void Input::SetMousePosition(const IntVector2& position)
  804. {
  805. if (!graphics_)
  806. return;
  807. SDL_WarpMouseInWindow(graphics_->GetImpl()->GetWindow(), position.x_, position.y_);
  808. }
  809. void Input::HandleSDLEvent(void* sdlEvent)
  810. {
  811. SDL_Event& evt = *static_cast<SDL_Event*>(sdlEvent);
  812. switch (evt.type)
  813. {
  814. case SDL_KEYDOWN:
  815. // Convert to uppercase to match Win32 virtual key codes
  816. SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, evt.key.keysym.raw, true);
  817. break;
  818. case SDL_KEYUP:
  819. SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, evt.key.keysym.raw, false);
  820. break;
  821. case SDL_TEXTINPUT:
  822. {
  823. textInput_ = &evt.text.text[0];
  824. unsigned unicode = textInput_.AtUTF8(0);
  825. if (unicode)
  826. {
  827. using namespace TextInput;
  828. VariantMap textInputEventData;
  829. textInputEventData[P_TEXT] = textInput_;
  830. textInputEventData[P_BUTTONS] = mouseButtonDown_;
  831. textInputEventData[P_QUALIFIERS] = GetQualifiers();
  832. SendEvent(E_TEXTINPUT, textInputEventData);
  833. }
  834. }
  835. break;
  836. case SDL_MOUSEBUTTONDOWN:
  837. SetMouseButton(1 << (evt.button.button - 1), true);
  838. break;
  839. case SDL_MOUSEBUTTONUP:
  840. SetMouseButton(1 << (evt.button.button - 1), false);
  841. break;
  842. case SDL_MOUSEMOTION:
  843. if (mouseVisible_)
  844. {
  845. mouseMove_.x_ += evt.motion.xrel;
  846. mouseMove_.y_ += evt.motion.yrel;
  847. using namespace MouseMove;
  848. VariantMap& eventData = GetEventDataMap();
  849. if (mouseVisible_)
  850. {
  851. eventData[P_X] = evt.motion.x;
  852. eventData[P_Y] = evt.motion.y;
  853. }
  854. eventData[P_DX] = evt.motion.xrel;
  855. eventData[P_DY] = evt.motion.yrel;
  856. eventData[P_BUTTONS] = mouseButtonDown_;
  857. eventData[P_QUALIFIERS] = GetQualifiers();
  858. SendEvent(E_MOUSEMOVE, eventData);
  859. }
  860. break;
  861. case SDL_MOUSEWHEEL:
  862. SetMouseWheel(evt.wheel.y);
  863. break;
  864. case SDL_FINGERDOWN:
  865. if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
  866. {
  867. int touchID = evt.tfinger.fingerId & 0x7ffffff;
  868. TouchState& state = touches_[touchID];
  869. state.touchID_ = touchID;
  870. state.lastPosition_ = state.position_ = IntVector2((int)(evt.tfinger.x * graphics_->GetWidth()),
  871. (int)(evt.tfinger.y * graphics_->GetHeight()));
  872. state.delta_ = IntVector2::ZERO;
  873. state.pressure_ = evt.tfinger.pressure;
  874. using namespace TouchBegin;
  875. VariantMap& eventData = GetEventDataMap();
  876. eventData[P_TOUCHID] = touchID;
  877. eventData[P_X] = state.position_.x_;
  878. eventData[P_Y] = state.position_.y_;
  879. eventData[P_PRESSURE] = state.pressure_;
  880. SendEvent(E_TOUCHBEGIN, eventData);
  881. }
  882. break;
  883. case SDL_FINGERUP:
  884. if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
  885. {
  886. int touchID = evt.tfinger.fingerId & 0x7ffffff;
  887. TouchState& state = touches_[touchID];
  888. using namespace TouchEnd;
  889. VariantMap& eventData = GetEventDataMap();
  890. // Do not trust the position in the finger up event. Instead use the last position stored in the
  891. // touch structure
  892. eventData[P_TOUCHID] = touchID;
  893. eventData[P_X] = state.position_.x_;
  894. eventData[P_Y] = state.position_.y_;
  895. SendEvent(E_TOUCHEND, eventData);
  896. touches_.Erase(touchID);
  897. }
  898. break;
  899. case SDL_FINGERMOTION:
  900. if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
  901. {
  902. int touchID = evt.tfinger.fingerId & 0x7ffffff;
  903. TouchState& state = touches_[touchID];
  904. state.touchID_ = touchID;
  905. state.position_ = IntVector2((int)(evt.tfinger.x * graphics_->GetWidth()),
  906. (int)(evt.tfinger.y * graphics_->GetHeight()));
  907. state.delta_ = state.position_ - state.lastPosition_;
  908. state.pressure_ = evt.tfinger.pressure;
  909. using namespace TouchMove;
  910. VariantMap& eventData = GetEventDataMap();
  911. eventData[P_TOUCHID] = touchID;
  912. eventData[P_X] = state.position_.x_;
  913. eventData[P_Y] = state.position_.y_;
  914. eventData[P_DX] = (int)(evt.tfinger.dx * graphics_->GetWidth());
  915. eventData[P_DY] = (int)(evt.tfinger.dy * graphics_->GetHeight());
  916. eventData[P_PRESSURE] = state.pressure_;
  917. SendEvent(E_TOUCHMOVE, eventData);
  918. }
  919. break;
  920. case SDL_DOLLARRECORD:
  921. {
  922. using namespace GestureRecorded;
  923. VariantMap& eventData = GetEventDataMap();
  924. eventData[P_GESTUREID] = (int)evt.dgesture.gestureId;
  925. SendEvent(E_GESTURERECORDED, eventData);
  926. }
  927. break;
  928. case SDL_DOLLARGESTURE:
  929. {
  930. using namespace GestureInput;
  931. VariantMap& eventData = GetEventDataMap();
  932. eventData[P_GESTUREID] = (int)evt.dgesture.gestureId;
  933. eventData[P_CENTERX] = (int)(evt.dgesture.x * graphics_->GetWidth());
  934. eventData[P_CENTERY] = (int)(evt.dgesture.y * graphics_->GetHeight());
  935. eventData[P_NUMFINGERS] = (int)evt.dgesture.numFingers;
  936. eventData[P_ERROR] = evt.dgesture.error;
  937. SendEvent(E_GESTUREINPUT, eventData);
  938. }
  939. break;
  940. case SDL_MULTIGESTURE:
  941. {
  942. using namespace MultiGesture;
  943. VariantMap& eventData = GetEventDataMap();
  944. eventData[P_CENTERX] = (int)(evt.mgesture.x * graphics_->GetWidth());
  945. eventData[P_CENTERY] = (int)(evt.mgesture.y * graphics_->GetHeight());
  946. eventData[P_NUMFINGERS] = (int)evt.mgesture.numFingers;
  947. eventData[P_DTHETA] = M_RADTODEG * evt.mgesture.dTheta;
  948. eventData[P_DDIST] = evt.mgesture.dDist;
  949. SendEvent(E_MULTIGESTURE, eventData);
  950. }
  951. break;
  952. case SDL_JOYDEVICEADDED:
  953. {
  954. using namespace JoystickConnected;
  955. SDL_JoystickID joystickID = OpenJoystick(evt.jdevice.which);
  956. VariantMap& eventData = GetEventDataMap();
  957. eventData[P_JOYSTICKID] = joystickID;
  958. SendEvent(E_JOYSTICKCONNECTED, eventData);
  959. }
  960. break;
  961. case SDL_JOYDEVICEREMOVED:
  962. {
  963. using namespace JoystickDisconnected;
  964. joysticks_.Erase(evt.jdevice.which);
  965. VariantMap& eventData = GetEventDataMap();
  966. eventData[P_JOYSTICKID] = evt.jdevice.which;
  967. SendEvent(E_JOYSTICKDISCONNECTED, eventData);
  968. }
  969. break;
  970. case SDL_JOYBUTTONDOWN:
  971. {
  972. using namespace JoystickButtonDown;
  973. unsigned button = evt.jbutton.button;
  974. SDL_JoystickID joystickID = evt.jbutton.which;
  975. JoystickState& state = joysticks_[joystickID];
  976. // Skip ordinary joystick event for a controller
  977. if (!state.controller_)
  978. {
  979. VariantMap& eventData = GetEventDataMap();
  980. eventData[P_JOYSTICKID] = joystickID;
  981. eventData[P_BUTTON] = button;
  982. if (button < state.buttons_.Size())
  983. {
  984. state.buttons_[button] = true;
  985. state.buttonPress_[button] = true;
  986. SendEvent(E_JOYSTICKBUTTONDOWN, eventData);
  987. }
  988. }
  989. }
  990. break;
  991. case SDL_JOYBUTTONUP:
  992. {
  993. using namespace JoystickButtonUp;
  994. unsigned button = evt.jbutton.button;
  995. SDL_JoystickID joystickID = evt.jbutton.which;
  996. JoystickState& state = joysticks_[joystickID];
  997. if (!state.controller_)
  998. {
  999. VariantMap& eventData = GetEventDataMap();
  1000. eventData[P_JOYSTICKID] = joystickID;
  1001. eventData[P_BUTTON] = button;
  1002. if (button < state.buttons_.Size())
  1003. {
  1004. if (!state.controller_)
  1005. state.buttons_[button] = false;
  1006. SendEvent(E_JOYSTICKBUTTONUP, eventData);
  1007. }
  1008. }
  1009. }
  1010. break;
  1011. case SDL_JOYAXISMOTION:
  1012. {
  1013. using namespace JoystickAxisMove;
  1014. SDL_JoystickID joystickID = evt.jaxis.which;
  1015. JoystickState& state = joysticks_[joystickID];
  1016. if (!state.controller_)
  1017. {
  1018. VariantMap& eventData = GetEventDataMap();
  1019. eventData[P_JOYSTICKID] = joystickID;
  1020. eventData[P_AXIS] = evt.jaxis.axis;
  1021. eventData[P_POSITION] = Clamp((float)evt.jaxis.value / 32767.0f, -1.0f, 1.0f);
  1022. if (evt.jaxis.axis < state.axes_.Size())
  1023. {
  1024. // If the joystick is a controller, only use the controller axis mappings
  1025. // (we'll also get the controller event)
  1026. if (!state.controller_)
  1027. state.axes_[evt.jaxis.axis] = eventData[P_POSITION].GetFloat();
  1028. SendEvent(E_JOYSTICKAXISMOVE, eventData);
  1029. }
  1030. }
  1031. }
  1032. break;
  1033. case SDL_JOYHATMOTION:
  1034. {
  1035. using namespace JoystickHatMove;
  1036. SDL_JoystickID joystickID = evt.jaxis.which;
  1037. JoystickState& state = joysticks_[joystickID];
  1038. VariantMap& eventData = GetEventDataMap();
  1039. eventData[P_JOYSTICKID] = joystickID;
  1040. eventData[P_HAT] = evt.jhat.hat;
  1041. eventData[P_POSITION] = evt.jhat.value;
  1042. if (evt.jhat.hat < state.hats_.Size())
  1043. {
  1044. state.hats_[evt.jhat.hat] = evt.jhat.value;
  1045. SendEvent(E_JOYSTICKHATMOVE, eventData);
  1046. }
  1047. }
  1048. break;
  1049. case SDL_CONTROLLERBUTTONDOWN:
  1050. {
  1051. using namespace JoystickButtonDown;
  1052. unsigned button = evt.cbutton.button;
  1053. SDL_JoystickID joystickID = evt.cbutton.which;
  1054. JoystickState& state = joysticks_[joystickID];
  1055. VariantMap& eventData = GetEventDataMap();
  1056. eventData[P_JOYSTICKID] = joystickID;
  1057. eventData[P_BUTTON] = button;
  1058. if (button < state.buttons_.Size())
  1059. {
  1060. state.buttons_[button] = true;
  1061. state.buttonPress_[button] = true;
  1062. SendEvent(E_JOYSTICKBUTTONDOWN, eventData);
  1063. }
  1064. }
  1065. break;
  1066. case SDL_CONTROLLERBUTTONUP:
  1067. {
  1068. using namespace JoystickButtonUp;
  1069. unsigned button = evt.cbutton.button;
  1070. SDL_JoystickID joystickID = evt.cbutton.which;
  1071. JoystickState& state = joysticks_[joystickID];
  1072. VariantMap& eventData = GetEventDataMap();
  1073. eventData[P_JOYSTICKID] = joystickID;
  1074. eventData[P_BUTTON] = button;
  1075. if (button < state.buttons_.Size())
  1076. {
  1077. state.buttons_[button] = false;
  1078. SendEvent(E_JOYSTICKBUTTONUP, eventData);
  1079. }
  1080. }
  1081. break;
  1082. case SDL_CONTROLLERAXISMOTION:
  1083. {
  1084. using namespace JoystickAxisMove;
  1085. SDL_JoystickID joystickID = evt.caxis.which;
  1086. JoystickState& state = joysticks_[joystickID];
  1087. VariantMap& eventData = GetEventDataMap();
  1088. eventData[P_JOYSTICKID] = joystickID;
  1089. eventData[P_AXIS] = evt.caxis.axis;
  1090. eventData[P_POSITION] = Clamp((float)evt.caxis.value / 32767.0f, -1.0f, 1.0f);
  1091. if (evt.caxis.axis < state.axes_.Size())
  1092. {
  1093. state.axes_[evt.caxis.axis] = eventData[P_POSITION].GetFloat();
  1094. SendEvent(E_JOYSTICKAXISMOVE, eventData);
  1095. }
  1096. }
  1097. break;
  1098. case SDL_WINDOWEVENT:
  1099. {
  1100. switch (evt.window.event)
  1101. {
  1102. case SDL_WINDOWEVENT_MINIMIZED:
  1103. minimized_ = true;
  1104. SendInputFocusEvent();
  1105. break;
  1106. case SDL_WINDOWEVENT_MAXIMIZED:
  1107. case SDL_WINDOWEVENT_RESTORED:
  1108. minimized_ = false;
  1109. SendInputFocusEvent();
  1110. #ifdef IOS
  1111. // On iOS we never lose the GL context, but may have done GPU object changes that could not be applied yet.
  1112. // Apply them now
  1113. graphics_->Restore();
  1114. #endif
  1115. break;
  1116. #ifdef ANDROID
  1117. case SDL_WINDOWEVENT_FOCUS_GAINED:
  1118. // Restore GPU objects to the new GL context
  1119. graphics_->Restore();
  1120. break;
  1121. #endif
  1122. case SDL_WINDOWEVENT_RESIZED:
  1123. graphics_->WindowResized();
  1124. break;
  1125. }
  1126. }
  1127. break;
  1128. case SDL_DROPFILE:
  1129. {
  1130. using namespace DropFile;
  1131. VariantMap& eventData = GetEventDataMap();
  1132. eventData[P_FILENAME] = GetInternalPath(String(evt.drop.file));
  1133. SDL_free(evt.drop.file);
  1134. SendEvent(E_DROPFILE, eventData);
  1135. }
  1136. break;
  1137. case SDL_QUIT:
  1138. SendEvent(E_EXITREQUESTED);
  1139. break;
  1140. }
  1141. }
  1142. void Input::HandleScreenMode(StringHash eventType, VariantMap& eventData)
  1143. {
  1144. // Reset input state on subsequent initializations
  1145. if (!initialized_)
  1146. Initialize();
  1147. else
  1148. ResetState();
  1149. // Re-enable cursor clipping, and re-center the cursor (if needed) to the new screen size, so that there is no erroneous
  1150. // mouse move event. Also get new window ID if it changed
  1151. SDL_Window* window = graphics_->GetImpl()->GetWindow();
  1152. windowID_ = SDL_GetWindowID(window);
  1153. if (!mouseVisible_)
  1154. {
  1155. IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
  1156. SetMousePosition(center);
  1157. lastMousePosition_ = center;
  1158. }
  1159. focusedThisFrame_ = true;
  1160. // After setting a new screen mode we should not be minimized
  1161. minimized_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) != 0;
  1162. }
  1163. void Input::HandleBeginFrame(StringHash eventType, VariantMap& eventData)
  1164. {
  1165. // Update input right at the beginning of the frame
  1166. Update();
  1167. }
  1168. void Input::HandleScreenJoystickTouch(StringHash eventType, VariantMap& eventData)
  1169. {
  1170. using namespace TouchBegin;
  1171. // Only interested in events from screen joystick(s)
  1172. TouchState& state = touches_[eventData[P_TOUCHID].GetInt()];
  1173. IntVector2 position(state.position_.x_, state.position_.y_);
  1174. UIElement* element = eventType == E_TOUCHBEGIN ? GetSubsystem<UI>()->GetElementAt(position) : state.touchedElement_;
  1175. if (!element)
  1176. return;
  1177. Variant variant = element->GetVar(VAR_SCREEN_JOYSTICK_ID);
  1178. if (variant.IsEmpty())
  1179. return;
  1180. SDL_JoystickID joystickID = variant.GetInt();
  1181. if (eventType == E_TOUCHEND)
  1182. state.touchedElement_.Reset();
  1183. else
  1184. state.touchedElement_ = element;
  1185. // Prepare a fake SDL event
  1186. SDL_Event evt;
  1187. const String& name = element->GetName();
  1188. if (name.StartsWith("Button"))
  1189. {
  1190. if (eventType == E_TOUCHMOVE)
  1191. return;
  1192. // Determine whether to inject a joystick event or keyboard event
  1193. Variant variant = element->GetVar(VAR_BUTTON_KEY_BINDING);
  1194. if (variant.IsEmpty())
  1195. {
  1196. evt.type = eventType == E_TOUCHBEGIN ? SDL_JOYBUTTONDOWN : SDL_JOYBUTTONUP;
  1197. evt.jbutton.which = joystickID;
  1198. evt.jbutton.button = ToUInt(name.Substring(6));
  1199. }
  1200. else
  1201. {
  1202. evt.type = eventType == E_TOUCHBEGIN ? SDL_KEYDOWN : SDL_KEYUP;
  1203. evt.key.keysym.sym = variant.GetInt();
  1204. evt.key.keysym.scancode = SDL_SCANCODE_UNKNOWN;
  1205. }
  1206. }
  1207. else if (name.StartsWith("Hat"))
  1208. {
  1209. Variant variant = element->GetVar(VAR_BUTTON_KEY_BINDING);
  1210. if (variant.IsEmpty())
  1211. {
  1212. evt.type = SDL_JOYHATMOTION;
  1213. evt.jaxis.which = joystickID;
  1214. evt.jhat.hat = ToUInt(name.Substring(3));
  1215. evt.jhat.value = HAT_CENTER;
  1216. if (eventType != E_TOUCHEND)
  1217. {
  1218. IntVector2 relPosition = position - element->GetScreenPosition() - element->GetSize() / 2;
  1219. if (relPosition.y_ < 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  1220. evt.jhat.value |= HAT_UP;
  1221. if (relPosition.y_ > 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  1222. evt.jhat.value |= HAT_DOWN;
  1223. if (relPosition.x_ < 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  1224. evt.jhat.value |= HAT_LEFT;
  1225. if (relPosition.x_ > 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  1226. evt.jhat.value |= HAT_RIGHT;
  1227. }
  1228. }
  1229. else
  1230. {
  1231. // Hat is binded by 4 keys, like 'WASD'
  1232. String keyBinding = variant.GetString();
  1233. if (eventType == E_TOUCHEND)
  1234. {
  1235. evt.type = SDL_KEYUP;
  1236. evt.key.keysym.sym = element->GetVar(VAR_LAST_KEYSYM).GetInt();
  1237. if (!evt.key.keysym.sym)
  1238. return;
  1239. element->SetVar(VAR_LAST_KEYSYM, 0);
  1240. }
  1241. else
  1242. {
  1243. evt.type = SDL_KEYDOWN;
  1244. IntVector2 relPosition = position - element->GetScreenPosition() - element->GetSize() / 2;
  1245. if (relPosition.y_ < 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  1246. evt.key.keysym.sym = keyBinding[0];
  1247. else if (relPosition.y_ > 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  1248. evt.key.keysym.sym = keyBinding[1];
  1249. else if (relPosition.x_ < 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  1250. evt.key.keysym.sym = keyBinding[2];
  1251. else if (relPosition.x_ > 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  1252. evt.key.keysym.sym = keyBinding[3];
  1253. else
  1254. return;
  1255. if (eventType == E_TOUCHMOVE && evt.key.keysym.sym != element->GetVar(VAR_LAST_KEYSYM).GetInt())
  1256. {
  1257. // Dragging past the directional boundary will cause an additional key up event for previous key symbol
  1258. SDL_Event evt;
  1259. evt.type = SDL_KEYUP;
  1260. evt.key.keysym.sym = element->GetVar(VAR_LAST_KEYSYM).GetInt();
  1261. if (evt.key.keysym.sym)
  1262. {
  1263. evt.key.keysym.scancode = SDL_SCANCODE_UNKNOWN;
  1264. HandleSDLEvent(&evt);
  1265. }
  1266. element->SetVar(VAR_LAST_KEYSYM, 0);
  1267. }
  1268. evt.key.keysym.scancode = SDL_SCANCODE_UNKNOWN;
  1269. element->SetVar(VAR_LAST_KEYSYM, evt.key.keysym.sym);
  1270. }
  1271. }
  1272. }
  1273. else
  1274. return;
  1275. // Handle the fake SDL event to turn it into Urho3D genuine event
  1276. HandleSDLEvent(&evt);
  1277. }
  1278. }