diff --git a/indra/llxuixml/llregistry.h b/indra/llxuixml/llregistry.h
index eee9933739..546cf38eb5 100644
--- a/indra/llxuixml/llregistry.h
+++ b/indra/llxuixml/llregistry.h
@@ -343,4 +343,9 @@ private:
ScopedRegistrar* mStaticScope;
};
+// helper macro for doing static registration
+#define GLUED_TOKEN(x, y) x ## y
+#define GLUE_TOKENS(x, y) GLUED_TOKEN(x, y)
+#define LLREGISTER_STATIC(REGISTRY, KEY, VALUE) static REGISTRY::StaticRegistrar GLUE_TOKENS(reg, __COUNTER__)(KEY, VALUE);
+
#endif
diff --git a/indra/newview/app_settings/keys.xml b/indra/newview/app_settings/keys.xml
new file mode 100644
index 0000000000..d085475c6c
--- /dev/null
+++ b/indra/newview/app_settings/keys.xml
@@ -0,0 +1,350 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Basic editing camera control
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 956f67df86..a9bdabe794 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -820,16 +820,22 @@ bool LLAppViewer::init()
gGLManager.getGLInfo(gDebugInfo);
gGLManager.printGLInfoString();
- //load key settings
- bind_keyboard_functions();
-
// Load Default bindings
- if (!gViewerKeyboard.loadBindings(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"keys.ini")))
+ std::string key_bindings_file = gDirUtilp->findFile("keys.xml",
+ gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
+ gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
+
+
+ if (!gViewerKeyboard.loadBindingsXML(key_bindings_file))
{
- LL_ERRS("InitInfo") << "Unable to open keys.ini" << LL_ENDL;
+ std::string key_bindings_file = gDirUtilp->findFile("keys.ini",
+ gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
+ gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
+ if (!gViewerKeyboard.loadBindings(key_bindings_file))
+ {
+ LL_ERRS("InitInfo") << "Unable to open keys.ini" << LL_ENDL;
+ }
}
- // Load Custom bindings (override defaults)
- gViewerKeyboard.loadBindings(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"custom_keys.ini"));
// If we don't have the right GL requirements, exit.
if (!gGLManager.mHasRequirements && !gNoRender)
diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp
index d7e15e7d6c..570f372950 100644
--- a/indra/newview/llviewerkeyboard.cpp
+++ b/indra/newview/llviewerkeyboard.cpp
@@ -40,6 +40,7 @@
#include "llviewerwindow.h"
#include "llvoavatarself.h"
#include "llfloatercamera.h"
+#include "llinitparam.h"
//
// Constants
@@ -53,6 +54,11 @@ 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
+struct LLKeyboardActionRegistry
+: public LLRegistrySingleton, LLKeyboardActionRegistry>
+{
+};
+
LLViewerKeyboard gViewerKeyboard;
void agent_jump( EKeystate s )
@@ -550,49 +556,47 @@ void start_gesture( EKeystate s )
}
}
-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);
- gViewerKeyboard.bindNamedFunction("start_gesture", start_gesture);
-}
+#define REGISTER_KEYBOARD_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, ACTION);
+REGISTER_KEYBOARD_ACTION("jump", agent_jump);
+REGISTER_KEYBOARD_ACTION("push_down", agent_push_down);
+REGISTER_KEYBOARD_ACTION("push_forward", agent_push_forward);
+REGISTER_KEYBOARD_ACTION("push_backward", agent_push_backward);
+REGISTER_KEYBOARD_ACTION("look_up", agent_look_up);
+REGISTER_KEYBOARD_ACTION("look_down", agent_look_down);
+REGISTER_KEYBOARD_ACTION("toggle_fly", agent_toggle_fly);
+REGISTER_KEYBOARD_ACTION("turn_left", agent_turn_left);
+REGISTER_KEYBOARD_ACTION("turn_right", agent_turn_right);
+REGISTER_KEYBOARD_ACTION("slide_left", agent_slide_left);
+REGISTER_KEYBOARD_ACTION("slide_right", agent_slide_right);
+REGISTER_KEYBOARD_ACTION("spin_around_ccw", camera_spin_around_ccw);
+REGISTER_KEYBOARD_ACTION("spin_around_cw", camera_spin_around_cw);
+REGISTER_KEYBOARD_ACTION("spin_around_ccw_sitting", camera_spin_around_ccw_sitting);
+REGISTER_KEYBOARD_ACTION("spin_around_cw_sitting", camera_spin_around_cw_sitting);
+REGISTER_KEYBOARD_ACTION("spin_over", camera_spin_over);
+REGISTER_KEYBOARD_ACTION("spin_under", camera_spin_under);
+REGISTER_KEYBOARD_ACTION("spin_over_sitting", camera_spin_over_sitting);
+REGISTER_KEYBOARD_ACTION("spin_under_sitting", camera_spin_under_sitting);
+REGISTER_KEYBOARD_ACTION("move_forward", camera_move_forward);
+REGISTER_KEYBOARD_ACTION("move_backward", camera_move_backward);
+REGISTER_KEYBOARD_ACTION("move_forward_sitting", camera_move_forward_sitting);
+REGISTER_KEYBOARD_ACTION("move_backward_sitting", camera_move_backward_sitting);
+REGISTER_KEYBOARD_ACTION("pan_up", camera_pan_up);
+REGISTER_KEYBOARD_ACTION("pan_down", camera_pan_down);
+REGISTER_KEYBOARD_ACTION("pan_left", camera_pan_left);
+REGISTER_KEYBOARD_ACTION("pan_right", camera_pan_right);
+REGISTER_KEYBOARD_ACTION("pan_in", camera_pan_in);
+REGISTER_KEYBOARD_ACTION("pan_out", camera_pan_out);
+REGISTER_KEYBOARD_ACTION("move_forward_fast", camera_move_forward_fast);
+REGISTER_KEYBOARD_ACTION("move_backward_fast", camera_move_backward_fast);
+REGISTER_KEYBOARD_ACTION("edit_avatar_spin_ccw", edit_avatar_spin_ccw);
+REGISTER_KEYBOARD_ACTION("edit_avatar_spin_cw", edit_avatar_spin_cw);
+REGISTER_KEYBOARD_ACTION("edit_avatar_spin_over", edit_avatar_spin_over);
+REGISTER_KEYBOARD_ACTION("edit_avatar_spin_under", edit_avatar_spin_under);
+REGISTER_KEYBOARD_ACTION("edit_avatar_move_forward", edit_avatar_move_forward);
+REGISTER_KEYBOARD_ACTION("edit_avatar_move_backward", edit_avatar_move_backward);
+REGISTER_KEYBOARD_ACTION("stop_moving", stop_moving);
+REGISTER_KEYBOARD_ACTION("start_chat", start_chat);
+REGISTER_KEYBOARD_ACTION("start_gesture", start_gesture);
LLViewerKeyboard::LLViewerKeyboard() :
mNamedFunctionCount(0)
@@ -764,6 +768,61 @@ BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, c
return TRUE;
}
+LLViewerKeyboard::KeyBinding::KeyBinding()
+: key("key"),
+ mask("mask"),
+ command("command")
+{}
+
+LLViewerKeyboard::KeyMode::KeyMode(EKeyboardMode _mode)
+: bindings("binding"),
+ mode(_mode)
+{}
+
+LLViewerKeyboard::Keys::Keys()
+: first_person("first_person", KeyMode(MODE_FIRST_PERSON)),
+ third_person("third_person", KeyMode(MODE_THIRD_PERSON)),
+ edit("edit", KeyMode(MODE_EDIT)),
+ sitting("sitting", KeyMode(MODE_SITTING)),
+ edit_avatar("edit_avatar", KeyMode(MODE_EDIT_AVATAR))
+{}
+
+S32 LLViewerKeyboard::loadBindingsXML(const std::string& filename)
+{
+ S32 binding_count = 0;
+ Keys keys;
+ LLSimpleXUIParser parser;
+
+ if (parser.readXUI(filename, keys)
+ && keys.validateBlock())
+ {
+ binding_count += loadBindingMode(keys.first_person);
+ binding_count += loadBindingMode(keys.third_person);
+ binding_count += loadBindingMode(keys.edit);
+ binding_count += loadBindingMode(keys.sitting);
+ binding_count += loadBindingMode(keys.edit_avatar);
+ }
+ return binding_count;
+}
+
+S32 LLViewerKeyboard::loadBindingMode(const LLViewerKeyboard::KeyMode& keymode)
+{
+ S32 binding_count = 0;
+ for (LLInitParam::ParamIterator::const_iterator it = keymode.bindings.begin(),
+ end_it = keymode.bindings.end();
+ it != end_it;
+ ++it)
+ {
+ KEY key;
+ MASK mask;
+ LLKeyboard::keyFromString(it->key, &key);
+ LLKeyboard::maskFromString(it->mask, &mask);
+ bindKey(keymode.mode, key, mask, it->command);
+ binding_count++;
+ }
+
+ return binding_count;
+}
S32 LLViewerKeyboard::loadBindings(const std::string& filename)
{
diff --git a/indra/newview/llviewerkeyboard.h b/indra/newview/llviewerkeyboard.h
index 2fa5d5dfa6..6e758cc7b3 100644
--- a/indra/newview/llviewerkeyboard.h
+++ b/indra/newview/llviewerkeyboard.h
@@ -55,10 +55,36 @@ typedef enum e_keyboard_mode
void bind_keyboard_functions();
-
class LLViewerKeyboard
{
public:
+ struct KeyBinding : public LLInitParam::Block
+ {
+ Mandatory key,
+ mask,
+ command;
+
+ KeyBinding();
+ };
+
+ struct KeyMode : public LLInitParam::Block
+ {
+ Multiple bindings;
+ EKeyboardMode mode;
+ KeyMode(EKeyboardMode mode);
+ };
+
+ struct Keys : public LLInitParam::Block
+ {
+ Optional first_person,
+ third_person,
+ edit,
+ sitting,
+ edit_avatar;
+
+ Keys();
+ };
+
LLViewerKeyboard();
BOOL handleKey(KEY key, MASK mask, BOOL repeated);
@@ -66,13 +92,17 @@ public:
void bindNamedFunction(const std::string& name, LLKeyFunc func);
S32 loadBindings(const std::string& filename); // returns number bound, 0 on error
+ S32 loadBindingsXML(const std::string& filename); // returns number bound, 0 on error
EKeyboardMode getMode();
BOOL modeFromString(const std::string& string, S32 *mode); // False on failure
void scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level);
-protected:
+
+private:
+ S32 loadBindingMode(const LLViewerKeyboard::KeyMode& keymode);
BOOL bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name);
+
S32 mNamedFunctionCount;
LLNamedFunction mNamedFunctions[MAX_NAMED_FUNCTIONS];