Input.cpp 48 KB

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