summaryrefslogtreecommitdiff
path: root/indra/newview/llviewerkeyboard.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewerkeyboard.cpp')
-rw-r--r--indra/newview/llviewerkeyboard.cpp833
1 files changed, 833 insertions, 0 deletions
diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp
new file mode 100644
index 0000000000..8f31f1192a
--- /dev/null
+++ b/indra/newview/llviewerkeyboard.cpp
@@ -0,0 +1,833 @@
+/**
+ * @file llviewerkeyboard.cpp
+ * @brief LLViewerKeyboard class implementation
+ *
+ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewerkeyboard.h"
+#include "llmath.h"
+#include "llagent.h"
+#include "llchatbar.h"
+#include "llviewercontrol.h"
+#include "llfocusmgr.h"
+#include "llmorphview.h"
+#include "llmoveview.h"
+#include "lltoolfocus.h"
+#include "llviewerwindow.h"
+#include "llvoavatar.h"
+
+//
+// Constants
+//
+
+const F32 FLY_TIME = 0.5f;
+const F32 FLY_FRAMES = 4;
+
+const F32 NUDGE_TIME = 0.25f; // in seconds
+const S32 NUDGE_FRAMES = 2;
+const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed
+const F32 YAW_NUDGE_RATE = 0.05f; // fraction of normal speed
+
+LLViewerKeyboard gViewerKeyboard;
+
+void agent_jump( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ F32 time = gKeyboard->getCurKeyElapsedTime();
+ S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
+
+ if( time < FLY_TIME
+ || frame_count <= FLY_FRAMES
+ || gAgent.upGrabbed()
+ || !gSavedSettings.getBOOL("AutomaticFly"))
+ {
+ gAgent.moveUp(1);
+ }
+ else
+ {
+ gAgent.setFlying(TRUE);
+ gAgent.moveUp(1);
+ }
+}
+
+void agent_push_down( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.moveUp(-1);
+}
+
+void agent_push_forward( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ F32 time = gKeyboard->getCurKeyElapsedTime();
+ S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
+
+ if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
+ {
+ gAgent.moveAtNudge(1);
+ }
+ else
+ {
+ gAgent.moveAt(1);
+ }
+}
+
+
+void agent_push_backward( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
+ F32 time = gKeyboard->getCurKeyElapsedTime();
+
+ if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
+ {
+ gAgent.moveAtNudge(-1);
+ }
+ else
+ {
+ gAgent.moveAt(-1);
+ }
+}
+
+void agent_slide_left( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ F32 time = gKeyboard->getCurKeyElapsedTime();
+ S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
+
+ if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
+ {
+ if (frame_count == 0)
+ {
+ // only send nudge on first frame
+ gAgent.moveLeftNudge(1);
+ }
+ }
+ else
+ {
+ gAgent.moveLeft(1);
+ }
+}
+
+
+void agent_slide_right( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ F32 time = gKeyboard->getCurKeyElapsedTime();
+ S32 frame_count = llround(gKeyboard->getCurKeyElapsedFrameCount());
+
+ if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
+ {
+ if (frame_count == 0)
+ {
+ // only send nudge on first frame
+ gAgent.moveLeftNudge(-1);
+ }
+ }
+ else
+ {
+ gAgent.moveLeft(-1);
+ }
+}
+
+void agent_turn_left( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ F32 time = gKeyboard->getCurKeyElapsedTime();
+ if (gToolCamera->mouseSteerMode())
+ {
+ agent_slide_left(s);
+ }
+ else
+ {
+ gAgent.moveYaw( LLFloaterMove::getYawRate( time ) );
+ }
+}
+
+
+void agent_turn_right( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ F32 time = gKeyboard->getCurKeyElapsedTime();
+ if (gToolCamera->mouseSteerMode())
+ {
+ agent_slide_right(s);
+ }
+ else
+ {
+ gAgent.moveYaw( -LLFloaterMove::getYawRate( time ) );
+ }
+}
+
+void agent_look_up( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.movePitch(-1);
+ //gAgent.rotate(-2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
+}
+
+
+void agent_look_down( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.movePitch(1);
+ //gAgent.rotate(2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
+}
+
+void agent_toggle_fly( EKeystate s )
+{
+ // Only catch the edge
+ if (KEYSTATE_DOWN == s )
+ {
+ gAgent.toggleFlying();
+ }
+}
+
+F32 get_orbit_rate()
+{
+ F32 time = gKeyboard->getCurKeyElapsedTime();
+ if( time < NUDGE_TIME )
+ {
+ F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME;
+ //llinfos << rate << llendl;
+ return rate;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+void camera_spin_around_ccw( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.unlockView();
+ gAgent.setOrbitLeftKey( get_orbit_rate() );
+}
+
+
+void camera_spin_around_cw( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.unlockView();
+ gAgent.setOrbitRightKey( get_orbit_rate() );
+}
+
+void camera_spin_around_ccw_sitting( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ if (gAgent.rotateGrabbed() || gAgent.sitCameraEnabled())
+ {
+ //send keystrokes, but do not change camera
+ agent_turn_right(s);
+ }
+ else
+ {
+ //change camera but do not send keystrokes
+ gAgent.setOrbitLeftKey( get_orbit_rate() );
+ }
+}
+
+
+void camera_spin_around_cw_sitting( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ if (gAgent.rotateGrabbed() || gAgent.sitCameraEnabled())
+ {
+ //send keystrokes, but do not change camera
+ agent_turn_left(s);
+ }
+ else
+ {
+ //change camera but do not send keystrokes
+ gAgent.setOrbitRightKey( get_orbit_rate() );
+ }
+}
+
+
+void camera_spin_over( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.unlockView();
+ gAgent.setOrbitUpKey( get_orbit_rate() );
+}
+
+
+void camera_spin_under( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.unlockView();
+ gAgent.setOrbitDownKey( get_orbit_rate() );
+}
+
+void camera_spin_over_sitting( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ if (gAgent.upGrabbed() || gAgent.sitCameraEnabled())
+ {
+ //send keystrokes, but do not change camera
+ agent_jump(s);
+ }
+ else
+ {
+ //change camera but do not send keystrokes
+ gAgent.setOrbitUpKey( get_orbit_rate() );
+ }
+}
+
+
+void camera_spin_under_sitting( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ if (gAgent.downGrabbed() || gAgent.sitCameraEnabled())
+ {
+ //send keystrokes, but do not change camera
+ agent_push_down(s);
+ }
+ else
+ {
+ //change camera but do not send keystrokes
+ gAgent.setOrbitDownKey( get_orbit_rate() );
+ }
+}
+
+void camera_move_forward( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.unlockView();
+ gAgent.setOrbitInKey( get_orbit_rate() );
+}
+
+
+void camera_move_backward( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.unlockView();
+ gAgent.setOrbitOutKey( get_orbit_rate() );
+}
+
+void camera_move_forward_sitting( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ if (gAgent.forwardGrabbed() || gAgent.sitCameraEnabled())
+ {
+ agent_push_forward(s);
+ }
+ else
+ {
+ gAgent.setOrbitInKey( get_orbit_rate() );
+ }
+}
+
+
+void camera_move_backward_sitting( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+
+ if (gAgent.backwardGrabbed() || gAgent.sitCameraEnabled())
+ {
+ agent_push_backward(s);
+ }
+ else
+ {
+ gAgent.setOrbitOutKey( get_orbit_rate() );
+ }
+}
+
+void camera_pan_up( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.unlockView();
+ gAgent.setPanUpKey( get_orbit_rate() );
+}
+
+void camera_pan_down( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.unlockView();
+ gAgent.setPanDownKey( get_orbit_rate() );
+}
+
+void camera_pan_left( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.unlockView();
+ gAgent.setPanLeftKey( get_orbit_rate() );
+}
+
+void camera_pan_right( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.unlockView();
+ gAgent.setPanRightKey( get_orbit_rate() );
+}
+
+void camera_pan_in( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.unlockView();
+ gAgent.setPanInKey( get_orbit_rate() );
+}
+
+void camera_pan_out( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.unlockView();
+ gAgent.setPanOutKey( get_orbit_rate() );
+}
+
+void camera_move_forward_fast( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.unlockView();
+ gAgent.setOrbitInKey(2.5f);
+}
+
+void camera_move_backward_fast( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gAgent.unlockView();
+ gAgent.setOrbitOutKey(2.5f);
+}
+
+
+void edit_avatar_spin_ccw( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gMorphView->setCameraDrivenByKeys( TRUE );
+ gAgent.setOrbitLeftKey( get_orbit_rate() );
+ //gMorphView->orbitLeft( get_orbit_rate() );
+}
+
+
+void edit_avatar_spin_cw( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gMorphView->setCameraDrivenByKeys( TRUE );
+ gAgent.setOrbitRightKey( get_orbit_rate() );
+ //gMorphView->orbitRight( get_orbit_rate() );
+}
+
+void edit_avatar_spin_over( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gMorphView->setCameraDrivenByKeys( TRUE );
+ gAgent.setOrbitUpKey( get_orbit_rate() );
+ //gMorphView->orbitUp( get_orbit_rate() );
+}
+
+
+void edit_avatar_spin_under( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gMorphView->setCameraDrivenByKeys( TRUE );
+ gAgent.setOrbitDownKey( get_orbit_rate() );
+ //gMorphView->orbitDown( get_orbit_rate() );
+}
+
+void edit_avatar_move_forward( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gMorphView->setCameraDrivenByKeys( TRUE );
+ gAgent.setOrbitInKey( get_orbit_rate() );
+ //gMorphView->orbitIn();
+}
+
+
+void edit_avatar_move_backward( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ gMorphView->setCameraDrivenByKeys( TRUE );
+ gAgent.setOrbitOutKey( get_orbit_rate() );
+ //gMorphView->orbitOut();
+}
+
+void stop_moving( EKeystate s )
+{
+ if( KEYSTATE_UP == s ) return;
+ // stop agent
+ gAgent.setControlFlags(AGENT_CONTROL_STOP);
+
+ // cancel autopilot
+ gAgent.stopAutoPilot();
+}
+
+void start_chat( EKeystate s )
+{
+ if (!gChatBar->inputEditorHasFocus())
+ {
+ // start chat
+ gChatBar->startChat(NULL);
+ }
+}
+
+void bind_keyboard_functions()
+{
+ gViewerKeyboard.bindNamedFunction("jump", agent_jump);
+ gViewerKeyboard.bindNamedFunction("push_down", agent_push_down);
+ gViewerKeyboard.bindNamedFunction("push_forward", agent_push_forward);
+ gViewerKeyboard.bindNamedFunction("push_backward", agent_push_backward);
+ gViewerKeyboard.bindNamedFunction("look_up", agent_look_up);
+ gViewerKeyboard.bindNamedFunction("look_down", agent_look_down);
+ gViewerKeyboard.bindNamedFunction("toggle_fly", agent_toggle_fly);
+ gViewerKeyboard.bindNamedFunction("turn_left", agent_turn_left);
+ gViewerKeyboard.bindNamedFunction("turn_right", agent_turn_right);
+ gViewerKeyboard.bindNamedFunction("slide_left", agent_slide_left);
+ gViewerKeyboard.bindNamedFunction("slide_right", agent_slide_right);
+ gViewerKeyboard.bindNamedFunction("spin_around_ccw", camera_spin_around_ccw);
+ gViewerKeyboard.bindNamedFunction("spin_around_cw", camera_spin_around_cw);
+ gViewerKeyboard.bindNamedFunction("spin_around_ccw_sitting", camera_spin_around_ccw_sitting);
+ gViewerKeyboard.bindNamedFunction("spin_around_cw_sitting", camera_spin_around_cw_sitting);
+ gViewerKeyboard.bindNamedFunction("spin_over", camera_spin_over);
+ gViewerKeyboard.bindNamedFunction("spin_under", camera_spin_under);
+ gViewerKeyboard.bindNamedFunction("spin_over_sitting", camera_spin_over_sitting);
+ gViewerKeyboard.bindNamedFunction("spin_under_sitting", camera_spin_under_sitting);
+ gViewerKeyboard.bindNamedFunction("move_forward", camera_move_forward);
+ gViewerKeyboard.bindNamedFunction("move_backward", camera_move_backward);
+ gViewerKeyboard.bindNamedFunction("move_forward_sitting", camera_move_forward_sitting);
+ gViewerKeyboard.bindNamedFunction("move_backward_sitting", camera_move_backward_sitting);
+ gViewerKeyboard.bindNamedFunction("pan_up", camera_pan_up);
+ gViewerKeyboard.bindNamedFunction("pan_down", camera_pan_down);
+ gViewerKeyboard.bindNamedFunction("pan_left", camera_pan_left);
+ gViewerKeyboard.bindNamedFunction("pan_right", camera_pan_right);
+ gViewerKeyboard.bindNamedFunction("pan_in", camera_pan_in);
+ gViewerKeyboard.bindNamedFunction("pan_out", camera_pan_out);
+ gViewerKeyboard.bindNamedFunction("move_forward_fast", camera_move_forward_fast);
+ gViewerKeyboard.bindNamedFunction("move_backward_fast", camera_move_backward_fast);
+ gViewerKeyboard.bindNamedFunction("edit_avatar_spin_ccw", edit_avatar_spin_ccw);
+ gViewerKeyboard.bindNamedFunction("edit_avatar_spin_cw", edit_avatar_spin_cw);
+ gViewerKeyboard.bindNamedFunction("edit_avatar_spin_over", edit_avatar_spin_over);
+ gViewerKeyboard.bindNamedFunction("edit_avatar_spin_under", edit_avatar_spin_under);
+ gViewerKeyboard.bindNamedFunction("edit_avatar_move_forward", edit_avatar_move_forward);
+ gViewerKeyboard.bindNamedFunction("edit_avatar_move_backward", edit_avatar_move_backward);
+ gViewerKeyboard.bindNamedFunction("stop_moving", stop_moving);
+ gViewerKeyboard.bindNamedFunction("start_chat", start_chat);
+}
+
+LLViewerKeyboard::LLViewerKeyboard()
+{
+ for (S32 i = 0; i < MODE_COUNT; i++)
+ {
+ mBindingCount[i] = 0;
+ }
+
+ for (S32 i = 0; i < KEY_COUNT; i++)
+ {
+ mKeyHandledByUI[i] = FALSE;
+ }
+ // we want the UI to never see these keys so that they can always control the avatar/camera
+ for(KEY k = KEY_PAD_UP; k <= KEY_PAD_DIVIDE; k++)
+ {
+ mKeysSkippedByUI.insert(k);
+ }
+}
+
+
+void LLViewerKeyboard::bindNamedFunction(const char *name, LLKeyFunc func)
+{
+ S32 i = mNamedFunctionCount;
+ mNamedFunctions[i].mName = name;
+ mNamedFunctions[i].mFunction = func;
+ mNamedFunctionCount++;
+}
+
+
+BOOL LLViewerKeyboard::modeFromString(const char *string, S32 *mode)
+{
+ if (!strcmp(string, "FIRST_PERSON"))
+ {
+ *mode = MODE_FIRST_PERSON;
+ return TRUE;
+ }
+ else if (!strcmp(string, "THIRD_PERSON"))
+ {
+ *mode = MODE_THIRD_PERSON;
+ return TRUE;
+ }
+ else if (!strcmp(string, "EDIT"))
+ {
+ *mode = MODE_EDIT;
+ return TRUE;
+ }
+ else if (!strcmp(string, "EDIT_AVATAR"))
+ {
+ *mode = MODE_EDIT_AVATAR;
+ return TRUE;
+ }
+ else if (!strcmp(string, "SITTING"))
+ {
+ *mode = MODE_SITTING;
+ return TRUE;
+ }
+ else
+ {
+ *mode = MODE_THIRD_PERSON;
+ return FALSE;
+ }
+}
+
+BOOL LLViewerKeyboard::handleKey(KEY translated_key, MASK translated_mask, BOOL repeated)
+{
+ // check for re-map
+ EKeyboardMode mode = gViewerKeyboard.getMode();
+ U32 keyidx = (translated_mask<<16) | translated_key;
+ key_remap_t::iterator iter = mRemapKeys[mode].find(keyidx);
+ if (iter != mRemapKeys[mode].end())
+ {
+ translated_key = (iter->second) & 0xff;
+ translated_mask = (iter->second)>>16;
+ }
+
+ // No repeats of F-keys
+ BOOL repeatable_key = (translated_key < KEY_F1 || translated_key > KEY_F12);
+ if (!repeatable_key && repeated)
+ {
+ return FALSE;
+ }
+
+ lldebugst(LLERR_USER_INPUT) << "keydown -" << translated_key << "-" << llendl;
+ // skip skipped keys
+ if(mKeysSkippedByUI.find(translated_key) != mKeysSkippedByUI.end())
+ {
+ mKeyHandledByUI[translated_key] = FALSE;
+ }
+ else
+ {
+ // it is sufficient to set this value once per call to handlekey
+ // without clearing it, as it is only used in the subsequent call to scanKey
+ mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask);
+ }
+ return mKeyHandledByUI[translated_key];
+}
+
+
+
+BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, const char *function_name)
+{
+ S32 i,index;
+ void (*function)(EKeystate keystate) = NULL;
+ const char *name = NULL;
+
+ // Allow remapping of F2-F12
+ if (function_name[0] == 'F')
+ {
+ int c1 = function_name[1] - '0';
+ int c2 = function_name[2] ? function_name[2] - '0' : -1;
+ if (c1 >= 0 && c1 <= 9 && c2 >= -1 && c2 <= 9)
+ {
+ int idx = c1;
+ if (c2 >= 0)
+ idx = idx*10 + c2;
+ if (idx >=2 && idx <= 12)
+ {
+ U32 keyidx = ((mask<<16)|key);
+ (mRemapKeys[mode])[keyidx] = ((0<<16)|KEY_F1+(idx-1));
+ return TRUE;
+ }
+ }
+ }
+
+ // Not remapped, look for a function
+ for (i = 0; i < mNamedFunctionCount; i++)
+ {
+ if (!strcmp(function_name, mNamedFunctions[i].mName))
+ {
+ function = mNamedFunctions[i].mFunction;
+ name = mNamedFunctions[i].mName;
+ }
+ }
+
+ if (!function)
+ {
+ llerrs << "Can't bind key to function " << function_name << ", no function with this name found" << llendl;
+ return FALSE;
+ }
+
+ // check for duplicate first and overwrite
+ for (index = 0; index < mBindingCount[mode]; index++)
+ {
+ if (key == mBindings[mode][index].mKey && mask == mBindings[mode][index].mMask)
+ break;
+ }
+
+ if (index >= MAX_KEY_BINDINGS)
+ {
+ llerrs << "LLKeyboard::bindKey() - too many keys for mode " << mode << llendl;
+ return FALSE;
+ }
+
+ if (mode >= MODE_COUNT)
+ {
+ llerror("LLKeyboard::bindKey() - unknown mode passed", mode);
+ return FALSE;
+ }
+
+ mBindings[mode][index].mKey = key;
+ mBindings[mode][index].mMask = mask;
+// mBindings[mode][index].mName = name;
+ mBindings[mode][index].mFunction = function;
+
+ if (index == mBindingCount[mode])
+ mBindingCount[mode]++;
+
+ // printf("Bound key %c to %s\n", key, name);
+
+ return TRUE;
+}
+
+
+S32 LLViewerKeyboard::loadBindings(const char *filename)
+{
+ FILE *fp;
+ const S32 BUFFER_SIZE = 2048;
+ char buffer[BUFFER_SIZE];
+ char mode_string[MAX_STRING];
+ char key_string[MAX_STRING];
+ char mask_string[MAX_STRING];
+ char function_string[MAX_STRING];
+ S32 mode = MODE_THIRD_PERSON;
+ KEY key = 0;
+ MASK mask = 0;
+ S32 tokens_read;
+ S32 binding_count = 0;
+ S32 line_count = 0;
+
+ fp = LLFile::fopen(filename, "r");
+
+ if (!fp)
+ {
+ return 0;
+ }
+
+
+ while (!feof(fp))
+ {
+ line_count++;
+ if (!fgets(buffer, BUFFER_SIZE, fp))
+ break;
+
+ // skip over comments, blank lines
+ if (buffer[0] == '#' || buffer[0] == '\n') continue;
+
+ // grab the binding strings
+ tokens_read = sscanf(buffer, "%s %s %s %s", mode_string, key_string, mask_string, function_string);
+
+ if (tokens_read == EOF)
+ {
+ llinfos << "Unexpected end-of-file at line " << line_count << " of key binding file " << filename << llendl;
+ fclose(fp);
+ return 0;
+ }
+ else if (tokens_read < 4)
+ {
+ llinfos << "Can't read line " << line_count << " of key binding file " << filename << llendl;
+ continue;
+ }
+
+ // convert mode
+ if (!modeFromString(mode_string, &mode))
+ {
+ llinfos << "Unknown mode on line " << line_count << " of key binding file " << filename << llendl;
+ llinfos << "Mode must be one of FIRST_PERSON, THIRD_PERSON, EDIT, EDIT_AVATAR" << llendl;
+ continue;
+ }
+
+ // convert key
+ if (!LLKeyboard::keyFromString(key_string, &key))
+ {
+ llinfos << "Can't interpret key on line " << line_count << " of key binding file " << filename << llendl;
+ continue;
+ }
+
+ // convert mask
+ if (!LLKeyboard::maskFromString(mask_string, &mask))
+ {
+ llinfos << "Can't interpret mask on line " << line_count << " of key binding file " << filename << llendl;
+ continue;
+ }
+
+ // bind key
+ if (bindKey(mode, key, mask, function_string))
+ {
+ binding_count++;
+ }
+ }
+
+ fclose(fp);
+
+ return binding_count;
+}
+
+
+EKeyboardMode LLViewerKeyboard::getMode()
+{
+ if ( gAgent.cameraMouselook() )
+ {
+ return MODE_FIRST_PERSON;
+ }
+ else if ( gMorphView && gMorphView->getVisible())
+ {
+ return MODE_EDIT_AVATAR;
+ }
+ else if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting)
+ {
+ return MODE_SITTING;
+ }
+ else
+ {
+ return MODE_THIRD_PERSON;
+ }
+}
+
+
+// Called from scanKeyboard.
+void LLViewerKeyboard::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
+{
+ S32 mode = getMode();
+ // Consider keyboard scanning as NOT mouse event. JC
+ MASK mask = gKeyboard->currentMask(FALSE);
+
+ LLKeyBinding* binding = mBindings[mode];
+ S32 binding_count = mBindingCount[mode];
+
+
+ if (mKeyHandledByUI[key])
+ {
+ return;
+ }
+
+ // don't process key down on repeated keys
+ BOOL repeat = gKeyboard->getKeyRepeated(key);
+
+ for (S32 i = 0; i < binding_count; i++)
+ {
+ //for (S32 key = 0; key < KEY_COUNT; key++)
+ if (binding[i].mKey == key)
+ {
+ //if (binding[i].mKey == key && binding[i].mMask == mask)
+ if (binding[i].mMask == mask)
+ {
+ if (key_down && !repeat)
+ {
+ // ...key went down this frame, call function
+ (*binding[i].mFunction)( KEYSTATE_DOWN );
+ }
+ else if (key_up)
+ {
+ // ...key went down this frame, call function
+ (*binding[i].mFunction)( KEYSTATE_UP );
+ }
+ else if (key_level)
+ {
+ // ...key held down from previous frame
+ // Not windows, just call the function.
+ (*binding[i].mFunction)( KEYSTATE_LEVEL );
+ }//if
+ }//if
+ }//for
+ }//for
+}