diff options
-rw-r--r-- | indra/newview/llfloaterpreference.cpp | 369 | ||||
-rw-r--r-- | indra/newview/llfloaterpreference.h | 4 | ||||
-rw-r--r-- | indra/newview/llkeyconflict.cpp | 426 | ||||
-rw-r--r-- | indra/newview/llkeyconflict.h | 117 | ||||
-rw-r--r-- | indra/newview/llviewerinput.cpp | 76 | ||||
-rw-r--r-- | indra/newview/llviewerwindow.cpp | 2 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/panel_preferences_controls.xml | 55 |
7 files changed, 510 insertions, 539 deletions
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index c0e334795a..088a0820aa 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -185,18 +185,53 @@ public: static void onCancel(void* user_data); static void onBlank(void* user_data); static void onDefault(void* user_data); + static void onClickTimeout(void* user_data, MASK mask); + + class Updater; private: + void setKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore); LLPanelPreferenceControls* pParent; LLCheckBoxCtrl* pCheckBox; - U32 mKeyMask; + U32 mKeyFilterMask; + Updater *pUpdater; +}; + +class LLSetKeyBindDialog::Updater : public LLEventTimer +{ +public: + + typedef boost::function<void(MASK)> callback_t; + + Updater(callback_t cb, F32 period, MASK mask) + :LLEventTimer(period), + mMask(mask), + mCallback(cb) + { + mEventTimer.start(); + } + + virtual ~Updater(){} + +protected: + BOOL tick() + { + mCallback(mMask); + // Deletes itseft after execution + return TRUE; + } + +private: + MASK mMask; + callback_t mCallback; }; LLSetKeyBindDialog::LLSetKeyBindDialog(const LLSD& key) : LLModalDialog(key), pParent(NULL), - mKeyMask(DEFAULT_KEY_FILTER) + mKeyFilterMask(DEFAULT_KEY_FILTER), + pUpdater(NULL) { } @@ -227,13 +262,19 @@ void LLSetKeyBindDialog::onClose(bool app_quiting) pParent->onCancelKeyBind(); pParent = NULL; } + if (pUpdater) + { + // Doubleclick timer has't fired, delete it + delete pUpdater; + pUpdater = NULL; + } LLModalDialog::onClose(app_quiting); } void LLSetKeyBindDialog::setParent(LLPanelPreferenceControls* parent, U32 key_mask) { pParent = parent; - mKeyMask = key_mask; + mKeyFilterMask = key_mask; LLTextBase *text_ctrl = getChild<LLTextBase>("descritption"); @@ -259,24 +300,18 @@ void LLSetKeyBindDialog::setParent(LLPanelPreferenceControls* parent, U32 key_ma BOOL LLSetKeyBindDialog::handleKeyHere(KEY key, MASK mask) { - BOOL result = TRUE; - if ((key == 'Q' && mask == MASK_CONTROL) || key == KEY_ESCAPE) { closeFloater(); - return true; + return TRUE; } if (key == KEY_DELETE) { - if (pParent) - { - pParent->onSetKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false); - pParent = NULL; - } + setKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false); closeFloater(); - return true; + return FALSE; } // forbidden keys @@ -284,40 +319,41 @@ BOOL LLSetKeyBindDialog::handleKeyHere(KEY key, MASK mask) || key == KEY_RETURN || key == KEY_BACKSPACE) { - return false; + return FALSE; } - if ((mKeyMask & ALLOW_MASKS) == 0 + if ((mKeyFilterMask & ALLOW_MASKS) == 0 && (key == KEY_CONTROL || key == KEY_SHIFT || key == KEY_ALT)) { // mask by themself are not allowed - return false; + return FALSE; } - else if ((mKeyMask & ALLOW_KEYS) == 0) + else if ((mKeyFilterMask & ALLOW_KEYS) == 0) { // basic keys not allowed - return false; + return FALSE; } - else if ((mKeyMask & ALLOW_MASK_KEYS) == 0 && mask != 0) + else if ((mKeyFilterMask & ALLOW_MASK_KEYS) == 0 && mask != 0) { // masked keys not allowed - return false; + return FALSE; } - if (pParent) - { - pParent->onSetKeyBind(CLICK_NONE, key, mask, pCheckBox->getValue().asBoolean()); - pParent = NULL; - } - closeFloater(); - return result; + setKeyBind(CLICK_NONE, key, mask, pCheckBox->getValue().asBoolean()); + closeFloater(); + return TRUE; } BOOL LLSetKeyBindDialog::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down) { BOOL result = FALSE; - - if (clicktype == CLICK_LEFT) + if (!pParent) + { + // we already processed 'down' event, this is 'up', consume + closeFloater(); + result = TRUE; + } + if (!result && clicktype == CLICK_LEFT) { // try handling buttons first if (down) @@ -328,25 +364,38 @@ BOOL LLSetKeyBindDialog::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClic { result = LLView::handleMouseUp(x, y, mask); } + if (result) + { + setFocus(TRUE); + gFocusMgr.setKeystrokesOnly(TRUE); + } + // ignore selection related combinations + else if (down && (mask & (MASK_SHIFT | MASK_CONTROL)) == 0) + { + // this can be a double click, wait a bit; + if (!pUpdater) + { + // Note: default doubleclick time is 500ms, but can stretch up to 5s + pUpdater = new Updater(boost::bind(&onClickTimeout, this, _1), 0.7f, mask); + result = TRUE; + } + } } if (!result - && ((mKeyMask & ALLOW_MOUSE) != 0) + && (clicktype != CLICK_LEFT) // subcases were handled above + && ((mKeyFilterMask & ALLOW_MOUSE) != 0) && (clicktype != CLICK_RIGHT || mask != 0) // reassigning menu button is not supported - && ((mKeyMask & ALLOW_MASK_MOUSE) != 0 || mask == 0)) + && ((mKeyFilterMask & ALLOW_MASK_MOUSE) != 0 || mask == 0)) // reserved for selection { - if (pParent) + setKeyBind(clicktype, KEY_NONE, mask, pCheckBox->getValue().asBoolean()); + result = TRUE; + if (!down) { - pParent->onSetKeyBind(clicktype, KEY_NONE, mask, pCheckBox->getValue().asBoolean()); - pParent = NULL; + // wait for 'up' event before closing + // alternative: set pUpdater + closeFloater(); } - result = TRUE; - closeFloater(); - } - - if (!result) - { - result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down); } return result; @@ -356,7 +405,7 @@ BOOL LLSetKeyBindDialog::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClic void LLSetKeyBindDialog::onCancel(void* user_data) { LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data; - self->closeFloater(); + self->closeFloater(); } //static @@ -364,11 +413,7 @@ void LLSetKeyBindDialog::onBlank(void* user_data) { LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data; // tmp needs 'no key' button - if (self->pParent) - { - self->pParent->onSetKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false); - self->pParent = NULL; - } + self->setKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false); self->closeFloater(); } @@ -376,7 +421,6 @@ void LLSetKeyBindDialog::onBlank(void* user_data) void LLSetKeyBindDialog::onDefault(void* user_data) { LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data; - // tmp needs 'no key' button if (self->pParent) { self->pParent->onDefaultKeyBind(); @@ -385,6 +429,27 @@ void LLSetKeyBindDialog::onDefault(void* user_data) self->closeFloater(); } +//static +void LLSetKeyBindDialog::onClickTimeout(void* user_data, MASK mask) +{ + LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data; + + // timer will delete itself after timeout + self->pUpdater = NULL; + + self->setKeyBind(CLICK_LEFT, KEY_NONE, mask, self->pCheckBox->getValue().asBoolean()); + self->closeFloater(); +} + +void LLSetKeyBindDialog::setKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore) +{ + if (pParent) + { + pParent->onSetKeyBind(click, key, mask, ignore); + pParent = NULL; + } +} + // global functions @@ -2972,9 +3037,72 @@ void LLPanelPreferenceGraphics::setHardwareDefaults() //------------------------LLPanelPreferenceControls-------------------------------- static LLPanelInjector<LLPanelPreferenceControls> t_pref_contrls("panel_preference_controls"); +//name of control and name of icon if it is a group, likely 'TEMP' until xml gets properly populated +typedef std::vector<std::pair<std::string, std::string> > controls_to_icon_t; +static const controls_to_icon_t commands_and_headers = +{ + //{ "control_view_actions", "Search_Icon" }, + //{ "control_interactions", "Command_Gestures_Icon" }, + { "control_movements", "Move_Walk_Off" }, + { "walk_to", "" }, + { "teleport_to", "" }, + { "push_forward", "" }, + { "push_backward", "" }, + { "turn_left", "" }, + { "turn_right", "" }, + { "slide_left", "" }, + { "slide_right", "" }, + { "jump", "" }, + { "push_down", "" }, + { "run_forward", "" }, + { "run_backward", "" }, + { "run_left", "" }, + { "run_right", "" }, + { "toggle_run", "" }, + { "toggle_fly", "" }, + { "toggle_sit", "" }, + { "stop_moving", "" }, + { "control_camera", "Cam_FreeCam_Off" }, + { "look_up", "" }, + { "look_down", "" }, + { "move_forward", "" }, + { "move_backward", "" }, + { "move_forward_fast", "" }, + { "move_backward_fast", "" }, + { "move_forward_sitting", "" }, + { "move_backward_sitting", "" }, + { "spin_over", "" }, + { "spin_under", "" }, + { "spin_over_sitting", "" }, + { "spin_under_sitting", "" }, + { "pan_up", "" }, + { "pan_down", "" }, + { "pan_left", "" }, + { "pan_right", "" }, + { "pan_in", "" }, + { "pan_out", "" }, + { "spin_around_ccw", "" }, + { "spin_around_cw", "" }, + { "spin_around_ccw_sitting", "" }, + { "spin_around_cw_sitting", "" }, + { "control_edit_title", "Tool_Dozer" }, + { "edit_avatar_spin_ccw", "" }, + { "edit_avatar_spin_cw", "" }, + { "edit_avatar_spin_over", "" }, + { "edit_avatar_spin_under", "" }, + { "edit_avatar_move_forward", "" }, + { "edit_avatar_move_backward", "" }, + { "control_mediacontent", "Audio_Press" }, + { "toggle_pause_media", "" }, + { "toggle_enable_media", "" }, + { "voice_follow_key", "" }, + { "toggle_voice", "" }, + { "start_chat", "" }, + { "start_gesture", "" }, +}; + LLPanelPreferenceControls::LLPanelPreferenceControls() :LLPanelPreference(), - mEditingIndex(-1), mEditingColumn(-1), mEditingMode(0), mShowKeyDialog(false), @@ -3013,8 +3141,8 @@ BOOL LLPanelPreferenceControls::handleHover(S32 x, S32 y, MASK mask) if (mShowKeyDialog) { mShowKeyDialog = false; - if (mEditingIndex > 0 - && mConflictHandler[mEditingMode].canAssignControl((LLKeyConflictHandler::EControlTypes)mEditingIndex)) + if (!mEditingControl.empty() + && mConflictHandler[mEditingMode].canAssignControl(mEditingControl)) { LLScrollListItem* item = pControlsTable->getFirstSelected(); // don't use pControlsTable->hitItem(x, y) dur to drift; if (item) @@ -3042,10 +3170,10 @@ BOOL LLPanelPreferenceControls::handleHover(S32 x, S32 y, MASK mask) return LLPanelPreference::handleHover(x, y, mask); } -void LLPanelPreferenceControls::addGroupRow(const std::string &icon, S32 index) +void LLPanelPreferenceControls::addGroupRow(const std::string &control_name, const std::string &icon) { LLScrollListItem::Params item_params; - item_params.value = LLSD::Integer(-1); + item_params.value = ""; LLScrollListCell::Params icon_cell_params; icon_cell_params.font = LLFontGL::getFontSansSerif(); @@ -3057,7 +3185,6 @@ void LLPanelPreferenceControls::addGroupRow(const std::string &icon, S32 index) cell_params.font = LLFontGL::getFontSansSerif(); cell_params.font_halign = LLFontGL::LEFT; - std::string control_name = LLKeyConflictHandler::getControlName((LLKeyConflictHandler::EControlTypes)index); std::string label; if (hasString(control_name)) { @@ -3110,76 +3237,48 @@ void LLPanelPreferenceControls::populateControlTable() cell_params.column = ""; cell_params.value = label; - S32 start = mEditingMode == LLKeyConflictHandler::MODE_GENERAL ? LLKeyConflictHandler::CONTROL_VIEW_ACTIONS : LLKeyConflictHandler::CONTROL_MOVEMENTS; - S32 end = mEditingMode == LLKeyConflictHandler::MODE_GENERAL ? LLKeyConflictHandler::CONTROL_NUM_INDICES : LLKeyConflictHandler::CONTROL_RESERVED; - for (S32 i = start; i < end; i++) + controls_to_icon_t::const_iterator iter = commands_and_headers.begin(); + controls_to_icon_t::const_iterator end = commands_and_headers.end(); + for (; iter != end; ++iter) { - LLKeyConflictHandler::EControlTypes type = (LLKeyConflictHandler::EControlTypes)i; - switch (type) + if (iter->second.empty()) { - case LLKeyConflictHandler::CONTROL_VIEW_ACTIONS: - addSeparator(); - addGroupRow("Search_Icon", i); - break; - case LLKeyConflictHandler::CONTROL_INTERACTIONS: - addSeparator(); - addGroupRow("Command_Gestures_Icon", i); - break; - case LLKeyConflictHandler::CONTROL_MOVEMENTS: - addSeparator(); - addGroupRow("Move_Walk_Off", i); - break; - case LLKeyConflictHandler::CONTROL_MEDIACONTENT: - addSeparator(); - addGroupRow("Audio_Press", i); - break; - case LLKeyConflictHandler::CONTROL_CAMERA: - addSeparator(); - addGroupRow("Cam_FreeCam_Off", i); - break; - case LLKeyConflictHandler::CONTROL_EDIT_TITLE: - addSeparator(); - addGroupRow("Tool_Dozer", i); - break; - case LLKeyConflictHandler::CONTROL_RESERVED: - addSeparator(); - addGroupRow("Info_Small", i); - break; - default: + // general control + LLScrollListItem::Params item_params; + item_params.value = LLSD(iter->first); + + cell_params.column = "lst_action"; + bool enabled = mConflictHandler[mEditingMode].canAssignControl(iter->first); + if (hasString(iter->first)) { - //default insert - LLScrollListItem::Params item_params; - item_params.value = LLSD::Integer(i); - - cell_params.column = "lst_action"; - bool enabled = mConflictHandler[mEditingMode].canAssignControl(type); - control_name = LLKeyConflictHandler::getControlName(type); - if (hasString(control_name)) - { - label = getString(control_name); - } - else - { - label = control_name; - } - cell_params.value = label; - item_params.columns.add(cell_params); - cell_params.column = "lst_ctrl1"; - cell_params.value = mConflictHandler[mEditingMode].getControlString(type, 0); - cell_params.enabled = enabled; - item_params.columns.add(cell_params); - cell_params.column = "lst_ctrl2"; - cell_params.value = mConflictHandler[mEditingMode].getControlString(type, 1); - cell_params.enabled = enabled; - item_params.columns.add(cell_params); - cell_params.column = "lst_ctrl3"; - cell_params.value = mConflictHandler[mEditingMode].getControlString(type, 2); - cell_params.enabled = enabled; - item_params.columns.add(cell_params); - - pControlsTable->addRow(item_params, EAddPosition::ADD_BOTTOM); - break; + label = getString(iter->first); } + else + { + label = iter->first; + } + cell_params.value = label; + item_params.columns.add(cell_params); + cell_params.column = "lst_ctrl1"; + cell_params.value = mConflictHandler[mEditingMode].getControlString(iter->first, 0); + cell_params.enabled = enabled; + item_params.columns.add(cell_params); + cell_params.column = "lst_ctrl2"; + cell_params.value = mConflictHandler[mEditingMode].getControlString(iter->first, 1); + cell_params.enabled = enabled; + item_params.columns.add(cell_params); + cell_params.column = "lst_ctrl3"; + cell_params.value = mConflictHandler[mEditingMode].getControlString(iter->first, 2); + cell_params.enabled = enabled; + item_params.columns.add(cell_params); + + pControlsTable->addRow(item_params, EAddPosition::ADD_BOTTOM); + } + else + { + // header + addSeparator(); + addGroupRow(iter->first, iter->second); } } } @@ -3195,13 +3294,13 @@ void LLPanelPreferenceControls::addSeparator() void LLPanelPreferenceControls::updateTable() { + mEditingControl.clear(); std::vector<LLScrollListItem*> list = pControlsTable->getAllData(); for (S32 i = 0; i < list.size(); ++i) { - S32 value = list[i]->getValue().asInteger(); - if (value > 0) + std::string control = list[i]->getValue(); + if (!control.empty()) { - LLKeyConflictHandler::EControlTypes control = (LLKeyConflictHandler::EControlTypes)value; LLScrollListCell* cell = list[i]->getColumn(1); cell->setValue(mConflictHandler[mEditingMode].getControlString(control, 0)); cell = list[i]->getColumn(2); @@ -3258,6 +3357,7 @@ void LLPanelPreferenceControls::saveSettings() if (mConflictHandler[i].hasUnsavedChanges()) { mConflictHandler[i].saveToSettings(); + mConflictHandler[i].clear(); } } @@ -3280,20 +3380,21 @@ void LLPanelPreferenceControls::resetDirtyChilds() void LLPanelPreferenceControls::onListCommit() { + mShowKeyDialog = false; LLScrollListItem* item = pControlsTable->getFirstSelected(); if (item == NULL) { return; } - S32 control = item->getValue().asInteger(); + std::string control = item->getValue(); - if (control <= 0) + if (control.empty()) { return; } - if (!mConflictHandler[mEditingMode].canAssignControl((LLKeyConflictHandler::EControlTypes)control)) + if (!mConflictHandler[mEditingMode].canAssignControl(control)) { return; } @@ -3302,7 +3403,7 @@ void LLPanelPreferenceControls::onListCommit() // fresh mouse coordinates are not yet accessible during onCommit() and there are other issues, // so we cheat: remember item user clicked at, trigger 'key dialog' on hover that comes next, // use coordinates from hover to calculate cell - mEditingIndex = control; + mEditingControl = control; mShowKeyDialog = true; if (mHighlightedCell) @@ -3320,18 +3421,16 @@ void LLPanelPreferenceControls::onModeCommit() // todo: copy onSetKeyBind to interface and inherit from interface void LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore_mask) { - LLKeyConflictHandler::EControlTypes control = (LLKeyConflictHandler::EControlTypes)mEditingIndex; - - if (!mConflictHandler[mEditingMode].canAssignControl(control)) + if (!mConflictHandler[mEditingMode].canAssignControl(mEditingControl)) { return; } pControlsTable->deselectAllItems(); - pControlsTable->selectByValue(mEditingIndex); + pControlsTable->selectByValue(mEditingControl); if ( mEditingColumn > 0) { - mConflictHandler[mEditingMode].registerControl(control, mEditingColumn - 1, click, key, mask, ignore_mask); + mConflictHandler[mEditingMode].registerControl(mEditingControl, mEditingColumn - 1, click, key, mask, ignore_mask); } updateTable(); @@ -3347,19 +3446,17 @@ void LLPanelPreferenceControls::onRestoreDefaults() void LLPanelPreferenceControls::onDefaultKeyBind() { - LLKeyConflictHandler::EControlTypes control = (LLKeyConflictHandler::EControlTypes)mEditingIndex; - - if (!mConflictHandler[mEditingMode].canAssignControl(control)) + if (!mConflictHandler[mEditingMode].canAssignControl(mEditingControl)) { return; } pControlsTable->deselectAllItems(); - pControlsTable->selectByValue(mEditingIndex); + pControlsTable->selectByValue(mEditingControl); if (mEditingColumn > 0) { - mConflictHandler[mEditingMode].resetToDefault(control, mEditingColumn - 1); + mConflictHandler[mEditingMode].resetToDefault(mEditingControl, mEditingColumn - 1); } updateTable(); } diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 513fda96df..2fe3b98abd 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -317,7 +317,7 @@ public: void onCancelKeyBind(); private: - void addGroupRow(const std::string &icon, S32 index); + void addGroupRow(const std::string &control_name, const std::string &icon); void regenerateControls(); void populateControlTable(); void addSeparator(); @@ -327,7 +327,7 @@ private: LLComboBox *pKeyModeBox; LLScrollListCell *mHighlightedCell; LLKeyConflictHandler mConflictHandler[LLKeyConflictHandler::MODE_COUNT]; - S32 mEditingIndex; + std::string mEditingControl; S32 mEditingColumn; S32 mEditingMode; bool mShowKeyDialog; diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index e81d121e3b..c74eea6e47 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -41,135 +41,7 @@ #include "llxuiparser.h" //#include "llstring.h" -static const std::string typetostring[LLKeyConflictHandler::CONTROL_NUM_INDICES] = { - "control_view_actions", - "control_about", - "control_orbit", - "control_pan", - "control_world_map", - "control_zoom", - "control_interactions", - "control_build", - //"control_drag", - "control_edit", - //"control_menu", - "control_open", - "control_touch", - "control_wear", - "control_movements", - "walk_to", - "teleport_to", - "push_forward", - "push_backward", - "turn_left", - "turn_right", - "slide_left", - "slide_right", - "jump", - "push_down", - //"control_run", - "toggle_run", - "toggle_fly", - "toggle_sit", - "stop_moving", - "control_camera", - "look_up", - "look_down", - "move_forward", - "move_backward", - "move_forward_fast", - "move_backward_fast", - "move_forward_sitting", - "move_backward_sitting", - "spin_over", - "spin_under", - "spin_over_sitting", - "spin_under_sitting", - "pan_up", - "pan_down", - "pan_left", - "pan_right", - "pan_in", - "pan_out", - "spin_around_ccw", - "spin_around_cw", - "spin_around_ccw_sitting", - "spin_around_cw_sitting", - "control_edit_title", - "edit_avatar_spin_ccw", - "edit_avatar_spin_cw", - "edit_avatar_spin_over", - "edit_avatar_spin_under", - "edit_avatar_move_forward", - "edit_avatar_move_backward", - "control_mediacontent", - "toggle_pause_media", - "toggle_enable_media", - "voice_follow_key", - "toggle_voice", - "start_chat", - "start_gesture", - "control_reserved", - "control_delete", - "control_menu", - "control_reserved_select", - "control_shift_select", - "control_cntrl_select" -}; - -// note, a solution is needed that will keep this up to date with llviewerinput -typedef std::map<std::string, LLKeyConflictHandler::EControlTypes> control_enum_t; -static const control_enum_t command_to_key = -{ - { "jump", LLKeyConflictHandler::CONTROL_JUMP }, - { "push_down", LLKeyConflictHandler::CONTROL_DOWN }, - { "push_forward", LLKeyConflictHandler::CONTROL_FORWARD }, - { "push_backward", LLKeyConflictHandler::CONTROL_BACKWARD }, - { "look_up", LLKeyConflictHandler::CONTROL_LOOK_UP }, - { "look_down", LLKeyConflictHandler::CONTROL_LOOK_DOWN }, - { "toggle_fly", LLKeyConflictHandler::CONTROL_TOGGLE_FLY }, - { "turn_left", LLKeyConflictHandler::CONTROL_LEFT }, - { "turn_right", LLKeyConflictHandler::CONTROL_RIGHT }, - { "slide_left", LLKeyConflictHandler::CONTROL_LSTRAFE }, - { "slide_right", LLKeyConflictHandler::CONTROL_RSTRAFE }, - { "spin_around_ccw", LLKeyConflictHandler::CONTROL_CAMERA_SPIN_CCW }, // todo, no idea what these spins are - { "spin_around_cw", LLKeyConflictHandler::CONTROL_CAMERA_SPIN_CW }, - { "spin_around_ccw_sitting", LLKeyConflictHandler::CONTROL_CAMERA_SPIN_CCW_SITTING }, - { "spin_around_cw_sitting", LLKeyConflictHandler::CONTROL_CAMERA_SPIN_CCW_SITTING }, - { "spin_over", LLKeyConflictHandler::CONTROL_CAMERA_SOVER }, - { "spin_under", LLKeyConflictHandler::CONTROL_CAMERA_SUNDER }, - { "spin_over_sitting", LLKeyConflictHandler::CONTROL_CAMERA_SOVER_SITTING }, - { "spin_under_sitting", LLKeyConflictHandler::CONTROL_CAMERA_SUNDER_SITTING }, - { "move_forward", LLKeyConflictHandler::CONTROL_CAMERA_FORWARD }, - { "move_backward", LLKeyConflictHandler::CONTROL_CAMERA_BACKWARD }, - { "move_forward_sitting", LLKeyConflictHandler::CONTROL_CAMERA_FSITTING }, - { "move_backward_sitting", LLKeyConflictHandler::CONTROL_CAMERA_BSITTING }, - { "pan_up", LLKeyConflictHandler::CONTROL_CAMERA_PANUP }, - { "pan_down", LLKeyConflictHandler::CONTROL_CAMERA_PANDOWN }, - { "pan_left", LLKeyConflictHandler::CONTROL_CAMERA_PANLEFT }, - { "pan_right", LLKeyConflictHandler::CONTROL_CAMERA_PANRIGHT }, - { "pan_in", LLKeyConflictHandler::CONTROL_CAMERA_PANIN }, - { "pan_out", LLKeyConflictHandler::CONTROL_CAMERA_PANOUT }, - { "move_forward_fast", LLKeyConflictHandler::CONTROL_CAMERA_FFORWARD }, - { "move_backward_fast", LLKeyConflictHandler::CONTROL_CAMERA_FBACKWARD }, - { "edit_avatar_spin_ccw", LLKeyConflictHandler::CONTROL_EDIT_AV_SPIN_CCW }, - { "edit_avatar_spin_cw", LLKeyConflictHandler::CONTROL_EDIT_AV_SPIN_CW }, - { "edit_avatar_spin_over", LLKeyConflictHandler::CONTROL_EDIT_AV_SPIN_OVER }, - { "edit_avatar_spin_under", LLKeyConflictHandler::CONTROL_EDIT_AV_SPIN_UNDER }, - { "edit_avatar_move_forward", LLKeyConflictHandler::CONTROL_EDIT_AV_MV_FORWARD }, - { "edit_avatar_move_backward", LLKeyConflictHandler::CONTROL_EDIT_AV_MV_BACKWARD }, - { "stop_moving", LLKeyConflictHandler::CONTROL_STOP }, - { "start_chat", LLKeyConflictHandler::CONTROL_START_CHAT }, - { "start_gesture", LLKeyConflictHandler::CONTROL_START_GESTURE }, - { "toggle_run", LLKeyConflictHandler::CONTROL_TOGGLE_RUN }, - { "toggle_sit", LLKeyConflictHandler::CONTROL_SIT }, - { "toggle_parcel_media", LLKeyConflictHandler::CONTROL_PAUSE_MEDIA }, - { "toggle_enable_media", LLKeyConflictHandler::CONTROL_ENABLE_MEDIA }, - { "walk_to", LLKeyConflictHandler::CONTROL_MOVETO }, - { "teleport_to", LLKeyConflictHandler::CONTROL_TELEPORTTO }, - { "toggle_voice", LLKeyConflictHandler::CONTROL_TOGGLE_VOICE }, - { "voice_follow_key", LLKeyConflictHandler::CONTROL_VOICE }, -}; +static const std::string saved_settings_key_controls[] = { "placeholder" }; // LLKeyboard::stringFromMask is meant for UI and is OS dependent, @@ -267,29 +139,29 @@ LLKeyConflictHandler::LLKeyConflictHandler(ESourceMode mode) loadFromSettings(mode); } -bool LLKeyConflictHandler::canHandleControl(LLKeyConflictHandler::EControlTypes control_type, EMouseClickType mouse_ind, KEY key, MASK mask) +bool LLKeyConflictHandler::canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask) { - return mControlsMap[control_type].canHandle(mouse_ind, key, mask); + return mControlsMap[control_name].canHandle(mouse_ind, key, mask); } -bool LLKeyConflictHandler::canHandleKey(EControlTypes control_type, KEY key, MASK mask) +bool LLKeyConflictHandler::canHandleKey(const std::string &control_name, KEY key, MASK mask) { - return canHandleControl(control_type, CLICK_NONE, key, mask); + return canHandleControl(control_name, CLICK_NONE, key, mask); } -bool LLKeyConflictHandler::canHandleMouse(LLKeyConflictHandler::EControlTypes control_type, EMouseClickType mouse_ind, MASK mask) +bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask) { - return canHandleControl(control_type, mouse_ind, KEY_NONE, mask); + return canHandleControl(control_name, mouse_ind, KEY_NONE, mask); } -bool LLKeyConflictHandler::canHandleMouse(EControlTypes control_type, S32 mouse_ind, MASK mask) +bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask) { - return canHandleControl(control_type, (EMouseClickType)mouse_ind, KEY_NONE, mask); + return canHandleControl(control_name, (EMouseClickType)mouse_ind, KEY_NONE, mask); } -bool LLKeyConflictHandler::canAssignControl(EControlTypes control_type) +bool LLKeyConflictHandler::canAssignControl(const std::string &control_name) { - std::map<EControlTypes, LLKeyConflict>::iterator iter = mControlsMap.find(control_type); + control_map_t::iterator iter = mControlsMap.find(control_name); if (iter != mControlsMap.end()) { return iter->second.mAssignable; @@ -297,9 +169,13 @@ bool LLKeyConflictHandler::canAssignControl(EControlTypes control_type) return false; } -bool LLKeyConflictHandler::registerControl(EControlTypes control_type, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask) +bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask) { - LLKeyConflict &type_data = mControlsMap[control_type]; + if (control_name.empty()) + { + return false; + } + LLKeyConflict &type_data = mControlsMap[control_name]; if (!type_data.mAssignable) { LL_ERRS() << "Error in code, user or system should not be able to change certain controls" << LL_ENDL; @@ -319,9 +195,13 @@ bool LLKeyConflictHandler::registerControl(EControlTypes control_type, U32 index return false; } -LLKeyData LLKeyConflictHandler::getControl(EControlTypes control_type, U32 index) +LLKeyData LLKeyConflictHandler::getControl(const std::string &control_name, U32 index) { - return mControlsMap[control_type].getKeyData(index); + if (control_name.empty()) + { + return LLKeyData(); + } + return mControlsMap[control_name].getKeyData(index); } // static @@ -341,24 +221,37 @@ std::string LLKeyConflictHandler::getStringFromKeyData(const LLKeyData& keydata) { result = LLKeyboard::stringFromAccelerator(keydata.mMask); } + else if (keydata.mIgnoreMasks) + { + result = "acc+"; + } result += string_from_mouse(keydata.mMouse); return result; } -// static -std::string LLKeyConflictHandler::getControlName(EControlTypes control_type) +std::string LLKeyConflictHandler::getControlString(const std::string &control_name, U32 index) { - return typetostring[control_type]; + if (control_name.empty()) + { + return ""; + } + return getStringFromKeyData(mControlsMap[control_name].getKeyData(index)); } -std::string LLKeyConflictHandler::getControlString(EControlTypes control_type, U32 index) +void LLKeyConflictHandler::loadFromControlSettings(const std::string &name) { - return getStringFromKeyData(mControlsMap[control_type].getKeyData(index)); + LLControlVariablePtr var = gSavedSettings.getControl(name); + if (var) + { + LLKeyBind bind(var->getValue()); + LLKeyConflict key(bind, true, 0); + mControlsMap[name] = key; + } } -void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymode, control_map_t *destination) +void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymode, control_map_t *destination) { for (LLInitParam::ParamIterator<LLViewerInput::KeyBinding>::const_iterator it = keymode.bindings.begin(), end_it = keymode.bindings.end(); @@ -378,28 +271,23 @@ void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymo LLKeyboard::keyFromString(it->key, &key); } LLKeyboard::maskFromString(it->mask, &mask); - std::string command_name = it->command; - // it->command - // It might be better to have <string,bind> map, but at the moment enum is easier to iterate through. - // Besides keys.xml might not contain all commands - control_enum_t::const_iterator iter = command_to_key.find(command_name); - if (iter != command_to_key.end()) - { - LLKeyConflict &type_data = (*destination)[iter->second]; - type_data.mAssignable = true; - // Don't care about conflict level, all movement and view commands already account for it - type_data.mKeyBind.addKeyData(mouse, key, mask, ignore); - } + // Note: it->command is also the name of UI element, howhever xml we are loading from + // might not know all the commands, so UI will have to know what to fill by its own + LLKeyConflict &type_data = (*destination)[it->command]; + type_data.mAssignable = true; + type_data.mKeyBind.addKeyData(mouse, key, mask, ignore); } } -void LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination) +bool LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination) { if (filename.empty()) { - return; + return false; } + bool res = false; + LLViewerInput::Keys keys; LLSimpleXUIParser parser; @@ -412,39 +300,45 @@ void LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const if (keys.first_person.isProvided()) { loadFromSettings(keys.first_person, destination); + res = true; } break; case MODE_THIRD_PERSON: if (keys.third_person.isProvided()) { loadFromSettings(keys.third_person, destination); + res = true; } break; case MODE_EDIT: if (keys.edit.isProvided()) { loadFromSettings(keys.edit, destination); + res = true; } break; case MODE_EDIT_AVATAR: if (keys.edit_avatar.isProvided()) { loadFromSettings(keys.edit_avatar, destination); + res = true; } break; case MODE_SITTING: if (keys.sitting.isProvided()) { loadFromSettings(keys.sitting, destination); + res = true; } break; default: break; } } + return res; } -void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) +void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) { mControlsMap.clear(); mDefaultsMap.clear(); @@ -454,48 +348,26 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) if (load_mode == MODE_GENERAL) { - for (U32 i = 0; i < CONTROL_NUM_INDICES; i++) + // load settings clss knows about, but it also possible to load settings by name separately + const S32 size = std::extent<decltype(saved_settings_key_controls)>::value; + for (U32 i = 0; i < size; i++) { - EControlTypes type = (EControlTypes)i; - switch (type) - { - case LLKeyConflictHandler::CONTROL_VIEW_ACTIONS: - case LLKeyConflictHandler::CONTROL_INTERACTIONS: - case LLKeyConflictHandler::CONTROL_MOVEMENTS: - case LLKeyConflictHandler::CONTROL_MEDIACONTENT: - case LLKeyConflictHandler::CONTROL_CAMERA: - case LLKeyConflictHandler::CONTROL_EDIT_TITLE: - case LLKeyConflictHandler::CONTROL_RESERVED: - // ignore 'headers', they are for representation and organization purposes - break; - default: - { - std::string name = getControlName(type); - LLControlVariablePtr var = gSavedSettings.getControl(name); - if (var) - { - LLKeyBind bind(var->getValue()); - LLKeyConflict key(bind, true, 0); - mControlsMap[type] = key; - } - break; - } - } + loadFromControlSettings(saved_settings_key_controls[i]); } } else { // load defaults std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "keys.xml"); - loadFromSettings(load_mode, filename, &mDefaultsMap); + if (!loadFromSettings(load_mode, filename, &mDefaultsMap)) + { + LL_WARNS() << "Failed to load default settings, aborting" << LL_ENDL; + return; + } // load user's filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "keys.xml"); - if (gDirUtilp->fileExists(filename)) - { - loadFromSettings(load_mode, filename, &mControlsMap); - } - else + if (!gDirUtilp->fileExists(filename) || loadFromSettings(load_mode, filename, &mControlsMap)) { // mind placeholders mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end()); @@ -504,7 +376,7 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) mLoadMode = load_mode; } -void LLKeyConflictHandler::saveToSettings() +void LLKeyConflictHandler::saveToSettings() { if (mControlsMap.empty()) { @@ -513,39 +385,33 @@ void LLKeyConflictHandler::saveToSettings() if (mLoadMode == MODE_GENERAL) { - for (U32 i = 0; i < CONTROL_NUM_INDICES; i++) + control_map_t::iterator iter = mControlsMap.begin(); + control_map_t::iterator end = mControlsMap.end(); + + for (; iter != end; ++iter) { - EControlTypes type = (EControlTypes)i; - switch (type) + if (iter->first.empty()) { - case LLKeyConflictHandler::CONTROL_VIEW_ACTIONS: - case LLKeyConflictHandler::CONTROL_INTERACTIONS: - case LLKeyConflictHandler::CONTROL_MOVEMENTS: - case LLKeyConflictHandler::CONTROL_MEDIACONTENT: - case LLKeyConflictHandler::CONTROL_CAMERA: - case LLKeyConflictHandler::CONTROL_EDIT_TITLE: - case LLKeyConflictHandler::CONTROL_RESERVED: - // ignore 'headers', they are for representation and organization purposes - break; - default: + continue; + } + + LLKeyConflict &key = iter->second; + key.mKeyBind.trimEmpty(); + if (!key.mAssignable) { - if (mControlsMap[type].mAssignable) - { - std::string name = getControlName(type); - if (gSavedSettings.controlExists(name)) - { - gSavedSettings.setLLSD(name, mControlsMap[type].mKeyBind.asLLSD()); - } - else if (!mControlsMap[type].mKeyBind.empty()) - { - // shouldn't happen user side since all settings are supposed to be declared already, but handy when creating new ones - // (just don't forget to change comment and to copy them from user's folder) - LL_INFOS() << "Creating new keybinding " << name << LL_ENDL; - gSavedSettings.declareLLSD(name, mControlsMap[type].mKeyBind.asLLSD(), "comment", LLControlVariable::PERSIST_ALWAYS); - } - } - break; + continue; + } + + if (gSavedSettings.controlExists(iter->first)) + { + gSavedSettings.setLLSD(iter->first, key.mKeyBind.asLLSD()); } + else if (!key.mKeyBind.empty()) + { + // Note: this is currently not in use, might be better for load mechanics to ask for and retain control group + // otherwise settings loaded from other control groups will end in this one + LL_INFOS() << "Creating new keybinding " << iter->first << LL_ENDL; + gSavedSettings.declareLLSD(iter->first, key.mKeyBind.asLLSD(), "comment", LLControlVariable::PERSIST_ALWAYS); } } } @@ -564,8 +430,8 @@ void LLKeyConflictHandler::saveToSettings() { // replace category we edited - // todo: fix this - // workaround to avoid doing own param container + // mode is a HACK to correctly reset bindings without reparsing whole file and avoid doing + // own param container (which will face issues with inasseesible members of LLInitParam) LLViewerInput::KeyMode mode; LLViewerInput::KeyBinding binding; @@ -581,8 +447,20 @@ void LLKeyConflictHandler::saveToSettings() U32 size = iter->second.mKeyBind.getDataCount(); for (U32 i = 0; i < size; ++i) { - // Still write empty keys to make sure we will maintain UI position - LLKeyData data = iter->second.mKeyBind.getKeyData(i); + if (iter->first.empty()) + { + continue; + } + + LLKeyConflict &key = iter->second; + key.mKeyBind.trimEmpty(); + if (key.mKeyBind.empty() || !key.mAssignable) + { + continue; + } + + LLKeyData data = key.mKeyBind.getKeyData(i); + // Still write empty LLKeyData to make sure we will maintain UI position if (data.mKey == KEY_NONE) { binding.key = ""; @@ -595,7 +473,7 @@ void LLKeyConflictHandler::saveToSettings() binding.mask = string_from_mask(data.mMask); binding.mouse.set(string_from_mouse(data.mMouse), true); //set() because 'optional', for compatibility purposes binding.ignore.set(data.mIgnoreMasks, true); - binding.command = getControlName(iter->first); + binding.command = iter->first; mode.bindings.add(binding); } } @@ -664,12 +542,15 @@ void LLKeyConflictHandler::saveToSettings() mHasUnsavedChanges = false; } -LLKeyData LLKeyConflictHandler::getDefaultControl(EControlTypes control_type, U32 index) +LLKeyData LLKeyConflictHandler::getDefaultControl(const std::string &control_name, U32 index) { + if (control_name.empty()) + { + return LLKeyData(); + } if (mLoadMode == MODE_GENERAL) { - std::string name = getControlName(control_type); - LLControlVariablePtr var = gSavedSettings.getControl(name); + LLControlVariablePtr var = gSavedSettings.getControl(control_name); if (var) { return LLKeyBind(var->getDefault()).getKeyData(index); @@ -678,7 +559,7 @@ LLKeyData LLKeyConflictHandler::getDefaultControl(EControlTypes control_type, U3 } else { - control_map_t::iterator iter = mDefaultsMap.find(control_type); + control_map_t::iterator iter = mDefaultsMap.find(control_name); if (iter != mDefaultsMap.end()) { return iter->second.mKeyBind.getKeyData(index); @@ -687,24 +568,31 @@ LLKeyData LLKeyConflictHandler::getDefaultControl(EControlTypes control_type, U3 } } -void LLKeyConflictHandler::resetToDefault(EControlTypes control_type, U32 index) +void LLKeyConflictHandler::resetToDefault(const std::string &control_name, U32 index) { - LLKeyData data = getDefaultControl(control_type, index); + if (control_name.empty()) + { + return; + } + LLKeyData data = getDefaultControl(control_name, index); - if (data != mControlsMap[control_type].getKeyData(index)) + if (data != mControlsMap[control_name].getKeyData(index)) { // reset controls that might have been switched to our current control - removeConflicts(data, mControlsMap[control_type].mConflictMask); - mControlsMap[control_type].setKeyData(data, index); + removeConflicts(data, mControlsMap[control_name].mConflictMask); + mControlsMap[control_name].setKeyData(data, index); } } -void LLKeyConflictHandler::resetToDefaultAndResolve(EControlTypes control_type, bool ignore_conflicts) +void LLKeyConflictHandler::resetToDefaultAndResolve(const std::string &control_name, bool ignore_conflicts) { + if (control_name.empty()) + { + return; + } if (mLoadMode == MODE_GENERAL) { - std::string name = getControlName(control_type); - LLControlVariablePtr var = gSavedSettings.getControl(name); + LLControlVariablePtr var = gSavedSettings.getControl(control_name); if (var) { LLKeyBind bind(var->getDefault()); @@ -712,67 +600,53 @@ void LLKeyConflictHandler::resetToDefaultAndResolve(EControlTypes control_type, { for (S32 i = 0; i < bind.getDataCount(); ++i) { - removeConflicts(bind.getKeyData(i), mControlsMap[control_type].mConflictMask); + removeConflicts(bind.getKeyData(i), mControlsMap[control_name].mConflictMask); } } - mControlsMap[control_type].mKeyBind = bind; + mControlsMap[control_name].mKeyBind = bind; } else { - mControlsMap[control_type].mKeyBind.clear(); + mControlsMap[control_name].mKeyBind.clear(); } } else { - control_map_t::iterator iter = mDefaultsMap.find(control_type); + control_map_t::iterator iter = mDefaultsMap.find(control_name); if (iter != mDefaultsMap.end()) { if (!ignore_conflicts) { for (S32 i = 0; i < iter->second.mKeyBind.getDataCount(); ++i) { - removeConflicts(iter->second.mKeyBind.getKeyData(i), mControlsMap[control_type].mConflictMask); + removeConflicts(iter->second.mKeyBind.getKeyData(i), mControlsMap[control_name].mConflictMask); } } - mControlsMap[control_type].mKeyBind = iter->second.mKeyBind; + mControlsMap[control_name].mKeyBind = iter->second.mKeyBind; } else { - mControlsMap[control_type].mKeyBind.clear(); + mControlsMap[control_name].mKeyBind.clear(); } } } -void LLKeyConflictHandler::resetToDefault(EControlTypes control_type) +void LLKeyConflictHandler::resetToDefault(const std::string &control_name) { // reset specific binding without ignoring conflicts - resetToDefaultAndResolve(control_type, false); + resetToDefaultAndResolve(control_name, false); } void LLKeyConflictHandler::resetToDefaults(ESourceMode mode) { if (mode == MODE_GENERAL) { - for (U32 i = 0; i < CONTROL_NUM_INDICES; i++) + control_map_t::iterator iter = mControlsMap.begin(); + control_map_t::iterator end = mControlsMap.end(); + + for (; iter != end; ++iter) { - EControlTypes type = (EControlTypes)i; - switch (type) - { - case LLKeyConflictHandler::CONTROL_VIEW_ACTIONS: - case LLKeyConflictHandler::CONTROL_INTERACTIONS: - case LLKeyConflictHandler::CONTROL_MOVEMENTS: - case LLKeyConflictHandler::CONTROL_MEDIACONTENT: - case LLKeyConflictHandler::CONTROL_CAMERA: - case LLKeyConflictHandler::CONTROL_EDIT_TITLE: - case LLKeyConflictHandler::CONTROL_RESERVED: - // ignore 'headers', they are for representation and organization purposes - break; - default: - { - resetToDefaultAndResolve(type, true); - break; - } - } + resetToDefaultAndResolve(iter->first, true); } } else @@ -834,7 +708,7 @@ bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &con // Can't conflict return true; } - std::map<EControlTypes, S32> conflict_list; + std::map<std::string, S32> conflict_list; control_map_t::iterator cntrl_iter = mControlsMap.begin(); control_map_t::iterator cntrl_end = mControlsMap.end(); for (; cntrl_iter != cntrl_end; ++cntrl_iter) @@ -859,8 +733,8 @@ bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &con } } - std::map<EControlTypes, S32>::iterator cnflct_iter = conflict_list.begin(); - std::map<EControlTypes, S32>::iterator cnflct_end = conflict_list.end(); + std::map<std::string, S32>::iterator cnflct_iter = conflict_list.begin(); + std::map<std::string, S32>::iterator cnflct_end = conflict_list.end(); for (; cnflct_iter != cnflct_end; ++cnflct_iter) { mControlsMap[cnflct_iter->first].mKeyBind.resetKeyData(cnflct_iter->second); @@ -868,9 +742,9 @@ bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &con return true; } -void LLKeyConflictHandler::registerTemporaryControl(EControlTypes control_type, EMouseClickType mouse, KEY key, MASK mask, U32 conflict_mask) +void LLKeyConflictHandler::registerTemporaryControl(const std::string &control_name, EMouseClickType mouse, KEY key, MASK mask, U32 conflict_mask) { - LLKeyConflict *type_data = &mControlsMap[control_type]; + LLKeyConflict *type_data = &mControlsMap[control_name]; type_data->mAssignable = false; type_data->mConflictMask = conflict_mask; type_data->mKeyBind.addKeyData(mouse, key, mask, false); diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h index e4a6da30d0..a0886bedce 100644 --- a/indra/newview/llkeyconflict.h +++ b/indra/newview/llkeyconflict.h @@ -70,114 +70,35 @@ public: // at the moment this just means that key will conflict with everything that is identical const U32 CONFLICT_ANY = U32_MAX; - // todo, unfortunately will have to remove this and use map/array of strings - enum EControlTypes - { - CONTROL_VIEW_ACTIONS = 0, // Group control, for visual representation in view, not for use - CONTROL_ABOUT, - CONTROL_ORBIT, - CONTROL_PAN, - CONTROL_WORLD_MAP, - CONTROL_ZOOM, - CONTROL_INTERACTIONS, // Group control, for visual representation - CONTROL_BUILD, - //CONTROL_DRAG, - CONTROL_EDIT, - //CONTROL_MENU, - CONTROL_OPEN, - CONTROL_TOUCH, - CONTROL_WEAR, - CONTROL_MOVEMENTS, // Group control, for visual representation - CONTROL_MOVETO, - CONTROL_TELEPORTTO, - CONTROL_FORWARD, - CONTROL_BACKWARD, - CONTROL_LEFT, // Check and sinc name with real movement names - CONTROL_RIGHT, - CONTROL_LSTRAFE, - CONTROL_RSTRAFE, - CONTROL_JUMP, - CONTROL_DOWN, - //CONTROL_RUN, - CONTROL_TOGGLE_RUN, - CONTROL_TOGGLE_FLY, - CONTROL_SIT, - CONTROL_STOP, - CONTROL_CAMERA, // Group control, for visual representation - CONTROL_LOOK_UP, - CONTROL_LOOK_DOWN, - CONTROL_CAMERA_FORWARD, - CONTROL_CAMERA_BACKWARD, - CONTROL_CAMERA_FFORWARD, - CONTROL_CAMERA_FBACKWARD, - CONTROL_CAMERA_FSITTING, - CONTROL_CAMERA_BSITTING, - CONTROL_CAMERA_SOVER, - CONTROL_CAMERA_SUNDER, - CONTROL_CAMERA_SOVER_SITTING, - CONTROL_CAMERA_SUNDER_SITTING, - CONTROL_CAMERA_PANUP, - CONTROL_CAMERA_PANDOWN, - CONTROL_CAMERA_PANLEFT, - CONTROL_CAMERA_PANRIGHT, - CONTROL_CAMERA_PANIN, - CONTROL_CAMERA_PANOUT, - CONTROL_CAMERA_SPIN_CCW, - CONTROL_CAMERA_SPIN_CW, - CONTROL_CAMERA_SPIN_CCW_SITTING, - CONTROL_CAMERA_SPIN_CW_SITTING, - CONTROL_EDIT_TITLE, // Group control, for visual representation - CONTROL_EDIT_AV_SPIN_CCW, - CONTROL_EDIT_AV_SPIN_CW, - CONTROL_EDIT_AV_SPIN_OVER, - CONTROL_EDIT_AV_SPIN_UNDER, - CONTROL_EDIT_AV_MV_FORWARD, - CONTROL_EDIT_AV_MV_BACKWARD, - CONTROL_MEDIACONTENT, // Group control, for visual representation - CONTROL_PAUSE_MEDIA, // Play pause - CONTROL_ENABLE_MEDIA, // Play stop - CONTROL_VOICE, // Keep pressing for voice to be ON - CONTROL_TOGGLE_VOICE, // Press once to ON/OFF - CONTROL_START_CHAT, // Press once to ON/OFF - CONTROL_START_GESTURE, // Press once to ON/OFF - CONTROL_RESERVED, // Special group control, controls that are disabled by default and not meant to be changed - CONTROL_DELETE, - CONTROL_RESERVED_MENU, - CONTROL_RESERVED_SELECT, - CONTROL_SHIFT_SELECT, - CONTROL_CNTRL_SELECT, - CONTROL_NUM_INDICES // Size, always should be last - }; - // Note: missed selection and edition commands (would be really nice to go through selection via MB4/5 or wheel) LLKeyConflictHandler(); LLKeyConflictHandler(ESourceMode mode); - bool canHandleControl(EControlTypes control_type, EMouseClickType mouse_ind, KEY key, MASK mask); - bool canHandleKey(EControlTypes control_type, KEY key, MASK mask); - bool canHandleMouse(EControlTypes control_type, EMouseClickType mouse_ind, MASK mask); - bool canHandleMouse(EControlTypes control_type, S32 mouse_ind, MASK mask); //Just for convinience - bool canAssignControl(EControlTypes control_type); - bool registerControl(EControlTypes control_type, U32 data_index, EMouseClickType mouse_ind, KEY key, MASK mask, bool ignore_mask); //todo: return conflicts? - - LLKeyData getControl(EControlTypes control_type, U32 data_index); + bool canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask); + bool canHandleKey(const std::string &control_name, KEY key, MASK mask); + bool canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask); + bool canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask); //Just for convinience + bool canAssignControl(const std::string &control_name); + bool registerControl(const std::string &control_name, U32 data_index, EMouseClickType mouse_ind, KEY key, MASK mask, bool ignore_mask); //todo: return conflicts? - static std::string LLKeyConflictHandler::getStringFromKeyData(const LLKeyData& keydata); - static std::string getControlName(EControlTypes control_type); - std::string getControlString(EControlTypes control_type, U32 data_index); + LLKeyData getControl(const std::string &control_name, U32 data_index); + static std::string getStringFromKeyData(const LLKeyData& keydata); + std::string getControlString(const std::string &control_name, U32 data_index); + // Load single control, overrides existing one if names match + void loadFromControlSettings(const std::string &name); // Drops any changes loads controls with ones from 'saved settings' or from xml void loadFromSettings(ESourceMode load_mode); // Saves settings to 'saved settings' or to xml void saveToSettings(); - LLKeyData getDefaultControl(EControlTypes control_type, U32 data_index); + LLKeyData getDefaultControl(const std::string &control_name, U32 data_index); // Resets keybinding to default variant from 'saved settings' or xml - void resetToDefault(EControlTypes control_type, U32 index); - void resetToDefault(EControlTypes control_type); - // resets current mode to defaults, + void resetToDefault(const std::string &control_name, U32 index); + void resetToDefault(const std::string &control_name); + // resets current mode to defaults void resetToDefaults(); bool empty() { return mControlsMap.empty(); } @@ -188,15 +109,15 @@ public: ESourceMode getLoadMode() { return mLoadMode; } private: - void resetToDefaultAndResolve(EControlTypes control_type, bool ignore_conflicts); + void resetToDefaultAndResolve(const std::string &control_name, bool ignore_conflicts); void resetToDefaults(ESourceMode mode); // at the moment these kind of control is not savable, but takes part will take part in conflict resolution - void registerTemporaryControl(EControlTypes control_type, EMouseClickType mouse_ind, KEY key, MASK mask, U32 conflict_mask); + void registerTemporaryControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask, U32 conflict_mask); - typedef std::map<EControlTypes, LLKeyConflict> control_map_t; + typedef std::map<std::string, LLKeyConflict> control_map_t; void loadFromSettings(const LLViewerInput::KeyMode& keymode, control_map_t *destination); - void loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination); + bool loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination); void resetKeyboardBindings(); void generatePlaceholders(ESourceMode load_mode); //E.x. non-assignable values // returns false in case user is trying to reuse control that can't be reassigned diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 11f430cda3..eff578cf26 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -648,6 +648,78 @@ bool start_gesture( EKeystate s ) return true; } +bool run_forward(EKeystate s) +{ + if (KEYSTATE_DOWN == s) + { + gAgent.setAlwaysRun(); + gAgent.setRunning(); + gAgent.sendWalkRun(true); + } + else if(KEYSTATE_UP == s) + { + gAgent.clearAlwaysRun(); + gAgent.clearRunning(); + gAgent.sendWalkRun(false); + } + agent_push_forward(s); + return true; +} + +bool run_backward(EKeystate s) +{ + if (KEYSTATE_DOWN == s) + { + gAgent.setAlwaysRun(); + gAgent.setRunning(); + gAgent.sendWalkRun(true); + } + else if (KEYSTATE_UP == s) + { + gAgent.clearAlwaysRun(); + gAgent.clearRunning(); + gAgent.sendWalkRun(false); + } + agent_push_backward(s); + return true; +} + +bool run_left(EKeystate s) +{ + if (KEYSTATE_DOWN == s) + { + gAgent.setAlwaysRun(); + gAgent.setRunning(); + gAgent.sendWalkRun(true); + } + else if (KEYSTATE_UP == s) + { + gAgent.clearAlwaysRun(); + gAgent.clearRunning(); + gAgent.sendWalkRun(false); + } + agent_slide_left(s); + return true; +} + +bool run_right(EKeystate s) +{ + if (KEYSTATE_DOWN == s) + { + gAgent.setAlwaysRun(); + gAgent.setRunning(); + gAgent.sendWalkRun(true); + } + else if (KEYSTATE_UP == s) + { + gAgent.clearAlwaysRun(); + gAgent.clearRunning(); + gAgent.sendWalkRun(false); + } + agent_slide_right(s); + return true; +} + bool toggle_run(EKeystate s) { if (KEYSTATE_DOWN != s) return true; @@ -789,6 +861,10 @@ 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); +REGISTER_KEYBOARD_ACTION("run_forward", run_forward); +REGISTER_KEYBOARD_ACTION("run_backward", run_backward); +REGISTER_KEYBOARD_ACTION("run_left", run_left); +REGISTER_KEYBOARD_ACTION("run_right", run_right); REGISTER_KEYBOARD_ACTION("toggle_run", toggle_run); REGISTER_KEYBOARD_ACTION("toggle_sit", toggle_sit); REGISTER_KEYBOARD_ACTION("toggle_pause_media", toggle_pause_media); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 5388d13a04..3c2ec369ec 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -955,6 +955,8 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK m case CLICK_BUTTON5: buttonname = "Button 5"; break; + default: + break; // COUNT and NONE } LLView::sMouseHandlerMessage.clear(); diff --git a/indra/newview/skins/default/xui/en/panel_preferences_controls.xml b/indra/newview/skins/default/xui/en/panel_preferences_controls.xml index 62267dce8a..385d4796a0 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_controls.xml @@ -10,6 +10,10 @@ top="1" width="517"> <panel.string + name="walk_to"> + Walk to + </panel.string> + <panel.string name="control_view_actions"> View Actions </panel.string> @@ -70,8 +74,8 @@ Move Actions </panel.string> <panel.string - name="control_moveto"> - Move To + name="teleport_to"> + Teleport to </panel.string> <panel.string name="toggle_sit"> @@ -119,6 +123,22 @@ Run </panel.string> <panel.string + name="run_forward"> + Run Forward + </panel.string> + <panel.string + name="run_backward"> + Run Backward + </panel.string> + <panel.string + name="run_left"> + Run Left + </panel.string> + <panel.string + name="run_right"> + Run Right + </panel.string> + <panel.string name="toggle_run"> Toggle Run </panel.string> @@ -127,6 +147,10 @@ Fly/Stop flying </panel.string> <panel.string + name="stop_moving"> + Stop Moving + </panel.string> + <panel.string name="control_camera"> Camera </panel.string> @@ -215,36 +239,13 @@ Play/Stop All Media </panel.string> <panel.string - name="control_voice"> + name="voice_follow_key"> Voice </panel.string> <panel.string - name="control_toggle_voice"> + name="toggle_voice"> Toggle Voice </panel.string> - <panel.string - name="control_reserved"> - Reserved Controls - </panel.string> - <panel.string - name="control_delete"> - Delete - </panel.string> - <!-- - name="control_menu" not needed - --> - <panel.string - name="control_reserved_select"> - Select - </panel.string> - <panel.string - name="control_shift_select"> - Multi-Select - </panel.string> - <panel.string - name="control_cntrl_select"> - Add to Selection - </panel.string> <combo_box follows="top|left" |