llviewerkeyboard.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llappviewer.h"
00035 #include "llviewerkeyboard.h"
00036 #include "llmath.h"
00037 #include "llagent.h"
00038 #include "llchatbar.h"
00039 #include "llviewercontrol.h"
00040 #include "llfocusmgr.h"
00041 #include "llmorphview.h"
00042 #include "llmoveview.h"
00043 #include "lltoolfocus.h"
00044 #include "llviewerwindow.h"
00045 #include "llvoavatar.h"
00046 
00047 //
00048 // Constants
00049 //
00050 
00051 const F32 FLY_TIME = 0.5f;
00052 const F32 FLY_FRAMES = 4;
00053 
00054 const F32 NUDGE_TIME = 0.25f;  // in seconds
00055 const S32 NUDGE_FRAMES = 2;
00056 const F32 ORBIT_NUDGE_RATE = 0.05f;  // fraction of normal speed
00057 const F32 YAW_NUDGE_RATE = 0.05f;  // fraction of normal speed
00058 
00059 LLViewerKeyboard gViewerKeyboard;
00060 
00061 void agent_jump( EKeystate s )
00062 {
00063         if( KEYSTATE_UP == s  ) return;
00064         F32 time = gKeyboard->getCurKeyElapsedTime();
00065         S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
00066 
00067         if( time < FLY_TIME 
00068                 || frame_count <= FLY_FRAMES 
00069                 || gAgent.upGrabbed()
00070                 || !gSavedSettings.getBOOL("AutomaticFly"))
00071         {
00072                 gAgent.moveUp(1);
00073         }
00074         else
00075         {
00076                 gAgent.setFlying(TRUE);
00077                 gAgent.moveUp(1);
00078         }
00079 }
00080 
00081 void agent_push_down( EKeystate s )
00082 {
00083         if( KEYSTATE_UP == s  ) return;
00084         gAgent.moveUp(-1);
00085 }
00086 
00087 static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode mode)
00088 {
00089         if (KEYSTATE_UP == s)
00090         {
00091                 if (gAgent.mDoubleTapRunMode == mode &&
00092                     gAgent.getRunning() &&
00093                     !gAgent.getAlwaysRun())
00094                 {
00095                         // Turn off temporary running.
00096                         gAgent.clearRunning();
00097                         gAgent.sendWalkRun(gAgent.getRunning());
00098                 }
00099         }
00100         else if (gAllowTapTapHoldRun &&
00101                  KEYSTATE_DOWN == s &&
00102                  !gAgent.getRunning())
00103         {
00104                 if (gAgent.mDoubleTapRunMode == mode &&
00105                     gAgent.mDoubleTapRunTimer.getElapsedTimeF32() < NUDGE_TIME)
00106                 {
00107                         // Same walk-key was pushed again quickly; this is a
00108                         // double-tap so engage temporary running.
00109                         gAgent.setRunning();
00110                         gAgent.sendWalkRun(gAgent.getRunning());
00111                 }
00112 
00113                 // Pressing any walk-key resets the double-tap timer
00114                 gAgent.mDoubleTapRunTimer.reset();
00115                 gAgent.mDoubleTapRunMode = mode;
00116         }
00117 }
00118 
00119 static void agent_push_forwardbackward( EKeystate s, S32 direction, LLAgent::EDoubleTapRunMode mode )
00120 {
00121         agent_handle_doubletap_run(s, mode);
00122         if (KEYSTATE_UP == s) return;
00123 
00124         F32 time = gKeyboard->getCurKeyElapsedTime();
00125         S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
00126 
00127         if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
00128         {
00129                 gAgent.moveAtNudge(direction);
00130         }
00131         else
00132         {
00133                 gAgent.moveAt(direction);
00134         }
00135 }
00136 
00137 void agent_push_forward( EKeystate s )
00138 {
00139         agent_push_forwardbackward(s, 1, LLAgent::DOUBLETAP_FORWARD);
00140 }
00141 
00142 
00143 void agent_push_backward( EKeystate s )
00144 {
00145         agent_push_forwardbackward(s, -1, LLAgent::DOUBLETAP_BACKWARD);
00146 }
00147 
00148 static void agent_slide_leftright( EKeystate s, S32 direction, LLAgent::EDoubleTapRunMode mode )
00149 {
00150         agent_handle_doubletap_run(s, mode);
00151         if( KEYSTATE_UP == s ) return;
00152         F32 time = gKeyboard->getCurKeyElapsedTime();
00153         S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
00154 
00155         if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
00156         {
00157                 gAgent.moveLeftNudge(direction);
00158         }
00159         else
00160         {
00161                 gAgent.moveLeft(direction);
00162         }
00163 }
00164 
00165 
00166 void agent_slide_left( EKeystate s )
00167 {
00168         agent_slide_leftright(s, 1, LLAgent::DOUBLETAP_SLIDELEFT);
00169 }
00170 
00171 
00172 void agent_slide_right( EKeystate s )
00173 {
00174         agent_slide_leftright(s, -1, LLAgent::DOUBLETAP_SLIDERIGHT);
00175 }
00176 
00177 void agent_turn_left( EKeystate s )
00178 {
00179         if (LLToolCamera::getInstance()->mouseSteerMode())
00180         {
00181                 agent_slide_left(s);
00182         }
00183         else
00184         {
00185                 if (KEYSTATE_UP == s) return;
00186                 F32 time = gKeyboard->getCurKeyElapsedTime();
00187                 gAgent.moveYaw( LLFloaterMove::getYawRate( time ) );
00188         }
00189 }
00190 
00191 
00192 void agent_turn_right( EKeystate s )
00193 {
00194         if (LLToolCamera::getInstance()->mouseSteerMode())
00195         {
00196                 agent_slide_right(s);
00197         }
00198         else
00199         {
00200                 if (KEYSTATE_UP == s) return;
00201                 F32 time = gKeyboard->getCurKeyElapsedTime();
00202                 gAgent.moveYaw( -LLFloaterMove::getYawRate( time ) );
00203         }
00204 }
00205 
00206 void agent_look_up( EKeystate s )
00207 {
00208         if( KEYSTATE_UP == s  ) return;
00209         gAgent.movePitch(-1);
00210         //gAgent.rotate(-2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
00211 }
00212 
00213 
00214 void agent_look_down( EKeystate s )
00215 {
00216         if( KEYSTATE_UP == s  ) return;
00217         gAgent.movePitch(1);
00218         //gAgent.rotate(2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
00219 }
00220 
00221 void agent_toggle_fly( EKeystate s )
00222 {
00223         // Only catch the edge
00224         if (KEYSTATE_DOWN == s )
00225         {
00226                 gAgent.toggleFlying();
00227         }
00228 }
00229 
00230 F32 get_orbit_rate()
00231 {
00232         F32 time = gKeyboard->getCurKeyElapsedTime();
00233         if( time < NUDGE_TIME )
00234         {
00235                 F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME;
00236                 //llinfos << rate << llendl;
00237                 return rate;
00238         }
00239         else
00240         {
00241                 return 1;
00242         }
00243 }
00244 
00245 void camera_spin_around_ccw( EKeystate s )
00246 {
00247         if( KEYSTATE_UP == s  ) return;
00248         gAgent.unlockView();
00249         gAgent.setOrbitLeftKey( get_orbit_rate() );
00250 }
00251 
00252 
00253 void camera_spin_around_cw( EKeystate s )
00254 {
00255         if( KEYSTATE_UP == s  ) return;
00256         gAgent.unlockView();
00257         gAgent.setOrbitRightKey( get_orbit_rate() );
00258 }
00259 
00260 void camera_spin_around_ccw_sitting( EKeystate s )
00261 {
00262         if( KEYSTATE_UP == s ) return;
00263         if (gAgent.rotateGrabbed() || gAgent.sitCameraEnabled())
00264         {
00265                 //send keystrokes, but do not change camera
00266                 agent_turn_right(s);
00267         }
00268         else
00269         {
00270                 //change camera but do not send keystrokes
00271                 gAgent.setOrbitLeftKey( get_orbit_rate() );
00272         }
00273 }
00274 
00275 
00276 void camera_spin_around_cw_sitting( EKeystate s )
00277 {
00278         if( KEYSTATE_UP == s  ) return;
00279         if (gAgent.rotateGrabbed() || gAgent.sitCameraEnabled())
00280         {
00281                 //send keystrokes, but do not change camera
00282                 agent_turn_left(s);
00283         }
00284         else
00285         {
00286                 //change camera but do not send keystrokes
00287                 gAgent.setOrbitRightKey( get_orbit_rate() );
00288         }
00289 }
00290 
00291 
00292 void camera_spin_over( EKeystate s )
00293 {
00294         if( KEYSTATE_UP == s  ) return;
00295         gAgent.unlockView();
00296         gAgent.setOrbitUpKey( get_orbit_rate() );
00297 }
00298 
00299 
00300 void camera_spin_under( EKeystate s )
00301 {
00302         if( KEYSTATE_UP == s  ) return;
00303         gAgent.unlockView();
00304         gAgent.setOrbitDownKey( get_orbit_rate() );
00305 }
00306 
00307 void camera_spin_over_sitting( EKeystate s )
00308 {
00309         if( KEYSTATE_UP == s  ) return;
00310         if (gAgent.upGrabbed() || gAgent.sitCameraEnabled())
00311         {
00312                 //send keystrokes, but do not change camera
00313                 agent_jump(s);
00314         }
00315         else
00316         {
00317                 //change camera but do not send keystrokes
00318                 gAgent.setOrbitUpKey( get_orbit_rate() );
00319         }
00320 }
00321 
00322 
00323 void camera_spin_under_sitting( EKeystate s )
00324 {
00325         if( KEYSTATE_UP == s  ) return;
00326         if (gAgent.downGrabbed() || gAgent.sitCameraEnabled())
00327         {
00328                 //send keystrokes, but do not change camera
00329                 agent_push_down(s);
00330         }
00331         else
00332         {
00333                 //change camera but do not send keystrokes
00334                 gAgent.setOrbitDownKey( get_orbit_rate() );
00335         }
00336 }
00337 
00338 void camera_move_forward( EKeystate s )
00339 {
00340         if( KEYSTATE_UP == s  ) return;
00341         gAgent.unlockView();
00342         gAgent.setOrbitInKey( get_orbit_rate() );
00343 }
00344 
00345 
00346 void camera_move_backward( EKeystate s )
00347 {
00348         if( KEYSTATE_UP == s  ) return;
00349         gAgent.unlockView();
00350         gAgent.setOrbitOutKey( get_orbit_rate() );
00351 }
00352 
00353 void camera_move_forward_sitting( EKeystate s )
00354 {
00355         if( KEYSTATE_UP == s  ) return;
00356         if (gAgent.forwardGrabbed() || gAgent.sitCameraEnabled())
00357         {
00358                 agent_push_forward(s);
00359         }
00360         else
00361         {
00362                 gAgent.setOrbitInKey( get_orbit_rate() );
00363         }
00364 }
00365 
00366 
00367 void camera_move_backward_sitting( EKeystate s )
00368 {
00369         if( KEYSTATE_UP == s  ) return;
00370 
00371         if (gAgent.backwardGrabbed() || gAgent.sitCameraEnabled())
00372         {
00373                 agent_push_backward(s);
00374         }
00375         else
00376         {
00377                 gAgent.setOrbitOutKey( get_orbit_rate() );
00378         }
00379 }
00380 
00381 void camera_pan_up( EKeystate s )
00382 {
00383         if( KEYSTATE_UP == s  ) return;
00384         gAgent.unlockView();
00385         gAgent.setPanUpKey( get_orbit_rate() );
00386 }
00387 
00388 void camera_pan_down( EKeystate s )
00389 {
00390         if( KEYSTATE_UP == s  ) return;
00391         gAgent.unlockView();
00392         gAgent.setPanDownKey( get_orbit_rate() );
00393 }
00394 
00395 void camera_pan_left( EKeystate s )
00396 {
00397         if( KEYSTATE_UP == s  ) return;
00398         gAgent.unlockView();
00399         gAgent.setPanLeftKey( get_orbit_rate() );
00400 }
00401 
00402 void camera_pan_right( EKeystate s )
00403 {
00404         if( KEYSTATE_UP == s  ) return;
00405         gAgent.unlockView();
00406         gAgent.setPanRightKey( get_orbit_rate() );
00407 }
00408 
00409 void camera_pan_in( EKeystate s )
00410 {
00411         if( KEYSTATE_UP == s  ) return;
00412         gAgent.unlockView();
00413         gAgent.setPanInKey( get_orbit_rate() );
00414 }
00415 
00416 void camera_pan_out( EKeystate s )
00417 {
00418         if( KEYSTATE_UP == s  ) return;
00419         gAgent.unlockView();
00420         gAgent.setPanOutKey( get_orbit_rate() );
00421 }
00422 
00423 void camera_move_forward_fast( EKeystate s )
00424 {
00425         if( KEYSTATE_UP == s  ) return;
00426         gAgent.unlockView();
00427         gAgent.setOrbitInKey(2.5f);
00428 }
00429 
00430 void camera_move_backward_fast( EKeystate s )
00431 {
00432         if( KEYSTATE_UP == s  ) return;
00433         gAgent.unlockView();
00434         gAgent.setOrbitOutKey(2.5f);
00435 }
00436 
00437 
00438 void edit_avatar_spin_ccw( EKeystate s )
00439 {
00440         if( KEYSTATE_UP == s  ) return;
00441         gMorphView->setCameraDrivenByKeys( TRUE );
00442         gAgent.setOrbitLeftKey( get_orbit_rate() );
00443         //gMorphView->orbitLeft( get_orbit_rate() );
00444 }
00445 
00446 
00447 void edit_avatar_spin_cw( EKeystate s )
00448 {
00449         if( KEYSTATE_UP == s  ) return;
00450         gMorphView->setCameraDrivenByKeys( TRUE );
00451         gAgent.setOrbitRightKey( get_orbit_rate() );
00452         //gMorphView->orbitRight( get_orbit_rate() );
00453 }
00454 
00455 void edit_avatar_spin_over( EKeystate s )
00456 {
00457         if( KEYSTATE_UP == s  ) return;
00458         gMorphView->setCameraDrivenByKeys( TRUE );
00459         gAgent.setOrbitUpKey( get_orbit_rate() );
00460         //gMorphView->orbitUp( get_orbit_rate() );
00461 }
00462 
00463 
00464 void edit_avatar_spin_under( EKeystate s )
00465 {
00466         if( KEYSTATE_UP == s  ) return;
00467         gMorphView->setCameraDrivenByKeys( TRUE );
00468         gAgent.setOrbitDownKey( get_orbit_rate() );
00469         //gMorphView->orbitDown( get_orbit_rate() );
00470 }
00471 
00472 void edit_avatar_move_forward( EKeystate s )
00473 {
00474         if( KEYSTATE_UP == s  ) return;
00475         gMorphView->setCameraDrivenByKeys( TRUE );
00476         gAgent.setOrbitInKey( get_orbit_rate() );
00477         //gMorphView->orbitIn();
00478 }
00479 
00480 
00481 void edit_avatar_move_backward( EKeystate s )
00482 {
00483         if( KEYSTATE_UP == s  ) return;
00484         gMorphView->setCameraDrivenByKeys( TRUE );
00485         gAgent.setOrbitOutKey( get_orbit_rate() );
00486         //gMorphView->orbitOut();
00487 }
00488 
00489 void stop_moving( EKeystate s )
00490 {
00491         if( KEYSTATE_UP == s  ) return;
00492         // stop agent
00493         gAgent.setControlFlags(AGENT_CONTROL_STOP);
00494 
00495         // cancel autopilot
00496         gAgent.stopAutoPilot();
00497 }
00498 
00499 void start_chat( EKeystate s )
00500 {
00501         // start chat
00502         gChatBar->startChat(NULL);
00503 }
00504 
00505 void start_gesture( EKeystate s )
00506 {
00507         if (KEYSTATE_UP == s &&
00508                 !(gFocusMgr.getKeyboardFocus() && gFocusMgr.getKeyboardFocus()->acceptsTextInput()))
00509         {
00510                 if (gChatBar->getCurrentChat().empty())
00511                 {
00512                         // No existing chat in chat editor, insert '/'
00513                         gChatBar->startChat("/");
00514                 }
00515                 else
00516                 {
00517                         // Don't overwrite existing text in chat editor
00518                         gChatBar->startChat(NULL);
00519                 }
00520         }
00521 }
00522 
00523 void bind_keyboard_functions()
00524 {
00525         gViewerKeyboard.bindNamedFunction("jump", agent_jump);
00526         gViewerKeyboard.bindNamedFunction("push_down", agent_push_down);
00527         gViewerKeyboard.bindNamedFunction("push_forward", agent_push_forward);
00528         gViewerKeyboard.bindNamedFunction("push_backward", agent_push_backward);
00529         gViewerKeyboard.bindNamedFunction("look_up", agent_look_up);
00530         gViewerKeyboard.bindNamedFunction("look_down", agent_look_down);
00531         gViewerKeyboard.bindNamedFunction("toggle_fly", agent_toggle_fly);
00532         gViewerKeyboard.bindNamedFunction("turn_left", agent_turn_left);
00533         gViewerKeyboard.bindNamedFunction("turn_right", agent_turn_right);
00534         gViewerKeyboard.bindNamedFunction("slide_left", agent_slide_left);
00535         gViewerKeyboard.bindNamedFunction("slide_right", agent_slide_right);
00536         gViewerKeyboard.bindNamedFunction("spin_around_ccw", camera_spin_around_ccw);
00537         gViewerKeyboard.bindNamedFunction("spin_around_cw", camera_spin_around_cw);
00538         gViewerKeyboard.bindNamedFunction("spin_around_ccw_sitting", camera_spin_around_ccw_sitting);
00539         gViewerKeyboard.bindNamedFunction("spin_around_cw_sitting", camera_spin_around_cw_sitting);
00540         gViewerKeyboard.bindNamedFunction("spin_over", camera_spin_over);
00541         gViewerKeyboard.bindNamedFunction("spin_under", camera_spin_under);
00542         gViewerKeyboard.bindNamedFunction("spin_over_sitting", camera_spin_over_sitting);
00543         gViewerKeyboard.bindNamedFunction("spin_under_sitting", camera_spin_under_sitting);
00544         gViewerKeyboard.bindNamedFunction("move_forward", camera_move_forward);
00545         gViewerKeyboard.bindNamedFunction("move_backward", camera_move_backward);
00546         gViewerKeyboard.bindNamedFunction("move_forward_sitting", camera_move_forward_sitting);
00547         gViewerKeyboard.bindNamedFunction("move_backward_sitting", camera_move_backward_sitting);
00548         gViewerKeyboard.bindNamedFunction("pan_up", camera_pan_up);
00549         gViewerKeyboard.bindNamedFunction("pan_down", camera_pan_down);
00550         gViewerKeyboard.bindNamedFunction("pan_left", camera_pan_left);
00551         gViewerKeyboard.bindNamedFunction("pan_right", camera_pan_right);
00552         gViewerKeyboard.bindNamedFunction("pan_in", camera_pan_in);
00553         gViewerKeyboard.bindNamedFunction("pan_out", camera_pan_out);
00554         gViewerKeyboard.bindNamedFunction("move_forward_fast", camera_move_forward_fast);
00555         gViewerKeyboard.bindNamedFunction("move_backward_fast", camera_move_backward_fast);
00556         gViewerKeyboard.bindNamedFunction("edit_avatar_spin_ccw", edit_avatar_spin_ccw);
00557         gViewerKeyboard.bindNamedFunction("edit_avatar_spin_cw", edit_avatar_spin_cw);
00558         gViewerKeyboard.bindNamedFunction("edit_avatar_spin_over", edit_avatar_spin_over);
00559         gViewerKeyboard.bindNamedFunction("edit_avatar_spin_under", edit_avatar_spin_under);
00560         gViewerKeyboard.bindNamedFunction("edit_avatar_move_forward", edit_avatar_move_forward);
00561         gViewerKeyboard.bindNamedFunction("edit_avatar_move_backward", edit_avatar_move_backward);
00562         gViewerKeyboard.bindNamedFunction("stop_moving", stop_moving);
00563         gViewerKeyboard.bindNamedFunction("start_chat", start_chat);
00564         gViewerKeyboard.bindNamedFunction("start_gesture", start_gesture);
00565 }
00566 
00567 LLViewerKeyboard::LLViewerKeyboard()
00568 {
00569         for (S32 i = 0; i < MODE_COUNT; i++)
00570         {
00571                 mBindingCount[i] = 0;
00572         }
00573 
00574         for (S32 i = 0; i < KEY_COUNT; i++)
00575         {
00576                 mKeyHandledByUI[i] = FALSE;
00577         }
00578         // we want the UI to never see these keys so that they can always control the avatar/camera
00579         for(KEY k = KEY_PAD_UP; k <= KEY_PAD_DIVIDE; k++) 
00580         {
00581                 mKeysSkippedByUI.insert(k);     
00582         }
00583 }
00584 
00585 
00586 void LLViewerKeyboard::bindNamedFunction(const char *name, LLKeyFunc func)
00587 {
00588         S32 i = mNamedFunctionCount;
00589         mNamedFunctions[i].mName = name;
00590         mNamedFunctions[i].mFunction = func;
00591         mNamedFunctionCount++;
00592 }
00593 
00594 
00595 BOOL LLViewerKeyboard::modeFromString(const char *string, S32 *mode)
00596 {
00597         if (!strcmp(string, "FIRST_PERSON"))
00598         {
00599                 *mode = MODE_FIRST_PERSON;
00600                 return TRUE;
00601         }
00602         else if (!strcmp(string, "THIRD_PERSON"))
00603         {
00604                 *mode = MODE_THIRD_PERSON;
00605                 return TRUE;
00606         }
00607         else if (!strcmp(string, "EDIT"))
00608         {
00609                 *mode = MODE_EDIT;
00610                 return TRUE;
00611         }
00612         else if (!strcmp(string, "EDIT_AVATAR"))
00613         {
00614                 *mode = MODE_EDIT_AVATAR;
00615                 return TRUE;
00616         }
00617         else if (!strcmp(string, "SITTING"))
00618         {
00619                 *mode = MODE_SITTING;
00620                 return TRUE;
00621         }
00622         else
00623         {
00624                 *mode = MODE_THIRD_PERSON;
00625                 return FALSE;
00626         }
00627 }
00628 
00629 BOOL LLViewerKeyboard::handleKey(KEY translated_key,  MASK translated_mask, BOOL repeated)
00630 {
00631         // check for re-map
00632         EKeyboardMode mode = gViewerKeyboard.getMode();
00633         U32 keyidx = (translated_mask<<16) | translated_key;
00634         key_remap_t::iterator iter = mRemapKeys[mode].find(keyidx);
00635         if (iter != mRemapKeys[mode].end())
00636         {
00637                 translated_key = (iter->second) & 0xff;
00638                 translated_mask = (iter->second)>>16;
00639         }
00640 
00641         // No repeats of F-keys
00642         BOOL repeatable_key = (translated_key < KEY_F1 || translated_key > KEY_F12);
00643         if (!repeatable_key && repeated)
00644         {
00645                 return FALSE;
00646         }
00647 
00648         lldebugst(LLERR_USER_INPUT) << "keydown -" << translated_key << "-" << llendl;
00649         // skip skipped keys
00650         if(mKeysSkippedByUI.find(translated_key) != mKeysSkippedByUI.end()) 
00651         {
00652                 mKeyHandledByUI[translated_key] = FALSE;
00653         }
00654         else
00655         {
00656                 // it is sufficient to set this value once per call to handlekey
00657                 // without clearing it, as it is only used in the subsequent call to scanKey
00658                 mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask);
00659         }
00660         return mKeyHandledByUI[translated_key];
00661 }
00662 
00663 
00664 
00665 BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, const char *function_name)
00666 {
00667         S32 i,index;
00668         void (*function)(EKeystate keystate) = NULL;
00669         const char *name = NULL;
00670 
00671         // Allow remapping of F2-F12
00672         if (function_name[0] == 'F')
00673         {
00674                 int c1 = function_name[1] - '0';
00675                 int c2 = function_name[2] ? function_name[2] - '0' : -1;
00676                 if (c1 >= 0 && c1 <= 9 && c2 >= -1 && c2 <= 9)
00677                 {
00678                         int idx = c1;
00679                         if (c2 >= 0)
00680                                 idx = idx*10 + c2;
00681                         if (idx >=2 && idx <= 12)
00682                         {
00683                                 U32 keyidx = ((mask<<16)|key);
00684                                 (mRemapKeys[mode])[keyidx] = ((0<<16)|KEY_F1+(idx-1));
00685                                 return TRUE;
00686                         }
00687                 }
00688         }
00689 
00690         // Not remapped, look for a function
00691         for (i = 0; i < mNamedFunctionCount; i++)
00692         {
00693                 if (!strcmp(function_name, mNamedFunctions[i].mName))
00694                 {
00695                         function = mNamedFunctions[i].mFunction;
00696                         name = mNamedFunctions[i].mName;
00697                 }
00698         }
00699 
00700         if (!function)
00701         {
00702                 llerrs << "Can't bind key to function " << function_name << ", no function with this name found" << llendl;
00703                 return FALSE;
00704         }
00705 
00706         // check for duplicate first and overwrite
00707         for (index = 0; index < mBindingCount[mode]; index++)
00708         {
00709                 if (key == mBindings[mode][index].mKey && mask == mBindings[mode][index].mMask)
00710                         break;
00711         }
00712 
00713         if (index >= MAX_KEY_BINDINGS)
00714         {
00715                 llerrs << "LLKeyboard::bindKey() - too many keys for mode " << mode << llendl;
00716                 return FALSE;
00717         }
00718 
00719         if (mode >= MODE_COUNT)
00720         {
00721                 llerror("LLKeyboard::bindKey() - unknown mode passed", mode);
00722                 return FALSE;
00723         }
00724 
00725         mBindings[mode][index].mKey = key;
00726         mBindings[mode][index].mMask = mask;
00727 //      mBindings[mode][index].mName = name;
00728         mBindings[mode][index].mFunction = function;
00729 
00730         if (index == mBindingCount[mode])
00731                 mBindingCount[mode]++;
00732 
00733         // printf("Bound key %c to %s\n", key, name);
00734 
00735         return TRUE;
00736 }
00737 
00738 
00739 S32 LLViewerKeyboard::loadBindings(const char *filename)
00740 {
00741         LLFILE *fp;
00742         const S32 BUFFER_SIZE = 2048;
00743         char buffer[BUFFER_SIZE];       /* Flawfinder: ignore */
00744         // *NOTE: This buffer size is hard coded into scanf() below.
00745         char mode_string[MAX_STRING];   /* Flawfinder: ignore */
00746         char key_string[MAX_STRING];    /* Flawfinder: ignore */
00747         char mask_string[MAX_STRING];   /* Flawfinder: ignore */
00748         char function_string[MAX_STRING];       /* Flawfinder: ignore */
00749         S32 mode = MODE_THIRD_PERSON;
00750         KEY key = 0;
00751         MASK mask = 0;
00752         S32 tokens_read;
00753         S32 binding_count = 0;
00754         S32 line_count = 0;
00755 
00756         if(!filename)
00757         {
00758                 llerrs << " No filename specified" << llendl;
00759                 return 0;
00760         }
00761 
00762         fp = LLFile::fopen(filename, "r");
00763 
00764         if (!fp)
00765         {
00766                 return 0;
00767         }
00768 
00769 
00770         while (!feof(fp))
00771         {
00772                 line_count++;
00773                 if (!fgets(buffer, BUFFER_SIZE, fp))
00774                         break;
00775 
00776                 // skip over comments, blank lines
00777                 if (buffer[0] == '#' || buffer[0] == '\n') continue;
00778 
00779                 // grab the binding strings
00780                 tokens_read = sscanf(   /* Flawfinder: ignore */
00781                         buffer,
00782                         "%254s %254s %254s %254s",
00783                         mode_string,
00784                         key_string,
00785                         mask_string,
00786                         function_string);
00787 
00788                 if (tokens_read == EOF)
00789                 {
00790                         llinfos << "Unexpected end-of-file at line " << line_count << " of key binding file " << filename << llendl;
00791                         fclose(fp);
00792                         return 0;
00793                 }
00794                 else if (tokens_read < 4)
00795                 {
00796                         llinfos << "Can't read line " << line_count << " of key binding file " << filename << llendl;
00797                         continue;
00798                 }
00799 
00800                 // convert mode
00801                 if (!modeFromString(mode_string, &mode))
00802                 {
00803                         llinfos << "Unknown mode on line " << line_count << " of key binding file " << filename << llendl;
00804                         llinfos << "Mode must be one of FIRST_PERSON, THIRD_PERSON, EDIT, EDIT_AVATAR" << llendl;
00805                         continue;
00806                 }
00807 
00808                 // convert key
00809                 if (!LLKeyboard::keyFromString(key_string, &key))
00810                 {
00811                         llinfos << "Can't interpret key on line " << line_count << " of key binding file " << filename << llendl;
00812                         continue;
00813                 }
00814 
00815                 // convert mask
00816                 if (!LLKeyboard::maskFromString(mask_string, &mask))
00817                 {
00818                         llinfos << "Can't interpret mask on line " << line_count << " of key binding file " << filename << llendl;
00819                         continue;
00820                 }
00821 
00822                 // bind key
00823                 if (bindKey(mode, key, mask, function_string))
00824                 {
00825                         binding_count++;
00826                 }
00827         }
00828 
00829         fclose(fp);
00830 
00831         return binding_count;
00832 }
00833 
00834 
00835 EKeyboardMode LLViewerKeyboard::getMode()
00836 {
00837         if ( gAgent.cameraMouselook() )
00838         {
00839                 return MODE_FIRST_PERSON;
00840         }
00841         else if ( gMorphView && gMorphView->getVisible())
00842         {
00843                 return MODE_EDIT_AVATAR;
00844         }
00845         else if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting)
00846         {
00847                 return MODE_SITTING;
00848         }
00849         else
00850         {
00851                 return MODE_THIRD_PERSON;
00852         }
00853 }
00854 
00855 
00856 // Called from scanKeyboard.
00857 void LLViewerKeyboard::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
00858 {
00859         S32 mode = getMode();
00860         // Consider keyboard scanning as NOT mouse event. JC
00861         MASK mask = gKeyboard->currentMask(FALSE);
00862 
00863         LLKeyBinding* binding = mBindings[mode];
00864         S32 binding_count = mBindingCount[mode];
00865 
00866 
00867         if (mKeyHandledByUI[key])
00868         {
00869                 return;
00870         }
00871 
00872         // don't process key down on repeated keys
00873         BOOL repeat = gKeyboard->getKeyRepeated(key);
00874 
00875         for (S32 i = 0; i < binding_count; i++)
00876         {
00877                 //for (S32 key = 0; key < KEY_COUNT; key++)
00878                 if (binding[i].mKey == key)
00879                 {
00880                         //if (binding[i].mKey == key && binding[i].mMask == mask)
00881                         if (binding[i].mMask == mask)
00882                         {
00883                                 if (key_down && !repeat)
00884                                 {
00885                                         // ...key went down this frame, call function
00886                                         (*binding[i].mFunction)( KEYSTATE_DOWN );
00887                                 }
00888                                 else if (key_up)
00889                                 {
00890                                         // ...key went down this frame, call function
00891                                         (*binding[i].mFunction)( KEYSTATE_UP );
00892                                 }
00893                                 else if (key_level)
00894                                 {
00895                                         // ...key held down from previous frame
00896                                         // Not windows, just call the function.
00897                                         (*binding[i].mFunction)( KEYSTATE_LEVEL );
00898                                 }//if
00899                         }//if
00900                 }//for
00901         }//for
00902 }

Generated on Fri May 16 08:34:10 2008 for SecondLife by  doxygen 1.5.5