Input.cpp 46 KB

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