diff options
author | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2020-06-15 20:35:58 +0300 |
---|---|---|
committer | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2020-06-15 23:58:18 +0300 |
commit | b291bc32e96bf5eab50df74d118ba61c924c67fa (patch) | |
tree | 78a14d2d948bbe5e39242803482de43ff7feb3ef | |
parent | 6f06ccc10a40ebfb89f670149d816cf5f9e3716e (diff) |
SL-13418 Restored previously removed 'click on land' controls from 'move & view'
According to UX UI engineer. Also adapted it to new system, but it needs a better solution.
-rw-r--r-- | indra/newview/llfloaterpreference.cpp | 212 | ||||
-rw-r--r-- | indra/newview/llfloaterpreference.h | 22 | ||||
-rw-r--r-- | indra/newview/llkeyconflict.cpp | 16 | ||||
-rw-r--r-- | indra/newview/llkeyconflict.h | 5 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/panel_preferences_move.xml | 64 |
5 files changed, 312 insertions, 7 deletions
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index dc5905b6e7..ed28756473 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -311,6 +311,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) sSkin = gSavedSettings.getString("SkinCurrent"); + mCommitCallbackRegistrar.add("Pref.ClickActionChange", boost::bind(&LLFloaterPreference::onClickActionChange, this)); + gSavedSettings.getControl("NameTagShowUsernames")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2)); gSavedSettings.getControl("NameTagShowFriends")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2)); gSavedSettings.getControl("UseDisplayNames")->getCommitSignal()->connect(boost::bind(&handleDisplayNamesOptionChanged, _2)); @@ -609,6 +611,8 @@ void LLFloaterPreference::cancel() // reverts any changes to current skin gSavedSettings.setString("SkinCurrent", sSkin); + updateClickActionViews(); + LLFloaterPreferenceProxy * advanced_proxy_settings = LLFloaterReg::findTypedInstance<LLFloaterPreferenceProxy>("prefs_proxy"); if (advanced_proxy_settings) { @@ -690,6 +694,9 @@ void LLFloaterPreference::onOpen(const LLSD& key) onChangeTextureFolder(); onChangeSoundFolder(); onChangeAnimationFolder(); + + // Load (double-)click to walk/teleport settings. + updateClickActionViews(); // Enabled/disabled popups, might have been changed by user actions // while preferences floater was closed. @@ -1486,6 +1493,7 @@ void LLFloaterPreference::refresh() { advanced->refresh(); } + updateClickActionViews(); } void LLFloaterPreferenceGraphicsAdvanced::refresh() @@ -1995,6 +2003,11 @@ void LLFloaterPreference::onClickAdvanced() } } +void LLFloaterPreference::onClickActionChange() +{ + updateClickActionControls(); +} + void LLFloaterPreference::onClickPermsDefault() { LLFloaterReg::showInstance("perms_default"); @@ -2032,6 +2045,86 @@ void LLFloaterPreference::onLogChatHistorySaved() } } +void LLFloaterPreference::updateClickActionControls() +{ + const int single_clk_action = getChild<LLComboBox>("single_click_action_combo")->getValue().asInteger(); + const int double_clk_action = getChild<LLComboBox>("double_click_action_combo")->getValue().asInteger(); + + // Todo: This is a very ugly way to get access to keybindings. + // Reconsider possible options. + // Potential option: make constructor of LLKeyConflictHandler private + // but add a getter that will return shared pointer for specific + // mode, pointer should only exist so long as there are external users. + // In such case we won't need to do this 'dynamic_cast' nightmare. + // updateTable() can also be avoided + LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core"); + for (child_list_t::const_iterator iter = tabcontainer->getChildList()->begin(); + iter != tabcontainer->getChildList()->end(); ++iter) + { + LLView* view = *iter; + LLPanelPreferenceControls* panel = dynamic_cast<LLPanelPreferenceControls*>(view); + if (panel) + { + panel->setKeyBind("walk_to", + EMouseClickType::CLICK_LEFT, + KEY_NONE, + MASK_NONE, + single_clk_action == 1); + + panel->setKeyBind("walk_to", + EMouseClickType::CLICK_DOUBLELEFT, + KEY_NONE, + MASK_NONE, + double_clk_action == 1); + + panel->setKeyBind("teleport_to", + EMouseClickType::CLICK_DOUBLELEFT, + KEY_NONE, + MASK_NONE, + double_clk_action == 2); + + panel->updateTable(); + } + } +} + +void LLFloaterPreference::updateClickActionViews() +{ + bool click_to_walk = false; + bool dbl_click_to_walk = false; + bool dbl_click_to_teleport = false; + + // Todo: This is a very ugly way to get access to keybindings. + // Reconsider possible options. + LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core"); + for (child_list_t::const_iterator iter = tabcontainer->getChildList()->begin(); + iter != tabcontainer->getChildList()->end(); ++iter) + { + LLView* view = *iter; + LLPanelPreferenceControls* panel = dynamic_cast<LLPanelPreferenceControls*>(view); + if (panel) + { + click_to_walk = panel->canKeyBindHandle("walk_to", + EMouseClickType::CLICK_LEFT, + KEY_NONE, + MASK_NONE); + + dbl_click_to_walk = panel->canKeyBindHandle("walk_to", + EMouseClickType::CLICK_DOUBLELEFT, + KEY_NONE, + MASK_NONE); + + dbl_click_to_teleport = panel->canKeyBindHandle("teleport_to", + EMouseClickType::CLICK_DOUBLELEFT, + KEY_NONE, + MASK_NONE); + } + } + + getChild<LLComboBox>("single_click_action_combo")->setValue((int)click_to_walk); + getChild<LLComboBox>("double_click_action_combo")->setValue(dbl_click_to_teleport ? 2 : (int)dbl_click_to_walk); +} + void LLFloaterPreference::applyUIColor(LLUICtrl* ctrl, const LLSD& param) { LLUIColorTable::instance().setColor(param.asString(), LLColor4(ctrl->getValue())); @@ -2856,7 +2949,7 @@ void LLPanelPreferenceControls::saveSettings() } S32 mode = pKeyModeBox->getValue().asInteger(); - if (mConflictHandler[mode].empty()) + if (mConflictHandler[mode].empty() || pControlsTable->isEmpty()) { regenerateControls(); } @@ -2951,6 +3044,13 @@ void LLPanelPreferenceControls::onRestoreDefaultsResponse(const LLSD& notificati mConflictHandler[i].resetToDefaults(); // Apply changes to viewer as 'temporary' mConflictHandler[i].saveToSettings(true); + + // notify comboboxes in move&view about potential change + LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); + if (instance) + { + instance->updateClickActionViews(); + } } updateTable(); @@ -2960,6 +3060,16 @@ void LLPanelPreferenceControls::onRestoreDefaultsResponse(const LLSD& notificati // Apply changes to viewer as 'temporary' mConflictHandler[mEditingMode].saveToSettings(true); + if (mEditingMode == LLKeyConflictHandler::MODE_THIRD_PERSON) + { + // notify comboboxes in move&view about potential change + LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); + if (instance) + { + instance->updateClickActionViews(); + } + } + updateTable(); break; case 2: // Cancel @@ -2969,7 +3079,80 @@ void LLPanelPreferenceControls::onRestoreDefaultsResponse(const LLSD& notificati } } -// todo: copy onSetKeyBind to interface and inherit from interface +// Bypass to let Move & view read values without need to create own key binding handler +// Assumes third person view +// Might be better idea to just move whole mConflictHandler into LLFloaterPreference +bool LLPanelPreferenceControls::canKeyBindHandle(const std::string &control, EMouseClickType click, KEY key, MASK mask) +{ + S32 mode = LLKeyConflictHandler::MODE_THIRD_PERSON; + if (mConflictHandler[mode].empty()) + { + // opening for first time + mConflictHandler[mode].loadFromSettings(LLKeyConflictHandler::MODE_THIRD_PERSON); + } + + return mConflictHandler[mode].canHandleControl(control, click, key, mask); +} + +// Bypass to let Move & view modify values without need to create own key binding handler +// Assumes third person view +// Might be better idea to just move whole mConflictHandler into LLFloaterPreference +void LLPanelPreferenceControls::setKeyBind(const std::string &control, EMouseClickType click, KEY key, MASK mask, bool set) +{ + S32 mode = LLKeyConflictHandler::MODE_THIRD_PERSON; + if (mConflictHandler[mode].empty()) + { + // opening for first time + mConflictHandler[mode].loadFromSettings(LLKeyConflictHandler::MODE_THIRD_PERSON); + } + + if (!mConflictHandler[mode].canAssignControl(mEditingControl)) + { + return; + } + + bool already_recorded = mConflictHandler[mode].canHandleControl(control, click, key, mask); + if (set) + { + if (already_recorded) + { + // nothing to do + return; + } + + // find free spot to add data, if no free spot, assign to first + S32 index = 0; + for (S32 i = 0; i < 3; i++) + { + if (mConflictHandler[mode].getControl(control, i).isEmpty()) + { + index = i; + break; + } + } + mConflictHandler[mode].registerControl(control, index, click, key, mask, true); + } + else if (!set) + { + if (!already_recorded) + { + // nothing to do + return; + } + + // find specific control and reset it + for (S32 i = 0; i < 3; i++) + { + LLKeyData data = mConflictHandler[mode].getControl(control, i); + if (data.mMouse == click && data.mKey == key && data.mMask == mask) + { + mConflictHandler[mode].clearControl(control, i); + } + } + } +} + +// from LLSetKeybindDialog's interface bool LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes) { if (!mConflictHandler[mEditingMode].canAssignControl(mEditingControl)) @@ -3001,6 +3184,21 @@ bool LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MAS } updateTable(); + + if ((mEditingMode == LLKeyConflictHandler::MODE_THIRD_PERSON || all_modes) + && (mEditingControl == "walk_to" + || mEditingControl == "teleport_to" + || click == CLICK_LEFT + || click == CLICK_DOUBLELEFT)) + { + // notify comboboxes in move&view about potential change + LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); + if (instance) + { + instance->updateClickActionViews(); + } + } + return true; } @@ -3034,6 +3232,16 @@ void LLPanelPreferenceControls::onDefaultKeyBind(bool all_modes) } } updateTable(); + + if (mEditingMode == LLKeyConflictHandler::MODE_THIRD_PERSON || all_modes) + { + // notify comboboxes in move&view about potential change + LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); + if (instance) + { + instance->updateClickActionViews(); + } + } } void LLPanelPreferenceControls::onCancelKeyBind() diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index ea6e1070cd..066deb97ee 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -106,6 +106,8 @@ public: void selectPrivacyPanel(); void selectChatPanel(); void getControlNames(std::vector<std::string>& names); + // updates click/double-click action controls depending on values from settings.xml + void updateClickActionViews(); protected: void onBtnOK(const LLSD& userdata); @@ -131,6 +133,11 @@ protected: // callback for when client turns on impostors void onAvatarImpostorsEnable(); + // callback for commit in the "Single click on land" and "Double click on land" comboboxes. + void onClickActionChange(); + // updates click/double-click action keybindngs depending on view values + void updateClickActionControls(); + public: // This function squirrels away the current values of the controls so that // cancel() can restore them. @@ -304,9 +311,20 @@ public: void onModeCommit(); void onRestoreDefaultsBtn(); void onRestoreDefaultsResponse(const LLSD& notification, const LLSD& response); + + // Bypass to let Move & view read values without need to create own key binding handler + // Todo: consider a better way to share access to keybindings + bool canKeyBindHandle(const std::string &control, EMouseClickType click, KEY key, MASK mask); + // Bypasses to let Move & view modify values without need to create own key binding handler + void setKeyBind(const std::string &control, EMouseClickType click, KEY key, MASK mask, bool set /*set or reset*/ ); + + // from interface /*virtual*/ bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes); /*virtual*/ void onDefaultKeyBind(bool all_modes); - /*virtual*/ void onCancelKeyBind(); + /*virtual*/ void onCancelKeyBind(); + + // Updates keybindings from storage to table + void updateTable(); private: // reloads settings, discards current changes, updates table @@ -319,8 +337,6 @@ private: // Cleans content and then adds content from xml files according to current mEditingMode void populateControlTable(); - // Updates keybindings from storage to table - void updateTable(); LLScrollListCtrl* pControlsTable; LLComboBox *pKeyModeBox; diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 5f966624ca..b426dc14fc 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -217,6 +217,22 @@ bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 return false; } +bool LLKeyConflictHandler::clearControl(const std::string &control_name, U32 data_index) +{ + if (control_name.empty()) + { + return false; + } + LLKeyConflict &type_data = mControlsMap[control_name]; + if (!type_data.mAssignable) + { + // Example: user tried to assign camera spin to all modes, but first person mode doesn't support it + return false; + } + type_data.mKeyBind.resetKeyData(data_index); + return true; +} + LLKeyData LLKeyConflictHandler::getControl(const std::string &control_name, U32 index) { if (control_name.empty()) diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h index 5451c16ae2..7566303cdd 100644 --- a/indra/newview/llkeyconflict.h +++ b/indra/newview/llkeyconflict.h @@ -86,8 +86,8 @@ public: // @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 + // 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 than that // @mouse_ind - mouse action (middle click, MB5 etc) // @key - keyboard key action // @mask - shift/ctrl/alt flags @@ -95,6 +95,7 @@ public: // 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? + bool clearControl(const std::string &control_name, U32 data_index); LLKeyData getControl(const std::string &control_name, U32 data_index); diff --git a/indra/newview/skins/default/xui/en/panel_preferences_move.xml b/indra/newview/skins/default/xui/en/panel_preferences_move.xml index d106456b31..8794e3bf95 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_move.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_move.xml @@ -195,6 +195,70 @@ name="invert_mouse" top_delta="0" width="128" /> + <text + follows="left|top" + type="string" + length="1" + height="10" + layout="topleft" + left="86" + name="single_click_action_lbl" + width="150" + top_pad="20"> + Single click on land: + </text> + <combo_box + height="23" + layout="topleft" + left_pad="10" + top_delta="-6" + name="single_click_action_combo" + width="200"> + <combo_box.item + label="No action" + name="0" + value="0"/> + <combo_box.item + label="Move to clicked point" + name="1" + value="1"/> + <combo_box.commit_callback + function="Pref.ClickActionChange"/> + </combo_box> + <text + follows="left|top" + type="string" + length="1" + height="10" + layout="topleft" + left="86" + name="double_click_action_lbl" + width="150" + top_pad="12"> + Double click on land: + </text> + <combo_box + height="23" + layout="topleft" + left_pad="10" + top_delta="-6" + name="double_click_action_combo" + width="200"> + <combo_box.item + label="No action" + name="0" + value="0"/> + <combo_box.item + label="Move to clicked point" + name="1" + value="1"/> + <combo_box.item + label="Teleport to clicked point" + name="2" + value="2"/> + <combo_box.commit_callback + function="Pref.ClickActionChange"/> + </combo_box> <button height="23" label="Other Devices" |