llviewerkeyboard.cpp 22 KB

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