summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rwxr-xr-xindra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rwxr-xr-xindra/newview/app_settings/logcontrol.xml1
-rwxr-xr-xindra/newview/app_settings/settings.xml15
-rwxr-xr-xindra/newview/app_settings/settings_per_account.xml11
-rwxr-xr-xindra/newview/llavataractions.cpp14
-rwxr-xr-xindra/newview/llavataractions.h2
-rwxr-xr-xindra/newview/llfloaterhoverheight.cpp157
-rwxr-xr-xindra/newview/llfloaterhoverheight.h52
-rwxr-xr-xindra/newview/llfloaterperms.cpp11
-rwxr-xr-xindra/newview/llinspecttoast.cpp5
-rwxr-xr-xindra/newview/llpanelobjectinventory.cpp4
-rwxr-xr-xindra/newview/llstartup.cpp8
-rwxr-xr-xindra/newview/llviewerfloaterreg.cpp4
-rwxr-xr-xindra/newview/llviewermenu.cpp15
-rwxr-xr-xindra/newview/llviewerregion.cpp30
-rwxr-xr-xindra/newview/llviewerregion.h12
-rwxr-xr-xindra/newview/llvoavatar.cpp134
-rwxr-xr-xindra/newview/llvoavatar.h6
-rwxr-xr-xindra/newview/llvoavatarself.cpp103
-rwxr-xr-xindra/newview/llvoavatarself.h11
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_edit_hover_height.xml38
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_attachment_self.xml8
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_avatar_self.xml8
24 files changed, 613 insertions, 40 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index a7c5dbff82..78f04dccae 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -245,6 +245,7 @@ set(viewer_SOURCE_FILES
llfloaterhandler.cpp
llfloaterhardwaresettings.cpp
llfloaterhelpbrowser.cpp
+ llfloaterhoverheight.cpp
llfloaterhud.cpp
llfloaterimagepreview.cpp
llfloaterimsessiontab.cpp
@@ -849,6 +850,7 @@ set(viewer_HEADER_FILES
llfloaterhandler.h
llfloaterhardwaresettings.h
llfloaterhelpbrowser.h
+ llfloaterhoverheight.h
llfloaterhud.h
llfloaterimagepreview.h
llfloaterimnearbychat.h
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index e5403775b2..7c35ff8c4b 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.7.26
+3.7.28
diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 15cb5bc0eb..de3732f339 100755
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -43,6 +43,7 @@
<key>tags</key>
<array>
<!-- sample entry for debugging specific items
+ <string>Avatar</string>
<string>Inventory</string>
<string>SceneLoadTiming</string>
<string>Avatar</string>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index e3ab45c53e..88d74deb08 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -665,6 +665,21 @@
<key>Value</key>
<integer>2</integer>
</map>
+ <key>AvatarPosFinalOffset</key>
+ <map>
+ <key>Comment</key>
+ <string>After-everything-else fixup for avatar position.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Vector3</string>
+ <key>Value</key>
+ <array>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ </array>
+ </map>
<key>AvatarPickerURL</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index fc6f1f6395..d119504017 100755
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -1,5 +1,16 @@
<llsd>
<map>
+ <key>AvatarHoverOffsetZ</key>
+ <map>
+ <key>Comment</key>
+ <string>After-everything-else fixup for avatar Z position.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.0</real>
+ </map>
<key>DoNotDisturbResponseChanged</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 0e30c079ff..8dc8a2ff20 100755
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -745,7 +745,7 @@ namespace action_give_inventory
}
std::string residents;
- LLAvatarActions::buildResidentsString(avatar_names, residents);
+ LLAvatarActions::buildResidentsString(avatar_names, residents, true);
std::string items;
build_items_string(inventory_selected_uuids, items);
@@ -777,7 +777,7 @@ namespace action_give_inventory
}
// static
-void LLAvatarActions::buildResidentsString(std::vector<LLAvatarName> avatar_names, std::string& residents_string)
+void LLAvatarActions::buildResidentsString(std::vector<LLAvatarName> avatar_names, std::string& residents_string, bool complete_name)
{
llassert(avatar_names.size() > 0);
@@ -785,7 +785,15 @@ void LLAvatarActions::buildResidentsString(std::vector<LLAvatarName> avatar_name
const std::string& separator = LLTrans::getString("words_separator");
for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; )
{
- residents_string.append((*it).getCompleteName());
+ if(complete_name)
+ {
+ residents_string.append((*it).getCompleteName());
+ }
+ else
+ {
+ residents_string.append((*it).getDisplayName());
+ }
+
if (++it == avatar_names.end())
{
break;
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
index 85813f2152..bd0ac24e93 100755
--- a/indra/newview/llavataractions.h
+++ b/indra/newview/llavataractions.h
@@ -221,7 +221,7 @@ public:
* @param avatar_names - a vector of given avatar names from which resulting string is built
* @param residents_string - the resulting string
*/
- static void buildResidentsString(std::vector<LLAvatarName> avatar_names, std::string& residents_string);
+ static void buildResidentsString(std::vector<LLAvatarName> avatar_names, std::string& residents_string, bool complete_name = false);
/**
* Builds a string of residents' display names separated by "words_separator" string.
diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
new file mode 100755
index 0000000000..8908626de6
--- /dev/null
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -0,0 +1,157 @@
+/**
+* @file llfloaterhoverheight.cpp
+* @brief Controller for self avatar hover height
+* @author vir@lindenlab.com
+*
+* $LicenseInfo:firstyear=2014&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2014, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterhoverheight.h"
+#include "llsliderctrl.h"
+#include "llviewercontrol.h"
+#include "llsdserialize.h"
+#include "llhttpclient.h"
+#include "llagent.h"
+#include "llviewerregion.h"
+#include "llvoavatarself.h"
+
+LLFloaterHoverHeight::LLFloaterHoverHeight(const LLSD& key) : LLFloater(key)
+{
+}
+
+void LLFloaterHoverHeight::syncFromPreferenceSetting(void *user_data)
+{
+ F32 value = gSavedPerAccountSettings.getF32("AvatarHoverOffsetZ");
+
+ LLFloaterHoverHeight *self = static_cast<LLFloaterHoverHeight*>(user_data);
+ LLSliderCtrl* sldrCtrl = self->getChild<LLSliderCtrl>("HoverHeightSlider");
+ sldrCtrl->setValue(value,FALSE);
+
+ if (isAgentAvatarValid())
+ {
+ LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z));
+ LL_INFOS("Avatar") << "setting hover from preference setting " << offset[2] << LL_ENDL;
+ gAgentAvatarp->setHoverOffset(offset);
+ //gAgentAvatarp->sendHoverHeight();
+ }
+}
+
+BOOL LLFloaterHoverHeight::postBuild()
+{
+ LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
+ sldrCtrl->setMinValue(MIN_HOVER_Z);
+ sldrCtrl->setMaxValue(MAX_HOVER_Z);
+ sldrCtrl->setSliderMouseUpCallback(boost::bind(&LLFloaterHoverHeight::onFinalCommit,this));
+ sldrCtrl->setSliderEditorCommitCallback(boost::bind(&LLFloaterHoverHeight::onFinalCommit,this));
+ childSetCommitCallback("HoverHeightSlider", &LLFloaterHoverHeight::onSliderMoved, NULL);
+
+ // Initialize slider from pref setting.
+ syncFromPreferenceSetting(this);
+ // Update slider on future pref changes.
+ if (gSavedPerAccountSettings.getControl("AvatarHoverOffsetZ"))
+ {
+ gSavedPerAccountSettings.getControl("AvatarHoverOffsetZ")->getCommitSignal()->connect(boost::bind(&syncFromPreferenceSetting, this));
+ }
+ else
+ {
+ LL_WARNS() << "Control not found for AvatarHoverOffsetZ" << LL_ENDL;
+ }
+
+ updateEditEnabled();
+
+ if (!mRegionChangedSlot.connected())
+ {
+ mRegionChangedSlot = gAgent.addRegionChangedCallback(boost::bind(&LLFloaterHoverHeight::onRegionChanged,this));
+ }
+ // Set up based on initial region.
+ onRegionChanged();
+
+ return TRUE;
+}
+
+void LLFloaterHoverHeight::onClose(bool app_quitting)
+{
+ if (mRegionChangedSlot.connected())
+ {
+ mRegionChangedSlot.disconnect();
+ }
+}
+
+// static
+void LLFloaterHoverHeight::onSliderMoved(LLUICtrl* ctrl, void* userData)
+{
+ LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
+ F32 value = sldrCtrl->getValueF32();
+ LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z));
+ LL_INFOS("Avatar") << "setting hover from slider moved" << offset[2] << LL_ENDL;
+ gAgentAvatarp->setHoverOffset(offset, false);
+}
+
+// Do send-to-the-server work when slider drag completes, or new
+// value entered as text.
+void LLFloaterHoverHeight::onFinalCommit()
+{
+ LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
+ F32 value = sldrCtrl->getValueF32();
+ gSavedPerAccountSettings.setF32("AvatarHoverOffsetZ",value);
+
+ LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z));
+ LL_INFOS("Avatar") << "setting hover from slider final commit " << offset[2] << LL_ENDL;
+ gAgentAvatarp->setHoverOffset(offset, true); // will send update this time.
+}
+
+void LLFloaterHoverHeight::onRegionChanged()
+{
+ LLViewerRegion *region = gAgent.getRegion();
+ if (region && region->simulatorFeaturesReceived())
+ {
+ updateEditEnabled();
+ }
+ else if (region)
+ {
+ region->setSimulatorFeaturesReceivedCallback(boost::bind(&LLFloaterHoverHeight::onSimulatorFeaturesReceived,this,_1));
+ }
+}
+
+void LLFloaterHoverHeight::onSimulatorFeaturesReceived(const LLUUID &region_id)
+{
+ LLViewerRegion *region = gAgent.getRegion();
+ if (region && (region->getRegionID()==region_id))
+ {
+ updateEditEnabled();
+ }
+}
+
+void LLFloaterHoverHeight::updateEditEnabled()
+{
+ bool enabled = gAgent.getRegion() && gAgent.getRegion()->avatarHoverHeightEnabled();
+ LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
+ sldrCtrl->setEnabled(enabled);
+ if (enabled)
+ {
+ syncFromPreferenceSetting(this);
+ }
+}
+
+
diff --git a/indra/newview/llfloaterhoverheight.h b/indra/newview/llfloaterhoverheight.h
new file mode 100755
index 0000000000..ee065bc184
--- /dev/null
+++ b/indra/newview/llfloaterhoverheight.h
@@ -0,0 +1,52 @@
+/**
+* @file llfloaterhoverheight.h
+* @brief Controller for self avatar hover height.
+* @author vir@lindenlab.com
+*
+* $LicenseInfo:firstyear=2014&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2014, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+#ifndef LL_LLFLOATERHOVERHEIGHT_H
+#define LL_LLFLOATERHOVERHEIGHT_H
+
+#include "llfloater.h"
+
+class LLFloaterHoverHeight: public LLFloater
+{
+public:
+ LLFloaterHoverHeight(const LLSD& key);
+ BOOL postBuild();
+
+ static void onSliderMoved(LLUICtrl* ctrl, void* userData);
+
+ void onFinalCommit();
+
+ static void syncFromPreferenceSetting(void *user_data);
+
+ void onRegionChanged();
+ void onSimulatorFeaturesReceived(const LLUUID &region_id);
+ void updateEditEnabled();
+
+ /*virtual*/ void onClose(bool app_quitting);
+ boost::signals2::connection mRegionChangedSlot;
+};
+
+#endif
diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp
index 0880a5f35a..849aa7cd14 100755
--- a/indra/newview/llfloaterperms.cpp
+++ b/indra/newview/llfloaterperms.cpp
@@ -35,6 +35,8 @@
#include "llagent.h"
#include "llviewerregion.h"
#include "llnotificationsutil.h"
+#include "llsdserialize.h"
+#include "llvoavatar.h"
LLFloaterPerms::LLFloaterPerms(const LLSD& seed)
: LLFloater(seed)
@@ -171,8 +173,9 @@ public:
private:
static std::string sPreviousReason;
- void error(U32 status, const std::string& reason)
+ void httpFailure()
{
+ const std::string& reason = getReason();
// Do not display the same error more than once in a row
if (reason != sPreviousReason)
{
@@ -182,8 +185,12 @@ private:
LLNotificationsUtil::add("DefaultObjectPermissions", args);
}
}
- void result(const LLSD& content)
+
+ void httpSuccess()
{
+ //const LLSD& content = getContent();
+ //dump_sequential_xml("perms_responder_result.xml", content);
+
// Since we have had a successful POST call be sure to display the next error message
// even if it is the same as a previous one.
sPreviousReason = "";
diff --git a/indra/newview/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp
index 0bc7bd188d..d04378daaf 100755
--- a/indra/newview/llinspecttoast.cpp
+++ b/indra/newview/llinspecttoast.cpp
@@ -89,6 +89,11 @@ void LLInspectToast::onOpen(const LLSD& notification_id)
mConnection = toast->setOnToastDestroyedCallback(boost::bind(&LLInspectToast::onToastDestroy, this, _1));
LLPanel * panel = toast->getPanel();
+ if (panel == NULL)
+ {
+ LL_WARNS() << "Could not get toast's panel." << LL_ENDL;
+ return;
+ }
panel->setVisible(TRUE);
panel->setMouseOpaque(FALSE);
if(mPanel != NULL && mPanel->getParent() == this)
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index 8b927a0c6b..1ae9d916b3 100755
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -689,10 +689,6 @@ void LLTaskInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
else if (canOpenItem())
{
items.push_back(std::string("Task Open"));
- if (!isItemCopyable())
- {
- disabled_items.push_back(std::string("Task Open"));
- }
}
items.push_back(std::string("Task Properties"));
if(isItemRenameable())
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index b3278b2437..e519032b9e 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1353,11 +1353,11 @@ bool idle_startup()
{
LLStringUtil::format_map_t args;
args["[NUMBER]"] = llformat("%d", num_retries + 1);
- set_startup_status(0.4f, LLTrans::getString("LoginRetrySeedCapGrant", args), gAgent.mMOTD);
+ set_startup_status(0.4f, LLTrans::getString("LoginRetrySeedCapGrant", args), gAgent.mMOTD.c_str());
}
else
{
- set_startup_status(0.4f, LLTrans::getString("LoginRequestSeedCapGrant"), gAgent.mMOTD);
+ set_startup_status(0.4f, LLTrans::getString("LoginRequestSeedCapGrant"), gAgent.mMOTD.c_str());
}
}
display_startup();
@@ -2071,7 +2071,7 @@ bool idle_startup()
update_texture_fetch();
set_startup_status(0.60f + 0.30f * timeout_frac,
LLTrans::getString("LoginPrecaching"),
- gAgent.mMOTD);
+ gAgent.mMOTD.c_str());
display_startup();
}
@@ -2211,6 +2211,8 @@ bool idle_startup()
llassert(LLPathfindingManager::getInstance() != NULL);
LLPathfindingManager::getInstance()->initSystem();
+ gAgentAvatarp->sendHoverHeight();
+
return TRUE;
}
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index e19fe9ca75..fc18b20758 100755
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -70,6 +70,7 @@
#include "llfloatergroups.h"
#include "llfloaterhardwaresettings.h"
#include "llfloaterhelpbrowser.h"
+#include "llfloaterhoverheight.h"
#include "llfloaterhud.h"
#include "llfloaterimagepreview.h"
#include "llfloaterimsession.h"
@@ -221,7 +222,8 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("god_tools", "floater_god_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGodTools>);
LLFloaterReg::add("group_picker", "floater_choose_group.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGroupPicker>);
- LLFloaterReg::add("help_browser", "floater_help_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHelpBrowser>);
+ LLFloaterReg::add("help_browser", "floater_help_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHelpBrowser>);
+ LLFloaterReg::add("edit_hover_height", "floater_edit_hover_height.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHoverHeight>);
LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>);
LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterIMSession>);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 22a032563e..9d680e23d1 100755
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -3891,6 +3891,14 @@ class LLEnableEditShape : public view_listener_t
}
};
+class LLEnableHoverHeight : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ return gAgent.getRegion() && gAgent.getRegion()->avatarHoverHeightEnabled();
+ }
+};
+
class LLEnableEditPhysics : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -6088,6 +6096,11 @@ void handle_edit_shape()
LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_shape"));
}
+void handle_hover_height()
+{
+ LLFloaterReg::showInstance("edit_hover_height");
+}
+
void handle_edit_physics()
{
LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_physics"));
@@ -8584,10 +8597,12 @@ void initialize_menus()
view_listener_t::addMenu(new LLEditEnableTakeOff(), "Edit.EnableTakeOff");
view_listener_t::addMenu(new LLEditEnableCustomizeAvatar(), "Edit.EnableCustomizeAvatar");
view_listener_t::addMenu(new LLEnableEditShape(), "Edit.EnableEditShape");
+ view_listener_t::addMenu(new LLEnableHoverHeight(), "Edit.EnableHoverHeight");
view_listener_t::addMenu(new LLEnableEditPhysics(), "Edit.EnableEditPhysics");
commit.add("CustomizeAvatar", boost::bind(&handle_customize_avatar));
commit.add("EditOutfit", boost::bind(&handle_edit_outfit));
commit.add("EditShape", boost::bind(&handle_edit_shape));
+ commit.add("HoverHeight", boost::bind(&handle_hover_height));
commit.add("EditPhysics", boost::bind(&handle_edit_physics));
// View menu
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index bac742b0bb..75cb0d16ef 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -425,6 +425,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
mCacheDirty(FALSE),
mReleaseNotesRequested(FALSE),
mCapabilitiesReceived(false),
+ mSimulatorFeaturesReceived(false),
mBitsReceived(0.f),
mPacketsReceived(0.f),
mDead(FALSE),
@@ -2038,6 +2039,26 @@ void LLViewerRegion::getInfo(LLSD& info)
info["Region"]["Handle"]["y"] = (LLSD::Integer)y;
}
+boost::signals2::connection LLViewerRegion::setSimulatorFeaturesReceivedCallback(const caps_received_signal_t::slot_type& cb)
+{
+ return mSimulatorFeaturesReceivedSignal.connect(cb);
+}
+
+void LLViewerRegion::setSimulatorFeaturesReceived(bool received)
+{
+ mSimulatorFeaturesReceived = received;
+ if (received)
+ {
+ mSimulatorFeaturesReceivedSignal(getRegionID());
+ mSimulatorFeaturesReceivedSignal.disconnect_all_slots();
+ }
+}
+
+bool LLViewerRegion::simulatorFeaturesReceived() const
+{
+ return mSimulatorFeaturesReceived;
+}
+
void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features) const
{
sim_features = mSimulatorFeatures;
@@ -2051,6 +2072,9 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features)
LLSDSerialize::toPrettyXML(sim_features, str);
LL_INFOS() << str.str() << LL_ENDL;
mSimulatorFeatures = sim_features;
+
+ setSimulatorFeaturesReceived(true);
+
}
//this is called when the parent is not cacheable.
@@ -3099,6 +3123,12 @@ bool LLViewerRegion::dynamicPathfindingEnabled() const
return ( mSimulatorFeatures.has("DynamicPathfindingEnabled") &&
mSimulatorFeatures["DynamicPathfindingEnabled"].asBoolean());
}
+
+bool LLViewerRegion::avatarHoverHeightEnabled() const
+{
+ return ( mSimulatorFeatures.has("AvatarHoverHeightEnabled") &&
+ mSimulatorFeatures["AvatarHoverHeightEnabled"].asBoolean());
+}
/* Static Functions */
void log_capabilities(const CapabilityMap &capmap)
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index d01e746936..c14fa5aee8 100755
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -309,12 +309,19 @@ public:
bool meshRezEnabled() const;
bool meshUploadEnabled() const;
+ // has region received its simulator features list? Requires an additional query after caps received.
+ void setSimulatorFeaturesReceived(bool);
+ bool simulatorFeaturesReceived() const;
+ boost::signals2::connection setSimulatorFeaturesReceivedCallback(const caps_received_signal_t::slot_type& cb);
+
void getSimulatorFeatures(LLSD& info) const;
void setSimulatorFeatures(const LLSD& info);
bool dynamicPathfindingEnabled() const;
+ bool avatarHoverHeightEnabled() const;
+
typedef enum
{
CACHE_MISS_TYPE_FULL = 0,
@@ -512,6 +519,7 @@ private:
BOOL mCacheDirty;
BOOL mAlive; // can become false if circuit disconnects
BOOL mCapabilitiesReceived;
+ BOOL mSimulatorFeaturesReceived;
BOOL mReleaseNotesRequested;
BOOL mDead; //if true, this region is in the process of deleting.
BOOL mPaused; //pause processing the objects in the region
@@ -532,11 +540,13 @@ private:
CacheMissItem::cache_miss_list_t mCacheMissList;
caps_received_signal_t mCapabilitiesReceivedSignal;
+ caps_received_signal_t mSimulatorFeaturesReceivedSignal;
+
LLSD mSimulatorFeatures;
// the materials capability throttle
LLFrameTimer mMaterialsCapThrottleTimer;
-LLFrameTimer mRenderInfoRequestTimer;
+ LLFrameTimer mRenderInfoRequestTimer;
};
inline BOOL LLViewerRegion::getRegionProtocol(U64 protocol) const
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 7292af99a4..75b81cdeed 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -111,6 +111,9 @@ extern F32 ANIM_SPEED_MAX;
extern F32 ANIM_SPEED_MIN;
extern U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG;
+const F32 MAX_HOVER_Z = 2.0;
+const F32 MIN_HOVER_Z = -2.0;
+
// #define OUTPUT_BREAST_DATA
using namespace LLAvatarAppearanceDefines;
@@ -252,6 +255,8 @@ struct LLAppearanceMessageContents
//U32 appearance_flags = 0;
std::vector<F32> mParamWeights;
std::vector<LLVisualParam*> mParams;
+ LLVector3 mHoverOffset;
+ bool mHoverOffsetWasSet;
};
struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock<LLVOAvatarChildJoint>
@@ -721,7 +726,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mCachedInMuteList(false)
{
//VTResume(); // VTune
-
+ setHoverOffset(LLVector3(0.0, 0.0, 0.0));
+
// mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline
const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job
mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim );
@@ -774,6 +780,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mRuthTimer.reset();
mRuthDebugTimer.reset();
mDebugExistenceTimer.reset();
+ mLastAppearanceMessageTimer.reset();
if(LLSceneMonitor::getInstance()->isEnabled())
{
@@ -1957,6 +1964,11 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys,
// Do base class updates...
U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);
+ //LLTEContents tec;
+ //S32 te_retval = parseTEMessage(mesgsys, _PREHASH_ObjectData, block_num, tec);
+
+ LL_DEBUGS("Avatar") << avString() << update_type << LL_ENDL;
+
// Print out arrival information once we have name of avatar.
if (has_name && getNVPair("FirstName"))
{
@@ -3185,12 +3197,8 @@ bool LLVOAvatar::isInMuteList()
return muted;
}
-//------------------------------------------------------------------------
-// updateCharacter()
-// called on both your avatar and other avatars
-//------------------------------------------------------------------------
-BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
-{
+void LLVOAvatar::updateDebugText()
+{
// clear debug text
mDebugText.clear();
@@ -3227,6 +3235,22 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
debug_line += llformat(" - cof rcv:%d", last_received_cof_version);
}
debug_line += llformat(" bsz-z: %f avofs-z: %f", mBodySize[2], mAvatarOffset[2]);
+ bool hover_enabled = getRegion() && getRegion()->avatarHoverHeightEnabled();
+ debug_line += hover_enabled ? " H" : " h";
+ const LLVector3& hover_offset = getHoverOffset();
+ if (hover_offset[2] != 0.0)
+ {
+ debug_line += llformat(" hov_z: %f", hover_offset[2]);
+ debug_line += llformat(" %s", (mIsSitting ? "S" : "T"));
+ debug_line += llformat("%s", (isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED) ? "G" : "-"));
+ }
+ F32 elapsed = mLastAppearanceMessageTimer.getElapsedTimeF32();
+ static const char *elapsed_chars = "Xx*...";
+ U32 bucket = U32(elapsed*2);
+ if (bucket < strlen(elapsed_chars))
+ {
+ debug_line += llformat(" %c", elapsed_chars[bucket]);
+ }
addDebugText(debug_line);
}
if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked"))
@@ -3234,7 +3258,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
if (!mBakedTextureDebugText.empty())
addDebugText(mBakedTextureDebugText);
}
-
+
if (LLVOAvatar::sShowAnimationDebug)
{
for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin();
@@ -3263,6 +3287,27 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
}
}
+ if (!mDebugText.size() && mText.notNull())
+ {
+ mText->markDead();
+ mText = NULL;
+ }
+ else if (mDebugText.size())
+ {
+ setDebugText(mDebugText);
+ }
+ mDebugText.clear();
+
+}
+
+//------------------------------------------------------------------------
+// updateCharacter()
+// called on both your avatar and other avatars
+//------------------------------------------------------------------------
+BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
+{
+ updateDebugText();
+
if (!mIsBuilt)
{
return FALSE;
@@ -3371,9 +3416,15 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
LLVector3 xyVel = getVelocity();
xyVel.mV[VZ] = 0.0f;
speed = xyVel.length();
-
+ // remembering the value here prevents a display glitch if the
+ // animation gets toggled during this update.
+ bool was_sit_ground_constrained = isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED);
+
if (!(mIsSitting && getParent()))
{
+ // This case includes all configurations except sitting on an
+ // object, so does include ground sit.
+
//--------------------------------------------------------------------
// get timing info
// handle initial condition case
@@ -3427,9 +3478,14 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
// correct for the fact that the pelvis is not necessarily the center
// of the agent's physical representation
root_pos.mdV[VZ] -= (0.5f * mBodySize.mV[VZ]) - mPelvisToFoot;
+ if (!mIsSitting && !was_sit_ground_constrained)
+ {
+ root_pos += LLVector3d(getHoverOffset());
+ }
LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos);
+
if (newPosition != mRoot->getXform()->getWorldPosition())
{
mRoot->touch();
@@ -3594,7 +3650,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
}
else if (mDrawable.notNull())
{
- mRoot->setPosition(mDrawable->getPosition());
+ LLVector3 pos = mDrawable->getPosition();
+ pos += getHoverOffset() * mDrawable->getRotation();
+ mRoot->setPosition(pos);
mRoot->setRotation(mDrawable->getRotation());
}
@@ -3613,7 +3671,21 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
{
updateMotions(LLCharacter::NORMAL_UPDATE);
}
-
+
+ // Special handling for sitting on ground.
+ if (!getParent() && (mIsSitting || was_sit_ground_constrained))
+ {
+
+ F32 off_z = LLVector3d(getHoverOffset()).mdV[VZ];
+ if (off_z != 0.0)
+ {
+ LLVector3 pos = mRoot->getWorldPosition();
+ pos.mV[VZ] += off_z;
+ mRoot->touch();
+ mRoot->setWorldPosition(pos);
+ }
+ }
+
// update head position
updateHeadOffset();
@@ -3697,17 +3769,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
mRoot->updateWorldMatrixChildren();
- if (!mDebugText.size() && mText.notNull())
- {
- mText->markDead();
- mText = NULL;
- }
- else if (mDebugText.size())
- {
- setDebugText(mDebugText);
- }
- mDebugText.clear();
-
//mesh vertices need to be reskinned
mNeedsSkin = TRUE;
return TRUE;
@@ -7145,6 +7206,17 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
// For future use:
//mesgsys->getU32Fast(_PREHASH_AppearanceData, _PREHASH_Flags, appearance_flags, 0);
}
+
+ // Parse the AppearanceData field, if any.
+ contents.mHoverOffsetWasSet = false;
+ if (mesgsys->has(_PREHASH_AppearanceHover))
+ {
+ LLVector3 hover;
+ mesgsys->getVector3Fast(_PREHASH_AppearanceHover, _PREHASH_HoverHeight, hover);
+ LL_DEBUGS("Avatar") << avString() << " hover received " << hover.mV[ VX ] << "," << hover.mV[ VY ] << "," << hover.mV[ VZ ] << LL_ENDL;
+ contents.mHoverOffset = hover;
+ contents.mHoverOffsetWasSet = true;
+ }
// Parse visual params, if any.
S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam);
@@ -7262,6 +7334,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
return;
}
+ mLastAppearanceMessageTimer.reset();
+
ESex old_sex = getSex();
LLAppearanceMessageContents contents;
@@ -7446,6 +7520,22 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
}
}
+ if (contents.mHoverOffsetWasSet && !isSelf())
+ {
+ // Got an update for some other avatar
+ // Ignore updates for self, because we have a more authoritative value in the preferences.
+ setHoverOffset(contents.mHoverOffset);
+ LL_INFOS("Avatar") << avString() << "setting hover from message" << contents.mHoverOffset[2] << LL_ENDL;
+ }
+
+ if (!contents.mHoverOffsetWasSet && !isSelf())
+ {
+ // If we don't get a value at all, we are presumably in a
+ // region that does not support hover height.
+ LL_WARNS() << avString() << "zeroing hover because not defined in appearance message" << LL_ENDL;
+ setHoverOffset(LLVector3(0.0, 0.0, 0.0));
+ }
+
setCompositeUpdatesEnabled( TRUE );
// If all of the avatars are completely baked, release the global image caches to conserve memory.
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 7034f8349f..1c3f4f2aa7 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -214,7 +214,6 @@ public:
/*virtual*/ LLVector3 getPosAgentFromGlobal(const LLVector3d &position);
virtual void updateVisualParams();
-
/** Inherited
** **
*******************************************************************************/
@@ -234,6 +233,7 @@ private: //aligned members
// Updates
//--------------------------------------------------------------------
public:
+ void updateDebugText();
virtual BOOL updateCharacter(LLAgent &agent);
void idleUpdateVoiceVisualizer(bool voice_enabled);
void idleUpdateMisc(bool detailed_update);
@@ -992,6 +992,7 @@ public:
protected:
LLFrameTimer mRuthDebugTimer; // For tracking how long it takes for av to rez
LLFrameTimer mDebugExistenceTimer; // Debugging for how long the avatar has been in memory.
+ LLFrameTimer mLastAppearanceMessageTimer; // Time since last appearance message received.
//--------------------------------------------------------------------
// COF monitoring
@@ -1024,6 +1025,9 @@ protected: // Shared with LLVOAvatarSelf
extern const F32 SELF_ADDITIONAL_PRI;
extern const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL;
+extern const F32 MAX_HOVER_Z;
+extern const F32 MIN_HOVER_Z;
+
std::string get_sequential_numbered_file_name(const std::string& prefix,
const std::string& suffix);
void dump_sequential_xml(const std::string outprefix, const LLSD& content);
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 3f3cd25f95..ae7a233876 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -127,6 +127,25 @@ struct LocalTextureData
LLTextureEntry *mTexEntry;
};
+// TODO - this class doesn't really do anything, could just use a base
+// class responder if nothing else gets added.
+class LLHoverHeightResponder: public LLHTTPClient::Responder
+{
+public:
+ LLHoverHeightResponder(): LLHTTPClient::Responder() {}
+
+private:
+ void httpFailure()
+ {
+ LL_WARNS() << dumpResponse() << LL_ENDL;
+ }
+
+ void httpSuccess()
+ {
+ LL_INFOS() << dumpResponse() << LL_ENDL;
+ }
+};
+
//-----------------------------------------------------------------------------
// Callback data
//-----------------------------------------------------------------------------
@@ -159,7 +178,10 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id,
mScreenp(NULL),
mLastRegionHandle(0),
mRegionCrossingCount(0),
- mInitialBakesLoaded(false)
+ mInitialBakesLoaded(false),
+ // Value outside legal range, so will always be a mismatch the
+ // first time through.
+ mLastHoverOffsetSent(LLVector3(0.0f, 0.0f, -999.0f))
{
mMotionController.mIsSelf = TRUE;
@@ -220,11 +242,40 @@ void LLVOAvatarSelf::initInstance()
return;
}
+ setHoverIfRegionEnabled();
+
//doPeriodically(output_self_av_texture_diagnostics, 30.0);
doPeriodically(update_avatar_rez_metrics, 5.0);
doPeriodically(boost::bind(&LLVOAvatarSelf::checkStuckAppearance, this), 30.0);
}
+void LLVOAvatarSelf::setHoverIfRegionEnabled()
+{
+ if (getRegion() && getRegion()->simulatorFeaturesReceived())
+ {
+ if (getRegion()->avatarHoverHeightEnabled())
+ {
+ F32 hover_z = gSavedPerAccountSettings.getF32("AvatarHoverOffsetZ");
+ setHoverOffset(LLVector3(0.0, 0.0, llclamp(hover_z,MIN_HOVER_Z,MAX_HOVER_Z)));
+ LL_INFOS("Avatar") << avString() << " set hover height from debug setting " << hover_z << LL_ENDL;
+ }
+ else
+ {
+ setHoverOffset(LLVector3(0.0, 0.0, 0.0));
+ LL_INFOS("Avatar") << avString() << " zeroing hover height, region does not support" << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_INFOS("Avatar") << avString() << " region or simulator features not known, no change on hover" << LL_ENDL;
+ if (getRegion())
+ {
+ getRegion()->setSimulatorFeaturesReceivedCallback(boost::bind(&LLVOAvatarSelf::onSimulatorFeaturesReceived,this,_1));
+ }
+
+ }
+}
+
bool LLVOAvatarSelf::checkStuckAppearance()
{
const F32 CONDITIONAL_UNSTICK_INTERVAL = 300.0;
@@ -835,6 +886,12 @@ void LLVOAvatarSelf::removeMissingBakedTextures()
}
}
+void LLVOAvatarSelf::onSimulatorFeaturesReceived(const LLUUID& region_id)
+{
+ LL_INFOS("Avatar") << "simulator features received, setting hover based on region props" << LL_ENDL;
+ setHoverIfRegionEnabled();
+}
+
//virtual
void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp)
{
@@ -853,6 +910,17 @@ void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp)
//LL_INFOS() << "pos_from_old_region is " << global_pos_from_old_region
// << " while pos_from_new_region is " << pos_from_new_region
// << LL_ENDL;
+
+ // Update hover height, or schedule callback, based on whether
+ // it's supported in this region.
+ if (regionp->simulatorFeaturesReceived())
+ {
+ setHoverIfRegionEnabled();
+ }
+ else
+ {
+ regionp->setSimulatorFeaturesReceivedCallback(boost::bind(&LLVOAvatarSelf::onSimulatorFeaturesReceived,this,_1));
+ }
}
if (!regionp || (regionp->getHandle() != mLastRegionHandle))
@@ -2709,6 +2777,39 @@ bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const
return success;
}
+//------------------------------------------------------------------------
+// sendHoverHeight()
+//------------------------------------------------------------------------
+void LLVOAvatarSelf::sendHoverHeight() const
+{
+ std::string url = gAgent.getRegion()->getCapability("AgentPreferences");
+
+ if (!url.empty())
+ {
+ LLSD update = LLSD::emptyMap();
+ const LLVector3& hover_offset = getHoverOffset();
+ update["hover_height"] = hover_offset[2];
+
+ LL_DEBUGS("Avatar") << avString() << "sending hover height value " << hover_offset[2] << LL_ENDL;
+ LLHTTPClient::post(url, update, new LLHoverHeightResponder);
+
+ mLastHoverOffsetSent = hover_offset;
+ }
+}
+
+void LLVOAvatarSelf::setHoverOffset(const LLVector3& hover_offset, bool send_update)
+{
+ if (getHoverOffset() != hover_offset)
+ {
+ LL_INFOS("Avatar") << avString() << " setting hover due to change " << hover_offset[2] << LL_ENDL;
+ LLVOAvatar::setHoverOffset(hover_offset, send_update);
+ }
+ if (send_update && (hover_offset != mLastHoverOffsetSent))
+ {
+ LL_INFOS("Avatar") << avString() << " sending hover due to change " << hover_offset[2] << LL_ENDL;
+ sendHoverHeight();
+ }
+}
//------------------------------------------------------------------------
// needsRenderBeam()
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 5f36872575..b8e9bbb77a 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -75,6 +75,9 @@ protected:
// LLViewerObject interface and related
//--------------------------------------------------------------------
public:
+ boost::signals2::connection mRegionChangedSlot;
+
+ void onSimulatorFeaturesReceived(const LLUUID& region_id);
/*virtual*/ void updateRegion(LLViewerRegion *regionp);
/*virtual*/ void idleUpdate(LLAgent &agent, const F64 &time);
@@ -328,6 +331,14 @@ public:
public:
bool sendAppearanceMessage(LLMessageSystem *mesgsys) const;
+ // -- care and feeding of hover height.
+ void setHoverIfRegionEnabled();
+ void sendHoverHeight() const;
+ /*virtual*/ void setHoverOffset(const LLVector3& hover_offset, bool send_update=true);
+
+private:
+ mutable LLVector3 mLastHoverOffsetSent;
+
/** Appearance
** **
*******************************************************************************/
diff --git a/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
new file mode 100755
index 0000000000..8ec6735a01
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ positioning="cascading"
+ ignore_ui_scale="false"
+ legacy_header_height="225"
+ can_minimize="true"
+ can_close="true"
+ can_resize="true"
+ min_height="65"
+ min_width="515"
+ height="65"
+ layout="topleft"
+ name="HoverHeight"
+ single_instance="true"
+ help_topic="hover_height"
+ save_rect="true"
+ save_visibility="true"
+ title="SET HOVER HEIGHT"
+ width="515">
+ <slider
+ enabled="false"
+ control_name="HoverHeightSlider"
+ decimal_digits="3"
+ follows="top|left"
+ height="15"
+ increment="0.001"
+ initial_value="0.0"
+ label="Height"
+ label_width="60"
+ left="10"
+ width="501"
+ layout="topleft"
+ name="HoverHeightSlider"
+ top="35"
+ can_edit_text="true"
+ >
+ </slider>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
index bcbc8d5b86..c6ae844d67 100755
--- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
@@ -91,6 +91,14 @@ name="Edit Outfit">
<menu_item_call.on_enable
function="Edit.EnableEditShape" />
</menu_item_call>
+ <menu_item_call label="Hover Height"
+ layout="topleft"
+ name="Hover Height">
+ <menu_item_call.on_click
+ function="HoverHeight" />
+ <menu_item_call.on_enable
+ function="Edit.EnableHoverHeight" />
+ </menu_item_call>
<menu_item_call
label="My Friends"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
index ca0c9bd5e4..d3b0b07f70 100755
--- a/indra/newview/skins/default/xui/en/menu_avatar_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
@@ -229,6 +229,14 @@
<menu_item_call.on_enable
function="Edit.EnableEditShape" />
</menu_item_call>
+ <menu_item_call label="Hover Height"
+ layout="topleft"
+ name="Hover Height">
+ <menu_item_call.on_click
+ function="HoverHeight" />
+ <menu_item_call.on_enable
+ function="Edit.EnableHoverHeight" />
+ </menu_item_call>
<menu_item_call
label="My Friends"
layout="topleft"