diff options
| -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" | 
