diff options
-rw-r--r-- | indra/llcommon/llkeybind.h | 2 | ||||
-rw-r--r-- | indra/newview/app_settings/key_bindings.xml | 1 | ||||
-rw-r--r-- | indra/newview/llappviewer.cpp | 99 | ||||
-rw-r--r-- | indra/newview/llkeyconflict.cpp | 67 | ||||
-rw-r--r-- | indra/newview/llkeyconflict.h | 16 |
5 files changed, 182 insertions, 3 deletions
diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h index ad0ebec67c..c6b4bd970f 100644 --- a/indra/llcommon/llkeybind.h +++ b/indra/llcommon/llkeybind.h @@ -53,7 +53,7 @@ public: EMouseClickType mMouse; KEY mKey; MASK mMask; - // Either to expect exact match or ignore not expected masks + // Either to expect exact match or ignore not expected masks as long as expected mask-bit is present bool mIgnoreMasks; }; diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml index 81423c4716..4f6deb1f98 100644 --- a/indra/newview/app_settings/key_bindings.xml +++ b/indra/newview/app_settings/key_bindings.xml @@ -224,7 +224,6 @@ <binding key="DIVIDE" mask="NONE" command="start_gesture"/> <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/> - <binding key="" mask="NONE" mouse="LMB" command="walk_to"/> </sitting> <edit_avatar> <!--Avatar editing camera controls--> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 4c2de27f42..911cc224a1 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -49,6 +49,7 @@ #include "llwindow.h" #include "llviewerstats.h" #include "llviewerstatsrecorder.h" +#include "llkeyconflict.h" // for legacy keybinding support, remove later #include "llmarketplacefunctions.h" #include "llmarketplacenotifications.h" #include "llmd5.h" @@ -1004,6 +1005,104 @@ bool LLAppViewer::init() // Load User's bindings std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml"); +#if 1 + // Legacy support + // Remove #if-#endif section half a year after DRTVWR-501 releases. + // Mouse actions are part of keybinding file since DRTVWR-501 instead of being stored in + // settings.xml. To support legacy viewers that were storing in settings.xml we need to + // transfer old variables to new format. + // Also part of backward compatibility is present in LLKeyConflictHandler to modify + // legacy variables on changes in new system (to make sure we won't enforce + // legacy values again if user dropped to defaults in new system) + if (mIsFirstRun + && !gDirUtilp->fileExists(key_bindings_file)) // if file is missing, assume that there were no changes by user yet + { + // copy mouse actions and voice key changes to new file + LL_INFOS("InitInfo") << "Converting legacy mouse bindings to new format" << LL_ENDL; + // Load settings from file + LLKeyConflictHandler third_person_view(LLKeyConflictHandler::MODE_THIRD_PERSON); + + // Since we are only modifying keybindings if personal file doesn't exist yet, + // it should be safe to just overwrite the value + // If key is already in use somewhere by default, LLKeyConflictHandler should resolve it. + BOOL value = gSavedSettings.getBOOL("DoubleClickAutoPilot"); + third_person_view.registerControl("walk_to", + 0, + value ? EMouseClickType::CLICK_DOUBLELEFT : EMouseClickType::CLICK_NONE, + KEY_NONE, + MASK_NONE, + value); + + U32 index = value ? 1 : 0; // we can store multiple combinations per action, so if first is in use by doubleclick, go to second + value = gSavedSettings.getBOOL("ClickToWalk"); + third_person_view.registerControl("walk_to", + index, + value ? EMouseClickType::CLICK_LEFT : EMouseClickType::CLICK_NONE, + KEY_NONE, + MASK_NONE, + value); + + value = gSavedSettings.getBOOL("DoubleClickTeleport"); + third_person_view.registerControl("teleport_to", + 0, + value ? EMouseClickType::CLICK_DOUBLELEFT : EMouseClickType::CLICK_NONE, + KEY_NONE, + MASK_NONE, + value); + + std::string key_string = gSavedSettings.getString("PushToTalkButton"); + EMouseClickType mouse = EMouseClickType::CLICK_NONE; + KEY key = KEY_NONE; + if (key_string == "MiddleMouse") + { + mouse = EMouseClickType::CLICK_MIDDLE; + } + else if (key_string == "MouseButton4") + { + mouse = EMouseClickType::CLICK_BUTTON4; + } + else if (key_string == "MouseButton5") + { + mouse = EMouseClickType::CLICK_BUTTON5; + } + else + { + LLKeyboard::keyFromString(key_string, &key); + } + + value = gSavedSettings.getBOOL("PushToTalkToggle"); + std::string control_name = value ? "toggle_voice" : "voice_follow_key"; + third_person_view.registerControl(control_name, 0, mouse, key, MASK_NONE, true); + + if (third_person_view.hasUnsavedChanges()) + { + // calls loadBindingsXML() + third_person_view.saveToSettings(); + } + + // in case of voice we need to repeat this in other modes (teleports and + // autopilot are not entirely practical when sitting or editing) + + for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i) + { + if (i != LLKeyConflictHandler::MODE_THIRD_PERSON) + { + LLKeyConflictHandler handler((LLKeyConflictHandler::ESourceMode)i); + + handler.registerControl(control_name, 0, mouse, key, MASK_NONE, true); + + if (handler.hasUnsavedChanges()) + { + // calls loadBindingsXML() + handler.saveToSettings(); + } + } + } + } + // since something might have gone wrong or there might have been nothing to save + // (and because otherwise following code will have to be encased in else{}), + // load everything one last time +#endif if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerInput.loadBindingsXML(key_bindings_file)) { // Failed to load custom bindings, try default ones diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index e44f79000e..5f966624ca 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -427,7 +427,7 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) 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 + // otherwise settings loaded from other control groups will end in gSavedSettings LL_INFOS() << "Creating new keybinding " << iter->first << LL_ENDL; gSavedSettings.declareLLSD(iter->first, key.mKeyBind.asLLSD(), "comment", LLControlVariable::PERSIST_ALWAYS); } @@ -598,6 +598,71 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) // will remove any temporary file if there were any clearUnsavedChanges(); } + +#if 1 + // Legacy support + // Remove #if-#endif section half a year after DRTVWR-501 releases. + // Update legacy settings in settings.xml + // We only care for third person view since legacy settings can't store + // more than one mode. + // We are saving this even if we are in temporary mode - preferences + // will restore values on cancel + if (mLoadMode == MODE_THIRD_PERSON) + { + bool value = canHandleMouse("walk_to", CLICK_DOUBLELEFT, MASK_NONE); + gSavedSettings.setBOOL("DoubleClickAutoPilot", value); + + value = canHandleMouse("walk_to", CLICK_LEFT, MASK_NONE); + gSavedSettings.setBOOL("ClickToWalk", value); + + value = canHandleMouse("teleport_to", CLICK_DOUBLELEFT, MASK_NONE); + gSavedSettings.setBOOL("DoubleClickTeleport", value); + + // new method can save both toggle and push-to-talk values simultaneously, + // but legacy one can save only one. It also doesn't support mask. + LLKeyData data = getControl("toggle_voice", 0); + bool can_toggle = !data.isEmpty(); + if (!can_toggle) + { + data = getControl("voice_follow_key", 0); + } + + gSavedSettings.setBOOL("PushToTalkToggle", can_toggle); + if (data.isEmpty()) + { + // legacy viewer has a bug that might crash it if NONE value is assigned. + // just reset to default + gSavedSettings.getControl("PushToTalkButton")->resetToDefault(false); + } + else + { + if (data.mKey != KEY_NONE) + { + gSavedSettings.setString("PushToTalkButton", LLKeyboard::stringFromKey(data.mKey)); + } + else + { + std::string ctrl_value; + switch (data.mMouse) + { + case CLICK_MIDDLE: + ctrl_value = "MiddleMouse"; + break; + case CLICK_BUTTON4: + ctrl_value = "MouseButton4"; + break; + case CLICK_BUTTON5: + ctrl_value = "MouseButton5"; + break; + default: + ctrl_value = "MiddleMouse"; + break; + } + gSavedSettings.setString("PushToTalkButton", ctrl_value); + } + } + } +#endif } LLKeyData LLKeyConflictHandler::getDefaultControl(const std::string &control_name, U32 index) diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h index 73d59cc217..5451c16ae2 100644 --- a/indra/newview/llkeyconflict.h +++ b/indra/newview/llkeyconflict.h @@ -82,6 +82,18 @@ public: bool canAssignControl(const std::string &control_name); static bool isReservedByMenu(const KEY &key, const MASK &mask); static bool isReservedByMenu(const LLKeyData &data); + + // @control_name - see REGISTER_KEYBOARD_ACTION in llviewerinput for avaliable options, + // usually this is just name of the function + // @data_index - single control (function) can have multiple key combinations trigering + // it, this index indicates combination function will change/add note that preferences + // floater can only display up to 3 options, but data_index can be bigger then that + // @mouse_ind - mouse action (middle click, MB5 etc) + // @key - keyboard key action + // @mask - shift/ctrl/alt flags + // @ignore_mask - Either to expect exact match (ctrl+K will not trigger if ctrl+shift+K + // is active) or ignore not expected masks as long as expected mask is present + // (ctrl+K will be triggered if ctrl+shift+K is active) bool registerControl(const std::string &control_name, U32 data_index, EMouseClickType mouse_ind, KEY key, MASK mask, bool ignore_mask); //todo: return conflicts? LLKeyData getControl(const std::string &control_name, U32 data_index); @@ -101,6 +113,10 @@ public: // 'temporary' does not support gSavedSettings, those are handled // by preferences, so 'temporary' is such case will simply not // reset mHasUnsavedChanges + // + // 'temporary' exists to support ability of live-editing settings in + // preferences: temporary for testing changes 'live' without saving them, + // then hitting ok/cancel and save/discard values permanently. void saveToSettings(bool apply_temporary = false); LLKeyData getDefaultControl(const std::string &control_name, U32 data_index); |