Input.cpp 85 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706
  1. //
  2. // Copyright (c) 2008-2016 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 "../Core/Context.h"
  24. #include "../Core/CoreEvents.h"
  25. #include "../Core/Mutex.h"
  26. #include "../Core/ProcessUtils.h"
  27. #include "../Core/Profiler.h"
  28. #include "../Core/StringUtils.h"
  29. #include "../Graphics/Graphics.h"
  30. #include "../Graphics/GraphicsEvents.h"
  31. #include "../Input/Input.h"
  32. #include "../IO/FileSystem.h"
  33. #include "../IO/Log.h"
  34. #include "../IO/RWOpsWrapper.h"
  35. #include "../Resource/ResourceCache.h"
  36. // ATOMIC BEGIN
  37. // #include "../UI/Text.h"
  38. #include "../UI/UI.h"
  39. #include "../UI/UIWidget.h"
  40. #include <SDL/include/SDL.h>
  41. // ATOMIC END
  42. #ifdef __EMSCRIPTEN__
  43. #include <emscripten/html5.h>
  44. #endif
  45. #include "../DebugNew.h"
  46. extern "C" int SDL_AddTouch(SDL_TouchID touchID, const char* name);
  47. // Use a "click inside window to focus" mechanism on desktop platforms when the mouse cursor is hidden
  48. // TODO: For now, in this particular case only, treat all the Linux on ARM as "desktop" (e.g. RPI, odroid, etc), revisit this again when we support "mobile" Linux on ARM
  49. #if defined(_WIN32) || (defined(__APPLE__) && !defined(IOS)) || (defined(__linux__) && !defined(__ANDROID__))
  50. #define REQUIRE_CLICK_TO_FOCUS
  51. #endif
  52. namespace Atomic
  53. {
  54. const int SCREEN_JOYSTICK_START_ID = 0x40000000;
  55. const StringHash VAR_BUTTON_KEY_BINDING("VAR_BUTTON_KEY_BINDING");
  56. const StringHash VAR_BUTTON_MOUSE_BUTTON_BINDING("VAR_BUTTON_MOUSE_BUTTON_BINDING");
  57. const StringHash VAR_LAST_KEYSYM("VAR_LAST_KEYSYM");
  58. const StringHash VAR_SCREEN_JOYSTICK_ID("VAR_SCREEN_JOYSTICK_ID");
  59. const unsigned TOUCHID_MAX = 32;
  60. /// Convert SDL keycode if necessary.
  61. int ConvertSDLKeyCode(int keySym, int scanCode)
  62. {
  63. if (scanCode == SCANCODE_AC_BACK)
  64. return KEY_ESCAPE;
  65. else
  66. return SDL_tolower(keySym);
  67. }
  68. UIWidget* TouchState::GetTouchedElement()
  69. {
  70. return touchedWidget_.Get();
  71. }
  72. #ifdef __EMSCRIPTEN__
  73. #define EM_TRUE 1
  74. #define EM_FALSE 0
  75. /// Glue between Urho Input and Emscripten HTML5
  76. /** HTML5 (Emscripten) is limited in the way it handles input. The EmscriptenInput class attempts to provide the glue between Urho3D Input behavior and HTML5, where SDL currently fails to do so.
  77. *
  78. * Mouse Input:
  79. * - The OS mouse cursor position can't be set.
  80. * - The mouse can be trapped within play area via 'PointerLock API', which requires a request and interaction between the user and browser.
  81. * - To request mouse lock, call SetMouseMode(MM_RELATIVE). The E_MOUSEMODECHANGED event will be sent if/when the user confirms the request.
  82. * NOTE: The request must be initiated by the user (eg: on mouse button down/up, key down/up).
  83. * - The user can press 'escape' key and browser will force user out of pointer lock. Urho will send the E_MOUSEMODECHANGED event.
  84. * - SetMouseMode(MM_ABSOLUTE) will leave pointer lock.
  85. * - MM_WRAP is unsupported.
  86. */
  87. /// % Emscripten Input glue. Intended to be used by the Input subsystem only.
  88. class EmscriptenInput
  89. {
  90. friend class Input;
  91. public:
  92. /// Constructor, expecting pointer to constructing Input instance.
  93. EmscriptenInput(Input* inputInst);
  94. /// Static callback method for Pointer Lock API. Handles change in Pointer Lock state and sends events for mouse mode change.
  95. static EM_BOOL HandlePointerLockChange(int eventType, const EmscriptenPointerlockChangeEvent* keyEvent, void* userData);
  96. /// Static callback method for tracking focus change events.
  97. static EM_BOOL HandleFocusChange(int eventType, const EmscriptenFocusEvent* keyEvent, void* userData);
  98. /// Static callback method for suppressing mouse jump.
  99. static EM_BOOL HandleMouseJump(int eventType, const EmscriptenMouseEvent * mouseEvent, void* userData);
  100. /// Static callback method to handle SDL events.
  101. static int HandleSDLEvents(void* userData, SDL_Event* event);
  102. /// Send request to user to gain pointer lock. This requires a user-browser interaction on the first call.
  103. void RequestPointerLock(MouseMode mode, bool suppressEvent = false);
  104. /// Send request to exit pointer lock. This has the benefit of not requiring the user-browser interaction on the next pointer lock request.
  105. void ExitPointerLock(bool suppressEvent = false);
  106. /// Returns whether the page is visible.
  107. bool IsVisible();
  108. private:
  109. /// Instance of Input subsystem that constructed this instance.
  110. Input* inputInst_;
  111. /// The mouse mode being requested for pointer-lock.
  112. static MouseMode requestedMouseMode_;
  113. /// Flag indicating whether to suppress the next mouse mode change event.
  114. static bool suppressMouseModeEvent_;
  115. /// The mouse mode of the previous request for pointer-lock.
  116. static MouseMode invalidatedRequestedMouseMode_;
  117. /// Flag indicating the previous request to suppress the next mouse mode change event.
  118. static bool invalidatedSuppressMouseModeEvent_;
  119. };
  120. bool EmscriptenInput::suppressMouseModeEvent_ = false;
  121. MouseMode EmscriptenInput::requestedMouseMode_ = MM_INVALID;
  122. bool EmscriptenInput::invalidatedSuppressMouseModeEvent_ = false;
  123. MouseMode EmscriptenInput::invalidatedRequestedMouseMode_ = MM_INVALID;
  124. EmscriptenInput::EmscriptenInput(Input* inputInst) :
  125. inputInst_(inputInst)
  126. {
  127. void* vInputInst = (void*)inputInst;
  128. // Handle pointer lock
  129. emscripten_set_pointerlockchange_callback(NULL, vInputInst, false, EmscriptenInput::HandlePointerLockChange);
  130. // Handle mouse events to prevent mouse jumps
  131. emscripten_set_mousedown_callback(NULL, vInputInst, true, EmscriptenInput::HandleMouseJump);
  132. emscripten_set_mousemove_callback(NULL, vInputInst, true, EmscriptenInput::HandleMouseJump);
  133. // Handle focus changes
  134. emscripten_set_focusout_callback(NULL, vInputInst, false, EmscriptenInput::HandleFocusChange);
  135. emscripten_set_focus_callback(NULL, vInputInst, false, EmscriptenInput::HandleFocusChange);
  136. // Handle SDL events
  137. SDL_AddEventWatch(EmscriptenInput::HandleSDLEvents, vInputInst);
  138. }
  139. void EmscriptenInput::RequestPointerLock(MouseMode mode, bool suppressEvent)
  140. {
  141. requestedMouseMode_ = mode;
  142. suppressMouseModeEvent_ = suppressEvent;
  143. emscripten_request_pointerlock(NULL, true);
  144. }
  145. void EmscriptenInput::ExitPointerLock(bool suppressEvent)
  146. {
  147. if (requestedMouseMode_ != MM_INVALID)
  148. {
  149. invalidatedRequestedMouseMode_ = requestedMouseMode_;
  150. invalidatedSuppressMouseModeEvent_ = suppressMouseModeEvent_;
  151. }
  152. requestedMouseMode_ = MM_INVALID;
  153. suppressMouseModeEvent_ = suppressEvent;
  154. if (inputInst_->IsMouseLocked())
  155. {
  156. inputInst_->emscriptenExitingPointerLock_ = true;
  157. emscripten_exit_pointerlock();
  158. }
  159. }
  160. bool EmscriptenInput::IsVisible()
  161. {
  162. EmscriptenVisibilityChangeEvent visibilityStatus;
  163. if (emscripten_get_visibility_status(&visibilityStatus) >= EMSCRIPTEN_RESULT_SUCCESS)
  164. return visibilityStatus.hidden >= EM_TRUE ? false : true;
  165. // Assume visible
  166. ATOMIC_LOGWARNING("Could not determine visibility status.");
  167. return true;
  168. }
  169. EM_BOOL EmscriptenInput::HandlePointerLockChange(int eventType, const EmscriptenPointerlockChangeEvent* keyEvent, void* userData)
  170. {
  171. Input* const inputInst = (Input*)userData;
  172. bool invalid = false;
  173. const bool suppress = suppressMouseModeEvent_;
  174. if (requestedMouseMode_ == MM_INVALID && invalidatedRequestedMouseMode_ != MM_INVALID)
  175. {
  176. invalid = true;
  177. requestedMouseMode_ = invalidatedRequestedMouseMode_;
  178. suppressMouseModeEvent_ = invalidatedSuppressMouseModeEvent_;
  179. invalidatedRequestedMouseMode_ = MM_INVALID;
  180. invalidatedSuppressMouseModeEvent_ = false;
  181. }
  182. if (keyEvent->isActive >= EM_TRUE)
  183. {
  184. // Pointer Lock is now active
  185. inputInst->emscriptenPointerLock_ = true;
  186. inputInst->emscriptenEnteredPointerLock_ = true;
  187. inputInst->SetMouseModeEmscriptenFinal(requestedMouseMode_, suppressMouseModeEvent_);
  188. }
  189. else
  190. {
  191. // Pointer Lock is now inactive
  192. inputInst->emscriptenPointerLock_ = false;
  193. if (inputInst->mouseMode_ == MM_RELATIVE)
  194. inputInst->SetMouseModeEmscriptenFinal(MM_FREE, suppressMouseModeEvent_);
  195. else if (inputInst->mouseMode_ == MM_ABSOLUTE)
  196. inputInst->SetMouseModeEmscriptenFinal(MM_ABSOLUTE, suppressMouseModeEvent_);
  197. inputInst->emscriptenExitingPointerLock_ = false;
  198. }
  199. if (invalid)
  200. {
  201. if (keyEvent->isActive >= EM_TRUE)
  202. {
  203. // ExitPointerLock was called before the pointer-lock request was accepted.
  204. // Exit from pointer-lock to avoid unexpected behavior.
  205. invalidatedRequestedMouseMode_ = MM_INVALID;
  206. inputInst->emscriptenInput_->ExitPointerLock(suppress);
  207. return EM_TRUE;
  208. }
  209. }
  210. requestedMouseMode_ = MM_INVALID;
  211. suppressMouseModeEvent_ = false;
  212. invalidatedRequestedMouseMode_ = MM_INVALID;
  213. invalidatedSuppressMouseModeEvent_ = false;
  214. return EM_TRUE;
  215. }
  216. EM_BOOL EmscriptenInput::HandleFocusChange(int eventType, const EmscriptenFocusEvent* keyEvent, void* userData)
  217. {
  218. Input* const inputInst = (Input*)userData;
  219. inputInst->SuppressNextMouseMove();
  220. if (eventType == EMSCRIPTEN_EVENT_FOCUSOUT)
  221. inputInst->LoseFocus();
  222. else if (eventType == EMSCRIPTEN_EVENT_FOCUS)
  223. inputInst->GainFocus();
  224. return EM_TRUE;
  225. }
  226. EM_BOOL EmscriptenInput::HandleMouseJump(int eventType, const EmscriptenMouseEvent * mouseEvent, void* userData)
  227. {
  228. // Suppress mouse jump on pointer-lock change
  229. Input* const inputInst = (Input*)userData;
  230. bool suppress = false;
  231. if (eventType == EMSCRIPTEN_EVENT_MOUSEDOWN && inputInst->emscriptenEnteredPointerLock_)
  232. {
  233. suppress = true;
  234. inputInst->emscriptenEnteredPointerLock_ = false;
  235. }
  236. else if (eventType == EMSCRIPTEN_EVENT_MOUSEMOVE && inputInst->emscriptenExitingPointerLock_)
  237. {
  238. suppress = true;
  239. }
  240. if (suppress)
  241. inputInst->SuppressNextMouseMove();
  242. return EM_FALSE;
  243. }
  244. int EmscriptenInput::HandleSDLEvents(void* userData, SDL_Event* event)
  245. {
  246. Input* const inputInst = (Input*)userData;
  247. inputInst->HandleSDLEvent(event);
  248. return 0;
  249. }
  250. #endif
  251. void JoystickState::Initialize(unsigned numButtons, unsigned numAxes, unsigned numHats)
  252. {
  253. buttons_.Resize(numButtons);
  254. buttonPress_.Resize(numButtons);
  255. axes_.Resize(numAxes);
  256. hats_.Resize(numHats);
  257. Reset();
  258. }
  259. void JoystickState::Reset()
  260. {
  261. // ATOMIC BEGIN
  262. StopRumble();
  263. // ATOMIC END
  264. for (unsigned i = 0; i < buttons_.Size(); ++i)
  265. {
  266. buttons_[i] = false;
  267. buttonPress_[i] = false;
  268. }
  269. for (unsigned i = 0; i < axes_.Size(); ++i)
  270. axes_[i] = 0.0f;
  271. for (unsigned i = 0; i < hats_.Size(); ++i)
  272. hats_[i] = HAT_CENTER;
  273. }
  274. // ATOMIC BEGIN
  275. /// Initialize the Rumble section of SDL Haptics
  276. /// if an error occurs, unset the canRumble_ to stop further init attempts, until Reset is called.
  277. bool JoystickState::StartRumble()
  278. {
  279. if ( haptic_ == NULL && canRumble_ )
  280. {
  281. const char *hname = SDL_HapticName(joystickID_);
  282. haptic_ = SDL_HapticOpen(joystickID_);
  283. if (haptic_ == NULL)
  284. {
  285. ATOMIC_LOGERRORF( "Unable to access haptic device[%d] %s", joystickID_, hname );
  286. canRumble_ = false;
  287. return false;
  288. }
  289. SDL_ClearError();
  290. if ( SDL_HapticRumbleSupported(haptic_) == SDL_FALSE)
  291. {
  292. ATOMIC_LOGERRORF( "The device `%s` does not support haptic operations", joystickID_, hname );
  293. SDL_HapticClose(haptic_);
  294. haptic_ = NULL;
  295. canRumble_ = false;
  296. return false;
  297. }
  298. SDL_ClearError();
  299. if ( SDL_HapticRumbleInit(haptic_) != 0)
  300. {
  301. ATOMIC_LOGERRORF( "Failed to initialize rumble: %s", SDL_GetError());
  302. canRumble_ = false;
  303. return false;
  304. }
  305. }
  306. return true;
  307. }
  308. /// clean up rumble
  309. void JoystickState::StopRumble()
  310. {
  311. if ( haptic_ )
  312. {
  313. SDL_HapticRumbleStop(haptic_);
  314. SDL_HapticClose(haptic_);
  315. haptic_ = NULL;
  316. }
  317. canRumble_ = true;
  318. }
  319. /// return if the joystick or game controller supports the force feedback rumble.
  320. bool JoystickState::IsRumble()
  321. {
  322. if ( canRumble_ )
  323. if ( !StartRumble() )
  324. return false;
  325. if ( haptic_ )
  326. {
  327. return SDL_HapticRumbleSupported(haptic_);
  328. }
  329. return false;
  330. }
  331. /// rumble player, strength is from 0.0 to 1.0, length is in milliseconds, 1000 is equal to 1 second.
  332. void JoystickState::DoRumble( float strength, unsigned int len)
  333. {
  334. StartRumble(); // lazy initialization
  335. if ( haptic_ && canRumble_ )
  336. {
  337. float stren1 = Clamp (strength, 0.0f, 1.0f );
  338. if (SDL_HapticRumblePlay(haptic_, stren1, len ) != 0 )
  339. ATOMIC_LOGINFOF( "Failed to play rumble: %s\n", SDL_GetError() );
  340. }
  341. }
  342. // ATOMIC END
  343. Input::Input(Context* context) :
  344. Object(context),
  345. mouseButtonDown_(0),
  346. mouseButtonPress_(0),
  347. lastVisibleMousePosition_(MOUSE_POSITION_OFFSCREEN),
  348. mouseMoveWheel_(0),
  349. windowID_(0),
  350. toggleFullscreen_(true),
  351. // ATOMIC BEGIN
  352. // default mouse to visible
  353. mouseVisible_(true),
  354. lastMouseVisible_(true),
  355. // ATOMIC END
  356. mouseGrabbed_(false),
  357. lastMouseGrabbed_(false),
  358. mouseMode_(MM_ABSOLUTE),
  359. lastMouseMode_(MM_ABSOLUTE),
  360. #ifndef __EMSCRIPTEN__
  361. sdlMouseRelative_(false),
  362. #else
  363. emscriptenPointerLock_(false),
  364. emscriptenEnteredPointerLock_(false),
  365. emscriptenExitingPointerLock_(false),
  366. #endif
  367. touchEmulation_(false),
  368. inputFocus_(false),
  369. minimized_(false),
  370. focusedThisFrame_(false),
  371. suppressNextMouseMove_(false),
  372. inResize_(false),
  373. screenModeChanged_(false),
  374. initialized_(false)
  375. {
  376. for (int i = 0; i < TOUCHID_MAX; i++)
  377. availableTouchIDs_.Push(i);
  378. SubscribeToEvent(E_SCREENMODE, ATOMIC_HANDLER(Input, HandleScreenMode));
  379. #if defined(__ANDROID__)
  380. SDL_SetHint(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1");
  381. #elif defined(__EMSCRIPTEN__)
  382. emscriptenInput_ = new EmscriptenInput(this);
  383. #endif
  384. // Try to initialize right now, but skip if screen mode is not yet set
  385. Initialize();
  386. }
  387. Input::~Input()
  388. {
  389. #ifdef __EMSCRIPTEN__
  390. delete emscriptenInput_;
  391. emscriptenInput_ = 0;
  392. #endif
  393. }
  394. void Input::Update()
  395. {
  396. assert(initialized_);
  397. ATOMIC_PROFILE(UpdateInput);
  398. #ifndef __EMSCRIPTEN__
  399. bool mouseMoved = false;
  400. if (mouseMove_ != IntVector2::ZERO)
  401. mouseMoved = true;
  402. ResetInputAccumulation();
  403. SDL_Event evt;
  404. while (SDL_PollEvent(&evt))
  405. HandleSDLEvent(&evt);
  406. if (suppressNextMouseMove_ && (mouseMove_ != IntVector2::ZERO || mouseMoved))
  407. UnsuppressMouseMove();
  408. #endif
  409. // Check for focus change this frame
  410. SDL_Window* window = graphics_->GetWindow();
  411. unsigned flags = window ? SDL_GetWindowFlags(window) & (SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS) : 0;
  412. #ifndef __EMSCRIPTEN__
  413. if (window)
  414. {
  415. #ifdef REQUIRE_CLICK_TO_FOCUS
  416. // When using the "click to focus" mechanism, only focus automatically in fullscreen or non-hidden mouse mode
  417. if (!inputFocus_ && ((mouseVisible_ || mouseMode_ == MM_FREE) || graphics_->GetFullscreen() || screenModeChanged_) && (flags & SDL_WINDOW_INPUT_FOCUS))
  418. #else
  419. if (!inputFocus_ && (flags & SDL_WINDOW_INPUT_FOCUS))
  420. #endif
  421. {
  422. screenModeChanged_ = false;
  423. focusedThisFrame_ = true;
  424. }
  425. if (focusedThisFrame_)
  426. GainFocus();
  427. // Check for losing focus. The window flags are not reliable when using an external window, so prevent losing focus in that case
  428. if (inputFocus_ && !graphics_->GetExternalWindow() && (flags & SDL_WINDOW_INPUT_FOCUS) == 0)
  429. LoseFocus();
  430. }
  431. else
  432. return;
  433. // Handle mouse mode MM_WRAP
  434. if (mouseVisible_ && mouseMode_ == MM_WRAP)
  435. {
  436. IntVector2 windowPos = graphics_->GetWindowPosition();
  437. IntVector2 mpos;
  438. SDL_GetGlobalMouseState(&mpos.x_, &mpos.y_);
  439. mpos -= windowPos;
  440. const int buffer = 5;
  441. const int width = graphics_->GetWidth() - buffer * 2;
  442. const int height = graphics_->GetHeight() - buffer * 2;
  443. bool warp = false;
  444. if (mpos.x_ < buffer)
  445. {
  446. warp = true;
  447. mpos.x_ += width;
  448. }
  449. if (mpos.x_ > buffer + width)
  450. {
  451. warp = true;
  452. mpos.x_ -= width;
  453. }
  454. if (mpos.y_ < buffer)
  455. {
  456. warp = true;
  457. mpos.y_ += height;
  458. }
  459. if (mpos.y_ > buffer + height)
  460. {
  461. warp = true;
  462. mpos.y_ -= height;
  463. }
  464. if (warp)
  465. {
  466. SetMousePosition(mpos);
  467. SuppressNextMouseMove();
  468. }
  469. }
  470. #else
  471. if (!window)
  472. return;
  473. #endif
  474. #ifndef __EMSCRIPTEN__
  475. if (!touchEmulation_ && (graphics_->GetExternalWindow() || ((!sdlMouseRelative_ && !mouseVisible_ && mouseMode_ != MM_FREE) && inputFocus_ && (flags & SDL_WINDOW_MOUSE_FOCUS))))
  476. #else
  477. if (!touchEmulation_ && !emscriptenPointerLock_ && (graphics_->GetExternalWindow() || (!mouseVisible_ && inputFocus_ && (flags & SDL_WINDOW_MOUSE_FOCUS))))
  478. #endif
  479. {
  480. const IntVector2 mousePosition = GetMousePosition();
  481. mouseMove_ = mousePosition - lastMousePosition_;
  482. #ifndef __EMSCRIPTEN__
  483. if (graphics_->GetExternalWindow())
  484. lastMousePosition_ = mousePosition;
  485. else
  486. {
  487. // Recenter the mouse cursor manually after move
  488. CenterMousePosition();
  489. }
  490. #else
  491. if (mouseMode_ == MM_ABSOLUTE || mouseMode_ == MM_FREE)
  492. lastMousePosition_ = mousePosition;
  493. if (emscriptenExitingPointerLock_)
  494. SuppressNextMouseMove();
  495. #endif
  496. // Send mouse move event if necessary
  497. if (mouseMove_ != IntVector2::ZERO)
  498. {
  499. if (!suppressNextMouseMove_)
  500. {
  501. using namespace MouseMove;
  502. VariantMap& eventData = GetEventDataMap();
  503. eventData[P_X] = mousePosition.x_;
  504. eventData[P_Y] = mousePosition.y_;
  505. eventData[P_DX] = mouseMove_.x_;
  506. eventData[P_DY] = mouseMove_.y_;
  507. eventData[P_BUTTONS] = mouseButtonDown_;
  508. eventData[P_QUALIFIERS] = GetQualifiers();
  509. SendEvent(E_MOUSEMOVE, eventData);
  510. }
  511. }
  512. }
  513. #ifndef __EMSCRIPTEN__
  514. else if (!touchEmulation_ && !mouseVisible_ && sdlMouseRelative_ && inputFocus_ && (flags & SDL_WINDOW_MOUSE_FOCUS))
  515. {
  516. // Keep the cursor trapped in window.
  517. CenterMousePosition();
  518. }
  519. #endif
  520. }
  521. void Input::SetMouseVisible(bool enable, bool suppressEvent)
  522. {
  523. const bool startMouseVisible = mouseVisible_;
  524. // In touch emulation mode only enabled mouse is allowed
  525. if (touchEmulation_)
  526. enable = true;
  527. // In mouse mode relative, the mouse should be invisible
  528. if (mouseMode_ == MM_RELATIVE)
  529. {
  530. if (!suppressEvent)
  531. lastMouseVisible_ = enable;
  532. enable = false;
  533. }
  534. // SDL Raspberry Pi "video driver" does not have proper OS mouse support yet, so no-op for now
  535. #ifndef RPI
  536. if (enable != mouseVisible_)
  537. {
  538. if (initialized_)
  539. {
  540. // External windows can only support visible mouse cursor
  541. if (graphics_->GetExternalWindow())
  542. {
  543. mouseVisible_ = true;
  544. if (!suppressEvent)
  545. lastMouseVisible_ = true;
  546. return;
  547. }
  548. if (!enable && inputFocus_)
  549. {
  550. #ifndef __EMSCRIPTEN__
  551. if (mouseVisible_)
  552. lastVisibleMousePosition_ = GetMousePosition();
  553. if (mouseMode_ == MM_ABSOLUTE)
  554. SetMouseModeAbsolute(SDL_TRUE);
  555. #else
  556. if (mouseMode_ == MM_ABSOLUTE && !emscriptenPointerLock_)
  557. emscriptenInput_->RequestPointerLock(MM_ABSOLUTE, suppressEvent);
  558. #endif
  559. SDL_ShowCursor(SDL_FALSE);
  560. mouseVisible_ = false;
  561. }
  562. else if (mouseMode_ != MM_RELATIVE)
  563. {
  564. SetMouseGrabbed(false, suppressEvent);
  565. SDL_ShowCursor(SDL_TRUE);
  566. mouseVisible_ = true;
  567. #ifndef __EMSCRIPTEN__
  568. if (mouseMode_ == MM_ABSOLUTE)
  569. SetMouseModeAbsolute(SDL_FALSE);
  570. // ATOMIC BEGIN
  571. /*
  572. // Update cursor position
  573. UI* ui = GetSubsystem<UI>();
  574. Cursor* cursor = ui->GetCursor();
  575. // If the UI Cursor was visible, use that position instead of last visible OS cursor position
  576. if (cursor && cursor->IsVisible())
  577. {
  578. IntVector2 pos = cursor->GetScreenPosition();
  579. if (pos != MOUSE_POSITION_OFFSCREEN)
  580. {
  581. SetMousePosition(pos);
  582. lastMousePosition_ = pos;
  583. }
  584. }
  585. else
  586. */
  587. //ATOMIC END
  588. {
  589. if (lastVisibleMousePosition_ != MOUSE_POSITION_OFFSCREEN)
  590. {
  591. SetMousePosition(lastVisibleMousePosition_);
  592. lastMousePosition_ = lastVisibleMousePosition_;
  593. }
  594. }
  595. #else
  596. if (mouseMode_ == MM_ABSOLUTE && emscriptenPointerLock_)
  597. emscriptenInput_->ExitPointerLock(suppressEvent);
  598. #endif
  599. }
  600. }
  601. if (mouseVisible_ != startMouseVisible)
  602. {
  603. SuppressNextMouseMove();
  604. if (!suppressEvent)
  605. {
  606. lastMouseVisible_ = mouseVisible_;
  607. using namespace MouseVisibleChanged;
  608. VariantMap& eventData = GetEventDataMap();
  609. eventData[P_VISIBLE] = mouseVisible_;
  610. SendEvent(E_MOUSEVISIBLECHANGED, eventData);
  611. }
  612. }
  613. }
  614. #endif
  615. }
  616. void Input::ResetMouseVisible()
  617. {
  618. #ifndef __EMSCRIPTEN__
  619. SetMouseVisible(lastMouseVisible_, false);
  620. #else
  621. SetMouseVisibleEmscripten(lastMouseVisible_, false);
  622. #endif
  623. }
  624. #ifdef __EMSCRIPTEN__
  625. void Input::SetMouseVisibleEmscripten(bool enable, bool suppressEvent)
  626. {
  627. if (enable != mouseVisible_)
  628. {
  629. if (mouseMode_ == MM_ABSOLUTE)
  630. {
  631. if (enable)
  632. {
  633. mouseVisible_ = true;
  634. SDL_ShowCursor(SDL_TRUE);
  635. emscriptenInput_->ExitPointerLock(suppressEvent);
  636. }
  637. else
  638. {
  639. if (emscriptenPointerLock_)
  640. {
  641. mouseVisible_ = false;
  642. SDL_ShowCursor(SDL_FALSE);
  643. }
  644. else
  645. emscriptenInput_->RequestPointerLock(MM_ABSOLUTE, suppressEvent);
  646. }
  647. }
  648. else
  649. {
  650. mouseVisible_ = enable;
  651. SDL_ShowCursor(enable ? SDL_TRUE : SDL_FALSE);
  652. }
  653. }
  654. if (!suppressEvent)
  655. lastMouseVisible_ = mouseVisible_;
  656. }
  657. void Input::SetMouseModeEmscriptenFinal(MouseMode mode, bool suppressEvent)
  658. {
  659. if (!suppressEvent)
  660. lastMouseMode_ = mode;
  661. mouseMode_ = mode;
  662. if (mode == MM_ABSOLUTE)
  663. {
  664. if (emscriptenPointerLock_)
  665. {
  666. SetMouseVisibleEmscripten(false, suppressEvent);
  667. }
  668. else
  669. {
  670. SetMouseVisibleEmscripten(true, suppressEvent);
  671. }
  672. SetMouseGrabbed(!mouseVisible_, suppressEvent);
  673. }
  674. else if (mode == MM_RELATIVE && emscriptenPointerLock_)
  675. {
  676. SetMouseGrabbed(true, suppressEvent);
  677. SetMouseVisibleEmscripten(false, suppressEvent);
  678. }
  679. else
  680. {
  681. SetMouseGrabbed(false, suppressEvent);
  682. }
  683. SuppressNextMouseMove();
  684. if (!suppressEvent)
  685. {
  686. VariantMap& eventData = GetEventDataMap();
  687. eventData[MouseModeChanged::P_MODE] = mode;
  688. eventData[MouseModeChanged::P_MOUSELOCKED] = IsMouseLocked();
  689. SendEvent(E_MOUSEMODECHANGED, eventData);
  690. }
  691. }
  692. void Input::SetMouseModeEmscripten(MouseMode mode, bool suppressEvent)
  693. {
  694. if (mode != mouseMode_)
  695. SuppressNextMouseMove();
  696. const MouseMode previousMode = mouseMode_;
  697. mouseMode_ = mode;
  698. // Handle changing from previous mode
  699. if (previousMode == MM_RELATIVE)
  700. ResetMouseVisible();
  701. // Handle changing to new mode
  702. if (mode == MM_FREE)
  703. {
  704. // Attempt to cancel pending pointer-lock requests
  705. emscriptenInput_->ExitPointerLock(suppressEvent);
  706. SetMouseGrabbed(!mouseVisible_, suppressEvent);
  707. }
  708. else if (mode == MM_ABSOLUTE)
  709. {
  710. if (!mouseVisible_)
  711. {
  712. if (emscriptenPointerLock_)
  713. {
  714. SetMouseVisibleEmscripten(false, suppressEvent);
  715. }
  716. else
  717. {
  718. SetMouseVisible(true, suppressEvent);
  719. // Deferred mouse mode change to pointer-lock callback
  720. mouseMode_ = previousMode;
  721. emscriptenInput_->RequestPointerLock(MM_ABSOLUTE, suppressEvent);
  722. }
  723. SetMouseGrabbed(!(mouseVisible_), suppressEvent);
  724. }
  725. }
  726. else if (mode == MM_RELATIVE)
  727. {
  728. if (emscriptenPointerLock_)
  729. {
  730. SetMouseVisibleEmscripten(false, true);
  731. SetMouseGrabbed(true, suppressEvent);
  732. }
  733. else
  734. {
  735. // Defer mouse mode change to pointer-lock callback
  736. SetMouseGrabbed(false, true);
  737. mouseMode_ = previousMode;
  738. emscriptenInput_->RequestPointerLock(MM_RELATIVE, suppressEvent);
  739. }
  740. }
  741. }
  742. #endif
  743. void Input::SetMouseGrabbed(bool grab, bool suppressEvent)
  744. {
  745. // To not interfere with touch UI operation, never report the mouse as grabbed on Android / iOS
  746. #if !defined(__ANDROID__) && !defined(IOS)
  747. mouseGrabbed_ = grab;
  748. if (!suppressEvent)
  749. lastMouseGrabbed_ = grab;
  750. #endif
  751. }
  752. void Input::ResetMouseGrabbed()
  753. {
  754. SetMouseGrabbed(lastMouseGrabbed_, true);
  755. }
  756. #ifndef __EMSCRIPTEN__
  757. void Input::SetMouseModeAbsolute(SDL_bool enable)
  758. {
  759. SDL_Window* const window = graphics_->GetWindow();
  760. SDL_SetWindowGrab(window, enable);
  761. }
  762. void Input::SetMouseModeRelative(SDL_bool enable)
  763. {
  764. SDL_Window* const window = graphics_->GetWindow();
  765. int result = SDL_SetRelativeMouseMode(enable);
  766. sdlMouseRelative_ = enable && (result == 0);
  767. if (result == -1)
  768. SDL_SetWindowGrab(window, enable);
  769. }
  770. #endif
  771. void Input::SetMouseMode(MouseMode mode, bool suppressEvent)
  772. {
  773. const MouseMode previousMode = mouseMode_;
  774. #ifdef __EMSCRIPTEN__
  775. SetMouseModeEmscripten(mode, suppressEvent);
  776. #else
  777. if (mode != mouseMode_)
  778. {
  779. SuppressNextMouseMove();
  780. mouseMode_ = mode;
  781. SDL_Window* const window = graphics_->GetWindow();
  782. // ATOMIC BEGIN
  783. //UI* const ui = GetSubsystem<UI>();
  784. //Cursor* const cursor = ui->GetCursor();
  785. // ATOMIC END
  786. // Handle changing from previous mode
  787. if (previousMode == MM_ABSOLUTE)
  788. {
  789. if (!mouseVisible_)
  790. SetMouseModeAbsolute(SDL_FALSE);
  791. }
  792. if (previousMode == MM_RELATIVE)
  793. {
  794. SetMouseModeRelative(SDL_FALSE);
  795. ResetMouseVisible();
  796. }
  797. else if (previousMode == MM_WRAP)
  798. SDL_SetWindowGrab(window, SDL_FALSE);
  799. // Handle changing to new mode
  800. if (mode == MM_ABSOLUTE)
  801. {
  802. if (!mouseVisible_)
  803. SetMouseModeAbsolute(SDL_TRUE);
  804. }
  805. else if (mode == MM_RELATIVE)
  806. {
  807. SetMouseVisible(false, true);
  808. SetMouseModeRelative(SDL_TRUE);
  809. }
  810. else if (mode == MM_WRAP)
  811. {
  812. SetMouseGrabbed(true, suppressEvent);
  813. SDL_SetWindowGrab(window, SDL_TRUE);
  814. }
  815. // ATOMIC BEGIN
  816. if (mode != MM_WRAP)
  817. {
  818. // SetMouseGrabbed(!(mouseVisible_ || (cursor && cursor->IsVisible())), suppressEvent);
  819. SetMouseGrabbed(!mouseVisible_, suppressEvent);
  820. }
  821. // ATOMIC END
  822. }
  823. #endif
  824. if (!suppressEvent)
  825. {
  826. lastMouseMode_ = mode;
  827. if (mouseMode_ != previousMode)
  828. {
  829. VariantMap& eventData = GetEventDataMap();
  830. eventData[MouseModeChanged::P_MODE] = mode;
  831. eventData[MouseModeChanged::P_MOUSELOCKED] = IsMouseLocked();
  832. SendEvent(E_MOUSEMODECHANGED, eventData);
  833. }
  834. }
  835. }
  836. void Input::ResetMouseMode()
  837. {
  838. SetMouseMode(lastMouseMode_, false);
  839. }
  840. void Input::SetToggleFullscreen(bool enable)
  841. {
  842. toggleFullscreen_ = enable;
  843. }
  844. static void PopulateKeyBindingMap(HashMap<String, int>& keyBindingMap)
  845. {
  846. if (keyBindingMap.Empty())
  847. {
  848. keyBindingMap.Insert(MakePair<String, int>("SPACE", KEY_SPACE));
  849. keyBindingMap.Insert(MakePair<String, int>("LCTRL", KEY_LCTRL));
  850. keyBindingMap.Insert(MakePair<String, int>("RCTRL", KEY_RCTRL));
  851. keyBindingMap.Insert(MakePair<String, int>("LSHIFT", KEY_LSHIFT));
  852. keyBindingMap.Insert(MakePair<String, int>("RSHIFT", KEY_RSHIFT));
  853. keyBindingMap.Insert(MakePair<String, int>("LALT", KEY_LALT));
  854. keyBindingMap.Insert(MakePair<String, int>("RALT", KEY_RALT));
  855. keyBindingMap.Insert(MakePair<String, int>("LGUI", KEY_LGUI));
  856. keyBindingMap.Insert(MakePair<String, int>("RGUI", KEY_RGUI));
  857. keyBindingMap.Insert(MakePair<String, int>("TAB", KEY_TAB));
  858. keyBindingMap.Insert(MakePair<String, int>("RETURN", KEY_RETURN));
  859. keyBindingMap.Insert(MakePair<String, int>("RETURN2", KEY_RETURN2));
  860. keyBindingMap.Insert(MakePair<String, int>("ENTER", KEY_KP_ENTER));
  861. keyBindingMap.Insert(MakePair<String, int>("SELECT", KEY_SELECT));
  862. keyBindingMap.Insert(MakePair<String, int>("LEFT", KEY_LEFT));
  863. keyBindingMap.Insert(MakePair<String, int>("RIGHT", KEY_RIGHT));
  864. keyBindingMap.Insert(MakePair<String, int>("UP", KEY_UP));
  865. keyBindingMap.Insert(MakePair<String, int>("DOWN", KEY_DOWN));
  866. keyBindingMap.Insert(MakePair<String, int>("PAGEUP", KEY_PAGEUP));
  867. keyBindingMap.Insert(MakePair<String, int>("PAGEDOWN", KEY_PAGEDOWN));
  868. keyBindingMap.Insert(MakePair<String, int>("F1", KEY_F1));
  869. keyBindingMap.Insert(MakePair<String, int>("F2", KEY_F2));
  870. keyBindingMap.Insert(MakePair<String, int>("F3", KEY_F3));
  871. keyBindingMap.Insert(MakePair<String, int>("F4", KEY_F4));
  872. keyBindingMap.Insert(MakePair<String, int>("F5", KEY_F5));
  873. keyBindingMap.Insert(MakePair<String, int>("F6", KEY_F6));
  874. keyBindingMap.Insert(MakePair<String, int>("F7", KEY_F7));
  875. keyBindingMap.Insert(MakePair<String, int>("F8", KEY_F8));
  876. keyBindingMap.Insert(MakePair<String, int>("F9", KEY_F9));
  877. keyBindingMap.Insert(MakePair<String, int>("F10", KEY_F10));
  878. keyBindingMap.Insert(MakePair<String, int>("F11", KEY_F11));
  879. keyBindingMap.Insert(MakePair<String, int>("F12", KEY_F12));
  880. }
  881. }
  882. static void PopulateMouseButtonBindingMap(HashMap<String, int>& mouseButtonBindingMap)
  883. {
  884. if (mouseButtonBindingMap.Empty())
  885. {
  886. mouseButtonBindingMap.Insert(MakePair<String, int>("LEFT", SDL_BUTTON_LEFT));
  887. mouseButtonBindingMap.Insert(MakePair<String, int>("MIDDLE", SDL_BUTTON_MIDDLE));
  888. mouseButtonBindingMap.Insert(MakePair<String, int>("RIGHT", SDL_BUTTON_RIGHT));
  889. mouseButtonBindingMap.Insert(MakePair<String, int>("X1", SDL_BUTTON_X1));
  890. mouseButtonBindingMap.Insert(MakePair<String, int>("X2", SDL_BUTTON_X2));
  891. }
  892. }
  893. SDL_JoystickID Input::AddScreenJoystick(XMLFile* layoutFile, XMLFile* styleFile)
  894. {
  895. // ATOMIC BEGIN
  896. /*
  897. static HashMap<String, int> keyBindingMap;
  898. static HashMap<String, int> mouseButtonBindingMap;
  899. if (!graphics_)
  900. {
  901. ATOMIC_LOGWARNING("Cannot add screen joystick in headless mode");
  902. return -1;
  903. }
  904. // If layout file is not given, use the default screen joystick layout
  905. if (!layoutFile)
  906. {
  907. ResourceCache* cache = GetSubsystem<ResourceCache>();
  908. layoutFile = cache->GetResource<XMLFile>("UI/ScreenJoystick.xml");
  909. if (!layoutFile) // Error is already logged
  910. return -1;
  911. }
  912. UI* ui = GetSubsystem<UI>();
  913. SharedPtr<UIElement> screenJoystick = ui->LoadLayout(layoutFile, styleFile);
  914. if (!screenJoystick) // Error is already logged
  915. return -1;
  916. screenJoystick->SetSize(ui->GetRoot()->GetSize());
  917. ui->GetRoot()->AddChild(screenJoystick);
  918. // Get an unused ID for the screen joystick
  919. /// \todo After a real joystick has been plugged in 1073741824 times, the ranges will overlap
  920. SDL_JoystickID joystickID = SCREEN_JOYSTICK_START_ID;
  921. while (joysticks_.Contains(joystickID))
  922. ++joystickID;
  923. JoystickState& state = joysticks_[joystickID];
  924. state.joystickID_ = joystickID;
  925. state.name_ = screenJoystick->GetName();
  926. state.screenJoystick_ = screenJoystick;
  927. unsigned numButtons = 0;
  928. unsigned numAxes = 0;
  929. unsigned numHats = 0;
  930. const Vector<SharedPtr<UIElement> >& children = state.screenJoystick_->GetChildren();
  931. for (Vector<SharedPtr<UIElement> >::ConstIterator iter = children.Begin(); iter != children.End(); ++iter)
  932. {
  933. UIElement* element = iter->Get();
  934. String name = element->GetName();
  935. if (name.StartsWith("Button"))
  936. {
  937. ++numButtons;
  938. // Check whether the button has key binding
  939. Text* text = element->GetChildDynamicCast<Text>("KeyBinding", false);
  940. if (text)
  941. {
  942. text->SetVisible(false);
  943. const String& key = text->GetText();
  944. int keyBinding;
  945. if (key.Length() == 1)
  946. keyBinding = key[0];
  947. else
  948. {
  949. PopulateKeyBindingMap(keyBindingMap);
  950. HashMap<String, int>::Iterator i = keyBindingMap.Find(key);
  951. if (i != keyBindingMap.End())
  952. keyBinding = i->second_;
  953. else
  954. {
  955. ATOMIC_LOGERRORF("Unsupported key binding: %s", key.CString());
  956. keyBinding = M_MAX_INT;
  957. }
  958. }
  959. if (keyBinding != M_MAX_INT)
  960. element->SetVar(VAR_BUTTON_KEY_BINDING, keyBinding);
  961. }
  962. // Check whether the button has mouse button binding
  963. text = element->GetChildDynamicCast<Text>("MouseButtonBinding", false);
  964. if (text)
  965. {
  966. text->SetVisible(false);
  967. const String& mouseButton = text->GetText();
  968. PopulateMouseButtonBindingMap(mouseButtonBindingMap);
  969. HashMap<String, int>::Iterator i = mouseButtonBindingMap.Find(mouseButton);
  970. if (i != mouseButtonBindingMap.End())
  971. element->SetVar(VAR_BUTTON_MOUSE_BUTTON_BINDING, i->second_);
  972. else
  973. ATOMIC_LOGERRORF("Unsupported mouse button binding: %s", mouseButton.CString());
  974. }
  975. }
  976. else if (name.StartsWith("Axis"))
  977. {
  978. ++numAxes;
  979. ///\todo Axis emulation for screen joystick is not fully supported yet.
  980. ATOMIC_LOGWARNING("Axis emulation for screen joystick is not fully supported yet");
  981. }
  982. else if (name.StartsWith("Hat"))
  983. {
  984. ++numHats;
  985. Text* text = element->GetChildDynamicCast<Text>("KeyBinding", false);
  986. if (text)
  987. {
  988. text->SetVisible(false);
  989. String keyBinding = text->GetText();
  990. int mappedKeyBinding[4] = {KEY_W, KEY_S, KEY_A, KEY_D};
  991. Vector<String> keyBindings;
  992. if (keyBinding.Contains(' ')) // e.g.: "UP DOWN LEFT RIGHT"
  993. keyBindings = keyBinding.Split(' '); // Attempt to split the text using ' ' as separator
  994. else if (keyBinding.Length() == 4)
  995. {
  996. keyBindings.Resize(4); // e.g.: "WSAD"
  997. for (unsigned i = 0; i < 4; ++i)
  998. keyBindings[i] = keyBinding.Substring(i, 1);
  999. }
  1000. if (keyBindings.Size() == 4)
  1001. {
  1002. PopulateKeyBindingMap(keyBindingMap);
  1003. for (unsigned j = 0; j < 4; ++j)
  1004. {
  1005. if (keyBindings[j].Length() == 1)
  1006. mappedKeyBinding[j] = keyBindings[j][0];
  1007. else
  1008. {
  1009. HashMap<String, int>::Iterator i = keyBindingMap.Find(keyBindings[j]);
  1010. if (i != keyBindingMap.End())
  1011. mappedKeyBinding[j] = i->second_;
  1012. else
  1013. ATOMIC_LOGERRORF("%s - %s cannot be mapped, fallback to '%c'", name.CString(), keyBindings[j].CString(),
  1014. mappedKeyBinding[j]);
  1015. }
  1016. }
  1017. }
  1018. else
  1019. ATOMIC_LOGERRORF("%s has invalid key binding %s, fallback to WSAD", name.CString(), keyBinding.CString());
  1020. element->SetVar(VAR_BUTTON_KEY_BINDING, IntRect(mappedKeyBinding));
  1021. }
  1022. }
  1023. element->SetVar(VAR_SCREEN_JOYSTICK_ID, joystickID);
  1024. }
  1025. // Make sure all the children are non-focusable so they do not mistakenly to be considered as active UI input controls by application
  1026. PODVector<UIElement*> allChildren;
  1027. state.screenJoystick_->GetChildren(allChildren, true);
  1028. for (PODVector<UIElement*>::Iterator iter = allChildren.Begin(); iter != allChildren.End(); ++iter)
  1029. (*iter)->SetFocusMode(FM_NOTFOCUSABLE);
  1030. state.Initialize(numButtons, numAxes, numHats);
  1031. // There could be potentially more than one screen joystick, however they all will be handled by a same handler method
  1032. // So there is no harm to replace the old handler with the new handler in each call to SubscribeToEvent()
  1033. SubscribeToEvent(E_TOUCHBEGIN, ATOMIC_HANDLER(Input, HandleScreenJoystickTouch));
  1034. SubscribeToEvent(E_TOUCHMOVE, ATOMIC_HANDLER(Input, HandleScreenJoystickTouch));
  1035. SubscribeToEvent(E_TOUCHEND, ATOMIC_HANDLER(Input, HandleScreenJoystickTouch));
  1036. return joystickID;
  1037. */
  1038. return 0;
  1039. // ATOMIC END
  1040. }
  1041. bool Input::RemoveScreenJoystick(SDL_JoystickID id)
  1042. {
  1043. if (!joysticks_.Contains(id))
  1044. {
  1045. ATOMIC_LOGERRORF("Failed to remove non-existing screen joystick ID #%d", id);
  1046. return false;
  1047. }
  1048. JoystickState& state = joysticks_[id];
  1049. // ATOMIC BEGIN
  1050. /*
  1051. if (!state.screenJoystick_)
  1052. {
  1053. ATOMIC_LOGERRORF("Failed to remove joystick with ID #%d which is not a screen joystick", id);
  1054. return false;
  1055. }
  1056. state.screenJoystick_->Remove();
  1057. */
  1058. // ATOMIC END
  1059. joysticks_.Erase(id);
  1060. return true;
  1061. }
  1062. void Input::SetScreenJoystickVisible(SDL_JoystickID id, bool enable)
  1063. {
  1064. if (joysticks_.Contains(id))
  1065. {
  1066. JoystickState& state = joysticks_[id];
  1067. // ATOMIC BEGIN
  1068. // if (state.screenJoystick_)
  1069. // state.screenJoystick_->SetVisible(enable);
  1070. // ATOMIC END
  1071. }
  1072. }
  1073. void Input::SetScreenKeyboardVisible(bool enable)
  1074. {
  1075. if (!graphics_)
  1076. return;
  1077. if (enable != IsScreenKeyboardVisible())
  1078. {
  1079. if (enable)
  1080. SDL_StartTextInput();
  1081. else
  1082. SDL_StopTextInput();
  1083. }
  1084. }
  1085. void Input::SetTouchEmulation(bool enable)
  1086. {
  1087. #if !defined(__ANDROID__) && !defined(IOS)
  1088. if (enable != touchEmulation_)
  1089. {
  1090. if (enable)
  1091. {
  1092. // Touch emulation needs the mouse visible
  1093. if (!mouseVisible_)
  1094. SetMouseVisible(true);
  1095. // Add a virtual touch device the first time we are enabling emulated touch
  1096. if (!SDL_GetNumTouchDevices())
  1097. SDL_AddTouch(0, "Emulated Touch");
  1098. }
  1099. else
  1100. ResetTouches();
  1101. touchEmulation_ = enable;
  1102. }
  1103. #endif
  1104. }
  1105. bool Input::RecordGesture()
  1106. {
  1107. // If have no touch devices, fail
  1108. if (!SDL_GetNumTouchDevices())
  1109. {
  1110. ATOMIC_LOGERROR("Can not record gesture: no touch devices");
  1111. return false;
  1112. }
  1113. return SDL_RecordGesture(-1) != 0;
  1114. }
  1115. bool Input::SaveGestures(Serializer& dest)
  1116. {
  1117. RWOpsWrapper<Serializer> wrapper(dest);
  1118. return SDL_SaveAllDollarTemplates(wrapper.GetRWOps()) != 0;
  1119. }
  1120. bool Input::SaveGesture(Serializer& dest, unsigned gestureID)
  1121. {
  1122. RWOpsWrapper<Serializer> wrapper(dest);
  1123. return SDL_SaveDollarTemplate(gestureID, wrapper.GetRWOps()) != 0;
  1124. }
  1125. unsigned Input::LoadGestures(Deserializer& source)
  1126. {
  1127. // If have no touch devices, fail
  1128. if (!SDL_GetNumTouchDevices())
  1129. {
  1130. ATOMIC_LOGERROR("Can not load gestures: no touch devices");
  1131. return 0;
  1132. }
  1133. RWOpsWrapper<Deserializer> wrapper(source);
  1134. return (unsigned)SDL_LoadDollarTemplates(-1, wrapper.GetRWOps());
  1135. }
  1136. bool Input::RemoveGesture(unsigned gestureID)
  1137. {
  1138. #ifdef __EMSCRIPTEN__
  1139. return false;
  1140. #else
  1141. return SDL_RemoveDollarTemplate(gestureID) != 0;
  1142. #endif
  1143. }
  1144. void Input::RemoveAllGestures()
  1145. {
  1146. #ifndef __EMSCRIPTEN__
  1147. SDL_RemoveAllDollarTemplates();
  1148. #endif
  1149. }
  1150. SDL_JoystickID Input::OpenJoystick(unsigned index)
  1151. {
  1152. SDL_Joystick* joystick = SDL_JoystickOpen(index);
  1153. if (!joystick)
  1154. {
  1155. ATOMIC_LOGERRORF("Cannot open joystick #%d", index);
  1156. return -1;
  1157. }
  1158. // Create joystick state for the new joystick
  1159. int joystickID = SDL_JoystickInstanceID(joystick);
  1160. JoystickState& state = joysticks_[joystickID];
  1161. state.joystick_ = joystick;
  1162. state.joystickID_ = joystickID;
  1163. state.name_ = SDL_JoystickName(joystick);
  1164. if (SDL_IsGameController(index))
  1165. state.controller_ = SDL_GameControllerOpen(index);
  1166. unsigned numButtons = (unsigned)SDL_JoystickNumButtons(joystick);
  1167. unsigned numAxes = (unsigned)SDL_JoystickNumAxes(joystick);
  1168. unsigned numHats = (unsigned)SDL_JoystickNumHats(joystick);
  1169. // When the joystick is a controller, make sure there's enough axes & buttons for the standard controller mappings
  1170. if (state.controller_)
  1171. {
  1172. if (numButtons < SDL_CONTROLLER_BUTTON_MAX)
  1173. numButtons = SDL_CONTROLLER_BUTTON_MAX;
  1174. if (numAxes < SDL_CONTROLLER_AXIS_MAX)
  1175. numAxes = SDL_CONTROLLER_AXIS_MAX;
  1176. }
  1177. state.Initialize(numButtons, numAxes, numHats);
  1178. return joystickID;
  1179. }
  1180. int Input::GetKeyFromName(const String& name) const
  1181. {
  1182. return SDL_GetKeyFromName(name.CString());
  1183. }
  1184. int Input::GetKeyFromScancode(int scancode) const
  1185. {
  1186. return SDL_GetKeyFromScancode((SDL_Scancode)scancode);
  1187. }
  1188. String Input::GetKeyName(int key) const
  1189. {
  1190. return String(SDL_GetKeyName(key));
  1191. }
  1192. int Input::GetScancodeFromKey(int key) const
  1193. {
  1194. return SDL_GetScancodeFromKey(key);
  1195. }
  1196. int Input::GetScancodeFromName(const String& name) const
  1197. {
  1198. return SDL_GetScancodeFromName(name.CString());
  1199. }
  1200. String Input::GetScancodeName(int scancode) const
  1201. {
  1202. return SDL_GetScancodeName((SDL_Scancode)scancode);
  1203. }
  1204. bool Input::GetKeyDown(int key) const
  1205. {
  1206. return keyDown_.Contains(SDL_tolower(key));
  1207. }
  1208. bool Input::GetKeyPress(int key) const
  1209. {
  1210. return keyPress_.Contains(SDL_tolower(key));
  1211. }
  1212. bool Input::GetScancodeDown(int scancode) const
  1213. {
  1214. return scancodeDown_.Contains(scancode);
  1215. }
  1216. bool Input::GetScancodePress(int scancode) const
  1217. {
  1218. return scancodePress_.Contains(scancode);
  1219. }
  1220. bool Input::GetMouseButtonDown(int button) const
  1221. {
  1222. return (mouseButtonDown_ & button) != 0;
  1223. }
  1224. bool Input::GetMouseButtonPress(int button) const
  1225. {
  1226. return (mouseButtonPress_ & button) != 0;
  1227. }
  1228. bool Input::GetQualifierDown(int qualifier) const
  1229. {
  1230. if (qualifier == QUAL_SHIFT)
  1231. return GetKeyDown(KEY_LSHIFT) || GetKeyDown(KEY_RSHIFT);
  1232. if (qualifier == QUAL_CTRL)
  1233. return GetKeyDown(KEY_LCTRL) || GetKeyDown(KEY_RCTRL);
  1234. if (qualifier == QUAL_ALT)
  1235. return GetKeyDown(KEY_LALT) || GetKeyDown(KEY_RALT);
  1236. return false;
  1237. }
  1238. bool Input::GetQualifierPress(int qualifier) const
  1239. {
  1240. if (qualifier == QUAL_SHIFT)
  1241. return GetKeyPress(KEY_LSHIFT) || GetKeyPress(KEY_RSHIFT);
  1242. if (qualifier == QUAL_CTRL)
  1243. return GetKeyPress(KEY_LCTRL) || GetKeyPress(KEY_RCTRL);
  1244. if (qualifier == QUAL_ALT)
  1245. return GetKeyPress(KEY_LALT) || GetKeyPress(KEY_RALT);
  1246. return false;
  1247. }
  1248. int Input::GetQualifiers() const
  1249. {
  1250. int ret = 0;
  1251. if (GetQualifierDown(QUAL_SHIFT))
  1252. ret |= QUAL_SHIFT;
  1253. if (GetQualifierDown(QUAL_CTRL))
  1254. ret |= QUAL_CTRL;
  1255. if (GetQualifierDown(QUAL_ALT))
  1256. ret |= QUAL_ALT;
  1257. return ret;
  1258. }
  1259. IntVector2 Input::GetMousePosition() const
  1260. {
  1261. IntVector2 ret = IntVector2::ZERO;
  1262. if (!initialized_)
  1263. return ret;
  1264. SDL_GetMouseState(&ret.x_, &ret.y_);
  1265. return ret;
  1266. }
  1267. const IntVector2& Input::GetMouseMove() const
  1268. {
  1269. if (!suppressNextMouseMove_)
  1270. return mouseMove_;
  1271. else
  1272. return IntVector2::ZERO;
  1273. }
  1274. int Input::GetMouseMoveX() const
  1275. {
  1276. if (!suppressNextMouseMove_)
  1277. return mouseMove_.x_;
  1278. else
  1279. return 0;
  1280. }
  1281. int Input::GetMouseMoveY() const
  1282. {
  1283. if (!suppressNextMouseMove_)
  1284. return mouseMove_.y_;
  1285. else
  1286. return 0;
  1287. }
  1288. TouchState* Input::GetTouch(unsigned index) const
  1289. {
  1290. if (index >= touches_.Size())
  1291. return 0;
  1292. HashMap<int, TouchState>::ConstIterator i = touches_.Begin();
  1293. while (index--)
  1294. ++i;
  1295. return const_cast<TouchState*>(&i->second_);
  1296. }
  1297. JoystickState* Input::GetJoystickByIndex(unsigned index)
  1298. {
  1299. unsigned compare = 0;
  1300. for (HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
  1301. {
  1302. if (compare++ == index)
  1303. return &(i->second_);
  1304. }
  1305. return 0;
  1306. }
  1307. JoystickState* Input::GetJoystickByName(const String& name)
  1308. {
  1309. for (HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
  1310. {
  1311. if (i->second_.name_ == name)
  1312. return &(i->second_);
  1313. }
  1314. return 0;
  1315. }
  1316. JoystickState* Input::GetJoystick(SDL_JoystickID id)
  1317. {
  1318. HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Find(id);
  1319. return i != joysticks_.End() ? &(i->second_) : 0;
  1320. }
  1321. bool Input::IsScreenJoystickVisible(SDL_JoystickID id) const
  1322. {
  1323. // ATOMIC BEGIN
  1324. //HashMap<SDL_JoystickID, JoystickState>::ConstIterator i = joysticks_.Find(id);
  1325. //return i != joysticks_.End() && i->second_.screenJoystick_ && i->second_.screenJoystick_->IsVisible();
  1326. return false;
  1327. // ATOMIC END
  1328. }
  1329. bool Input::GetScreenKeyboardSupport() const
  1330. {
  1331. return graphics_ ? SDL_HasScreenKeyboardSupport() != 0 : false;
  1332. }
  1333. bool Input::IsScreenKeyboardVisible() const
  1334. {
  1335. if (graphics_)
  1336. {
  1337. SDL_Window* window = graphics_->GetWindow();
  1338. return SDL_IsScreenKeyboardShown(window) != SDL_FALSE;
  1339. }
  1340. else
  1341. return false;
  1342. }
  1343. bool Input::IsMouseLocked() const
  1344. {
  1345. #ifdef __EMSCRIPTEN__
  1346. return emscriptenPointerLock_;
  1347. #else
  1348. return !((mouseMode_ == MM_ABSOLUTE && mouseVisible_) || mouseMode_ == MM_FREE);
  1349. #endif
  1350. }
  1351. bool Input::IsMinimized() const
  1352. {
  1353. // Return minimized state also when unfocused in fullscreen
  1354. if (!inputFocus_ && graphics_ && graphics_->GetFullscreen())
  1355. return true;
  1356. else
  1357. return minimized_;
  1358. }
  1359. void Input::Initialize()
  1360. {
  1361. Graphics* graphics = GetSubsystem<Graphics>();
  1362. if (!graphics || !graphics->IsInitialized())
  1363. return;
  1364. graphics_ = graphics;
  1365. // ATOMIC BEGIN
  1366. // get user gamecontroller configs for SDL
  1367. FileSystem* fs = GetSubsystem<FileSystem>();
  1368. const String configName = fs->GetUserDocumentsDir() + "/gamecontrollerdb.txt";
  1369. SDL_GameControllerAddMappingsFromFile(configName.CString());
  1370. // ATOMIC END
  1371. // In external window mode only visible mouse is supported
  1372. if (graphics_->GetExternalWindow())
  1373. mouseVisible_ = true;
  1374. // Set the initial activation
  1375. initialized_ = true;
  1376. #ifndef __EMSCRIPTEN__
  1377. GainFocus();
  1378. #else
  1379. // Note: Page visibility and focus are slightly different, however we can't query last focus with Emscripten (1.29.0)
  1380. if (emscriptenInput_->IsVisible())
  1381. GainFocus();
  1382. else
  1383. LoseFocus();
  1384. #endif
  1385. ResetJoysticks();
  1386. ResetState();
  1387. SubscribeToEvent(E_BEGINFRAME, ATOMIC_HANDLER(Input, HandleBeginFrame));
  1388. #ifdef __EMSCRIPTEN__
  1389. SubscribeToEvent(E_ENDFRAME, ATOMIC_HANDLER(Input, HandleEndFrame));
  1390. #endif
  1391. ATOMIC_LOGINFO("Initialized input");
  1392. }
  1393. void Input::ResetJoysticks()
  1394. {
  1395. joysticks_.Clear();
  1396. // Open each detected joystick automatically on startup
  1397. unsigned size = static_cast<unsigned>(SDL_NumJoysticks());
  1398. for (unsigned i = 0; i < size; ++i)
  1399. OpenJoystick(i);
  1400. }
  1401. void Input::ResetInputAccumulation()
  1402. {
  1403. // Reset input accumulation for this frame
  1404. keyPress_.Clear();
  1405. scancodePress_.Clear();
  1406. mouseButtonPress_ = 0;
  1407. mouseMove_ = IntVector2::ZERO;
  1408. mouseMoveWheel_ = 0;
  1409. for (HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
  1410. {
  1411. for (unsigned j = 0; j < i->second_.buttonPress_.Size(); ++j)
  1412. i->second_.buttonPress_[j] = false;
  1413. }
  1414. // Reset touch delta movement
  1415. for (HashMap<int, TouchState>::Iterator i = touches_.Begin(); i != touches_.End(); ++i)
  1416. {
  1417. TouchState& state = i->second_;
  1418. state.lastPosition_ = state.position_;
  1419. state.delta_ = IntVector2::ZERO;
  1420. }
  1421. }
  1422. void Input::GainFocus()
  1423. {
  1424. ResetState();
  1425. inputFocus_ = true;
  1426. focusedThisFrame_ = false;
  1427. // Restore mouse mode
  1428. #ifndef __EMSCRIPTEN__
  1429. const MouseMode mm = mouseMode_;
  1430. mouseMode_ = MM_FREE;
  1431. SetMouseMode(mm, true);
  1432. #endif
  1433. SuppressNextMouseMove();
  1434. // Re-establish mouse cursor hiding as necessary
  1435. if (!mouseVisible_)
  1436. SDL_ShowCursor(SDL_FALSE);
  1437. SendInputFocusEvent();
  1438. }
  1439. void Input::LoseFocus()
  1440. {
  1441. ResetState();
  1442. inputFocus_ = false;
  1443. focusedThisFrame_ = false;
  1444. // Show the mouse cursor when inactive
  1445. SDL_ShowCursor(SDL_TRUE);
  1446. // Change mouse mode -- removing any cursor grabs, etc.
  1447. #ifndef __EMSCRIPTEN__
  1448. const MouseMode mm = mouseMode_;
  1449. SetMouseMode(MM_FREE, true);
  1450. // Restore flags to reflect correct mouse state.
  1451. mouseMode_ = mm;
  1452. #endif
  1453. SendInputFocusEvent();
  1454. }
  1455. void Input::ResetState()
  1456. {
  1457. keyDown_.Clear();
  1458. keyPress_.Clear();
  1459. scancodeDown_.Clear();
  1460. scancodePress_.Clear();
  1461. /// \todo Check if resetting joystick state on input focus loss is even necessary
  1462. for (HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
  1463. i->second_.Reset();
  1464. ResetTouches();
  1465. // Use SetMouseButton() to reset the state so that mouse events will be sent properly
  1466. SetMouseButton(MOUSEB_LEFT, false);
  1467. SetMouseButton(MOUSEB_RIGHT, false);
  1468. SetMouseButton(MOUSEB_MIDDLE, false);
  1469. mouseMove_ = IntVector2::ZERO;
  1470. mouseMoveWheel_ = 0;
  1471. mouseButtonPress_ = 0;
  1472. }
  1473. void Input::ResetTouches()
  1474. {
  1475. for (HashMap<int, TouchState>::Iterator i = touches_.Begin(); i != touches_.End(); ++i)
  1476. {
  1477. TouchState& state = i->second_;
  1478. using namespace TouchEnd;
  1479. VariantMap& eventData = GetEventDataMap();
  1480. eventData[P_TOUCHID] = state.touchID_;
  1481. eventData[P_X] = state.position_.x_;
  1482. eventData[P_Y] = state.position_.y_;
  1483. SendEvent(E_TOUCHEND, eventData);
  1484. }
  1485. touches_.Clear();
  1486. touchIDMap_.Clear();
  1487. availableTouchIDs_.Clear();
  1488. for (int i = 0; i < TOUCHID_MAX; i++)
  1489. availableTouchIDs_.Push(i);
  1490. }
  1491. unsigned Input::GetTouchIndexFromID(int touchID)
  1492. {
  1493. HashMap<int, int>::ConstIterator i = touchIDMap_.Find(touchID);
  1494. if (i != touchIDMap_.End())
  1495. {
  1496. return (unsigned)i->second_;
  1497. }
  1498. unsigned index = PopTouchIndex();
  1499. touchIDMap_[touchID] = index;
  1500. return index;
  1501. }
  1502. unsigned Input::PopTouchIndex()
  1503. {
  1504. if (availableTouchIDs_.Empty())
  1505. return 0;
  1506. unsigned index = (unsigned)availableTouchIDs_.Front();
  1507. availableTouchIDs_.PopFront();
  1508. return index;
  1509. }
  1510. void Input::PushTouchIndex(int touchID)
  1511. {
  1512. HashMap<int, int>::ConstIterator ci = touchIDMap_.Find(touchID);
  1513. if (ci == touchIDMap_.End())
  1514. return;
  1515. int index = touchIDMap_[touchID];
  1516. touchIDMap_.Erase(touchID);
  1517. // Sorted insertion
  1518. bool inserted = false;
  1519. for (List<int>::Iterator i = availableTouchIDs_.Begin(); i != availableTouchIDs_.End(); ++i)
  1520. {
  1521. if (*i == index)
  1522. {
  1523. // This condition can occur when TOUCHID_MAX is reached.
  1524. inserted = true;
  1525. break;
  1526. }
  1527. if (*i > index)
  1528. {
  1529. availableTouchIDs_.Insert(i, index);
  1530. inserted = true;
  1531. break;
  1532. }
  1533. }
  1534. // If empty, or the lowest value then insert at end.
  1535. if (!inserted)
  1536. availableTouchIDs_.Push(index);
  1537. }
  1538. // ATOMIC BEGIN
  1539. bool Input::GetJoystickRumble(unsigned int id)
  1540. {
  1541. JoystickState *jss = GetJoystick((SDL_JoystickID)id);
  1542. if (jss)
  1543. return jss->IsRumble();
  1544. return false;
  1545. }
  1546. void Input::JoystickRumble(unsigned int id, float strength, unsigned int length)
  1547. {
  1548. JoystickState *jss = GetJoystick((SDL_JoystickID)id);
  1549. if (jss)
  1550. jss->DoRumble( strength, length);
  1551. }
  1552. // ATOMIC END
  1553. void Input::SendInputFocusEvent()
  1554. {
  1555. using namespace InputFocus;
  1556. VariantMap& eventData = GetEventDataMap();
  1557. eventData[P_FOCUS] = HasFocus();
  1558. eventData[P_MINIMIZED] = IsMinimized();
  1559. SendEvent(E_INPUTFOCUS, eventData);
  1560. }
  1561. void Input::SetMouseButton(int button, bool newState)
  1562. {
  1563. if (newState)
  1564. {
  1565. if (!(mouseButtonDown_ & button))
  1566. mouseButtonPress_ |= button;
  1567. mouseButtonDown_ |= button;
  1568. }
  1569. else
  1570. {
  1571. if (!(mouseButtonDown_ & button))
  1572. return;
  1573. mouseButtonDown_ &= ~button;
  1574. }
  1575. using namespace MouseButtonDown;
  1576. VariantMap& eventData = GetEventDataMap();
  1577. eventData[P_BUTTON] = button;
  1578. eventData[P_BUTTONS] = mouseButtonDown_;
  1579. eventData[P_QUALIFIERS] = GetQualifiers();
  1580. SendEvent(newState ? E_MOUSEBUTTONDOWN : E_MOUSEBUTTONUP, eventData);
  1581. }
  1582. void Input::SetKey(int key, int scancode, bool newState)
  1583. {
  1584. bool repeat = false;
  1585. if (newState)
  1586. {
  1587. scancodeDown_.Insert(scancode);
  1588. scancodePress_.Insert(scancode);
  1589. if (!keyDown_.Contains(key))
  1590. {
  1591. keyDown_.Insert(key);
  1592. keyPress_.Insert(key);
  1593. }
  1594. else
  1595. repeat = true;
  1596. }
  1597. else
  1598. {
  1599. scancodeDown_.Erase(scancode);
  1600. if (!keyDown_.Erase(key))
  1601. return;
  1602. }
  1603. using namespace KeyDown;
  1604. VariantMap& eventData = GetEventDataMap();
  1605. eventData[P_KEY] = key;
  1606. eventData[P_SCANCODE] = scancode;
  1607. eventData[P_BUTTONS] = mouseButtonDown_;
  1608. eventData[P_QUALIFIERS] = GetQualifiers();
  1609. if (newState)
  1610. eventData[P_REPEAT] = repeat;
  1611. SendEvent(newState ? E_KEYDOWN : E_KEYUP, eventData);
  1612. if ((key == KEY_RETURN || key == KEY_RETURN2 || key == KEY_KP_ENTER) && newState && !repeat && toggleFullscreen_ &&
  1613. (GetKeyDown(KEY_LALT) || GetKeyDown(KEY_RALT)))
  1614. graphics_->ToggleFullscreen();
  1615. }
  1616. void Input::SetMouseWheel(int delta)
  1617. {
  1618. if (delta)
  1619. {
  1620. mouseMoveWheel_ += delta;
  1621. using namespace MouseWheel;
  1622. VariantMap& eventData = GetEventDataMap();
  1623. eventData[P_WHEEL] = delta;
  1624. eventData[P_BUTTONS] = mouseButtonDown_;
  1625. eventData[P_QUALIFIERS] = GetQualifiers();
  1626. SendEvent(E_MOUSEWHEEL, eventData);
  1627. }
  1628. }
  1629. void Input::SetMousePosition(const IntVector2& position)
  1630. {
  1631. if (!graphics_)
  1632. return;
  1633. SDL_WarpMouseInWindow(graphics_->GetWindow(), position.x_, position.y_);
  1634. }
  1635. void Input::CenterMousePosition()
  1636. {
  1637. const IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
  1638. if (GetMousePosition() != center)
  1639. {
  1640. SetMousePosition(center);
  1641. lastMousePosition_ = center;
  1642. }
  1643. }
  1644. void Input::SuppressNextMouseMove()
  1645. {
  1646. suppressNextMouseMove_ = true;
  1647. mouseMove_ = IntVector2::ZERO;
  1648. }
  1649. void Input::UnsuppressMouseMove()
  1650. {
  1651. suppressNextMouseMove_ = false;
  1652. mouseMove_ = IntVector2::ZERO;
  1653. lastMousePosition_ = GetMousePosition();
  1654. }
  1655. void Input::HandleSDLEvent(void* sdlEvent)
  1656. {
  1657. SDL_Event& evt = *static_cast<SDL_Event*>(sdlEvent);
  1658. // While not having input focus, skip key/mouse/touch/joystick events, except for the "click to focus" mechanism
  1659. if (!inputFocus_ && evt.type >= SDL_KEYDOWN && evt.type <= SDL_MULTIGESTURE)
  1660. {
  1661. #ifdef REQUIRE_CLICK_TO_FOCUS
  1662. // Require the click to be at least 1 pixel inside the window to disregard clicks in the title bar
  1663. if (evt.type == SDL_MOUSEBUTTONDOWN && evt.button.x > 0 && evt.button.y > 0 && evt.button.x < graphics_->GetWidth() - 1 &&
  1664. evt.button.y < graphics_->GetHeight() - 1)
  1665. {
  1666. focusedThisFrame_ = true;
  1667. // Do not cause the click to actually go throughfin
  1668. return;
  1669. }
  1670. else if (evt.type == SDL_FINGERDOWN)
  1671. {
  1672. // When focusing by touch, call GainFocus() immediately as it resets the state; a touch has sustained state
  1673. // which should be kept
  1674. GainFocus();
  1675. }
  1676. else
  1677. #endif
  1678. return;
  1679. }
  1680. // Possibility for custom handling or suppression of default handling for the SDL event
  1681. {
  1682. using namespace SDLRawInput;
  1683. VariantMap eventData = GetEventDataMap();
  1684. eventData[P_SDLEVENT] = &evt;
  1685. eventData[P_CONSUMED] = false;
  1686. SendEvent(E_SDLRAWINPUT, eventData);
  1687. if (eventData[P_CONSUMED].GetBool())
  1688. return;
  1689. }
  1690. switch (evt.type)
  1691. {
  1692. case SDL_KEYDOWN:
  1693. #ifdef __EMSCRIPTEN__
  1694. SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, true);
  1695. #else
  1696. SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, true);
  1697. #endif
  1698. break;
  1699. case SDL_KEYUP:
  1700. #ifdef __EMSCRIPTEN__
  1701. SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, false);
  1702. #else
  1703. SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, false);
  1704. #endif
  1705. break;
  1706. case SDL_TEXTINPUT:
  1707. {
  1708. textInput_ = &evt.text.text[0];
  1709. unsigned unicode = textInput_.AtUTF8(0);
  1710. if (unicode)
  1711. {
  1712. using namespace TextInput;
  1713. VariantMap textInputEventData;
  1714. textInputEventData[P_TEXT] = textInput_;
  1715. textInputEventData[P_BUTTONS] = mouseButtonDown_;
  1716. textInputEventData[P_QUALIFIERS] = GetQualifiers();
  1717. SendEvent(E_TEXTINPUT, textInputEventData);
  1718. }
  1719. }
  1720. break;
  1721. case SDL_MOUSEBUTTONDOWN:
  1722. if (!touchEmulation_)
  1723. SetMouseButton(1 << (evt.button.button - 1), true);
  1724. else
  1725. {
  1726. int x, y;
  1727. SDL_GetMouseState(&x, &y);
  1728. SDL_Event event;
  1729. event.type = SDL_FINGERDOWN;
  1730. event.tfinger.touchId = 0;
  1731. event.tfinger.fingerId = evt.button.button - 1;
  1732. event.tfinger.pressure = 1.0f;
  1733. event.tfinger.x = (float)x / (float)graphics_->GetWidth();
  1734. event.tfinger.y = (float)y / (float)graphics_->GetHeight();
  1735. event.tfinger.dx = 0;
  1736. event.tfinger.dy = 0;
  1737. SDL_PushEvent(&event);
  1738. }
  1739. break;
  1740. case SDL_MOUSEBUTTONUP:
  1741. if (!touchEmulation_)
  1742. SetMouseButton(1 << (evt.button.button - 1), false);
  1743. else
  1744. {
  1745. int x, y;
  1746. SDL_GetMouseState(&x, &y);
  1747. SDL_Event event;
  1748. event.type = SDL_FINGERUP;
  1749. event.tfinger.touchId = 0;
  1750. event.tfinger.fingerId = evt.button.button - 1;
  1751. event.tfinger.pressure = 0.0f;
  1752. event.tfinger.x = (float)x / (float)graphics_->GetWidth();
  1753. event.tfinger.y = (float)y / (float)graphics_->GetHeight();
  1754. event.tfinger.dx = 0;
  1755. event.tfinger.dy = 0;
  1756. SDL_PushEvent(&event);
  1757. }
  1758. break;
  1759. case SDL_MOUSEMOTION:
  1760. #ifndef __EMSCRIPTEN__
  1761. if ((sdlMouseRelative_ || mouseVisible_ || mouseMode_ == MM_FREE) && !touchEmulation_)
  1762. #else
  1763. if ((mouseVisible_ || emscriptenPointerLock_ || mouseMode_ == MM_FREE) && !touchEmulation_)
  1764. #endif
  1765. {
  1766. #ifdef __EMSCRIPTEN__
  1767. if (emscriptenExitingPointerLock_)
  1768. {
  1769. SuppressNextMouseMove();
  1770. break;
  1771. }
  1772. #endif
  1773. mouseMove_.x_ += evt.motion.xrel;
  1774. mouseMove_.y_ += evt.motion.yrel;
  1775. if (!suppressNextMouseMove_)
  1776. {
  1777. using namespace MouseMove;
  1778. VariantMap& eventData = GetEventDataMap();
  1779. eventData[P_X] = evt.motion.x;
  1780. eventData[P_Y] = evt.motion.y;
  1781. eventData[P_DX] = evt.motion.xrel;
  1782. eventData[P_DY] = evt.motion.yrel;
  1783. eventData[P_BUTTONS] = mouseButtonDown_;
  1784. eventData[P_QUALIFIERS] = GetQualifiers();
  1785. SendEvent(E_MOUSEMOVE, eventData);
  1786. }
  1787. }
  1788. // Only the left mouse button "finger" moves along with the mouse movement
  1789. else if (touchEmulation_ && touches_.Contains(0))
  1790. {
  1791. int x, y;
  1792. SDL_GetMouseState(&x, &y);
  1793. SDL_Event event;
  1794. event.type = SDL_FINGERMOTION;
  1795. event.tfinger.touchId = 0;
  1796. event.tfinger.fingerId = 0;
  1797. event.tfinger.pressure = 1.0f;
  1798. event.tfinger.x = (float)x / (float)graphics_->GetWidth();
  1799. event.tfinger.y = (float)y / (float)graphics_->GetHeight();
  1800. event.tfinger.dx = (float)evt.motion.xrel / (float)graphics_->GetWidth();
  1801. event.tfinger.dy = (float)evt.motion.yrel / (float)graphics_->GetHeight();
  1802. SDL_PushEvent(&event);
  1803. }
  1804. break;
  1805. case SDL_MOUSEWHEEL:
  1806. if (!touchEmulation_)
  1807. SetMouseWheel(evt.wheel.y);
  1808. break;
  1809. case SDL_FINGERDOWN:
  1810. if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
  1811. {
  1812. int touchID = GetTouchIndexFromID(evt.tfinger.fingerId & 0x7ffffff);
  1813. TouchState& state = touches_[touchID];
  1814. state.touchID_ = touchID;
  1815. state.lastPosition_ = state.position_ = IntVector2((int)(evt.tfinger.x * graphics_->GetWidth()),
  1816. (int)(evt.tfinger.y * graphics_->GetHeight()));
  1817. state.delta_ = IntVector2::ZERO;
  1818. state.pressure_ = evt.tfinger.pressure;
  1819. using namespace TouchBegin;
  1820. VariantMap& eventData = GetEventDataMap();
  1821. eventData[P_TOUCHID] = touchID;
  1822. eventData[P_X] = state.position_.x_;
  1823. eventData[P_Y] = state.position_.y_;
  1824. eventData[P_PRESSURE] = state.pressure_;
  1825. SendEvent(E_TOUCHBEGIN, eventData);
  1826. // Finger touch may move the mouse cursor. Suppress next mouse move when cursor hidden to prevent jumps
  1827. if (!mouseVisible_)
  1828. SuppressNextMouseMove();
  1829. }
  1830. break;
  1831. case SDL_FINGERUP:
  1832. if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
  1833. {
  1834. int touchID = GetTouchIndexFromID(evt.tfinger.fingerId & 0x7ffffff);
  1835. TouchState& state = touches_[touchID];
  1836. using namespace TouchEnd;
  1837. VariantMap& eventData = GetEventDataMap();
  1838. // Do not trust the position in the finger up event. Instead use the last position stored in the
  1839. // touch structure
  1840. eventData[P_TOUCHID] = touchID;
  1841. eventData[P_X] = state.position_.x_;
  1842. eventData[P_Y] = state.position_.y_;
  1843. SendEvent(E_TOUCHEND, eventData);
  1844. // Add touch index back to list of available touch Ids
  1845. PushTouchIndex(evt.tfinger.fingerId & 0x7ffffff);
  1846. touches_.Erase(touchID);
  1847. }
  1848. break;
  1849. case SDL_FINGERMOTION:
  1850. if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
  1851. {
  1852. int touchID = GetTouchIndexFromID(evt.tfinger.fingerId & 0x7ffffff);
  1853. // We don't want this event to create a new touches_ event if it doesn't exist (touchEmulation)
  1854. if (touchEmulation_ && !touches_.Contains(touchID))
  1855. break;
  1856. TouchState& state = touches_[touchID];
  1857. state.touchID_ = touchID;
  1858. state.position_ = IntVector2((int)(evt.tfinger.x * graphics_->GetWidth()),
  1859. (int)(evt.tfinger.y * graphics_->GetHeight()));
  1860. state.delta_ = state.position_ - state.lastPosition_;
  1861. state.pressure_ = evt.tfinger.pressure;
  1862. // ATOMIC BEGIN
  1863. state.touchedWidget_ = GetSubsystem<UI>()->GetWidgetAt(state.position_.x_, state.position_.y_, true);
  1864. // ATOMIC END
  1865. using namespace TouchMove;
  1866. VariantMap& eventData = GetEventDataMap();
  1867. eventData[P_TOUCHID] = touchID;
  1868. eventData[P_X] = state.position_.x_;
  1869. eventData[P_Y] = state.position_.y_;
  1870. eventData[P_DX] = (int)(evt.tfinger.dx * graphics_->GetWidth());
  1871. eventData[P_DY] = (int)(evt.tfinger.dy * graphics_->GetHeight());
  1872. eventData[P_PRESSURE] = state.pressure_;
  1873. SendEvent(E_TOUCHMOVE, eventData);
  1874. // Finger touch may move the mouse cursor. Suppress next mouse move when cursor hidden to prevent jumps
  1875. if (!mouseVisible_)
  1876. SuppressNextMouseMove();
  1877. }
  1878. break;
  1879. case SDL_DOLLARRECORD:
  1880. {
  1881. using namespace GestureRecorded;
  1882. VariantMap& eventData = GetEventDataMap();
  1883. eventData[P_GESTUREID] = (int)evt.dgesture.gestureId;
  1884. SendEvent(E_GESTURERECORDED, eventData);
  1885. }
  1886. break;
  1887. case SDL_DOLLARGESTURE:
  1888. {
  1889. using namespace GestureInput;
  1890. VariantMap& eventData = GetEventDataMap();
  1891. eventData[P_GESTUREID] = (int)evt.dgesture.gestureId;
  1892. eventData[P_CENTERX] = (int)(evt.dgesture.x * graphics_->GetWidth());
  1893. eventData[P_CENTERY] = (int)(evt.dgesture.y * graphics_->GetHeight());
  1894. eventData[P_NUMFINGERS] = (int)evt.dgesture.numFingers;
  1895. eventData[P_ERROR] = evt.dgesture.error;
  1896. SendEvent(E_GESTUREINPUT, eventData);
  1897. }
  1898. break;
  1899. case SDL_MULTIGESTURE:
  1900. {
  1901. using namespace MultiGesture;
  1902. VariantMap& eventData = GetEventDataMap();
  1903. eventData[P_CENTERX] = (int)(evt.mgesture.x * graphics_->GetWidth());
  1904. eventData[P_CENTERY] = (int)(evt.mgesture.y * graphics_->GetHeight());
  1905. eventData[P_NUMFINGERS] = (int)evt.mgesture.numFingers;
  1906. eventData[P_DTHETA] = M_RADTODEG * evt.mgesture.dTheta;
  1907. eventData[P_DDIST] = evt.mgesture.dDist;
  1908. SendEvent(E_MULTIGESTURE, eventData);
  1909. }
  1910. break;
  1911. case SDL_JOYDEVICEADDED:
  1912. {
  1913. using namespace JoystickConnected;
  1914. SDL_JoystickID joystickID = OpenJoystick((unsigned)evt.jdevice.which);
  1915. VariantMap& eventData = GetEventDataMap();
  1916. eventData[P_JOYSTICKID] = joystickID;
  1917. SendEvent(E_JOYSTICKCONNECTED, eventData);
  1918. }
  1919. break;
  1920. case SDL_JOYDEVICEREMOVED:
  1921. {
  1922. using namespace JoystickDisconnected;
  1923. joysticks_.Erase(evt.jdevice.which);
  1924. VariantMap& eventData = GetEventDataMap();
  1925. eventData[P_JOYSTICKID] = evt.jdevice.which;
  1926. SendEvent(E_JOYSTICKDISCONNECTED, eventData);
  1927. }
  1928. break;
  1929. case SDL_JOYBUTTONDOWN:
  1930. {
  1931. using namespace JoystickButtonDown;
  1932. unsigned button = evt.jbutton.button;
  1933. SDL_JoystickID joystickID = evt.jbutton.which;
  1934. JoystickState& state = joysticks_[joystickID];
  1935. // Skip ordinary joystick event for a controller
  1936. if (!state.controller_)
  1937. {
  1938. VariantMap& eventData = GetEventDataMap();
  1939. eventData[P_JOYSTICKID] = joystickID;
  1940. eventData[P_BUTTON] = button;
  1941. if (button < state.buttons_.Size())
  1942. {
  1943. state.buttons_[button] = true;
  1944. state.buttonPress_[button] = true;
  1945. SendEvent(E_JOYSTICKBUTTONDOWN, eventData);
  1946. }
  1947. }
  1948. }
  1949. break;
  1950. case SDL_JOYBUTTONUP:
  1951. {
  1952. using namespace JoystickButtonUp;
  1953. unsigned button = evt.jbutton.button;
  1954. SDL_JoystickID joystickID = evt.jbutton.which;
  1955. JoystickState& state = joysticks_[joystickID];
  1956. if (!state.controller_)
  1957. {
  1958. VariantMap& eventData = GetEventDataMap();
  1959. eventData[P_JOYSTICKID] = joystickID;
  1960. eventData[P_BUTTON] = button;
  1961. if (button < state.buttons_.Size())
  1962. {
  1963. if (!state.controller_)
  1964. state.buttons_[button] = false;
  1965. SendEvent(E_JOYSTICKBUTTONUP, eventData);
  1966. }
  1967. }
  1968. }
  1969. break;
  1970. case SDL_JOYAXISMOTION:
  1971. {
  1972. using namespace JoystickAxisMove;
  1973. SDL_JoystickID joystickID = evt.jaxis.which;
  1974. JoystickState& state = joysticks_[joystickID];
  1975. if (!state.controller_)
  1976. {
  1977. VariantMap& eventData = GetEventDataMap();
  1978. eventData[P_JOYSTICKID] = joystickID;
  1979. eventData[P_AXIS] = evt.jaxis.axis;
  1980. eventData[P_POSITION] = Clamp((float)evt.jaxis.value / 32767.0f, -1.0f, 1.0f);
  1981. if (evt.jaxis.axis < state.axes_.Size())
  1982. {
  1983. // If the joystick is a controller, only use the controller axis mappings
  1984. // (we'll also get the controller event)
  1985. if (!state.controller_)
  1986. state.axes_[evt.jaxis.axis] = eventData[P_POSITION].GetFloat();
  1987. SendEvent(E_JOYSTICKAXISMOVE, eventData);
  1988. }
  1989. }
  1990. }
  1991. break;
  1992. case SDL_JOYHATMOTION:
  1993. {
  1994. using namespace JoystickHatMove;
  1995. SDL_JoystickID joystickID = evt.jaxis.which;
  1996. JoystickState& state = joysticks_[joystickID];
  1997. VariantMap& eventData = GetEventDataMap();
  1998. eventData[P_JOYSTICKID] = joystickID;
  1999. eventData[P_HAT] = evt.jhat.hat;
  2000. eventData[P_POSITION] = evt.jhat.value;
  2001. if (evt.jhat.hat < state.hats_.Size())
  2002. {
  2003. state.hats_[evt.jhat.hat] = evt.jhat.value;
  2004. SendEvent(E_JOYSTICKHATMOVE, eventData);
  2005. }
  2006. }
  2007. break;
  2008. case SDL_CONTROLLERBUTTONDOWN:
  2009. {
  2010. using namespace JoystickButtonDown;
  2011. unsigned button = evt.cbutton.button;
  2012. SDL_JoystickID joystickID = evt.cbutton.which;
  2013. JoystickState& state = joysticks_[joystickID];
  2014. VariantMap& eventData = GetEventDataMap();
  2015. eventData[P_JOYSTICKID] = joystickID;
  2016. eventData[P_BUTTON] = button;
  2017. if (button < state.buttons_.Size())
  2018. {
  2019. state.buttons_[button] = true;
  2020. state.buttonPress_[button] = true;
  2021. SendEvent(E_JOYSTICKBUTTONDOWN, eventData);
  2022. }
  2023. }
  2024. break;
  2025. case SDL_CONTROLLERBUTTONUP:
  2026. {
  2027. using namespace JoystickButtonUp;
  2028. unsigned button = evt.cbutton.button;
  2029. SDL_JoystickID joystickID = evt.cbutton.which;
  2030. JoystickState& state = joysticks_[joystickID];
  2031. VariantMap& eventData = GetEventDataMap();
  2032. eventData[P_JOYSTICKID] = joystickID;
  2033. eventData[P_BUTTON] = button;
  2034. if (button < state.buttons_.Size())
  2035. {
  2036. state.buttons_[button] = false;
  2037. SendEvent(E_JOYSTICKBUTTONUP, eventData);
  2038. }
  2039. }
  2040. break;
  2041. case SDL_CONTROLLERAXISMOTION:
  2042. {
  2043. using namespace JoystickAxisMove;
  2044. SDL_JoystickID joystickID = evt.caxis.which;
  2045. JoystickState& state = joysticks_[joystickID];
  2046. VariantMap& eventData = GetEventDataMap();
  2047. eventData[P_JOYSTICKID] = joystickID;
  2048. eventData[P_AXIS] = evt.caxis.axis;
  2049. eventData[P_POSITION] = Clamp((float)evt.caxis.value / 32767.0f, -1.0f, 1.0f);
  2050. if (evt.caxis.axis < state.axes_.Size())
  2051. {
  2052. state.axes_[evt.caxis.axis] = eventData[P_POSITION].GetFloat();
  2053. SendEvent(E_JOYSTICKAXISMOVE, eventData);
  2054. }
  2055. }
  2056. break;
  2057. case SDL_WINDOWEVENT:
  2058. {
  2059. switch (evt.window.event)
  2060. {
  2061. case SDL_WINDOWEVENT_MINIMIZED:
  2062. minimized_ = true;
  2063. SendInputFocusEvent();
  2064. break;
  2065. case SDL_WINDOWEVENT_MAXIMIZED:
  2066. case SDL_WINDOWEVENT_RESTORED:
  2067. #if defined(IOS) || defined (__ANDROID__)
  2068. // On iOS we never lose the GL context, but may have done GPU object changes that could not be applied yet. Apply them now
  2069. // On Android the old GL context may be lost already, restore GPU objects to the new GL context
  2070. graphics_->Restore();
  2071. #endif
  2072. minimized_ = false;
  2073. SendInputFocusEvent();
  2074. break;
  2075. case SDL_WINDOWEVENT_RESIZED:
  2076. inResize_ = true;
  2077. graphics_->OnWindowResized();
  2078. inResize_ = false;
  2079. break;
  2080. case SDL_WINDOWEVENT_MOVED:
  2081. graphics_->OnWindowMoved();
  2082. break;
  2083. default: break;
  2084. }
  2085. }
  2086. break;
  2087. case SDL_DROPFILE:
  2088. {
  2089. using namespace DropFile;
  2090. VariantMap& eventData = GetEventDataMap();
  2091. eventData[P_FILENAME] = GetInternalPath(String(evt.drop.file));
  2092. SDL_free(evt.drop.file);
  2093. SendEvent(E_DROPFILE, eventData);
  2094. }
  2095. break;
  2096. case SDL_QUIT:
  2097. SendEvent(E_EXITREQUESTED);
  2098. break;
  2099. default: break;
  2100. }
  2101. }
  2102. void Input::HandleScreenMode(StringHash eventType, VariantMap& eventData)
  2103. {
  2104. if (!initialized_)
  2105. Initialize();
  2106. // Re-enable cursor clipping, and re-center the cursor (if needed) to the new screen size, so that there is no erroneous
  2107. // mouse move event. Also get new window ID if it changed
  2108. SDL_Window* window = graphics_->GetWindow();
  2109. windowID_ = SDL_GetWindowID(window);
  2110. // If screen mode happens due to mouse drag resize, do not recenter the mouse as that would lead to erratic window sizes
  2111. if (!mouseVisible_ && mouseMode_ != MM_FREE && !inResize_)
  2112. {
  2113. CenterMousePosition();
  2114. focusedThisFrame_ = true;
  2115. }
  2116. else
  2117. lastMousePosition_ = GetMousePosition();
  2118. // ATOMIC BEGIN
  2119. /*
  2120. // Resize screen joysticks to new screen size
  2121. for (HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
  2122. {
  2123. UIElement* screenjoystick = i->second_.screenJoystick_;
  2124. if (screenjoystick)
  2125. screenjoystick->SetSize(graphics_->GetWidth(), graphics_->GetHeight());
  2126. }
  2127. */
  2128. // ATOMIC END
  2129. if (graphics_->GetFullscreen())
  2130. focusedThisFrame_ = true;
  2131. // After setting a new screen mode we should not be minimized
  2132. minimized_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) != 0;
  2133. // Remember that screen mode changed in case we lose focus (needed on Linux)
  2134. if (!inResize_)
  2135. screenModeChanged_ = true;
  2136. }
  2137. void Input::HandleBeginFrame(StringHash eventType, VariantMap& eventData)
  2138. {
  2139. // Update input right at the beginning of the frame
  2140. SendEvent(E_INPUTBEGIN);
  2141. Update();
  2142. SendEvent(E_INPUTEND);
  2143. }
  2144. #ifdef __EMSCRIPTEN__
  2145. void Input::HandleEndFrame(StringHash eventType, VariantMap& eventData)
  2146. {
  2147. if (suppressNextMouseMove_ && mouseMove_ != IntVector2::ZERO)
  2148. UnsuppressMouseMove();
  2149. ResetInputAccumulation();
  2150. }
  2151. #endif
  2152. void Input::HandleScreenJoystickTouch(StringHash eventType, VariantMap& eventData)
  2153. {
  2154. // ATOMIC BEGIN
  2155. /*
  2156. using namespace TouchBegin;
  2157. // Only interested in events from screen joystick(s)
  2158. TouchState& state = touches_[eventData[P_TOUCHID].GetInt()];
  2159. IntVector2 position(int(state.position_.x_ / GetSubsystem<UI>()->GetScale()), int(state.position_.y_ / GetSubsystem<UI>()->GetScale()));
  2160. UIElement* element = eventType == E_TOUCHBEGIN ? GetSubsystem<UI>()->GetElementAt(position) : state.touchedElement_;
  2161. if (!element)
  2162. return;
  2163. Variant variant = element->GetVar(VAR_SCREEN_JOYSTICK_ID);
  2164. if (variant.IsEmpty())
  2165. return;
  2166. SDL_JoystickID joystickID = variant.GetInt();
  2167. if (eventType == E_TOUCHEND)
  2168. state.touchedElement_.Reset();
  2169. else
  2170. state.touchedElement_ = element;
  2171. // Prepare a fake SDL event
  2172. SDL_Event evt;
  2173. const String& name = element->GetName();
  2174. if (name.StartsWith("Button"))
  2175. {
  2176. if (eventType == E_TOUCHMOVE)
  2177. return;
  2178. // Determine whether to inject a joystick event or keyboard/mouse event
  2179. Variant keyBindingVar = element->GetVar(VAR_BUTTON_KEY_BINDING);
  2180. Variant mouseButtonBindingVar = element->GetVar(VAR_BUTTON_MOUSE_BUTTON_BINDING);
  2181. if (keyBindingVar.IsEmpty() && mouseButtonBindingVar.IsEmpty())
  2182. {
  2183. evt.type = eventType == E_TOUCHBEGIN ? SDL_JOYBUTTONDOWN : SDL_JOYBUTTONUP;
  2184. evt.jbutton.which = joystickID;
  2185. evt.jbutton.button = (Uint8)ToUInt(name.Substring(6));
  2186. }
  2187. else
  2188. {
  2189. if (!keyBindingVar.IsEmpty())
  2190. {
  2191. evt.type = eventType == E_TOUCHBEGIN ? SDL_KEYDOWN : SDL_KEYUP;
  2192. evt.key.keysym.sym = ToLower(keyBindingVar.GetInt());
  2193. evt.key.keysym.scancode = SDL_SCANCODE_UNKNOWN;
  2194. }
  2195. if (!mouseButtonBindingVar.IsEmpty())
  2196. {
  2197. // Mouse button are sent as extra events besides key events
  2198. // Disable touch emulation handling during this to prevent endless loop
  2199. bool oldTouchEmulation = touchEmulation_;
  2200. touchEmulation_ = false;
  2201. SDL_Event mouseEvent;
  2202. mouseEvent.type = eventType == E_TOUCHBEGIN ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP;
  2203. mouseEvent.button.button = (Uint8)mouseButtonBindingVar.GetInt();
  2204. HandleSDLEvent(&mouseEvent);
  2205. touchEmulation_ = oldTouchEmulation;
  2206. }
  2207. }
  2208. }
  2209. else if (name.StartsWith("Hat"))
  2210. {
  2211. Variant keyBindingVar = element->GetVar(VAR_BUTTON_KEY_BINDING);
  2212. if (keyBindingVar.IsEmpty())
  2213. {
  2214. evt.type = SDL_JOYHATMOTION;
  2215. evt.jaxis.which = joystickID;
  2216. evt.jhat.hat = (Uint8)ToUInt(name.Substring(3));
  2217. evt.jhat.value = HAT_CENTER;
  2218. if (eventType != E_TOUCHEND)
  2219. {
  2220. IntVector2 relPosition = position - element->GetScreenPosition() - element->GetSize() / 2;
  2221. if (relPosition.y_ < 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  2222. evt.jhat.value |= HAT_UP;
  2223. if (relPosition.y_ > 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  2224. evt.jhat.value |= HAT_DOWN;
  2225. if (relPosition.x_ < 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  2226. evt.jhat.value |= HAT_LEFT;
  2227. if (relPosition.x_ > 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  2228. evt.jhat.value |= HAT_RIGHT;
  2229. }
  2230. }
  2231. else
  2232. {
  2233. // Hat is binded by 4 integers representing keysyms for 'w', 's', 'a', 'd' or something similar
  2234. IntRect keyBinding = keyBindingVar.GetIntRect();
  2235. if (eventType == E_TOUCHEND)
  2236. {
  2237. evt.type = SDL_KEYUP;
  2238. evt.key.keysym.sym = element->GetVar(VAR_LAST_KEYSYM).GetInt();
  2239. if (!evt.key.keysym.sym)
  2240. return;
  2241. element->SetVar(VAR_LAST_KEYSYM, 0);
  2242. }
  2243. else
  2244. {
  2245. evt.type = SDL_KEYDOWN;
  2246. IntVector2 relPosition = position - element->GetScreenPosition() - element->GetSize() / 2;
  2247. if (relPosition.y_ < 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  2248. evt.key.keysym.sym = keyBinding.left_; // The integers are encoded in WSAD order to l-t-r-b
  2249. else if (relPosition.y_ > 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  2250. evt.key.keysym.sym = keyBinding.top_;
  2251. else if (relPosition.x_ < 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  2252. evt.key.keysym.sym = keyBinding.right_;
  2253. else if (relPosition.x_ > 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  2254. evt.key.keysym.sym = keyBinding.bottom_;
  2255. else
  2256. return;
  2257. if (eventType == E_TOUCHMOVE && evt.key.keysym.sym != element->GetVar(VAR_LAST_KEYSYM).GetInt())
  2258. {
  2259. // Dragging past the directional boundary will cause an additional key up event for previous key symbol
  2260. SDL_Event keyEvent;
  2261. keyEvent.type = SDL_KEYUP;
  2262. keyEvent.key.keysym.sym = element->GetVar(VAR_LAST_KEYSYM).GetInt();
  2263. if (keyEvent.key.keysym.sym)
  2264. {
  2265. keyEvent.key.keysym.scancode = SDL_SCANCODE_UNKNOWN;
  2266. HandleSDLEvent(&keyEvent);
  2267. }
  2268. element->SetVar(VAR_LAST_KEYSYM, 0);
  2269. }
  2270. evt.key.keysym.scancode = SDL_SCANCODE_UNKNOWN;
  2271. element->SetVar(VAR_LAST_KEYSYM, evt.key.keysym.sym);
  2272. }
  2273. }
  2274. }
  2275. else
  2276. return;
  2277. // Handle the fake SDL event to turn it into Urho3D genuine event
  2278. HandleSDLEvent(&evt);
  2279. */
  2280. // ATOMIC END
  2281. }
  2282. // ATOMIC BEGIN
  2283. void Input::SimulateButtonDown(int button)
  2284. {
  2285. SDL_Event evt;
  2286. evt.type = SDL_KEYDOWN;
  2287. evt.key.keysym.sym = button;
  2288. HandleSDLEvent(&evt);
  2289. }
  2290. void Input::SimulateButtonUp(int button)
  2291. {
  2292. SDL_Event evt;
  2293. evt.type = SDL_KEYUP;
  2294. evt.key.keysym.sym = button;
  2295. HandleSDLEvent(&evt);
  2296. }
  2297. // ATOMIC END
  2298. }