diff options
| author | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2020-06-15 18:13:46 +0300 | 
|---|---|---|
| committer | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2020-06-15 18:15:43 +0300 | 
| commit | d07ef7df92cbc9c2fb16dcd0ddd0322665d440eb (patch) | |
| tree | f02fc95570620c9d8f16a5d35683b1d0058e2bc9 | |
| parent | ceea2df59634ab09d165943bd7591e7125ee0f80 (diff) | |
SL-13418 Added converter from old mouse binding settings to new ones
| -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 5630bb1a3f..775b6db94b 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); | 
