aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llviewerkeyboard.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llviewerkeyboard.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llviewerkeyboard.cpp852
1 files changed, 852 insertions, 0 deletions
diff --git a/linden/indra/newview/llviewerkeyboard.cpp b/linden/indra/newview/llviewerkeyboard.cpp
new file mode 100644
index 0000000..531cb89
--- /dev/null
+++ b/linden/indra/newview/llviewerkeyboard.cpp
@@ -0,0 +1,852 @@
1/**
2 * @file llviewerkeyboard.cpp
3 * @brief LLViewerKeyboard class implementation
4 *
5 * Copyright (c) 2005-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "llviewerkeyboard.h"
31#include "llmath.h"
32#include "llagent.h"
33#include "llchatbar.h"
34#include "llviewercontrol.h"
35#include "llfocusmgr.h"
36#include "llmorphview.h"
37#include "llmoveview.h"
38#include "lltoolfocus.h"
39#include "llviewerwindow.h"
40#include "llvoavatar.h"
41
42//
43// Constants
44//
45
46const F32 FLY_TIME = 0.5f;
47const F32 FLY_FRAMES = 4;
48
49const F32 NUDGE_TIME = 0.25f; // in seconds
50const S32 NUDGE_FRAMES = 2;
51const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed
52const F32 YAW_NUDGE_RATE = 0.05f; // fraction of normal speed
53
54LLViewerKeyboard gViewerKeyboard;
55
56void agent_jump( EKeystate s )
57{
58 if( KEYSTATE_UP == s ) return;
59 F32 time = gKeyboard->getCurKeyElapsedTime();
60 S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
61
62 if( time < FLY_TIME
63 || frame_count <= FLY_FRAMES
64 || gAgent.upGrabbed()
65 || !gSavedSettings.getBOOL("AutomaticFly"))
66 {
67 gAgent.moveUp(1);
68 }
69 else
70 {
71 gAgent.setFlying(TRUE);
72 gAgent.moveUp(1);
73 }
74}
75
76void agent_push_down( EKeystate s )
77{
78 if( KEYSTATE_UP == s ) return;
79 gAgent.moveUp(-1);
80}
81
82void agent_push_forward( EKeystate s )
83{
84 if( KEYSTATE_UP == s ) return;
85 F32 time = gKeyboard->getCurKeyElapsedTime();
86 S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
87
88 if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
89 {
90 gAgent.moveAtNudge(1);
91 }
92 else
93 {
94 gAgent.moveAt(1);
95 }
96}
97
98
99void agent_push_backward( EKeystate s )
100{
101 if( KEYSTATE_UP == s ) return;
102 S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
103 F32 time = gKeyboard->getCurKeyElapsedTime();
104
105 if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
106 {
107 gAgent.moveAtNudge(-1);
108 }
109 else
110 {
111 gAgent.moveAt(-1);
112 }
113}
114
115void agent_slide_left( EKeystate s )
116{
117 if( KEYSTATE_UP == s ) return;
118 F32 time = gKeyboard->getCurKeyElapsedTime();
119 S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
120
121 if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
122 {
123 if (frame_count == 0)
124 {
125 // only send nudge on first frame
126 gAgent.moveLeftNudge(1);
127 }
128 }
129 else
130 {
131 gAgent.moveLeft(1);
132 }
133}
134
135
136void agent_slide_right( EKeystate s )
137{
138 if( KEYSTATE_UP == s ) return;
139 F32 time = gKeyboard->getCurKeyElapsedTime();
140 S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
141
142 if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
143 {
144 if (frame_count == 0)
145 {
146 // only send nudge on first frame
147 gAgent.moveLeftNudge(-1);
148 }
149 }
150 else
151 {
152 gAgent.moveLeft(-1);
153 }
154}
155
156void agent_turn_left( EKeystate s )
157{
158 if( KEYSTATE_UP == s ) return;
159 F32 time = gKeyboard->getCurKeyElapsedTime();
160 if (gToolCamera->mouseSteerMode())
161 {
162 agent_slide_left(s);
163 }
164 else
165 {
166 gAgent.moveYaw( LLFloaterMove::getYawRate( time ) );
167 }
168}
169
170
171void agent_turn_right( EKeystate s )
172{
173 if( KEYSTATE_UP == s ) return;
174 F32 time = gKeyboard->getCurKeyElapsedTime();
175 if (gToolCamera->mouseSteerMode())
176 {
177 agent_slide_right(s);
178 }
179 else
180 {
181 gAgent.moveYaw( -LLFloaterMove::getYawRate( time ) );
182 }
183}
184
185void agent_look_up( EKeystate s )
186{
187 if( KEYSTATE_UP == s ) return;
188 gAgent.movePitch(-1);
189 //gAgent.rotate(-2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
190}
191
192
193void agent_look_down( EKeystate s )
194{
195 if( KEYSTATE_UP == s ) return;
196 gAgent.movePitch(1);
197 //gAgent.rotate(2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
198}
199
200void agent_toggle_fly( EKeystate s )
201{
202 // Only catch the edge
203 if (KEYSTATE_DOWN == s )
204 {
205 gAgent.toggleFlying();
206 }
207}
208
209F32 get_orbit_rate()
210{
211 F32 time = gKeyboard->getCurKeyElapsedTime();
212 if( time < NUDGE_TIME )
213 {
214 F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME;
215 //llinfos << rate << llendl;
216 return rate;
217 }
218 else
219 {
220 return 1;
221 }
222}
223
224void camera_spin_around_ccw( EKeystate s )
225{
226 if( KEYSTATE_UP == s ) return;
227 gAgent.unlockView();
228 gAgent.setOrbitLeftKey( get_orbit_rate() );
229}
230
231
232void camera_spin_around_cw( EKeystate s )
233{
234 if( KEYSTATE_UP == s ) return;
235 gAgent.unlockView();
236 gAgent.setOrbitRightKey( get_orbit_rate() );
237}
238
239void camera_spin_around_ccw_sitting( EKeystate s )
240{
241 if( KEYSTATE_UP == s ) return;
242 if (gAgent.rotateGrabbed() || gAgent.sitCameraEnabled())
243 {
244 //send keystrokes, but do not change camera
245 agent_turn_right(s);
246 }
247 else
248 {
249 //change camera but do not send keystrokes
250 gAgent.setOrbitLeftKey( get_orbit_rate() );
251 }
252}
253
254
255void camera_spin_around_cw_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_left(s);
262 }
263 else
264 {
265 //change camera but do not send keystrokes
266 gAgent.setOrbitRightKey( get_orbit_rate() );
267 }
268}
269
270
271void camera_spin_over( EKeystate s )
272{
273 if( KEYSTATE_UP == s ) return;
274 gAgent.unlockView();
275 gAgent.setOrbitUpKey( get_orbit_rate() );
276}
277
278
279void camera_spin_under( EKeystate s )
280{
281 if( KEYSTATE_UP == s ) return;
282 gAgent.unlockView();
283 gAgent.setOrbitDownKey( get_orbit_rate() );
284}
285
286void camera_spin_over_sitting( EKeystate s )
287{
288 if( KEYSTATE_UP == s ) return;
289 if (gAgent.upGrabbed() || gAgent.sitCameraEnabled())
290 {
291 //send keystrokes, but do not change camera
292 agent_jump(s);
293 }
294 else
295 {
296 //change camera but do not send keystrokes
297 gAgent.setOrbitUpKey( get_orbit_rate() );
298 }
299}
300
301
302void camera_spin_under_sitting( EKeystate s )
303{
304 if( KEYSTATE_UP == s ) return;
305 if (gAgent.downGrabbed() || gAgent.sitCameraEnabled())
306 {
307 //send keystrokes, but do not change camera
308 agent_push_down(s);
309 }
310 else
311 {
312 //change camera but do not send keystrokes
313 gAgent.setOrbitDownKey( get_orbit_rate() );
314 }
315}
316
317void camera_move_forward( EKeystate s )
318{
319 if( KEYSTATE_UP == s ) return;
320 gAgent.unlockView();
321 gAgent.setOrbitInKey( get_orbit_rate() );
322}
323
324
325void camera_move_backward( EKeystate s )
326{
327 if( KEYSTATE_UP == s ) return;
328 gAgent.unlockView();
329 gAgent.setOrbitOutKey( get_orbit_rate() );
330}
331
332void camera_move_forward_sitting( EKeystate s )
333{
334 if( KEYSTATE_UP == s ) return;
335 if (gAgent.forwardGrabbed() || gAgent.sitCameraEnabled())
336 {
337 agent_push_forward(s);
338 }
339 else
340 {
341 gAgent.setOrbitInKey( get_orbit_rate() );
342 }
343}
344
345
346void camera_move_backward_sitting( EKeystate s )
347{
348 if( KEYSTATE_UP == s ) return;
349
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
360void camera_pan_up( EKeystate s )
361{
362 if( KEYSTATE_UP == s ) return;
363 gAgent.unlockView();
364 gAgent.setPanUpKey( get_orbit_rate() );
365}
366
367void camera_pan_down( EKeystate s )
368{
369 if( KEYSTATE_UP == s ) return;
370 gAgent.unlockView();
371 gAgent.setPanDownKey( get_orbit_rate() );
372}
373
374void camera_pan_left( EKeystate s )
375{
376 if( KEYSTATE_UP == s ) return;
377 gAgent.unlockView();
378 gAgent.setPanLeftKey( get_orbit_rate() );
379}
380
381void camera_pan_right( EKeystate s )
382{
383 if( KEYSTATE_UP == s ) return;
384 gAgent.unlockView();
385 gAgent.setPanRightKey( get_orbit_rate() );
386}
387
388void camera_pan_in( EKeystate s )
389{
390 if( KEYSTATE_UP == s ) return;
391 gAgent.unlockView();
392 gAgent.setPanInKey( get_orbit_rate() );
393}
394
395void camera_pan_out( EKeystate s )
396{
397 if( KEYSTATE_UP == s ) return;
398 gAgent.unlockView();
399 gAgent.setPanOutKey( get_orbit_rate() );
400}
401
402void camera_move_forward_fast( EKeystate s )
403{
404 if( KEYSTATE_UP == s ) return;
405 gAgent.unlockView();
406 gAgent.setOrbitInKey(2.5f);
407}
408
409void camera_move_backward_fast( EKeystate s )
410{
411 if( KEYSTATE_UP == s ) return;
412 gAgent.unlockView();
413 gAgent.setOrbitOutKey(2.5f);
414}
415
416
417void edit_avatar_spin_ccw( EKeystate s )
418{
419 if( KEYSTATE_UP == s ) return;
420 gMorphView->setCameraDrivenByKeys( TRUE );
421 gAgent.setOrbitLeftKey( get_orbit_rate() );
422 //gMorphView->orbitLeft( get_orbit_rate() );
423}
424
425
426void edit_avatar_spin_cw( EKeystate s )
427{
428 if( KEYSTATE_UP == s ) return;
429 gMorphView->setCameraDrivenByKeys( TRUE );
430 gAgent.setOrbitRightKey( get_orbit_rate() );
431 //gMorphView->orbitRight( get_orbit_rate() );
432}
433
434void edit_avatar_spin_over( EKeystate s )
435{
436 if( KEYSTATE_UP == s ) return;
437 gMorphView->setCameraDrivenByKeys( TRUE );
438 gAgent.setOrbitUpKey( get_orbit_rate() );
439 //gMorphView->orbitUp( get_orbit_rate() );
440}
441
442
443void edit_avatar_spin_under( EKeystate s )
444{
445 if( KEYSTATE_UP == s ) return;
446 gMorphView->setCameraDrivenByKeys( TRUE );
447 gAgent.setOrbitDownKey( get_orbit_rate() );
448 //gMorphView->orbitDown( get_orbit_rate() );
449}
450
451void edit_avatar_move_forward( EKeystate s )
452{
453 if( KEYSTATE_UP == s ) return;
454 gMorphView->setCameraDrivenByKeys( TRUE );
455 gAgent.setOrbitInKey( get_orbit_rate() );
456 //gMorphView->orbitIn();
457}
458
459
460void edit_avatar_move_backward( EKeystate s )
461{
462 if( KEYSTATE_UP == s ) return;
463 gMorphView->setCameraDrivenByKeys( TRUE );
464 gAgent.setOrbitOutKey( get_orbit_rate() );
465 //gMorphView->orbitOut();
466}
467
468void stop_moving( EKeystate s )
469{
470 if( KEYSTATE_UP == s ) return;
471 // stop agent
472 gAgent.setControlFlags(AGENT_CONTROL_STOP);
473
474 // cancel autopilot
475 gAgent.stopAutoPilot();
476}
477
478void start_chat( EKeystate s )
479{
480 if (!gChatBar->inputEditorHasFocus())
481 {
482 // start chat
483 gChatBar->startChat(NULL);
484 }
485}
486
487void bind_keyboard_functions()
488{
489 gViewerKeyboard.bindNamedFunction("jump", agent_jump);
490 gViewerKeyboard.bindNamedFunction("push_down", agent_push_down);
491 gViewerKeyboard.bindNamedFunction("push_forward", agent_push_forward);
492 gViewerKeyboard.bindNamedFunction("push_backward", agent_push_backward);
493 gViewerKeyboard.bindNamedFunction("look_up", agent_look_up);
494 gViewerKeyboard.bindNamedFunction("look_down", agent_look_down);
495 gViewerKeyboard.bindNamedFunction("toggle_fly", agent_toggle_fly);
496 gViewerKeyboard.bindNamedFunction("turn_left", agent_turn_left);
497 gViewerKeyboard.bindNamedFunction("turn_right", agent_turn_right);
498 gViewerKeyboard.bindNamedFunction("slide_left", agent_slide_left);
499 gViewerKeyboard.bindNamedFunction("slide_right", agent_slide_right);
500 gViewerKeyboard.bindNamedFunction("spin_around_ccw", camera_spin_around_ccw);
501 gViewerKeyboard.bindNamedFunction("spin_around_cw", camera_spin_around_cw);
502 gViewerKeyboard.bindNamedFunction("spin_around_ccw_sitting", camera_spin_around_ccw_sitting);
503 gViewerKeyboard.bindNamedFunction("spin_around_cw_sitting", camera_spin_around_cw_sitting);
504 gViewerKeyboard.bindNamedFunction("spin_over", camera_spin_over);
505 gViewerKeyboard.bindNamedFunction("spin_under", camera_spin_under);
506 gViewerKeyboard.bindNamedFunction("spin_over_sitting", camera_spin_over_sitting);
507 gViewerKeyboard.bindNamedFunction("spin_under_sitting", camera_spin_under_sitting);
508 gViewerKeyboard.bindNamedFunction("move_forward", camera_move_forward);
509 gViewerKeyboard.bindNamedFunction("move_backward", camera_move_backward);
510 gViewerKeyboard.bindNamedFunction("move_forward_sitting", camera_move_forward_sitting);
511 gViewerKeyboard.bindNamedFunction("move_backward_sitting", camera_move_backward_sitting);
512 gViewerKeyboard.bindNamedFunction("pan_up", camera_pan_up);
513 gViewerKeyboard.bindNamedFunction("pan_down", camera_pan_down);
514 gViewerKeyboard.bindNamedFunction("pan_left", camera_pan_left);
515 gViewerKeyboard.bindNamedFunction("pan_right", camera_pan_right);
516 gViewerKeyboard.bindNamedFunction("pan_in", camera_pan_in);
517 gViewerKeyboard.bindNamedFunction("pan_out", camera_pan_out);
518 gViewerKeyboard.bindNamedFunction("move_forward_fast", camera_move_forward_fast);
519 gViewerKeyboard.bindNamedFunction("move_backward_fast", camera_move_backward_fast);
520 gViewerKeyboard.bindNamedFunction("edit_avatar_spin_ccw", edit_avatar_spin_ccw);
521 gViewerKeyboard.bindNamedFunction("edit_avatar_spin_cw", edit_avatar_spin_cw);
522 gViewerKeyboard.bindNamedFunction("edit_avatar_spin_over", edit_avatar_spin_over);
523 gViewerKeyboard.bindNamedFunction("edit_avatar_spin_under", edit_avatar_spin_under);
524 gViewerKeyboard.bindNamedFunction("edit_avatar_move_forward", edit_avatar_move_forward);
525 gViewerKeyboard.bindNamedFunction("edit_avatar_move_backward", edit_avatar_move_backward);
526 gViewerKeyboard.bindNamedFunction("stop_moving", stop_moving);
527 gViewerKeyboard.bindNamedFunction("start_chat", start_chat);
528}
529
530LLViewerKeyboard::LLViewerKeyboard()
531{
532 for (S32 i = 0; i < MODE_COUNT; i++)
533 {
534 mBindingCount[i] = 0;
535 }
536
537 for (S32 i = 0; i < KEY_COUNT; i++)
538 {
539 mKeyHandledByUI[i] = FALSE;
540 }
541 // we want the UI to never see these keys so that they can always control the avatar/camera
542 for(KEY k = KEY_PAD_UP; k <= KEY_PAD_DIVIDE; k++)
543 {
544 mKeysSkippedByUI.insert(k);
545 }
546}
547
548
549void LLViewerKeyboard::bindNamedFunction(const char *name, LLKeyFunc func)
550{
551 S32 i = mNamedFunctionCount;
552 mNamedFunctions[i].mName = name;
553 mNamedFunctions[i].mFunction = func;
554 mNamedFunctionCount++;
555}
556
557
558BOOL LLViewerKeyboard::modeFromString(const char *string, S32 *mode)
559{
560 if (!strcmp(string, "FIRST_PERSON"))
561 {
562 *mode = MODE_FIRST_PERSON;
563 return TRUE;
564 }
565 else if (!strcmp(string, "THIRD_PERSON"))
566 {
567 *mode = MODE_THIRD_PERSON;
568 return TRUE;
569 }
570 else if (!strcmp(string, "EDIT"))
571 {
572 *mode = MODE_EDIT;
573 return TRUE;
574 }
575 else if (!strcmp(string, "EDIT_AVATAR"))
576 {
577 *mode = MODE_EDIT_AVATAR;
578 return TRUE;
579 }
580 else if (!strcmp(string, "SITTING"))
581 {
582 *mode = MODE_SITTING;
583 return TRUE;
584 }
585 else
586 {
587 *mode = MODE_THIRD_PERSON;
588 return FALSE;
589 }
590}
591
592BOOL LLViewerKeyboard::handleKey(KEY translated_key, MASK translated_mask, BOOL repeated)
593{
594 // check for re-map
595 EKeyboardMode mode = gViewerKeyboard.getMode();
596 U32 keyidx = (translated_mask<<16) | translated_key;
597 key_remap_t::iterator iter = mRemapKeys[mode].find(keyidx);
598 if (iter != mRemapKeys[mode].end())
599 {
600 translated_key = (iter->second) & 0xff;
601 translated_mask = (iter->second)>>16;
602 }
603
604 // No repeats of F-keys
605 BOOL repeatable_key = (translated_key < KEY_F1 || translated_key > KEY_F12);
606 if (!repeatable_key && repeated)
607 {
608 return FALSE;
609 }
610
611 lldebugst(LLERR_USER_INPUT) << "keydown -" << translated_key << "-" << llendl;
612 // skip skipped keys
613 if(mKeysSkippedByUI.find(translated_key) != mKeysSkippedByUI.end())
614 {
615 mKeyHandledByUI[translated_key] = FALSE;
616 }
617 else
618 {
619 // it is sufficient to set this value once per call to handlekey
620 // without clearing it, as it is only used in the subsequent call to scanKey
621 mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask);
622 }
623 return mKeyHandledByUI[translated_key];
624}
625
626
627
628BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, const char *function_name)
629{
630 S32 i,index;
631 void (*function)(EKeystate keystate) = NULL;
632 const char *name = NULL;
633
634 // Allow remapping of F2-F12
635 if (function_name[0] == 'F')
636 {
637 int c1 = function_name[1] - '0';
638 int c2 = function_name[2] ? function_name[2] - '0' : -1;
639 if (c1 >= 0 && c1 <= 9 && c2 >= -1 && c2 <= 9)
640 {
641 int idx = c1;
642 if (c2 >= 0)
643 idx = idx*10 + c2;
644 if (idx >=2 && idx <= 12)
645 {
646 U32 keyidx = ((mask<<16)|key);
647 (mRemapKeys[mode])[keyidx] = ((0<<16)|KEY_F1+(idx-1));
648 return TRUE;
649 }
650 }
651 }
652
653 // Not remapped, look for a function
654 for (i = 0; i < mNamedFunctionCount; i++)
655 {
656 if (!strcmp(function_name, mNamedFunctions[i].mName))
657 {
658 function = mNamedFunctions[i].mFunction;
659 name = mNamedFunctions[i].mName;
660 }
661 }
662
663 if (!function)
664 {
665 llerrs << "Can't bind key to function " << function_name << ", no function with this name found" << llendl;
666 return FALSE;
667 }
668
669 // check for duplicate first and overwrite
670 for (index = 0; index < mBindingCount[mode]; index++)
671 {
672 if (key == mBindings[mode][index].mKey && mask == mBindings[mode][index].mMask)
673 break;
674 }
675
676 if (index >= MAX_KEY_BINDINGS)
677 {
678 llerrs << "LLKeyboard::bindKey() - too many keys for mode " << mode << llendl;
679 return FALSE;
680 }
681
682 if (mode >= MODE_COUNT)
683 {
684 llerror("LLKeyboard::bindKey() - unknown mode passed", mode);
685 return FALSE;
686 }
687
688 mBindings[mode][index].mKey = key;
689 mBindings[mode][index].mMask = mask;
690// mBindings[mode][index].mName = name;
691 mBindings[mode][index].mFunction = function;
692
693 if (index == mBindingCount[mode])
694 mBindingCount[mode]++;
695
696 // printf("Bound key %c to %s\n", key, name);
697
698 return TRUE;
699}
700
701
702S32 LLViewerKeyboard::loadBindings(const char *filename)
703{
704 FILE *fp;
705 const S32 BUFFER_SIZE = 2048;
706 char buffer[BUFFER_SIZE];
707 char mode_string[MAX_STRING];
708 char key_string[MAX_STRING];
709 char mask_string[MAX_STRING];
710 char function_string[MAX_STRING];
711 S32 mode = MODE_THIRD_PERSON;
712 KEY key = 0;
713 MASK mask = 0;
714 S32 tokens_read;
715 S32 binding_count = 0;
716 S32 line_count = 0;
717
718 fp = LLFile::fopen(filename, "r");
719
720 if (!fp)
721 {
722 return 0;
723 }
724
725
726 while (!feof(fp))
727 {
728 line_count++;
729 if (!fgets(buffer, BUFFER_SIZE, fp))
730 break;
731
732 // skip over comments, blank lines
733 if (buffer[0] == '#' || buffer[0] == '\n') continue;
734
735 // grab the binding strings
736 tokens_read = sscanf(buffer, "%s %s %s %s", mode_string, key_string, mask_string, function_string);
737
738 if (tokens_read == EOF)
739 {
740 llinfos << "Unexpected end-of-file at line " << line_count << " of key binding file " << filename << llendl;
741 fclose(fp);
742 return 0;
743 }
744 else if (tokens_read < 4)
745 {
746 llinfos << "Can't read line " << line_count << " of key binding file " << filename << llendl;
747 continue;
748 }
749
750 // convert mode
751 if (!modeFromString(mode_string, &mode))
752 {
753 llinfos << "Unknown mode on line " << line_count << " of key binding file " << filename << llendl;
754 llinfos << "Mode must be one of FIRST_PERSON, THIRD_PERSON, EDIT, EDIT_AVATAR" << llendl;
755 continue;
756 }
757
758 // convert key
759 if (!LLKeyboard::keyFromString(key_string, &key))
760 {
761 llinfos << "Can't interpret key on line " << line_count << " of key binding file " << filename << llendl;
762 continue;
763 }
764
765 // convert mask
766 if (!LLKeyboard::maskFromString(mask_string, &mask))
767 {
768 llinfos << "Can't interpret mask on line " << line_count << " of key binding file " << filename << llendl;
769 continue;
770 }
771
772 // bind key
773 if (bindKey(mode, key, mask, function_string))
774 {
775 binding_count++;
776 }
777 }
778
779 fclose(fp);
780
781 return binding_count;
782}
783
784
785EKeyboardMode LLViewerKeyboard::getMode()
786{
787 if ( gAgent.cameraMouselook() )
788 {
789 return MODE_FIRST_PERSON;
790 }
791 else if ( gMorphView && gMorphView->getVisible())
792 {
793 return MODE_EDIT_AVATAR;
794 }
795 else if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting)
796 {
797 return MODE_SITTING;
798 }
799 else
800 {
801 return MODE_THIRD_PERSON;
802 }
803}
804
805
806// Called from scanKeyboard.
807void LLViewerKeyboard::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
808{
809 S32 mode = getMode();
810 // Consider keyboard scanning as NOT mouse event. JC
811 MASK mask = gKeyboard->currentMask(FALSE);
812
813 LLKeyBinding* binding = mBindings[mode];
814 S32 binding_count = mBindingCount[mode];
815
816
817 if (mKeyHandledByUI[key])
818 {
819 return;
820 }
821
822 // don't process key down on repeated keys
823 BOOL repeat = gKeyboard->getKeyRepeated(key);
824
825 for (S32 i = 0; i < binding_count; i++)
826 {
827 //for (S32 key = 0; key < KEY_COUNT; key++)
828 if (binding[i].mKey == key)
829 {
830 //if (binding[i].mKey == key && binding[i].mMask == mask)
831 if (binding[i].mMask == mask)
832 {
833 if (key_down && !repeat)
834 {
835 // ...key went down this frame, call function
836 (*binding[i].mFunction)( KEYSTATE_DOWN );
837 }
838 else if (key_up)
839 {
840 // ...key went down this frame, call function
841 (*binding[i].mFunction)( KEYSTATE_UP );
842 }
843 else if (key_level)
844 {
845 // ...key held down from previous frame
846 // Not windows, just call the function.
847 (*binding[i].mFunction)( KEYSTATE_LEVEL );
848 }//if
849 }//if
850 }//for
851 }//for
852}