llviewerkeyboard.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:23k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llviewerkeyboard.cpp
  3.  * @brief LLViewerKeyboard class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2005&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2005-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llappviewer.h"
  34. #include "llviewerkeyboard.h"
  35. #include "llmath.h"
  36. #include "llagent.h"
  37. #include "llnearbychatbar.h"
  38. #include "llviewercontrol.h"
  39. #include "llfocusmgr.h"
  40. #include "llmorphview.h"
  41. #include "llmoveview.h"
  42. #include "lltoolfocus.h"
  43. #include "llviewerwindow.h"
  44. #include "llvoavatarself.h"
  45. #include "llfloatercamera.h"
  46. //
  47. // Constants
  48. //
  49. const F32 FLY_TIME = 0.5f;
  50. const F32 FLY_FRAMES = 4;
  51. const F32 NUDGE_TIME = 0.25f;  // in seconds
  52. const S32 NUDGE_FRAMES = 2;
  53. const F32 ORBIT_NUDGE_RATE = 0.05f;  // fraction of normal speed
  54. const F32 YAW_NUDGE_RATE = 0.05f;  // fraction of normal speed
  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. gAgent.unlockView();
  247. gAgent.setOrbitLeftKey( get_orbit_rate() );
  248. }
  249. void camera_spin_around_cw( EKeystate s )
  250. {
  251. if( KEYSTATE_UP == s  ) return;
  252. gAgent.unlockView();
  253. gAgent.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() || gAgent.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. gAgent.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() || gAgent.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. gAgent.setOrbitRightKey( get_orbit_rate() );
  281. }
  282. }
  283. void camera_spin_over( EKeystate s )
  284. {
  285. if( KEYSTATE_UP == s  ) return;
  286. gAgent.unlockView();
  287. gAgent.setOrbitUpKey( get_orbit_rate() );
  288. }
  289. void camera_spin_under( EKeystate s )
  290. {
  291. if( KEYSTATE_UP == s  ) return;
  292. gAgent.unlockView();
  293. gAgent.setOrbitDownKey( get_orbit_rate() );
  294. }
  295. void camera_spin_over_sitting( EKeystate s )
  296. {
  297. if( KEYSTATE_UP == s  ) return;
  298. if (gAgent.upGrabbed() || gAgent.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. gAgent.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() || gAgent.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. gAgent.setOrbitDownKey( get_orbit_rate() );
  321. }
  322. }
  323. void camera_move_forward( EKeystate s )
  324. {
  325. if( KEYSTATE_UP == s  ) return;
  326. gAgent.unlockView();
  327. gAgent.setOrbitInKey( get_orbit_rate() );
  328. }
  329. void camera_move_backward( EKeystate s )
  330. {
  331. if( KEYSTATE_UP == s  ) return;
  332. gAgent.unlockView();
  333. gAgent.setOrbitOutKey( get_orbit_rate() );
  334. }
  335. void camera_move_forward_sitting( EKeystate s )
  336. {
  337. if( KEYSTATE_UP == s  ) return;
  338. if (gAgent.forwardGrabbed() || gAgent.sitCameraEnabled())
  339. {
  340. agent_push_forward(s);
  341. }
  342. else
  343. {
  344. gAgent.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() || gAgent.sitCameraEnabled())
  351. {
  352. agent_push_backward(s);
  353. }
  354. else
  355. {
  356. gAgent.setOrbitOutKey( get_orbit_rate() );
  357. }
  358. }
  359. void camera_pan_up( EKeystate s )
  360. {
  361. if( KEYSTATE_UP == s  ) return;
  362. gAgent.unlockView();
  363. gAgent.setPanUpKey( get_orbit_rate() );
  364. }
  365. void camera_pan_down( EKeystate s )
  366. {
  367. if( KEYSTATE_UP == s  ) return;
  368. gAgent.unlockView();
  369. gAgent.setPanDownKey( get_orbit_rate() );
  370. }
  371. void camera_pan_left( EKeystate s )
  372. {
  373. if( KEYSTATE_UP == s  ) return;
  374. gAgent.unlockView();
  375. gAgent.setPanLeftKey( get_orbit_rate() );
  376. }
  377. void camera_pan_right( EKeystate s )
  378. {
  379. if( KEYSTATE_UP == s  ) return;
  380. gAgent.unlockView();
  381. gAgent.setPanRightKey( get_orbit_rate() );
  382. }
  383. void camera_pan_in( EKeystate s )
  384. {
  385. if( KEYSTATE_UP == s  ) return;
  386. gAgent.unlockView();
  387. gAgent.setPanInKey( get_orbit_rate() );
  388. }
  389. void camera_pan_out( EKeystate s )
  390. {
  391. if( KEYSTATE_UP == s  ) return;
  392. gAgent.unlockView();
  393. gAgent.setPanOutKey( get_orbit_rate() );
  394. }
  395. void camera_move_forward_fast( EKeystate s )
  396. {
  397. if( KEYSTATE_UP == s  ) return;
  398. gAgent.unlockView();
  399. gAgent.setOrbitInKey(2.5f);
  400. }
  401. void camera_move_backward_fast( EKeystate s )
  402. {
  403. if( KEYSTATE_UP == s  ) return;
  404. gAgent.unlockView();
  405. gAgent.setOrbitOutKey(2.5f);
  406. }
  407. void edit_avatar_spin_ccw( EKeystate s )
  408. {
  409. if( KEYSTATE_UP == s  ) return;
  410. gMorphView->setCameraDrivenByKeys( TRUE );
  411. gAgent.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. gAgent.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. gAgent.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. gAgent.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. gAgent.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. gAgent.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. void bind_keyboard_functions()
  481. {
  482. gViewerKeyboard.bindNamedFunction("jump", agent_jump);
  483. gViewerKeyboard.bindNamedFunction("push_down", agent_push_down);
  484. gViewerKeyboard.bindNamedFunction("push_forward", agent_push_forward);
  485. gViewerKeyboard.bindNamedFunction("push_backward", agent_push_backward);
  486. gViewerKeyboard.bindNamedFunction("look_up", agent_look_up);
  487. gViewerKeyboard.bindNamedFunction("look_down", agent_look_down);
  488. gViewerKeyboard.bindNamedFunction("toggle_fly", agent_toggle_fly);
  489. gViewerKeyboard.bindNamedFunction("turn_left", agent_turn_left);
  490. gViewerKeyboard.bindNamedFunction("turn_right", agent_turn_right);
  491. gViewerKeyboard.bindNamedFunction("slide_left", agent_slide_left);
  492. gViewerKeyboard.bindNamedFunction("slide_right", agent_slide_right);
  493. gViewerKeyboard.bindNamedFunction("spin_around_ccw", camera_spin_around_ccw);
  494. gViewerKeyboard.bindNamedFunction("spin_around_cw", camera_spin_around_cw);
  495. gViewerKeyboard.bindNamedFunction("spin_around_ccw_sitting", camera_spin_around_ccw_sitting);
  496. gViewerKeyboard.bindNamedFunction("spin_around_cw_sitting", camera_spin_around_cw_sitting);
  497. gViewerKeyboard.bindNamedFunction("spin_over", camera_spin_over);
  498. gViewerKeyboard.bindNamedFunction("spin_under", camera_spin_under);
  499. gViewerKeyboard.bindNamedFunction("spin_over_sitting", camera_spin_over_sitting);
  500. gViewerKeyboard.bindNamedFunction("spin_under_sitting", camera_spin_under_sitting);
  501. gViewerKeyboard.bindNamedFunction("move_forward", camera_move_forward);
  502. gViewerKeyboard.bindNamedFunction("move_backward", camera_move_backward);
  503. gViewerKeyboard.bindNamedFunction("move_forward_sitting", camera_move_forward_sitting);
  504. gViewerKeyboard.bindNamedFunction("move_backward_sitting", camera_move_backward_sitting);
  505. gViewerKeyboard.bindNamedFunction("pan_up", camera_pan_up);
  506. gViewerKeyboard.bindNamedFunction("pan_down", camera_pan_down);
  507. gViewerKeyboard.bindNamedFunction("pan_left", camera_pan_left);
  508. gViewerKeyboard.bindNamedFunction("pan_right", camera_pan_right);
  509. gViewerKeyboard.bindNamedFunction("pan_in", camera_pan_in);
  510. gViewerKeyboard.bindNamedFunction("pan_out", camera_pan_out);
  511. gViewerKeyboard.bindNamedFunction("move_forward_fast", camera_move_forward_fast);
  512. gViewerKeyboard.bindNamedFunction("move_backward_fast", camera_move_backward_fast);
  513. gViewerKeyboard.bindNamedFunction("edit_avatar_spin_ccw", edit_avatar_spin_ccw);
  514. gViewerKeyboard.bindNamedFunction("edit_avatar_spin_cw", edit_avatar_spin_cw);
  515. gViewerKeyboard.bindNamedFunction("edit_avatar_spin_over", edit_avatar_spin_over);
  516. gViewerKeyboard.bindNamedFunction("edit_avatar_spin_under", edit_avatar_spin_under);
  517. gViewerKeyboard.bindNamedFunction("edit_avatar_move_forward", edit_avatar_move_forward);
  518. gViewerKeyboard.bindNamedFunction("edit_avatar_move_backward", edit_avatar_move_backward);
  519. gViewerKeyboard.bindNamedFunction("stop_moving", stop_moving);
  520. gViewerKeyboard.bindNamedFunction("start_chat", start_chat);
  521. gViewerKeyboard.bindNamedFunction("start_gesture", start_gesture);
  522. }
  523. LLViewerKeyboard::LLViewerKeyboard() :
  524. mNamedFunctionCount(0)
  525. {
  526. for (S32 i = 0; i < MODE_COUNT; i++)
  527. {
  528. mBindingCount[i] = 0;
  529. }
  530. for (S32 i = 0; i < KEY_COUNT; i++)
  531. {
  532. mKeyHandledByUI[i] = FALSE;
  533. }
  534. // we want the UI to never see these keys so that they can always control the avatar/camera
  535. for(KEY k = KEY_PAD_UP; k <= KEY_PAD_DIVIDE; k++) 
  536. {
  537. mKeysSkippedByUI.insert(k);
  538. }
  539. }
  540. void LLViewerKeyboard::bindNamedFunction(const std::string& name, LLKeyFunc func)
  541. {
  542. S32 i = mNamedFunctionCount;
  543. mNamedFunctions[i].mName = name;
  544. mNamedFunctions[i].mFunction = func;
  545. mNamedFunctionCount++;
  546. }
  547. BOOL LLViewerKeyboard::modeFromString(const std::string& string, S32 *mode)
  548. {
  549. if (string == "FIRST_PERSON")
  550. {
  551. *mode = MODE_FIRST_PERSON;
  552. return TRUE;
  553. }
  554. else if (string == "THIRD_PERSON")
  555. {
  556. *mode = MODE_THIRD_PERSON;
  557. return TRUE;
  558. }
  559. else if (string == "EDIT")
  560. {
  561. *mode = MODE_EDIT;
  562. return TRUE;
  563. }
  564. else if (string == "EDIT_AVATAR")
  565. {
  566. *mode = MODE_EDIT_AVATAR;
  567. return TRUE;
  568. }
  569. else if (string == "SITTING")
  570. {
  571. *mode = MODE_SITTING;
  572. return TRUE;
  573. }
  574. else
  575. {
  576. *mode = MODE_THIRD_PERSON;
  577. return FALSE;
  578. }
  579. }
  580. BOOL LLViewerKeyboard::handleKey(KEY translated_key,  MASK translated_mask, BOOL repeated)
  581. {
  582. // check for re-map
  583. EKeyboardMode mode = gViewerKeyboard.getMode();
  584. U32 keyidx = (translated_mask<<16) | translated_key;
  585. key_remap_t::iterator iter = mRemapKeys[mode].find(keyidx);
  586. if (iter != mRemapKeys[mode].end())
  587. {
  588. translated_key = (iter->second) & 0xff;
  589. translated_mask = (iter->second)>>16;
  590. }
  591. // No repeats of F-keys
  592. BOOL repeatable_key = (translated_key < KEY_F1 || translated_key > KEY_F12);
  593. if (!repeatable_key && repeated)
  594. {
  595. return FALSE;
  596. }
  597. lldebugst(LLERR_USER_INPUT) << "keydown -" << translated_key << "-" << llendl;
  598. // skip skipped keys
  599. if(mKeysSkippedByUI.find(translated_key) != mKeysSkippedByUI.end()) 
  600. {
  601. mKeyHandledByUI[translated_key] = FALSE;
  602. }
  603. else
  604. {
  605. // it is sufficient to set this value once per call to handlekey
  606. // without clearing it, as it is only used in the subsequent call to scanKey
  607. mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask);
  608. }
  609. return mKeyHandledByUI[translated_key];
  610. }
  611. BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name)
  612. {
  613. S32 i,index;
  614. void (*function)(EKeystate keystate) = NULL;
  615. std::string name;
  616. // Allow remapping of F2-F12
  617. if (function_name[0] == 'F')
  618. {
  619. int c1 = function_name[1] - '0';
  620. int c2 = function_name[2] ? function_name[2] - '0' : -1;
  621. if (c1 >= 0 && c1 <= 9 && c2 >= -1 && c2 <= 9)
  622. {
  623. int idx = c1;
  624. if (c2 >= 0)
  625. idx = idx*10 + c2;
  626. if (idx >=2 && idx <= 12)
  627. {
  628. U32 keyidx = ((mask<<16)|key);
  629. (mRemapKeys[mode])[keyidx] = ((0<<16)|(KEY_F1+(idx-1)));
  630. return TRUE;
  631. }
  632. }
  633. }
  634. // Not remapped, look for a function
  635. for (i = 0; i < mNamedFunctionCount; i++)
  636. {
  637. if (function_name == mNamedFunctions[i].mName)
  638. {
  639. function = mNamedFunctions[i].mFunction;
  640. name = mNamedFunctions[i].mName;
  641. }
  642. }
  643. if (!function)
  644. {
  645. llerrs << "Can't bind key to function " << function_name << ", no function with this name found" << llendl;
  646. return FALSE;
  647. }
  648. // check for duplicate first and overwrite
  649. for (index = 0; index < mBindingCount[mode]; index++)
  650. {
  651. if (key == mBindings[mode][index].mKey && mask == mBindings[mode][index].mMask)
  652. break;
  653. }
  654. if (index >= MAX_KEY_BINDINGS)
  655. {
  656. llerrs << "LLKeyboard::bindKey() - too many keys for mode " << mode << llendl;
  657. return FALSE;
  658. }
  659. if (mode >= MODE_COUNT)
  660. {
  661. llerror("LLKeyboard::bindKey() - unknown mode passed", mode);
  662. return FALSE;
  663. }
  664. mBindings[mode][index].mKey = key;
  665. mBindings[mode][index].mMask = mask;
  666. //  mBindings[mode][index].mName = name;
  667. mBindings[mode][index].mFunction = function;
  668. if (index == mBindingCount[mode])
  669. mBindingCount[mode]++;
  670. return TRUE;
  671. }
  672. S32 LLViewerKeyboard::loadBindings(const std::string& filename)
  673. {
  674. LLFILE *fp;
  675. const S32 BUFFER_SIZE = 2048;
  676. char buffer[BUFFER_SIZE]; /* Flawfinder: ignore */
  677. // *NOTE: This buffer size is hard coded into scanf() below.
  678. char mode_string[MAX_STRING] = ""; /* Flawfinder: ignore */
  679. char key_string[MAX_STRING] = ""; /* Flawfinder: ignore */
  680. char mask_string[MAX_STRING] = ""; /* Flawfinder: ignore */
  681. char function_string[MAX_STRING] = ""; /* Flawfinder: ignore */
  682. S32 mode = MODE_THIRD_PERSON;
  683. KEY key = 0;
  684. MASK mask = 0;
  685. S32 tokens_read;
  686. S32 binding_count = 0;
  687. S32 line_count = 0;
  688. if(filename.empty())
  689. {
  690. llerrs << " No filename specified" << llendl;
  691. return 0;
  692. }
  693. fp = LLFile::fopen(filename, "r");
  694. if (!fp)
  695. {
  696. return 0;
  697. }
  698. while (!feof(fp))
  699. {
  700. line_count++;
  701. if (!fgets(buffer, BUFFER_SIZE, fp))
  702. break;
  703. // skip over comments, blank lines
  704. if (buffer[0] == '#' || buffer[0] == 'n') continue;
  705. // grab the binding strings
  706. tokens_read = sscanf( /* Flawfinder: ignore */
  707. buffer,
  708. "%254s %254s %254s %254s",
  709. mode_string,
  710. key_string,
  711. mask_string,
  712. function_string);
  713. if (tokens_read == EOF)
  714. {
  715. llinfos << "Unexpected end-of-file at line " << line_count << " of key binding file " << filename << llendl;
  716. fclose(fp);
  717. return 0;
  718. }
  719. else if (tokens_read < 4)
  720. {
  721. llinfos << "Can't read line " << line_count << " of key binding file " << filename << llendl;
  722. continue;
  723. }
  724. // convert mode
  725. if (!modeFromString(mode_string, &mode))
  726. {
  727. llinfos << "Unknown mode on line " << line_count << " of key binding file " << filename << llendl;
  728. llinfos << "Mode must be one of FIRST_PERSON, THIRD_PERSON, EDIT, EDIT_AVATAR" << llendl;
  729. continue;
  730. }
  731. // convert key
  732. if (!LLKeyboard::keyFromString(key_string, &key))
  733. {
  734. llinfos << "Can't interpret key on line " << line_count << " of key binding file " << filename << llendl;
  735. continue;
  736. }
  737. // convert mask
  738. if (!LLKeyboard::maskFromString(mask_string, &mask))
  739. {
  740. llinfos << "Can't interpret mask on line " << line_count << " of key binding file " << filename << llendl;
  741. continue;
  742. }
  743. // bind key
  744. if (bindKey(mode, key, mask, function_string))
  745. {
  746. binding_count++;
  747. }
  748. }
  749. fclose(fp);
  750. return binding_count;
  751. }
  752. EKeyboardMode LLViewerKeyboard::getMode()
  753. {
  754. if ( gAgent.cameraMouselook() )
  755. {
  756. return MODE_FIRST_PERSON;
  757. }
  758. else if ( gMorphView && gMorphView->getVisible())
  759. {
  760. return MODE_EDIT_AVATAR;
  761. }
  762. else if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->isSitting())
  763. {
  764. return MODE_SITTING;
  765. }
  766. else
  767. {
  768. return MODE_THIRD_PERSON;
  769. }
  770. }
  771. // Called from scanKeyboard.
  772. void LLViewerKeyboard::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
  773. {
  774. S32 mode = getMode();
  775. // Consider keyboard scanning as NOT mouse event. JC
  776. MASK mask = gKeyboard->currentMask(FALSE);
  777. LLKeyBinding* binding = mBindings[mode];
  778. S32 binding_count = mBindingCount[mode];
  779. if (mKeyHandledByUI[key])
  780. {
  781. return;
  782. }
  783. // don't process key down on repeated keys
  784. BOOL repeat = gKeyboard->getKeyRepeated(key);
  785. for (S32 i = 0; i < binding_count; i++)
  786. {
  787. //for (S32 key = 0; key < KEY_COUNT; key++)
  788. if (binding[i].mKey == key)
  789. {
  790. //if (binding[i].mKey == key && binding[i].mMask == mask)
  791. if (binding[i].mMask == mask)
  792. {
  793. if (key_down && !repeat)
  794. {
  795. // ...key went down this frame, call function
  796. (*binding[i].mFunction)( KEYSTATE_DOWN );
  797. }
  798. else if (key_up)
  799. {
  800. // ...key went down this frame, call function
  801. (*binding[i].mFunction)( KEYSTATE_UP );
  802. }
  803. else if (key_level)
  804. {
  805. // ...key held down from previous frame
  806. // Not windows, just call the function.
  807. (*binding[i].mFunction)( KEYSTATE_LEVEL );
  808. }//if
  809. }//if
  810. }//for
  811. }//for
  812. }