/indra/newview/llviewerkeyboard.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 978 lines · 765 code · 129 blank · 84 comment · 195 complexity · be892abf29f35a37cb161c53dff39fd8 MD5 · raw file

  1. /**
  2. * @file llviewerkeyboard.cpp
  3. * @brief LLViewerKeyboard class implementation
  4. *
  5. * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llappviewer.h"
  28. #include "llviewerkeyboard.h"
  29. #include "llmath.h"
  30. #include "llagent.h"
  31. #include "llagentcamera.h"
  32. #include "llnearbychatbar.h"
  33. #include "llviewercontrol.h"
  34. #include "llfocusmgr.h"
  35. #include "llmorphview.h"
  36. #include "llmoveview.h"
  37. #include "lltoolfocus.h"
  38. #include "llviewerwindow.h"
  39. #include "llvoavatarself.h"
  40. #include "llfloatercamera.h"
  41. #include "llinitparam.h"
  42. //
  43. // Constants
  44. //
  45. const F32 FLY_TIME = 0.5f;
  46. const F32 FLY_FRAMES = 4;
  47. const F32 NUDGE_TIME = 0.25f; // in seconds
  48. const S32 NUDGE_FRAMES = 2;
  49. const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed
  50. const F32 YAW_NUDGE_RATE = 0.05f; // fraction of normal speed
  51. struct LLKeyboardActionRegistry
  52. : public LLRegistrySingleton<std::string, boost::function<void (EKeystate keystate)>, LLKeyboardActionRegistry>
  53. {
  54. };
  55. LLViewerKeyboard gViewerKeyboard;
  56. void agent_jump( EKeystate s )
  57. {
  58. if( KEYSTATE_UP == s ) return;
  59. F32 time = gKeyboard->getCurKeyElapsedTime();
  60. S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
  61. if( time < FLY_TIME
  62. || frame_count <= FLY_FRAMES
  63. || gAgent.upGrabbed()
  64. || !gSavedSettings.getBOOL("AutomaticFly"))
  65. {
  66. gAgent.moveUp(1);
  67. }
  68. else
  69. {
  70. gAgent.setFlying(TRUE);
  71. gAgent.moveUp(1);
  72. }
  73. }
  74. void agent_push_down( EKeystate s )
  75. {
  76. if( KEYSTATE_UP == s ) return;
  77. gAgent.moveUp(-1);
  78. }
  79. static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode mode)
  80. {
  81. if (KEYSTATE_UP == s)
  82. {
  83. if (gAgent.mDoubleTapRunMode == mode &&
  84. gAgent.getRunning() &&
  85. !gAgent.getAlwaysRun())
  86. {
  87. // Turn off temporary running.
  88. gAgent.clearRunning();
  89. gAgent.sendWalkRun(gAgent.getRunning());
  90. }
  91. }
  92. else if (gSavedSettings.getBOOL("AllowTapTapHoldRun") &&
  93. KEYSTATE_DOWN == s &&
  94. !gAgent.getRunning())
  95. {
  96. if (gAgent.mDoubleTapRunMode == mode &&
  97. gAgent.mDoubleTapRunTimer.getElapsedTimeF32() < NUDGE_TIME)
  98. {
  99. // Same walk-key was pushed again quickly; this is a
  100. // double-tap so engage temporary running.
  101. gAgent.setRunning();
  102. gAgent.sendWalkRun(gAgent.getRunning());
  103. }
  104. // Pressing any walk-key resets the double-tap timer
  105. gAgent.mDoubleTapRunTimer.reset();
  106. gAgent.mDoubleTapRunMode = mode;
  107. }
  108. }
  109. static void agent_push_forwardbackward( EKeystate s, S32 direction, LLAgent::EDoubleTapRunMode mode )
  110. {
  111. agent_handle_doubletap_run(s, mode);
  112. if (KEYSTATE_UP == s) return;
  113. F32 time = gKeyboard->getCurKeyElapsedTime();
  114. S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
  115. if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
  116. {
  117. gAgent.moveAtNudge(direction);
  118. }
  119. else
  120. {
  121. gAgent.moveAt(direction);
  122. }
  123. }
  124. void camera_move_forward( EKeystate s );
  125. void agent_push_forward( EKeystate s )
  126. {
  127. //in free camera control mode we need to intercept keyboard events for avatar movements
  128. if (LLFloaterCamera::inFreeCameraMode())
  129. {
  130. camera_move_forward(s);
  131. return;
  132. }
  133. agent_push_forwardbackward(s, 1, LLAgent::DOUBLETAP_FORWARD);
  134. }
  135. void camera_move_backward( EKeystate s );
  136. void agent_push_backward( EKeystate s )
  137. {
  138. //in free camera control mode we need to intercept keyboard events for avatar movements
  139. if (LLFloaterCamera::inFreeCameraMode())
  140. {
  141. camera_move_backward(s);
  142. return;
  143. }
  144. agent_push_forwardbackward(s, -1, LLAgent::DOUBLETAP_BACKWARD);
  145. }
  146. static void agent_slide_leftright( EKeystate s, S32 direction, LLAgent::EDoubleTapRunMode mode )
  147. {
  148. agent_handle_doubletap_run(s, mode);
  149. if( KEYSTATE_UP == s ) return;
  150. F32 time = gKeyboard->getCurKeyElapsedTime();
  151. S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
  152. if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
  153. {
  154. gAgent.moveLeftNudge(direction);
  155. }
  156. else
  157. {
  158. gAgent.moveLeft(direction);
  159. }
  160. }
  161. void agent_slide_left( EKeystate s )
  162. {
  163. agent_slide_leftright(s, 1, LLAgent::DOUBLETAP_SLIDELEFT);
  164. }
  165. void agent_slide_right( EKeystate s )
  166. {
  167. agent_slide_leftright(s, -1, LLAgent::DOUBLETAP_SLIDERIGHT);
  168. }
  169. void camera_spin_around_cw( EKeystate s );
  170. void agent_turn_left( EKeystate s )
  171. {
  172. //in free camera control mode we need to intercept keyboard events for avatar movements
  173. if (LLFloaterCamera::inFreeCameraMode())
  174. {
  175. camera_spin_around_cw(s);
  176. return;
  177. }
  178. if (LLToolCamera::getInstance()->mouseSteerMode())
  179. {
  180. agent_slide_left(s);
  181. }
  182. else
  183. {
  184. if (KEYSTATE_UP == s) return;
  185. F32 time = gKeyboard->getCurKeyElapsedTime();
  186. gAgent.moveYaw( LLFloaterMove::getYawRate( time ) );
  187. }
  188. }
  189. void camera_spin_around_ccw( EKeystate s );
  190. void agent_turn_right( EKeystate s )
  191. {
  192. //in free camera control mode we need to intercept keyboard events for avatar movements
  193. if (LLFloaterCamera::inFreeCameraMode())
  194. {
  195. camera_spin_around_ccw(s);
  196. return;
  197. }
  198. if (LLToolCamera::getInstance()->mouseSteerMode())
  199. {
  200. agent_slide_right(s);
  201. }
  202. else
  203. {
  204. if (KEYSTATE_UP == s) return;
  205. F32 time = gKeyboard->getCurKeyElapsedTime();
  206. gAgent.moveYaw( -LLFloaterMove::getYawRate( time ) );
  207. }
  208. }
  209. void agent_look_up( EKeystate s )
  210. {
  211. if( KEYSTATE_UP == s ) return;
  212. gAgent.movePitch(-1);
  213. //gAgent.rotate(-2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
  214. }
  215. void agent_look_down( EKeystate s )
  216. {
  217. if( KEYSTATE_UP == s ) return;
  218. gAgent.movePitch(1);
  219. //gAgent.rotate(2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
  220. }
  221. void agent_toggle_fly( EKeystate s )
  222. {
  223. // Only catch the edge
  224. if (KEYSTATE_DOWN == s )
  225. {
  226. LLAgent::toggleFlying();
  227. }
  228. }
  229. F32 get_orbit_rate()
  230. {
  231. F32 time = gKeyboard->getCurKeyElapsedTime();
  232. if( time < NUDGE_TIME )
  233. {
  234. F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME;
  235. //llinfos << rate << llendl;
  236. return rate;
  237. }
  238. else
  239. {
  240. return 1;
  241. }
  242. }
  243. void camera_spin_around_ccw( EKeystate s )
  244. {
  245. if( KEYSTATE_UP == s ) return;
  246. gAgentCamera.unlockView();
  247. gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
  248. }
  249. void camera_spin_around_cw( EKeystate s )
  250. {
  251. if( KEYSTATE_UP == s ) return;
  252. gAgentCamera.unlockView();
  253. gAgentCamera.setOrbitRightKey( get_orbit_rate() );
  254. }
  255. void camera_spin_around_ccw_sitting( EKeystate s )
  256. {
  257. if( KEYSTATE_UP == s ) return;
  258. if (gAgent.rotateGrabbed() || gAgentCamera.sitCameraEnabled())
  259. {
  260. //send keystrokes, but do not change camera
  261. agent_turn_right(s);
  262. }
  263. else
  264. {
  265. //change camera but do not send keystrokes
  266. gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
  267. }
  268. }
  269. void camera_spin_around_cw_sitting( EKeystate s )
  270. {
  271. if( KEYSTATE_UP == s ) return;
  272. if (gAgent.rotateGrabbed() || gAgentCamera.sitCameraEnabled())
  273. {
  274. //send keystrokes, but do not change camera
  275. agent_turn_left(s);
  276. }
  277. else
  278. {
  279. //change camera but do not send keystrokes
  280. gAgentCamera.setOrbitRightKey( get_orbit_rate() );
  281. }
  282. }
  283. void camera_spin_over( EKeystate s )
  284. {
  285. if( KEYSTATE_UP == s ) return;
  286. gAgentCamera.unlockView();
  287. gAgentCamera.setOrbitUpKey( get_orbit_rate() );
  288. }
  289. void camera_spin_under( EKeystate s )
  290. {
  291. if( KEYSTATE_UP == s ) return;
  292. gAgentCamera.unlockView();
  293. gAgentCamera.setOrbitDownKey( get_orbit_rate() );
  294. }
  295. void camera_spin_over_sitting( EKeystate s )
  296. {
  297. if( KEYSTATE_UP == s ) return;
  298. if (gAgent.upGrabbed() || gAgentCamera.sitCameraEnabled())
  299. {
  300. //send keystrokes, but do not change camera
  301. agent_jump(s);
  302. }
  303. else
  304. {
  305. //change camera but do not send keystrokes
  306. gAgentCamera.setOrbitUpKey( get_orbit_rate() );
  307. }
  308. }
  309. void camera_spin_under_sitting( EKeystate s )
  310. {
  311. if( KEYSTATE_UP == s ) return;
  312. if (gAgent.downGrabbed() || gAgentCamera.sitCameraEnabled())
  313. {
  314. //send keystrokes, but do not change camera
  315. agent_push_down(s);
  316. }
  317. else
  318. {
  319. //change camera but do not send keystrokes
  320. gAgentCamera.setOrbitDownKey( get_orbit_rate() );
  321. }
  322. }
  323. void camera_move_forward( EKeystate s )
  324. {
  325. if( KEYSTATE_UP == s ) return;
  326. gAgentCamera.unlockView();
  327. gAgentCamera.setOrbitInKey( get_orbit_rate() );
  328. }
  329. void camera_move_backward( EKeystate s )
  330. {
  331. if( KEYSTATE_UP == s ) return;
  332. gAgentCamera.unlockView();
  333. gAgentCamera.setOrbitOutKey( get_orbit_rate() );
  334. }
  335. void camera_move_forward_sitting( EKeystate s )
  336. {
  337. if( KEYSTATE_UP == s ) return;
  338. if (gAgent.forwardGrabbed() || gAgentCamera.sitCameraEnabled())
  339. {
  340. agent_push_forward(s);
  341. }
  342. else
  343. {
  344. gAgentCamera.setOrbitInKey( get_orbit_rate() );
  345. }
  346. }
  347. void camera_move_backward_sitting( EKeystate s )
  348. {
  349. if( KEYSTATE_UP == s ) return;
  350. if (gAgent.backwardGrabbed() || gAgentCamera.sitCameraEnabled())
  351. {
  352. agent_push_backward(s);
  353. }
  354. else
  355. {
  356. gAgentCamera.setOrbitOutKey( get_orbit_rate() );
  357. }
  358. }
  359. void camera_pan_up( EKeystate s )
  360. {
  361. if( KEYSTATE_UP == s ) return;
  362. gAgentCamera.unlockView();
  363. gAgentCamera.setPanUpKey( get_orbit_rate() );
  364. }
  365. void camera_pan_down( EKeystate s )
  366. {
  367. if( KEYSTATE_UP == s ) return;
  368. gAgentCamera.unlockView();
  369. gAgentCamera.setPanDownKey( get_orbit_rate() );
  370. }
  371. void camera_pan_left( EKeystate s )
  372. {
  373. if( KEYSTATE_UP == s ) return;
  374. gAgentCamera.unlockView();
  375. gAgentCamera.setPanLeftKey( get_orbit_rate() );
  376. }
  377. void camera_pan_right( EKeystate s )
  378. {
  379. if( KEYSTATE_UP == s ) return;
  380. gAgentCamera.unlockView();
  381. gAgentCamera.setPanRightKey( get_orbit_rate() );
  382. }
  383. void camera_pan_in( EKeystate s )
  384. {
  385. if( KEYSTATE_UP == s ) return;
  386. gAgentCamera.unlockView();
  387. gAgentCamera.setPanInKey( get_orbit_rate() );
  388. }
  389. void camera_pan_out( EKeystate s )
  390. {
  391. if( KEYSTATE_UP == s ) return;
  392. gAgentCamera.unlockView();
  393. gAgentCamera.setPanOutKey( get_orbit_rate() );
  394. }
  395. void camera_move_forward_fast( EKeystate s )
  396. {
  397. if( KEYSTATE_UP == s ) return;
  398. gAgentCamera.unlockView();
  399. gAgentCamera.setOrbitInKey(2.5f);
  400. }
  401. void camera_move_backward_fast( EKeystate s )
  402. {
  403. if( KEYSTATE_UP == s ) return;
  404. gAgentCamera.unlockView();
  405. gAgentCamera.setOrbitOutKey(2.5f);
  406. }
  407. void edit_avatar_spin_ccw( EKeystate s )
  408. {
  409. if( KEYSTATE_UP == s ) return;
  410. gMorphView->setCameraDrivenByKeys( TRUE );
  411. gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
  412. //gMorphView->orbitLeft( get_orbit_rate() );
  413. }
  414. void edit_avatar_spin_cw( EKeystate s )
  415. {
  416. if( KEYSTATE_UP == s ) return;
  417. gMorphView->setCameraDrivenByKeys( TRUE );
  418. gAgentCamera.setOrbitRightKey( get_orbit_rate() );
  419. //gMorphView->orbitRight( get_orbit_rate() );
  420. }
  421. void edit_avatar_spin_over( EKeystate s )
  422. {
  423. if( KEYSTATE_UP == s ) return;
  424. gMorphView->setCameraDrivenByKeys( TRUE );
  425. gAgentCamera.setOrbitUpKey( get_orbit_rate() );
  426. //gMorphView->orbitUp( get_orbit_rate() );
  427. }
  428. void edit_avatar_spin_under( EKeystate s )
  429. {
  430. if( KEYSTATE_UP == s ) return;
  431. gMorphView->setCameraDrivenByKeys( TRUE );
  432. gAgentCamera.setOrbitDownKey( get_orbit_rate() );
  433. //gMorphView->orbitDown( get_orbit_rate() );
  434. }
  435. void edit_avatar_move_forward( EKeystate s )
  436. {
  437. if( KEYSTATE_UP == s ) return;
  438. gMorphView->setCameraDrivenByKeys( TRUE );
  439. gAgentCamera.setOrbitInKey( get_orbit_rate() );
  440. //gMorphView->orbitIn();
  441. }
  442. void edit_avatar_move_backward( EKeystate s )
  443. {
  444. if( KEYSTATE_UP == s ) return;
  445. gMorphView->setCameraDrivenByKeys( TRUE );
  446. gAgentCamera.setOrbitOutKey( get_orbit_rate() );
  447. //gMorphView->orbitOut();
  448. }
  449. void stop_moving( EKeystate s )
  450. {
  451. if( KEYSTATE_UP == s ) return;
  452. // stop agent
  453. gAgent.setControlFlags(AGENT_CONTROL_STOP);
  454. // cancel autopilot
  455. gAgent.stopAutoPilot();
  456. }
  457. void start_chat( EKeystate s )
  458. {
  459. // start chat
  460. LLNearbyChatBar::startChat(NULL);
  461. }
  462. void start_gesture( EKeystate s )
  463. {
  464. LLUICtrl* focus_ctrlp = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
  465. if (KEYSTATE_UP == s &&
  466. ! (focus_ctrlp && focus_ctrlp->acceptsTextInput()))
  467. {
  468. if (LLNearbyChatBar::getInstance()->getCurrentChat().empty())
  469. {
  470. // No existing chat in chat editor, insert '/'
  471. LLNearbyChatBar::startChat("/");
  472. }
  473. else
  474. {
  475. // Don't overwrite existing text in chat editor
  476. LLNearbyChatBar::startChat(NULL);
  477. }
  478. }
  479. }
  480. #define REGISTER_KEYBOARD_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, ACTION);
  481. REGISTER_KEYBOARD_ACTION("jump", agent_jump);
  482. REGISTER_KEYBOARD_ACTION("push_down", agent_push_down);
  483. REGISTER_KEYBOARD_ACTION("push_forward", agent_push_forward);
  484. REGISTER_KEYBOARD_ACTION("push_backward", agent_push_backward);
  485. REGISTER_KEYBOARD_ACTION("look_up", agent_look_up);
  486. REGISTER_KEYBOARD_ACTION("look_down", agent_look_down);
  487. REGISTER_KEYBOARD_ACTION("toggle_fly", agent_toggle_fly);
  488. REGISTER_KEYBOARD_ACTION("turn_left", agent_turn_left);
  489. REGISTER_KEYBOARD_ACTION("turn_right", agent_turn_right);
  490. REGISTER_KEYBOARD_ACTION("slide_left", agent_slide_left);
  491. REGISTER_KEYBOARD_ACTION("slide_right", agent_slide_right);
  492. REGISTER_KEYBOARD_ACTION("spin_around_ccw", camera_spin_around_ccw);
  493. REGISTER_KEYBOARD_ACTION("spin_around_cw", camera_spin_around_cw);
  494. REGISTER_KEYBOARD_ACTION("spin_around_ccw_sitting", camera_spin_around_ccw_sitting);
  495. REGISTER_KEYBOARD_ACTION("spin_around_cw_sitting", camera_spin_around_cw_sitting);
  496. REGISTER_KEYBOARD_ACTION("spin_over", camera_spin_over);
  497. REGISTER_KEYBOARD_ACTION("spin_under", camera_spin_under);
  498. REGISTER_KEYBOARD_ACTION("spin_over_sitting", camera_spin_over_sitting);
  499. REGISTER_KEYBOARD_ACTION("spin_under_sitting", camera_spin_under_sitting);
  500. REGISTER_KEYBOARD_ACTION("move_forward", camera_move_forward);
  501. REGISTER_KEYBOARD_ACTION("move_backward", camera_move_backward);
  502. REGISTER_KEYBOARD_ACTION("move_forward_sitting", camera_move_forward_sitting);
  503. REGISTER_KEYBOARD_ACTION("move_backward_sitting", camera_move_backward_sitting);
  504. REGISTER_KEYBOARD_ACTION("pan_up", camera_pan_up);
  505. REGISTER_KEYBOARD_ACTION("pan_down", camera_pan_down);
  506. REGISTER_KEYBOARD_ACTION("pan_left", camera_pan_left);
  507. REGISTER_KEYBOARD_ACTION("pan_right", camera_pan_right);
  508. REGISTER_KEYBOARD_ACTION("pan_in", camera_pan_in);
  509. REGISTER_KEYBOARD_ACTION("pan_out", camera_pan_out);
  510. REGISTER_KEYBOARD_ACTION("move_forward_fast", camera_move_forward_fast);
  511. REGISTER_KEYBOARD_ACTION("move_backward_fast", camera_move_backward_fast);
  512. REGISTER_KEYBOARD_ACTION("edit_avatar_spin_ccw", edit_avatar_spin_ccw);
  513. REGISTER_KEYBOARD_ACTION("edit_avatar_spin_cw", edit_avatar_spin_cw);
  514. REGISTER_KEYBOARD_ACTION("edit_avatar_spin_over", edit_avatar_spin_over);
  515. REGISTER_KEYBOARD_ACTION("edit_avatar_spin_under", edit_avatar_spin_under);
  516. REGISTER_KEYBOARD_ACTION("edit_avatar_move_forward", edit_avatar_move_forward);
  517. REGISTER_KEYBOARD_ACTION("edit_avatar_move_backward", edit_avatar_move_backward);
  518. REGISTER_KEYBOARD_ACTION("stop_moving", stop_moving);
  519. REGISTER_KEYBOARD_ACTION("start_chat", start_chat);
  520. REGISTER_KEYBOARD_ACTION("start_gesture", start_gesture);
  521. #undef REGISTER_KEYBOARD_ACTION
  522. LLViewerKeyboard::LLViewerKeyboard()
  523. {
  524. for (S32 i = 0; i < MODE_COUNT; i++)
  525. {
  526. mBindingCount[i] = 0;
  527. }
  528. for (S32 i = 0; i < KEY_COUNT; i++)
  529. {
  530. mKeyHandledByUI[i] = FALSE;
  531. }
  532. // we want the UI to never see these keys so that they can always control the avatar/camera
  533. for(KEY k = KEY_PAD_UP; k <= KEY_PAD_DIVIDE; k++)
  534. {
  535. mKeysSkippedByUI.insert(k);
  536. }
  537. }
  538. BOOL LLViewerKeyboard::modeFromString(const std::string& string, S32 *mode)
  539. {
  540. if (string == "FIRST_PERSON")
  541. {
  542. *mode = MODE_FIRST_PERSON;
  543. return TRUE;
  544. }
  545. else if (string == "THIRD_PERSON")
  546. {
  547. *mode = MODE_THIRD_PERSON;
  548. return TRUE;
  549. }
  550. else if (string == "EDIT")
  551. {
  552. *mode = MODE_EDIT;
  553. return TRUE;
  554. }
  555. else if (string == "EDIT_AVATAR")
  556. {
  557. *mode = MODE_EDIT_AVATAR;
  558. return TRUE;
  559. }
  560. else if (string == "SITTING")
  561. {
  562. *mode = MODE_SITTING;
  563. return TRUE;
  564. }
  565. else
  566. {
  567. *mode = MODE_THIRD_PERSON;
  568. return FALSE;
  569. }
  570. }
  571. BOOL LLViewerKeyboard::handleKey(KEY translated_key, MASK translated_mask, BOOL repeated)
  572. {
  573. // check for re-map
  574. EKeyboardMode mode = gViewerKeyboard.getMode();
  575. U32 keyidx = (translated_mask<<16) | translated_key;
  576. key_remap_t::iterator iter = mRemapKeys[mode].find(keyidx);
  577. if (iter != mRemapKeys[mode].end())
  578. {
  579. translated_key = (iter->second) & 0xff;
  580. translated_mask = (iter->second)>>16;
  581. }
  582. // No repeats of F-keys
  583. BOOL repeatable_key = (translated_key < KEY_F1 || translated_key > KEY_F12);
  584. if (!repeatable_key && repeated)
  585. {
  586. return FALSE;
  587. }
  588. lldebugst(LLERR_USER_INPUT) << "keydown -" << translated_key << "-" << llendl;
  589. // skip skipped keys
  590. if(mKeysSkippedByUI.find(translated_key) != mKeysSkippedByUI.end())
  591. {
  592. mKeyHandledByUI[translated_key] = FALSE;
  593. }
  594. else
  595. {
  596. // it is sufficient to set this value once per call to handlekey
  597. // without clearing it, as it is only used in the subsequent call to scanKey
  598. mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask);
  599. }
  600. return mKeyHandledByUI[translated_key];
  601. }
  602. BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name)
  603. {
  604. S32 index;
  605. typedef boost::function<void(EKeystate)> function_t;
  606. function_t function = NULL;
  607. std::string name;
  608. // Allow remapping of F2-F12
  609. if (function_name[0] == 'F')
  610. {
  611. int c1 = function_name[1] - '0';
  612. int c2 = function_name[2] ? function_name[2] - '0' : -1;
  613. if (c1 >= 0 && c1 <= 9 && c2 >= -1 && c2 <= 9)
  614. {
  615. int idx = c1;
  616. if (c2 >= 0)
  617. idx = idx*10 + c2;
  618. if (idx >=2 && idx <= 12)
  619. {
  620. U32 keyidx = ((mask<<16)|key);
  621. (mRemapKeys[mode])[keyidx] = ((0<<16)|(KEY_F1+(idx-1)));
  622. return TRUE;
  623. }
  624. }
  625. }
  626. // Not remapped, look for a function
  627. function_t* result = LLKeyboardActionRegistry::getValue(function_name);
  628. if (result)
  629. {
  630. function = *result;
  631. }
  632. if (!function)
  633. {
  634. llerrs << "Can't bind key to function " << function_name << ", no function with this name found" << llendl;
  635. return FALSE;
  636. }
  637. // check for duplicate first and overwrite
  638. for (index = 0; index < mBindingCount[mode]; index++)
  639. {
  640. if (key == mBindings[mode][index].mKey && mask == mBindings[mode][index].mMask)
  641. break;
  642. }
  643. if (index >= MAX_KEY_BINDINGS)
  644. {
  645. llerrs << "LLKeyboard::bindKey() - too many keys for mode " << mode << llendl;
  646. return FALSE;
  647. }
  648. if (mode >= MODE_COUNT)
  649. {
  650. llerror("LLKeyboard::bindKey() - unknown mode passed", mode);
  651. return FALSE;
  652. }
  653. mBindings[mode][index].mKey = key;
  654. mBindings[mode][index].mMask = mask;
  655. mBindings[mode][index].mFunction = function;
  656. if (index == mBindingCount[mode])
  657. mBindingCount[mode]++;
  658. return TRUE;
  659. }
  660. LLViewerKeyboard::KeyBinding::KeyBinding()
  661. : key("key"),
  662. mask("mask"),
  663. command("command")
  664. {}
  665. LLViewerKeyboard::KeyMode::KeyMode(EKeyboardMode _mode)
  666. : bindings("binding"),
  667. mode(_mode)
  668. {}
  669. LLViewerKeyboard::Keys::Keys()
  670. : first_person("first_person", KeyMode(MODE_FIRST_PERSON)),
  671. third_person("third_person", KeyMode(MODE_THIRD_PERSON)),
  672. edit("edit", KeyMode(MODE_EDIT)),
  673. sitting("sitting", KeyMode(MODE_SITTING)),
  674. edit_avatar("edit_avatar", KeyMode(MODE_EDIT_AVATAR))
  675. {}
  676. S32 LLViewerKeyboard::loadBindingsXML(const std::string& filename)
  677. {
  678. S32 binding_count = 0;
  679. Keys keys;
  680. LLSimpleXUIParser parser;
  681. if (parser.readXUI(filename, keys)
  682. && keys.validateBlock())
  683. {
  684. binding_count += loadBindingMode(keys.first_person);
  685. binding_count += loadBindingMode(keys.third_person);
  686. binding_count += loadBindingMode(keys.edit);
  687. binding_count += loadBindingMode(keys.sitting);
  688. binding_count += loadBindingMode(keys.edit_avatar);
  689. }
  690. return binding_count;
  691. }
  692. S32 LLViewerKeyboard::loadBindingMode(const LLViewerKeyboard::KeyMode& keymode)
  693. {
  694. S32 binding_count = 0;
  695. for (LLInitParam::ParamIterator<KeyBinding>::const_iterator it = keymode.bindings.begin(),
  696. end_it = keymode.bindings.end();
  697. it != end_it;
  698. ++it)
  699. {
  700. KEY key;
  701. MASK mask;
  702. LLKeyboard::keyFromString(it->key, &key);
  703. LLKeyboard::maskFromString(it->mask, &mask);
  704. bindKey(keymode.mode, key, mask, it->command);
  705. binding_count++;
  706. }
  707. return binding_count;
  708. }
  709. S32 LLViewerKeyboard::loadBindings(const std::string& filename)
  710. {
  711. LLFILE *fp;
  712. const S32 BUFFER_SIZE = 2048;
  713. char buffer[BUFFER_SIZE]; /* Flawfinder: ignore */
  714. // *NOTE: This buffer size is hard coded into scanf() below.
  715. char mode_string[MAX_STRING] = ""; /* Flawfinder: ignore */
  716. char key_string[MAX_STRING] = ""; /* Flawfinder: ignore */
  717. char mask_string[MAX_STRING] = ""; /* Flawfinder: ignore */
  718. char function_string[MAX_STRING] = ""; /* Flawfinder: ignore */
  719. S32 mode = MODE_THIRD_PERSON;
  720. KEY key = 0;
  721. MASK mask = 0;
  722. S32 tokens_read;
  723. S32 binding_count = 0;
  724. S32 line_count = 0;
  725. if(filename.empty())
  726. {
  727. llerrs << " No filename specified" << llendl;
  728. return 0;
  729. }
  730. fp = LLFile::fopen(filename, "r");
  731. if (!fp)
  732. {
  733. return 0;
  734. }
  735. while (!feof(fp))
  736. {
  737. line_count++;
  738. if (!fgets(buffer, BUFFER_SIZE, fp))
  739. break;
  740. // skip over comments, blank lines
  741. if (buffer[0] == '#' || buffer[0] == '\n') continue;
  742. // grab the binding strings
  743. tokens_read = sscanf( /* Flawfinder: ignore */
  744. buffer,
  745. "%254s %254s %254s %254s",
  746. mode_string,
  747. key_string,
  748. mask_string,
  749. function_string);
  750. if (tokens_read == EOF)
  751. {
  752. llinfos << "Unexpected end-of-file at line " << line_count << " of key binding file " << filename << llendl;
  753. fclose(fp);
  754. return 0;
  755. }
  756. else if (tokens_read < 4)
  757. {
  758. llinfos << "Can't read line " << line_count << " of key binding file " << filename << llendl;
  759. continue;
  760. }
  761. // convert mode
  762. if (!modeFromString(mode_string, &mode))
  763. {
  764. llinfos << "Unknown mode on line " << line_count << " of key binding file " << filename << llendl;
  765. llinfos << "Mode must be one of FIRST_PERSON, THIRD_PERSON, EDIT, EDIT_AVATAR" << llendl;
  766. continue;
  767. }
  768. // convert key
  769. if (!LLKeyboard::keyFromString(key_string, &key))
  770. {
  771. llinfos << "Can't interpret key on line " << line_count << " of key binding file " << filename << llendl;
  772. continue;
  773. }
  774. // convert mask
  775. if (!LLKeyboard::maskFromString(mask_string, &mask))
  776. {
  777. llinfos << "Can't interpret mask on line " << line_count << " of key binding file " << filename << llendl;
  778. continue;
  779. }
  780. // bind key
  781. if (bindKey(mode, key, mask, function_string))
  782. {
  783. binding_count++;
  784. }
  785. }
  786. fclose(fp);
  787. return binding_count;
  788. }
  789. EKeyboardMode LLViewerKeyboard::getMode()
  790. {
  791. if ( gAgentCamera.cameraMouselook() )
  792. {
  793. return MODE_FIRST_PERSON;
  794. }
  795. else if ( gMorphView && gMorphView->getVisible())
  796. {
  797. return MODE_EDIT_AVATAR;
  798. }
  799. else if (isAgentAvatarValid() && gAgentAvatarp->isSitting())
  800. {
  801. return MODE_SITTING;
  802. }
  803. else
  804. {
  805. return MODE_THIRD_PERSON;
  806. }
  807. }
  808. // Called from scanKeyboard.
  809. void LLViewerKeyboard::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
  810. {
  811. S32 mode = getMode();
  812. // Consider keyboard scanning as NOT mouse event. JC
  813. MASK mask = gKeyboard->currentMask(FALSE);
  814. LLKeyBinding* binding = mBindings[mode];
  815. S32 binding_count = mBindingCount[mode];
  816. if (mKeyHandledByUI[key])
  817. {
  818. return;
  819. }
  820. // don't process key down on repeated keys
  821. BOOL repeat = gKeyboard->getKeyRepeated(key);
  822. for (S32 i = 0; i < binding_count; i++)
  823. {
  824. //for (S32 key = 0; key < KEY_COUNT; key++)
  825. if (binding[i].mKey == key)
  826. {
  827. //if (binding[i].mKey == key && binding[i].mMask == mask)
  828. if (binding[i].mMask == mask)
  829. {
  830. if (key_down && !repeat)
  831. {
  832. // ...key went down this frame, call function
  833. binding[i].mFunction( KEYSTATE_DOWN );
  834. }
  835. else if (key_up)
  836. {
  837. // ...key went down this frame, call function
  838. binding[i].mFunction( KEYSTATE_UP );
  839. }
  840. else if (key_level)
  841. {
  842. // ...key held down from previous frame
  843. // Not windows, just call the function.
  844. binding[i].mFunction( KEYSTATE_LEVEL );
  845. }//if
  846. }//if
  847. }//for
  848. }//for
  849. }