From 2e0a8231d2ab9be0300083cb3d793bf57fcfb793 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 25 Sep 2014 17:37:46 -0400
Subject: Simple viewer-side hack to adjust avatar position

---
 indra/newview/app_settings/settings.xml | 15 +++++++++++++++
 indra/newview/llvoavatar.cpp            |  6 +++++-
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 000362ebfd..bd035899d0 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -654,6 +654,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/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 9f42776d78..dd7d42ee25 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -3412,9 +3412,11 @@ 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;
+		root_pos += LLVector3d(gSavedSettings.getVector3("AvatarPosFinalOffset"));
 		
 		LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos);
 
+
 		if (newPosition != mRoot->getXform()->getWorldPosition())
 		{		
 			mRoot->touch();
@@ -3580,7 +3582,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 	}
 	else if (mDrawable.notNull())
 	{
-		mRoot->setPosition(mDrawable->getPosition());
+		LLVector3 pos = mDrawable->getPosition();
+		pos += gSavedSettings.getVector3("AvatarPosFinalOffset");
+		mRoot->setPosition(pos);
 		mRoot->setRotation(mDrawable->getRotation());
 	}
 	
-- 
cgit v1.2.3


From 626ee6777e68c0df36c82290c8e00eaebe43b8b4 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 29 Sep 2014 16:39:08 -0400
Subject: SL-92 WIP - can edit hover height debug setting via slider

---
 indra/newview/CMakeLists.txt                       |  2 +
 indra/newview/llfloaterhoverheight.cpp             | 59 ++++++++++++++++++++++
 indra/newview/llfloaterhoverheight.h               | 41 +++++++++++++++
 indra/newview/llviewerfloaterreg.cpp               |  4 +-
 indra/newview/llviewermenu.cpp                     | 15 ++++++
 .../skins/default/xui/en/menu_attachment_self.xml  |  8 +++
 .../skins/default/xui/en/menu_avatar_self.xml      |  8 +++
 7 files changed, 136 insertions(+), 1 deletion(-)
 create mode 100755 indra/newview/llfloaterhoverheight.cpp
 create mode 100755 indra/newview/llfloaterhoverheight.h

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index b81b2aa9cf..eb7bddce33 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -244,6 +244,7 @@ set(viewer_SOURCE_FILES
     llfloaterhandler.cpp
     llfloaterhardwaresettings.cpp
     llfloaterhelpbrowser.cpp
+    llfloaterhoverheight.cpp
     llfloaterhud.cpp
     llfloaterimagepreview.cpp
     llfloaterimsessiontab.cpp
@@ -848,6 +849,7 @@ set(viewer_HEADER_FILES
     llfloaterhandler.h
     llfloaterhardwaresettings.h
     llfloaterhelpbrowser.h
+    llfloaterhoverheight.h
     llfloaterhud.h
     llfloaterimagepreview.h
     llfloaterimnearbychat.h
diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
new file mode 100755
index 0000000000..5222f7bb3f
--- /dev/null
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -0,0 +1,59 @@
+/** 
+* @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"
+
+LLFloaterHoverHeight::LLFloaterHoverHeight(const LLSD& key) : LLFloater(key)
+{
+}
+
+BOOL LLFloaterHoverHeight::postBuild()
+{
+	LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
+
+	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+	F32 value = offset[2];
+	sldrCtrl->setValue(value,FALSE);
+	childSetCommitCallback("HoverHeightSlider", &LLFloaterHoverHeight::onSliderMoved, NULL);
+
+	return TRUE;
+}
+
+// static
+void LLFloaterHoverHeight::onSliderMoved(LLUICtrl* ctrl, void* userData)
+{
+	LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
+	F32 value = sldrCtrl->getValueF32();
+
+	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+	offset[2] = value;
+	gSavedSettings.setVector3("AvatarPosFinalOffset",offset);
+}
diff --git a/indra/newview/llfloaterhoverheight.h b/indra/newview/llfloaterhoverheight.h
new file mode 100755
index 0000000000..4ede8f08e0
--- /dev/null
+++ b/indra/newview/llfloaterhoverheight.h
@@ -0,0 +1,41 @@
+/** 
+* @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);
+};
+
+#endif
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 4e491f257d..7c98e6ef74 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"
@@ -220,7 +221,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 8c9429c05d..885c85d6c5 100755
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -3871,6 +3871,14 @@ class LLEnableEditShape : public view_listener_t
 	}
 };
 
+class LLEnableHoverHeight : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		return true;
+	}
+};
+
 class LLEnableEditPhysics : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
@@ -6046,6 +6054,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"));
@@ -8542,10 +8555,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/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"
-- 
cgit v1.2.3


From 52ed6ac28697ffcfd7300602aec34db8eafc171a Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 30 Sep 2014 15:34:16 -0400
Subject: SL-92 WIP - ui floater tweaks for hover height control

---
 indra/llui/llsliderctrl.cpp            | 15 ++++++++++++++-
 indra/llui/llsliderctrl.h              |  5 ++++-
 indra/newview/llfloaterhoverheight.cpp | 12 +++++++++++-
 indra/newview/llfloaterhoverheight.h   |  2 ++
 4 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp
index 62c5ecb8f1..2da39fa54b 100755
--- a/indra/llui/llsliderctrl.cpp
+++ b/indra/llui/llsliderctrl.cpp
@@ -58,7 +58,8 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p)
 	mPrecision(p.decimal_digits),
 	mTextEnabledColor(p.text_color()),
 	mTextDisabledColor(p.text_disabled_color()),
-	mLabelWidth(p.label_width)
+	mLabelWidth(p.label_width),
+	mEditorCommitSignal(NULL)
 {
 	S32 top = getRect().getHeight();
 	S32 bottom = 0;
@@ -196,6 +197,11 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p)
 	updateText();
 }
 
+LLSliderCtrl::~LLSliderCtrl()
+{
+	delete mEditorCommitSignal;
+}
+
 // static
 void LLSliderCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata )
 {
@@ -308,6 +314,8 @@ void LLSliderCtrl::onEditorCommit( LLUICtrl* ctrl, const LLSD& userdata )
 	if( success )
 	{
 		self->onCommit();
+		if (self->mEditorCommitSignal)
+			(*(self->mEditorCommitSignal))(self, self->getValueF32());
 	}
 	else
 	{
@@ -421,6 +429,11 @@ boost::signals2::connection LLSliderCtrl::setSliderMouseUpCallback( const commit
 	return mSlider->setMouseUpCallback( cb );
 }
 
+boost::signals2::connection LLSliderCtrl::setSliderEditorCommitCallback( const commit_signal_t::slot_type& cb )   
+{ 
+	if (!mEditorCommitSignal) mEditorCommitSignal = new commit_signal_t();
+	return mEditorCommitSignal->connect(cb); 
+}
 void LLSliderCtrl::onTabInto()
 {
 	if( mEditor )
diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h
index 5153e33f49..67cca9ef04 100755
--- a/indra/llui/llsliderctrl.h
+++ b/indra/llui/llsliderctrl.h
@@ -81,7 +81,7 @@ protected:
 	LLSliderCtrl(const Params&);
 	friend class LLUICtrlFactory;
 public:
-	virtual ~LLSliderCtrl() {} // Children all cleaned up by default view destructor.
+	virtual ~LLSliderCtrl();
 
 	/*virtual*/ F32	getValueF32() const { return mSlider->getValueF32(); }
 	void			setValue(F32 v, BOOL from_event = FALSE);
@@ -112,6 +112,7 @@ public:
 
 	boost::signals2::connection setSliderMouseDownCallback(	const commit_signal_t::slot_type& cb );
 	boost::signals2::connection setSliderMouseUpCallback( const commit_signal_t::slot_type& cb );
+	boost::signals2::connection setSliderEditorCommitCallback( const commit_signal_t::slot_type& cb );
 
 	/*virtual*/ void	onTabInto();
 
@@ -150,6 +151,8 @@ private:
 
 	LLUIColor	mTextEnabledColor;
 	LLUIColor	mTextDisabledColor;
+
+	commit_signal_t*	mEditorCommitSignal;
 };
 
 #endif  // LL_LLSLIDERCTRL_H
diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
index 5222f7bb3f..6f7f8374d2 100755
--- a/indra/newview/llfloaterhoverheight.cpp
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -37,11 +37,14 @@ LLFloaterHoverHeight::LLFloaterHoverHeight(const LLSD& key) : LLFloater(key)
 
 BOOL LLFloaterHoverHeight::postBuild()
 {
-	LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
 
 	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
 	F32 value = offset[2];
+
+	LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
 	sldrCtrl->setValue(value,FALSE);
+	sldrCtrl->setSliderMouseUpCallback(boost::bind(&LLFloaterHoverHeight::onFinalCommit,this));
+	sldrCtrl->setSliderEditorCommitCallback(boost::bind(&LLFloaterHoverHeight::onFinalCommit,this));
 	childSetCommitCallback("HoverHeightSlider", &LLFloaterHoverHeight::onSliderMoved, NULL);
 
 	return TRUE;
@@ -57,3 +60,10 @@ void LLFloaterHoverHeight::onSliderMoved(LLUICtrl* ctrl, void* userData)
 	offset[2] = value;
 	gSavedSettings.setVector3("AvatarPosFinalOffset",offset);
 }
+
+// Do extra send-to-the-server work when slider drag completes, or new
+// value entered as text.
+void LLFloaterHoverHeight::onFinalCommit()
+{
+	LL_INFOS() << "FINAL FINAL!!!" << LL_ENDL;
+}
diff --git a/indra/newview/llfloaterhoverheight.h b/indra/newview/llfloaterhoverheight.h
index 4ede8f08e0..1aede19e57 100755
--- a/indra/newview/llfloaterhoverheight.h
+++ b/indra/newview/llfloaterhoverheight.h
@@ -36,6 +36,8 @@ public:
 	BOOL postBuild();
 
 	static void onSliderMoved(LLUICtrl* ctrl, void* userData);
+
+	void onFinalCommit();
 };
 
 #endif
-- 
cgit v1.2.3


From c7c549b7e24af3b9ee87d464a03adeab75ee6553 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 26 Nov 2014 11:39:16 -0500
Subject: LLFloaterPermsResponder switched to new Responder API

---
 indra/newview/app_settings/logcontrol.xml |  1 +
 indra/newview/llfloaterperms.cpp          | 11 +++++++++--
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 15cb5bc0eb..29639bb9c2 100755
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -42,6 +42,7 @@
 						</array>
 					<key>tags</key>
 						<array>
+						     <string>Avatar</string>
 						<!-- sample entry for debugging specific items	
 						     <string>Inventory</string>
 						     <string>SceneLoadTiming</string>
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 = "";
-- 
cgit v1.2.3


From 909c18ea978059976a25222b446ffaa426147627 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 1 Dec 2014 16:34:43 -0500
Subject: Added missing xui file

---
 .../default/xui/en/floater_edit_hover_height.xml   | 39 ++++++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100755 indra/newview/skins/default/xui/en/floater_edit_hover_height.xml

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..29d06b9b4e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
@@ -0,0 +1,39 @@
+<?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
+     control_name="HoverHeightSlider"
+     decimal_digits="3"
+     follows="top|left"
+     height="15"
+     increment="0.001"
+     max_val="2"
+     min_val="-2"
+     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>
-- 
cgit v1.2.3


From c9981ec59c4613531b2d5bb03f6ab8f6d914343c Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 8 Dec 2014 13:12:28 -0500
Subject: SL-92 WIP - hover height communicated via appearance messages.

---
 indra/llmessage/message_prehash.cpp        |  2 ++
 indra/llmessage/message_prehash.h          |  2 ++
 indra/newview/app_settings/logcontrol.xml  |  2 +-
 indra/newview/llfloaterhoverheight.cpp     | 46 ++++++++++++++++++++++++++----
 indra/newview/llfloaterhoverheight.h       |  2 ++
 indra/newview/llvoavatar.cpp               | 30 +++++++++++++++++--
 indra/newview/llvoavatar.h                 |  1 +
 indra/newview/llvoavatarself.cpp           |  2 ++
 scripts/messages/message_template.msg      |  4 +++
 scripts/messages/message_template.msg.sha1 |  2 +-
 10 files changed, 82 insertions(+), 11 deletions(-)

diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index 39cfb6019e..a62b9c3227 100755
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -1383,3 +1383,5 @@ char const* const _PREHASH_GroupAVSounds = LLMessageStringTable::getInstance()->
 char const* const _PREHASH_AppearanceData = LLMessageStringTable::getInstance()->getString("AppearanceData");
 char const* const _PREHASH_AppearanceVersion = LLMessageStringTable::getInstance()->getString("AppearanceVersion");
 char const* const _PREHASH_CofVersion = LLMessageStringTable::getInstance()->getString("CofVersion");
+char const* const _PREHASH_AppearanceHover = LLMessageStringTable::getInstance()->getString("AppearanceHover");
+char const* const _PREHASH_HoverHeight = LLMessageStringTable::getInstance()->getString("HoverHeight");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index 573e10dc0b..573c8e466f 100755
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -1383,4 +1383,6 @@ extern char const* const _PREHASH_GroupAVSounds;
 extern char const* const _PREHASH_AppearanceData;
 extern char const* const _PREHASH_AppearanceVersion;
 extern char const* const _PREHASH_CofVersion;
+extern char const* const _PREHASH_AppearanceHover;
+extern char const* const _PREHASH_HoverHeight;
 #endif
diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 29639bb9c2..de3732f339 100755
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -42,8 +42,8 @@
 						</array>
 					<key>tags</key>
 						<array>
-						     <string>Avatar</string>
 						<!-- sample entry for debugging specific items	
+						     <string>Avatar</string>
 						     <string>Inventory</string>
 						     <string>SceneLoadTiming</string>
 						     <string>Avatar</string>
diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
index 6f7f8374d2..f25d491910 100755
--- a/indra/newview/llfloaterhoverheight.cpp
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -30,6 +30,28 @@
 #include "llfloaterhoverheight.h"
 #include "llsliderctrl.h"
 #include "llviewercontrol.h"
+#include "llsdserialize.h"
+#include "llhttpclient.h"
+#include "llagent.h"
+#include "llviewerregion.h"
+#include "llvoavatarself.h"
+
+class LLHoverHeightResponder: public LLHTTPClient::Responder
+{
+public:
+	LLHoverHeightResponder(): LLHTTPClient::Responder() {}
+
+private:
+	void httpFailure()
+	{
+		LL_WARNS() << dumpResponse() << LL_ENDL;
+	}
+
+	void httpSuccess()
+	{
+		LL_INFOS() << dumpResponse() << LL_ENDL;
+	}
+};
 
 LLFloaterHoverHeight::LLFloaterHoverHeight(const LLSD& key) : LLFloater(key)
 {
@@ -53,12 +75,6 @@ BOOL LLFloaterHoverHeight::postBuild()
 // static
 void LLFloaterHoverHeight::onSliderMoved(LLUICtrl* ctrl, void* userData)
 {
-	LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-	F32 value = sldrCtrl->getValueF32();
-
-	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
-	offset[2] = value;
-	gSavedSettings.setVector3("AvatarPosFinalOffset",offset);
 }
 
 // Do extra send-to-the-server work when slider drag completes, or new
@@ -66,4 +82,22 @@ void LLFloaterHoverHeight::onSliderMoved(LLUICtrl* ctrl, void* userData)
 void LLFloaterHoverHeight::onFinalCommit()
 {
 	LL_INFOS() << "FINAL FINAL!!!" << LL_ENDL;
+	sendHoverHeightUpdate();
+}
+
+void LLFloaterHoverHeight::sendHoverHeightUpdate()
+{
+	LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
+	F32 value = sldrCtrl->getValueF32();
+
+	std::string url = gAgent.getRegion()->getCapability("AgentPreferences");
+
+	if (!url.empty())
+	{
+		LLSD update = LLSD::emptyMap();
+		update["hover_height"] = value;
+
+		LL_INFOS() << "updating hover height to " << value << LL_ENDL;
+		LLHTTPClient::post(url, update, new LLHoverHeightResponder);
+	}
 }
diff --git a/indra/newview/llfloaterhoverheight.h b/indra/newview/llfloaterhoverheight.h
index 1aede19e57..b81f293ae5 100755
--- a/indra/newview/llfloaterhoverheight.h
+++ b/indra/newview/llfloaterhoverheight.h
@@ -38,6 +38,8 @@ public:
 	static void onSliderMoved(LLUICtrl* ctrl, void* userData);
 
 	void onFinalCommit();
+
+	void sendHoverHeightUpdate();
 };
 
 #endif
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 2c1dedede0..d150ace455 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -252,6 +252,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>
@@ -717,7 +719,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	mIsEditingAppearance(FALSE),
 	mUseLocalAppearance(FALSE),
 	mLastUpdateRequestCOFVersion(-1),
-	mLastUpdateReceivedCOFVersion(-1)
+	mLastUpdateReceivedCOFVersion(-1),
+	mHoverOffset(0.0, 0.0, 0.0)
 {
 	//VTResume();  // VTune
 	
@@ -1959,6 +1962,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"))
 		{
@@ -3411,7 +3419,7 @@ 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;
-		root_pos += LLVector3d(gSavedSettings.getVector3("AvatarPosFinalOffset"));
+		root_pos += LLVector3d(mHoverOffset);
 		
 		LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos);
 
@@ -3581,7 +3589,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 	else if (mDrawable.notNull())
 	{
 		LLVector3 pos = mDrawable->getPosition();
-		pos += gSavedSettings.getVector3("AvatarPosFinalOffset");
+		pos += mHoverOffset;
 		mRoot->setPosition(pos);
 		mRoot->setRotation(mDrawable->getRotation());
 	}
@@ -7007,6 +7015,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);
@@ -7308,6 +7327,11 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		}
 	}
 
+	if (contents.mHoverOffsetWasSet)
+	{
+		mHoverOffset = contents.mHoverOffset;
+	}
+
 	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 42ff7bff92..445f0ff921 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -210,6 +210,7 @@ public:
 	/*virtual*/ LLVector3		getPosAgentFromGlobal(const LLVector3d &position);
 	virtual void				updateVisualParams();
 
+	LLVector3 mHoverOffset;
 
 /**                    Inherited
  **                                                                            **
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 42a7c2e576..f4c6472f7a 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -163,6 +163,8 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id,
 {
 	mMotionController.mIsSelf = TRUE;
 
+	mHoverOffset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+
 	LL_DEBUGS() << "Marking avatar as self " << id << LL_ENDL;
 }
 
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index 6702de9b4a..e0a80ee9cd 100755
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -3594,6 +3594,10 @@ version 2.0
 		{	CofVersion			S32	}
 		{	Flags				U32	}
 	}
+	{
+		AppearanceHover		Single
+		{	HoverHeight	LLVector3	}
+	}
 }
 
 // AvatarSitResponse - response to a request to sit on an object
diff --git a/scripts/messages/message_template.msg.sha1 b/scripts/messages/message_template.msg.sha1
index 7a31177f11..affee31086 100755
--- a/scripts/messages/message_template.msg.sha1
+++ b/scripts/messages/message_template.msg.sha1
@@ -1 +1 @@
-4dbf88396c3188ad4c54c4f847a7d8817793668d
\ No newline at end of file
+bc6a4d7f7fd9bfddefcef336c3e30b623497447f
\ No newline at end of file
-- 
cgit v1.2.3


From a357a4096cb645956a2432adfd5dcadc55c153f5 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 11 Dec 2014 16:33:34 -0500
Subject: SL-92 WIP

---
 indra/newview/llfloaterhoverheight.cpp | 62 ++++++++++++++--------------------
 indra/newview/llfloaterhoverheight.h   |  2 +-
 indra/newview/llstartup.cpp            |  2 ++
 indra/newview/llvoavatar.cpp           | 19 +++++++++--
 indra/newview/llvoavatarself.cpp       | 39 +++++++++++++++++++--
 indra/newview/llvoavatarself.h         |  2 ++
 6 files changed, 85 insertions(+), 41 deletions(-)

diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
index f25d491910..bcdab6b3a0 100755
--- a/indra/newview/llfloaterhoverheight.cpp
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -36,68 +36,58 @@
 #include "llviewerregion.h"
 #include "llvoavatarself.h"
 
-class LLHoverHeightResponder: public LLHTTPClient::Responder
+LLFloaterHoverHeight::LLFloaterHoverHeight(const LLSD& key) : LLFloater(key)
 {
-public:
-	LLHoverHeightResponder(): LLHTTPClient::Responder() {}
+}
 
-private:
-	void httpFailure()
-	{
-		LL_WARNS() << dumpResponse() << LL_ENDL;
-	}
+void LLFloaterHoverHeight::syncFromPreferenceSetting(void *user_data)
+{
+	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+	F32 value = offset[2];
 
-	void httpSuccess()
+	LLFloaterHoverHeight *self = static_cast<LLFloaterHoverHeight*>(user_data);
+	LLSliderCtrl* sldrCtrl = self->getChild<LLSliderCtrl>("HoverHeightSlider");
+	sldrCtrl->setValue(value,FALSE);
+	if (isAgentAvatarValid())
 	{
-		LL_INFOS() << dumpResponse() << LL_ENDL;
+		gAgentAvatarp->sendHoverHeight();
 	}
-};
-
-LLFloaterHoverHeight::LLFloaterHoverHeight(const LLSD& key) : LLFloater(key)
-{
 }
 
 BOOL LLFloaterHoverHeight::postBuild()
 {
-
-	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
-	F32 value = offset[2];
-
 	LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
-	sldrCtrl->setValue(value,FALSE);
 	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.
+	gSavedSettings.getControl("AvatarPosFinalOffset")->getCommitSignal()->connect(boost::bind(&syncFromPreferenceSetting, this));
+
 	return TRUE;
 }
 
 // static
 void LLFloaterHoverHeight::onSliderMoved(LLUICtrl* ctrl, void* userData)
 {
+	LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
+	F32 value = sldrCtrl->getValueF32();
+	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+	offset[2] = value;
+	gAgentAvatarp->mHoverOffset = offset;
 }
 
-// Do extra send-to-the-server work when slider drag completes, or new
+// Do send-to-the-server work when slider drag completes, or new
 // value entered as text.
 void LLFloaterHoverHeight::onFinalCommit()
-{
-	LL_INFOS() << "FINAL FINAL!!!" << LL_ENDL;
-	sendHoverHeightUpdate();
-}
-
-void LLFloaterHoverHeight::sendHoverHeightUpdate()
 {
 	LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
 	F32 value = sldrCtrl->getValueF32();
+	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+	offset[2] = value;
+	gSavedSettings.setVector3("AvatarPosFinalOffset",offset);
+}
 
-	std::string url = gAgent.getRegion()->getCapability("AgentPreferences");
 
-	if (!url.empty())
-	{
-		LLSD update = LLSD::emptyMap();
-		update["hover_height"] = value;
-
-		LL_INFOS() << "updating hover height to " << value << LL_ENDL;
-		LLHTTPClient::post(url, update, new LLHoverHeightResponder);
-	}
-}
diff --git a/indra/newview/llfloaterhoverheight.h b/indra/newview/llfloaterhoverheight.h
index b81f293ae5..586871374f 100755
--- a/indra/newview/llfloaterhoverheight.h
+++ b/indra/newview/llfloaterhoverheight.h
@@ -39,7 +39,7 @@ public:
 
 	void onFinalCommit();
 
-	void sendHoverHeightUpdate();
+	static void syncFromPreferenceSetting(void *user_data);
 };
 
 #endif
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 9da7717b74..d5f9268a64 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2210,6 +2210,8 @@ bool idle_startup()
 		llassert(LLPathfindingManager::getInstance() != NULL);
 		LLPathfindingManager::getInstance()->initSystem();
 
+		gAgentAvatarp->sendHoverHeight();
+
 		return TRUE;
 	}
 
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index d150ace455..118ed10eb2 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -3219,6 +3219,10 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 		{
 			debug_line += llformat(" - cof rcv:%d", last_received_cof_version);
 		}
+		if (mHoverOffset[2] != 0.0)
+		{
+			debug_line += llformat(" hov_z: %f", mHoverOffset[2]);
+		}
 		addDebugText(debug_line);
 	}
 	if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked"))
@@ -3589,7 +3593,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 	else if (mDrawable.notNull())
 	{
 		LLVector3 pos = mDrawable->getPosition();
-		pos += mHoverOffset;
+		pos += mHoverOffset * mDrawable->getRotation();
 		mRoot->setPosition(pos);
 		mRoot->setRotation(mDrawable->getRotation());
 	}
@@ -7327,11 +7331,22 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		}
 	}
 
-	if (contents.mHoverOffsetWasSet)
+	if (contents.mHoverOffsetWasSet && !isSelf())
 	{
+		// Got an update for some other avatar.
+		// (Ignore updates for self because they may be out of date.)
 		mHoverOffset = contents.mHoverOffset;
 	}
 
+	if (!contents.mHoverOffsetWasSet)
+	{
+		// If we don't get a value at all, we are presumably in a
+		// region that does not support hover height.
+// FIXME RESTORE AFTER TESTING
+		LL_WARNS() << "zeroing hover because not defined in appearance message" << LL_ENDL;
+		mHoverOffset = 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/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index f4c6472f7a..a5379f24ba 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
 //-----------------------------------------------------------------------------
@@ -163,8 +182,6 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id,
 {
 	mMotionController.mIsSelf = TRUE;
 
-	mHoverOffset = gSavedSettings.getVector3("AvatarPosFinalOffset");
-
 	LL_DEBUGS() << "Marking avatar as self " << id << LL_ENDL;
 }
 
@@ -222,6 +239,8 @@ void LLVOAvatarSelf::initInstance()
 		return;
 	}
 
+	mHoverOffset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+
 	//doPeriodically(output_self_av_texture_diagnostics, 30.0);
 	doPeriodically(update_avatar_rez_metrics, 5.0);
 	doPeriodically(boost::bind(&LLVOAvatarSelf::checkStuckAppearance, this), 30.0);
@@ -2687,6 +2706,22 @@ 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();
+		update["hover_height"] = mHoverOffset[2];
+
+		LL_DEBUGS("Avatar") << "sending hover height value " << mHoverOffset[2] << LL_ENDL;
+		LLHTTPClient::post(url, update, new LLHoverHeightResponder);
+	}
+}
 
 //------------------------------------------------------------------------
 // needsRenderBeam()
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index e03de9fa0b..7b932abd44 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -328,6 +328,8 @@ public:
 public:
 	bool			sendAppearanceMessage(LLMessageSystem *mesgsys) const;
 
+	void			sendHoverHeight() const;
+
 /**                    Appearance
  **                                                                            **
  *******************************************************************************/
-- 
cgit v1.2.3


From cce5bb5dae98102f6fc1f95fe78c8e20260d3f2e Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 15 Dec 2014 17:03:34 -0500
Subject: SL-92 WIP - more debug line monitoring, changed AppearanceHover block
 to be optional.

---
 indra/newview/llvoavatar.cpp               | 15 +++++++++++++++
 indra/newview/llvoavatar.h                 |  1 +
 scripts/messages/message_template.msg      |  2 +-
 scripts/messages/message_template.msg.sha1 |  2 +-
 4 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 118ed10eb2..765220cdd4 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -776,6 +776,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	mRuthTimer.reset();
 	mRuthDebugTimer.reset();
 	mDebugExistenceTimer.reset();
+	mLastAppearanceMessageTimer.reset();
 	mPelvisOffset = LLVector3(0.0f,0.0f,0.0f);
 	mLastPelvisToFoot = 0.0f;
 	mPelvisFixup = 0.0f;
@@ -3223,6 +3224,13 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 		{
 			debug_line += llformat(" hov_z: %f", mHoverOffset[2]);
 		}
+		F32 elapsed = mLastAppearanceMessageTimer.getElapsedTimeF32();
+		static 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"))
@@ -7147,6 +7155,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		return;
 	}
 
+	mLastAppearanceMessageTimer.reset();
+
 	ESex old_sex = getSex();
 
 	LLAppearanceMessageContents contents;
@@ -7331,6 +7341,11 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		}
 	}
 
+	if (isSelf())
+	{
+		LL_INFOS("Avatar") << "hover was set: " << contents.mHoverOffsetWasSet << " value_z " << contents.mHoverOffset[2] << LL_ENDL;
+	}
+	
 	if (contents.mHoverOffsetWasSet && !isSelf())
 	{
 		// Got an update for some other avatar.
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 445f0ff921..8135c3d4d8 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -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
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index e0a80ee9cd..3cec4ada1c 100755
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -3595,7 +3595,7 @@ version 2.0
 		{	Flags				U32	}
 	}
 	{
-		AppearanceHover		Single
+		AppearanceHover		Variable
 		{	HoverHeight	LLVector3	}
 	}
 }
diff --git a/scripts/messages/message_template.msg.sha1 b/scripts/messages/message_template.msg.sha1
index affee31086..e699efb03c 100755
--- a/scripts/messages/message_template.msg.sha1
+++ b/scripts/messages/message_template.msg.sha1
@@ -1 +1 @@
-bc6a4d7f7fd9bfddefcef336c3e30b623497447f
\ No newline at end of file
+2286adc795b1b06eb86fdda431a71a6f0874b4f1
\ No newline at end of file
-- 
cgit v1.2.3


From 6539fe4a671ae73badc3aea6e00d497daafc7733 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 16 Dec 2014 09:14:18 -0500
Subject: SL-92 WIP - track appearance message timing

---
 indra/newview/llvoavatar.cpp               | 15 +++++++++++++++
 indra/newview/llvoavatar.h                 |  1 +
 scripts/messages/message_template.msg      |  2 +-
 scripts/messages/message_template.msg.sha1 |  2 +-
 4 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 118ed10eb2..765220cdd4 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -776,6 +776,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	mRuthTimer.reset();
 	mRuthDebugTimer.reset();
 	mDebugExistenceTimer.reset();
+	mLastAppearanceMessageTimer.reset();
 	mPelvisOffset = LLVector3(0.0f,0.0f,0.0f);
 	mLastPelvisToFoot = 0.0f;
 	mPelvisFixup = 0.0f;
@@ -3223,6 +3224,13 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 		{
 			debug_line += llformat(" hov_z: %f", mHoverOffset[2]);
 		}
+		F32 elapsed = mLastAppearanceMessageTimer.getElapsedTimeF32();
+		static 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"))
@@ -7147,6 +7155,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		return;
 	}
 
+	mLastAppearanceMessageTimer.reset();
+
 	ESex old_sex = getSex();
 
 	LLAppearanceMessageContents contents;
@@ -7331,6 +7341,11 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		}
 	}
 
+	if (isSelf())
+	{
+		LL_INFOS("Avatar") << "hover was set: " << contents.mHoverOffsetWasSet << " value_z " << contents.mHoverOffset[2] << LL_ENDL;
+	}
+	
 	if (contents.mHoverOffsetWasSet && !isSelf())
 	{
 		// Got an update for some other avatar.
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 445f0ff921..8135c3d4d8 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -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
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index e0a80ee9cd..3cec4ada1c 100755
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -3595,7 +3595,7 @@ version 2.0
 		{	Flags				U32	}
 	}
 	{
-		AppearanceHover		Single
+		AppearanceHover		Variable
 		{	HoverHeight	LLVector3	}
 	}
 }
diff --git a/scripts/messages/message_template.msg.sha1 b/scripts/messages/message_template.msg.sha1
index affee31086..e699efb03c 100755
--- a/scripts/messages/message_template.msg.sha1
+++ b/scripts/messages/message_template.msg.sha1
@@ -1 +1 @@
-bc6a4d7f7fd9bfddefcef336c3e30b623497447f
\ No newline at end of file
+2286adc795b1b06eb86fdda431a71a6f0874b4f1
\ No newline at end of file
-- 
cgit v1.2.3


From 211c18d3b7de319570bb3be7f3607654d7ec98ac Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 16 Dec 2014 10:47:58 -0500
Subject: linux build fix

---
 indra/newview/app_settings/logcontrol.xml | 1 +
 indra/newview/llvoavatar.cpp              | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index de3732f339..6a798e1d42 100755
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -42,6 +42,7 @@
 						</array>
 					<key>tags</key>
 						<array>
+						     <string>Avatar</string>
 						<!-- sample entry for debugging specific items	
 						     <string>Avatar</string>
 						     <string>Inventory</string>
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 765220cdd4..25c7120a19 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -3225,7 +3225,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 			debug_line += llformat(" hov_z: %f", mHoverOffset[2]);
 		}
 		F32 elapsed = mLastAppearanceMessageTimer.getElapsedTimeF32();
-		static char *elapsed_chars = "Xx*...";
+		static const char *elapsed_chars = "Xx*...";
 		U32 bucket = U32(elapsed*2);
 		if (bucket < strlen(elapsed_chars))
 		{
-- 
cgit v1.2.3


From 553b7ede723ceed310f1dbbfba25f5bf555466e1 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 22 Dec 2014 11:14:15 -0500
Subject: Moved AvatarPosFinalOffset to per-account settings file

---
 indra/llcharacter/lljoint.cpp                       |  2 +-
 indra/newview/app_settings/settings.xml             | 15 ---------------
 indra/newview/app_settings/settings_per_account.xml | 15 +++++++++++++++
 indra/newview/llfloaterhoverheight.cpp              | 15 +++++++++++----
 indra/newview/llvoavatar.cpp                        |  4 ++--
 indra/newview/llvoavatarself.cpp                    |  5 +++--
 6 files changed, 32 insertions(+), 24 deletions(-)

diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index 6f22a7c6b7..40695bfa24 100755
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -290,7 +290,7 @@ const LLVector3& LLJoint::getPosition()
 
 bool do_debug_joint(const std::string& name)
 {
-	return true;
+	return false;
 }
 
 //--------------------------------------------------------------------
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 138bdde9e9..94d3c8a59f 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -654,21 +654,6 @@
       <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..7975fe9e3a 100755
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -1,5 +1,20 @@
 <llsd>
     <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>DoNotDisturbResponseChanged</key>
         <map>
         <key>Comment</key>
diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
index bcdab6b3a0..a858b891a9 100755
--- a/indra/newview/llfloaterhoverheight.cpp
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -42,7 +42,7 @@ LLFloaterHoverHeight::LLFloaterHoverHeight(const LLSD& key) : LLFloater(key)
 
 void LLFloaterHoverHeight::syncFromPreferenceSetting(void *user_data)
 {
-	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+	LLVector3 offset = gSavedPerAccountSettings.getVector3("AvatarPosFinalOffset");
 	F32 value = offset[2];
 
 	LLFloaterHoverHeight *self = static_cast<LLFloaterHoverHeight*>(user_data);
@@ -64,7 +64,14 @@ BOOL LLFloaterHoverHeight::postBuild()
 	// Initialize slider from pref setting.
 	syncFromPreferenceSetting(this);
 	// Update slider on future pref changes.
-	gSavedSettings.getControl("AvatarPosFinalOffset")->getCommitSignal()->connect(boost::bind(&syncFromPreferenceSetting, this));
+	if (gSavedPerAccountSettings.getControl("AvatarPosFinalOffset"))
+	{
+		gSavedPerAccountSettings.getControl("AvatarPosFinalOffset")->getCommitSignal()->connect(boost::bind(&syncFromPreferenceSetting, this));
+	}
+	else
+	{
+		LL_WARNS() << "Control not found for AvatarPosFinalOffset" << LL_ENDL;
+	}
 
 	return TRUE;
 }
@@ -85,9 +92,9 @@ void LLFloaterHoverHeight::onFinalCommit()
 {
 	LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
 	F32 value = sldrCtrl->getValueF32();
-	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+	LLVector3 offset = gSavedPerAccountSettings.getVector3("AvatarPosFinalOffset");
 	offset[2] = value;
-	gSavedSettings.setVector3("AvatarPosFinalOffset",offset);
+	gSavedPerAccountSettings.setVector3("AvatarPosFinalOffset",offset);
 }
 
 
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index da0e72a6ee..a6d006f13b 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -7457,7 +7457,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 
 	if (isSelf())
 	{
-		LL_INFOS("Avatar") << "hover was set: " << contents.mHoverOffsetWasSet << " value_z " << contents.mHoverOffset[2] << LL_ENDL;
+		LL_INFOS("Avatar") << avString() << "hover was set: " << contents.mHoverOffsetWasSet << " value_z " << contents.mHoverOffset[2] << LL_ENDL;
 	}
 	
 	if (contents.mHoverOffsetWasSet && !isSelf())
@@ -7471,7 +7471,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 	{
 		// If we don't get a value at all, we are presumably in a
 		// region that does not support hover height.
-// FIXME RESTORE AFTER TESTING
+
 		LL_WARNS() << "zeroing hover because not defined in appearance message" << LL_ENDL;
 		mHoverOffset = LLVector3(0.0, 0.0, 0.0);
 	}
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 3d82a6dab6..6e0c9cb68c 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -239,7 +239,8 @@ void LLVOAvatarSelf::initInstance()
 		return;
 	}
 
-	mHoverOffset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+	mHoverOffset = gSavedPerAccountSettings.getVector3("AvatarPosFinalOffset");
+	LL_INFOS("Avatar") << avString() << " set hover height from debug setting " << mHoverOffset[2] << LL_ENDL;
 
 	//doPeriodically(output_self_av_texture_diagnostics, 30.0);
 	doPeriodically(update_avatar_rez_metrics, 5.0);
@@ -2734,7 +2735,7 @@ void LLVOAvatarSelf::sendHoverHeight() const
 		LLSD update = LLSD::emptyMap();
 		update["hover_height"] = mHoverOffset[2];
 
-		LL_DEBUGS("Avatar") << "sending hover height value " << mHoverOffset[2] << LL_ENDL;
+		LL_DEBUGS("Avatar") << avString() << "sending hover height value " << mHoverOffset[2] << LL_ENDL;
 		LLHTTPClient::post(url, update, new LLHoverHeightResponder);
 	}
 }
-- 
cgit v1.2.3


From 79a89f5d921f99ba7a990a1dbf7428d1d3758bc6 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 22 Dec 2014 11:18:58 -0500
Subject: SL-92 WIP - moving AvatarPosFinalOffset to per-account settings

---
 indra/newview/llfloaterhoverheight.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
index a858b891a9..9efb168b55 100755
--- a/indra/newview/llfloaterhoverheight.cpp
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -81,7 +81,7 @@ void LLFloaterHoverHeight::onSliderMoved(LLUICtrl* ctrl, void* userData)
 {
 	LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
 	F32 value = sldrCtrl->getValueF32();
-	LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset");
+	LLVector3 offset = gSavedPerAccountSettings.getVector3("AvatarPosFinalOffset");
 	offset[2] = value;
 	gAgentAvatarp->mHoverOffset = offset;
 }
-- 
cgit v1.2.3


From 57363fdfd6921394be42000869e2d711e7212ea4 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 5 Jan 2015 14:13:19 -0500
Subject: SL-92 WIP - More consistent enforcement of min/max hover values.
 Setting is stored as a per-account F32 value.

---
 indra/newview/app_settings/settings_per_account.xml       |  6 +-----
 indra/newview/llfloaterhoverheight.cpp                    | 15 ++++++++-------
 indra/newview/llvoavatar.cpp                              |  3 +++
 indra/newview/llvoavatar.h                                |  3 +++
 indra/newview/llvoavatarself.cpp                          |  3 ++-
 .../skins/default/xui/en/floater_edit_hover_height.xml    |  2 --
 6 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index 7975fe9e3a..97d81153a7 100755
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -7,13 +7,9 @@
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
-      <string>Vector3</string>
+      <string>F32</string>
       <key>Value</key>
-      <array>
         <real>0.0</real>
-        <real>0.0</real>
-        <real>0.0</real>
-      </array>
     </map>
     <key>DoNotDisturbResponseChanged</key>
         <map>
diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
index 9efb168b55..dc8a3d6fb8 100755
--- a/indra/newview/llfloaterhoverheight.cpp
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -42,12 +42,14 @@ LLFloaterHoverHeight::LLFloaterHoverHeight(const LLSD& key) : LLFloater(key)
 
 void LLFloaterHoverHeight::syncFromPreferenceSetting(void *user_data)
 {
-	LLVector3 offset = gSavedPerAccountSettings.getVector3("AvatarPosFinalOffset");
-	F32 value = offset[2];
+	F32 value = gSavedPerAccountSettings.getF32("AvatarPosFinalOffset");
 
 	LLFloaterHoverHeight *self = static_cast<LLFloaterHoverHeight*>(user_data);
 	LLSliderCtrl* sldrCtrl = self->getChild<LLSliderCtrl>("HoverHeightSlider");
 	sldrCtrl->setValue(value,FALSE);
+
+	//value = sldrCtrl->getValueF32();
+	//gAgentAvatarp->mHoverOffset = LLVector3(0.0, 0.0, value);
 	if (isAgentAvatarValid())
 	{
 		gAgentAvatarp->sendHoverHeight();
@@ -57,6 +59,8 @@ void LLFloaterHoverHeight::syncFromPreferenceSetting(void *user_data)
 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);
@@ -81,8 +85,7 @@ void LLFloaterHoverHeight::onSliderMoved(LLUICtrl* ctrl, void* userData)
 {
 	LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
 	F32 value = sldrCtrl->getValueF32();
-	LLVector3 offset = gSavedPerAccountSettings.getVector3("AvatarPosFinalOffset");
-	offset[2] = value;
+	LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z));
 	gAgentAvatarp->mHoverOffset = offset;
 }
 
@@ -92,9 +95,7 @@ void LLFloaterHoverHeight::onFinalCommit()
 {
 	LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
 	F32 value = sldrCtrl->getValueF32();
-	LLVector3 offset = gSavedPerAccountSettings.getVector3("AvatarPosFinalOffset");
-	offset[2] = value;
-	gSavedPerAccountSettings.setVector3("AvatarPosFinalOffset",offset);
+	gSavedPerAccountSettings.setF32("AvatarPosFinalOffset",value);
 }
 
 
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index a6d006f13b..fd741e7e5f 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;
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index a3f599e2d7..a12e688087 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -1021,6 +1021,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 6e0c9cb68c..1b5901e581 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -239,7 +239,8 @@ void LLVOAvatarSelf::initInstance()
 		return;
 	}
 
-	mHoverOffset = gSavedPerAccountSettings.getVector3("AvatarPosFinalOffset");
+	F32 hover_z = gSavedPerAccountSettings.getF32("AvatarPosFinalOffset");
+	mHoverOffset = LLVector3(0.0, 0.0, llclamp(hover_z,MIN_HOVER_Z,MAX_HOVER_Z));
 	LL_INFOS("Avatar") << avString() << " set hover height from debug setting " << mHoverOffset[2] << LL_ENDL;
 
 	//doPeriodically(output_self_av_texture_diagnostics, 30.0);
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
index 29d06b9b4e..8fc20d28fb 100755
--- a/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
+++ b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
@@ -23,8 +23,6 @@
      follows="top|left"
      height="15"
      increment="0.001"
-     max_val="2"
-     min_val="-2"
      initial_value="0.0"
      label="Height"
      label_width="60"
-- 
cgit v1.2.3


From 62ab044b1ac9f757be40f951436ff11419feffb4 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 5 Jan 2015 15:34:40 -0500
Subject: SL-92 WIP - changed setting name to AvatarHoverOffsetZ

---
 indra/newview/app_settings/settings_per_account.xml |  4 ++--
 indra/newview/llfloaterhoverheight.cpp              | 14 +++++++-------
 indra/newview/llvoavatar.cpp                        |  4 ++--
 indra/newview/llvoavatarself.cpp                    |  2 +-
 4 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index 97d81153a7..d119504017 100755
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -1,9 +1,9 @@
 <llsd>
     <map>
-    <key>AvatarPosFinalOffset</key>
+    <key>AvatarHoverOffsetZ</key>
     <map>
       <key>Comment</key>
-      <string>After-everything-else fixup for avatar position.</string>
+      <string>After-everything-else fixup for avatar Z position.</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
index dc8a3d6fb8..2ac61efc0c 100755
--- a/indra/newview/llfloaterhoverheight.cpp
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -42,16 +42,16 @@ LLFloaterHoverHeight::LLFloaterHoverHeight(const LLSD& key) : LLFloater(key)
 
 void LLFloaterHoverHeight::syncFromPreferenceSetting(void *user_data)
 {
-	F32 value = gSavedPerAccountSettings.getF32("AvatarPosFinalOffset");
+	F32 value = gSavedPerAccountSettings.getF32("AvatarHoverOffsetZ");
 
 	LLFloaterHoverHeight *self = static_cast<LLFloaterHoverHeight*>(user_data);
 	LLSliderCtrl* sldrCtrl = self->getChild<LLSliderCtrl>("HoverHeightSlider");
 	sldrCtrl->setValue(value,FALSE);
 
-	//value = sldrCtrl->getValueF32();
-	//gAgentAvatarp->mHoverOffset = LLVector3(0.0, 0.0, value);
 	if (isAgentAvatarValid())
 	{
+		LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z));
+		gAgentAvatarp->mHoverOffset = offset;
 		gAgentAvatarp->sendHoverHeight();
 	}
 }
@@ -68,13 +68,13 @@ BOOL LLFloaterHoverHeight::postBuild()
 	// Initialize slider from pref setting.
 	syncFromPreferenceSetting(this);
 	// Update slider on future pref changes.
-	if (gSavedPerAccountSettings.getControl("AvatarPosFinalOffset"))
+	if (gSavedPerAccountSettings.getControl("AvatarHoverOffsetZ"))
 	{
-		gSavedPerAccountSettings.getControl("AvatarPosFinalOffset")->getCommitSignal()->connect(boost::bind(&syncFromPreferenceSetting, this));
+		gSavedPerAccountSettings.getControl("AvatarHoverOffsetZ")->getCommitSignal()->connect(boost::bind(&syncFromPreferenceSetting, this));
 	}
 	else
 	{
-		LL_WARNS() << "Control not found for AvatarPosFinalOffset" << LL_ENDL;
+		LL_WARNS() << "Control not found for AvatarHoverOffsetZ" << LL_ENDL;
 	}
 
 	return TRUE;
@@ -95,7 +95,7 @@ void LLFloaterHoverHeight::onFinalCommit()
 {
 	LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider");
 	F32 value = sldrCtrl->getValueF32();
-	gSavedPerAccountSettings.setF32("AvatarPosFinalOffset",value);
+	gSavedPerAccountSettings.setF32("AvatarHoverOffsetZ",value);
 }
 
 
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index fd741e7e5f..6669a797ce 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -7470,12 +7470,12 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		mHoverOffset = contents.mHoverOffset;
 	}
 
-	if (!contents.mHoverOffsetWasSet)
+	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() << "zeroing hover because not defined in appearance message" << LL_ENDL;
+		LL_WARNS() << avString() << "zeroing hover because not defined in appearance message" << LL_ENDL;
 		mHoverOffset = LLVector3(0.0, 0.0, 0.0);
 	}
 
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 1b5901e581..ed560b1c30 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -239,7 +239,7 @@ void LLVOAvatarSelf::initInstance()
 		return;
 	}
 
-	F32 hover_z = gSavedPerAccountSettings.getF32("AvatarPosFinalOffset");
+	F32 hover_z = gSavedPerAccountSettings.getF32("AvatarHoverOffsetZ");
 	mHoverOffset = LLVector3(0.0, 0.0, llclamp(hover_z,MIN_HOVER_Z,MAX_HOVER_Z));
 	LL_INFOS("Avatar") << avString() << " set hover height from debug setting " << mHoverOffset[2] << LL_ENDL;
 
-- 
cgit v1.2.3


From 07812106ed54d834a2cf0be28f312bbf0ad34a1d Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 5 Jan 2015 18:13:33 -0500
Subject: Moved mHoverOffset to LLCharacter so it's accessible inside
 animations. Apply offset when constrained to ground.

---
 indra/llcharacter/llcharacter.h        | 2 ++
 indra/llcharacter/llkeyframemotion.cpp | 1 +
 indra/newview/llvoavatar.cpp           | 6 +++---
 indra/newview/llvoavatar.h             | 2 --
 4 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h
index d4e3b76386..085b681854 100755
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -261,6 +261,8 @@ public:
 	static std::vector< LLCharacter* > sInstances;
 	static BOOL sAllowInstancesChange ; //debug use
 
+	LLVector3 mHoverOffset;
+
 protected:
 	LLMotionController	mMotionController;
 
diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp
index 22aa4f1d2f..89bec40323 100755
--- a/indra/llcharacter/llkeyframemotion.cpp
+++ b/indra/llcharacter/llkeyframemotion.cpp
@@ -984,6 +984,7 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
 	{
 	case CONSTRAINT_TARGET_TYPE_GROUND:
 		target_pos = mCharacter->getPosAgentFromGlobal(constraint->mGroundPos);
+		target_pos += mCharacter->mHoverOffset;
 //		LL_INFOS() << "Target Pos " << constraint->mGroundPos << " on " << mCharacter->findCollisionVolume(shared_data->mSourceConstraintVolume)->getName() << LL_ENDL;
 		break;
 	case CONSTRAINT_TARGET_TYPE_BODY:
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 6669a797ce..cbfda020b4 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -721,11 +721,11 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	mIsEditingAppearance(FALSE),
 	mUseLocalAppearance(FALSE),
 	mLastUpdateRequestCOFVersion(-1),
-	mLastUpdateReceivedCOFVersion(-1),
-	mHoverOffset(0.0, 0.0, 0.0)
+	mLastUpdateReceivedCOFVersion(-1)
+	//mHoverOffset(0.0, 0.0, 0.0)
 {
 	//VTResume();  // VTune
-	
+	mHoverOffset = 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 );
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index a12e688087..0daf679e8e 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -213,8 +213,6 @@ public:
 	/*virtual*/ LLVector3		getPosAgentFromGlobal(const LLVector3d &position);
 	virtual void				updateVisualParams();
 
-	LLVector3 mHoverOffset;
-
 /**                    Inherited
  **                                                                            **
  *******************************************************************************/
-- 
cgit v1.2.3


From ee63c30ea748857f68ac352a9751816644322ec3 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 8 Jan 2015 10:35:36 -0500
Subject: SL-92 WIP - remove hover for self if we receive an appearance with no
 hover specified

---
 indra/newview/llvoavatar.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index aa7b848d0e..059a03a072 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -7470,7 +7470,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		mHoverOffset = contents.mHoverOffset;
 	}
 
-	if (!contents.mHoverOffsetWasSet && !isSelf())
+	if (!contents.mHoverOffsetWasSet)
 	{
 		// If we don't get a value at all, we are presumably in a
 		// region that does not support hover height.
-- 
cgit v1.2.3


From d5ab47b1bc9eac98c1f443fa965a91a8f2cf0af7 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 13 Jan 2015 17:18:15 -0500
Subject: SL-92 WIP - added signal for simulator features received. Use to keep
 hover floater UI synced with region support for hover.

---
 indra/newview/llfloaterhoverheight.cpp             | 40 ++++++++++++++++++++++
 indra/newview/llfloaterhoverheight.h               |  7 ++++
 indra/newview/llviewermenu.cpp                     |  2 +-
 indra/newview/llviewerregion.cpp                   | 30 ++++++++++++++++
 indra/newview/llviewerregion.h                     | 12 ++++++-
 indra/newview/llvoavatar.cpp                       |  2 ++
 .../default/xui/en/floater_edit_hover_height.xml   |  1 +
 7 files changed, 92 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
index 2ac61efc0c..69b58b3af5 100755
--- a/indra/newview/llfloaterhoverheight.cpp
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -77,6 +77,13 @@ BOOL LLFloaterHoverHeight::postBuild()
 		LL_WARNS() << "Control not found for AvatarHoverOffsetZ" << LL_ENDL;
 	}
 
+	updateEditEnabled();
+
+	if (!mRegionBoundarySlot.connected())
+	{
+		mRegionBoundarySlot = gAgent.addRegionChangedCallback(boost::bind(&LLFloaterHoverHeight::onRegionChanged,this));
+	}
+
 	return TRUE;
 }
 
@@ -98,4 +105,37 @@ void LLFloaterHoverHeight::onFinalCommit()
 	gSavedPerAccountSettings.setF32("AvatarHoverOffsetZ",value);
 }
 
+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
index 586871374f..8fd24d8813 100755
--- a/indra/newview/llfloaterhoverheight.h
+++ b/indra/newview/llfloaterhoverheight.h
@@ -40,6 +40,13 @@ public:
 	void onFinalCommit();
 
 	static void syncFromPreferenceSetting(void *user_data);
+
+	void onRegionChanged();
+	void onSimulatorFeaturesReceived(const LLUUID &region_id);
+	void updateEditEnabled();
+
+
+	boost::signals2::connection                   mRegionBoundarySlot;
 };
 
 #endif
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 302dd6f889..c7bf8a1c31 100755
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -3885,7 +3885,7 @@ class LLEnableHoverHeight : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
 	{
-		return true;
+		return gAgent.getRegion() && gAgent.getRegion()->avatarHoverHeightEnabled();
 	}
 };
 
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 11cbf3fc24..b05e771f96 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -424,6 +424,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
 	mCacheDirty(FALSE),
 	mReleaseNotesRequested(FALSE),
 	mCapabilitiesReceived(false),
+	mSimulatorFeaturesReceived(false),
 	mBitsReceived(0.f),
 	mPacketsReceived(0.f),
 	mDead(FALSE),
@@ -2027,6 +2028,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;
@@ -2040,6 +2061,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.
@@ -3088,6 +3112,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 1e225553b8..aaa1466939 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 059a03a072..10bc6ad336 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -3220,6 +3220,8 @@ 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";
 		if (mHoverOffset[2] != 0.0)
 		{
 			debug_line += llformat(" hov_z: %f", mHoverOffset[2]);
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
index 8fc20d28fb..8ec6735a01 100755
--- a/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
+++ b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
@@ -18,6 +18,7 @@
  title="SET HOVER HEIGHT"
  width="515">
       <slider
+     enabled="false"
      control_name="HoverHeightSlider"
      decimal_digits="3"
      follows="top|left"
-- 
cgit v1.2.3


From be83e48fc12fbaf225f9f3e6ad5042320595ce26 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 14 Jan 2015 17:40:44 -0500
Subject: SL-92 WIP - more on region notification and managing hover

---
 indra/newview/llfloaterhoverheight.cpp |  6 +++--
 indra/newview/llfloaterhoverheight.h   |  2 +-
 indra/newview/llvoavatar.cpp           | 13 +++------
 indra/newview/llvoavatarself.cpp       | 48 +++++++++++++++++++++++++++++++---
 indra/newview/llvoavatarself.h         |  5 ++++
 5 files changed, 59 insertions(+), 15 deletions(-)

diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
index 69b58b3af5..7d0c011b74 100755
--- a/indra/newview/llfloaterhoverheight.cpp
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -52,6 +52,7 @@ void LLFloaterHoverHeight::syncFromPreferenceSetting(void *user_data)
 	{
 		LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z));
 		gAgentAvatarp->mHoverOffset = offset;
+		LL_INFOS("Avatar") << "set hover from preference setting" << offset[2] << LL_ENDL;
 		gAgentAvatarp->sendHoverHeight();
 	}
 }
@@ -79,9 +80,9 @@ BOOL LLFloaterHoverHeight::postBuild()
 
 	updateEditEnabled();
 
-	if (!mRegionBoundarySlot.connected())
+	if (!mRegionChangedSlot.connected())
 	{
-		mRegionBoundarySlot = gAgent.addRegionChangedCallback(boost::bind(&LLFloaterHoverHeight::onRegionChanged,this));
+		mRegionChangedSlot = gAgent.addRegionChangedCallback(boost::bind(&LLFloaterHoverHeight::onRegionChanged,this));
 	}
 
 	return TRUE;
@@ -93,6 +94,7 @@ 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") << "set hover from slider moved" << offset[2] << LL_ENDL;
 	gAgentAvatarp->mHoverOffset = offset;
 }
 
diff --git a/indra/newview/llfloaterhoverheight.h b/indra/newview/llfloaterhoverheight.h
index 8fd24d8813..8809fc1bf8 100755
--- a/indra/newview/llfloaterhoverheight.h
+++ b/indra/newview/llfloaterhoverheight.h
@@ -46,7 +46,7 @@ public:
 	void updateEditEnabled();
 
 
-	boost::signals2::connection                   mRegionBoundarySlot;
+	boost::signals2::connection                   mRegionChangedSlot;
 };
 
 #endif
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 10bc6ad336..b5bf174045 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -722,7 +722,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	mUseLocalAppearance(FALSE),
 	mLastUpdateRequestCOFVersion(-1),
 	mLastUpdateReceivedCOFVersion(-1)
-	//mHoverOffset(0.0, 0.0, 0.0)
 {
 	//VTResume();  // VTune
 	mHoverOffset = LLVector3(0.0, 0.0, 0.0);
@@ -7460,19 +7459,15 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		}
 	}
 
-	if (isSelf())
-	{
-		LL_INFOS("Avatar") << avString() << "hover was set: " << contents.mHoverOffsetWasSet << " value_z " << contents.mHoverOffset[2] << LL_ENDL;
-	}
-	
 	if (contents.mHoverOffsetWasSet && !isSelf())
 	{
-		// Got an update for some other avatar.
-		// (Ignore updates for self because they may be out of date.)
+		// Got an update for some other avatar
+		// Ignore updates for self, because we have a more authoritative value in the preferences.
 		mHoverOffset = contents.mHoverOffset;
+		LL_INFOS("Avatar") << avString() << "setting hover from message" << mHoverOffset[2] << LL_ENDL;
 	}
 
-	if (!contents.mHoverOffsetWasSet)
+	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.
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index ed560b1c30..5341c6f1c8 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -239,15 +239,40 @@ void LLVOAvatarSelf::initInstance()
 		return;
 	}
 
-	F32 hover_z = gSavedPerAccountSettings.getF32("AvatarHoverOffsetZ");
-	mHoverOffset = LLVector3(0.0, 0.0, llclamp(hover_z,MIN_HOVER_Z,MAX_HOVER_Z));
-	LL_INFOS("Avatar") << avString() << " set hover height from debug setting " << mHoverOffset[2] << LL_ENDL;
+	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");
+			mHoverOffset = LLVector3(0.0, 0.0, llclamp(hover_z,MIN_HOVER_Z,MAX_HOVER_Z));
+			LL_INFOS("Avatar") << avString() << " set hover height from debug setting " << mHoverOffset[2] << LL_ENDL;
+		}
+		else 
+		{
+			mHoverOffset = 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;
@@ -850,6 +875,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)
 {
@@ -868,6 +899,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))
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index a47b6c3463..6e585520da 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);
 
@@ -327,6 +330,8 @@ public:
 public:
 	bool			sendAppearanceMessage(LLMessageSystem *mesgsys) const;
 
+	// -- care and feeding of hover height.
+	void 			setHoverIfRegionEnabled();
 	void			sendHoverHeight() const;
 
 /**                    Appearance
-- 
cgit v1.2.3


From d2de97ad8e84eedd42f4a0fe5b258617a96f154b Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 15 Jan 2015 16:45:24 -0500
Subject: SL-92 WIP - more on hover management

---
 indra/llcharacter/llcharacter.h        |  6 ++++--
 indra/llcharacter/llkeyframemotion.cpp |  2 +-
 indra/newview/llfloaterhoverheight.cpp | 24 +++++++++++++++++++-----
 indra/newview/llfloaterhoverheight.h   |  4 ++--
 indra/newview/llvoavatar.cpp           | 18 ++++++++++--------
 indra/newview/llvoavatarself.cpp       | 32 ++++++++++++++++++++++++++------
 indra/newview/llvoavatarself.h         |  4 ++++
 7 files changed, 66 insertions(+), 24 deletions(-)

diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h
index 085b681854..1a3e307663 100755
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -261,7 +261,8 @@ public:
 	static std::vector< LLCharacter* > sInstances;
 	static BOOL sAllowInstancesChange ; //debug use
 
-	LLVector3 mHoverOffset;
+	virtual void	setHoverOffset(const LLVector3& hover_offset, bool send_update=true) { mHoverOffset = hover_offset; }
+	const LLVector3& getHoverOffset() const { return mHoverOffset; }
 
 protected:
 	LLMotionController	mMotionController;
@@ -275,7 +276,6 @@ protected:
 	U32					mSkeletonSerialNum;
 	LLAnimPauseRequest	mPauseRequest;
 
-
 private:
 	// visual parameter stuff
 	typedef std::map<S32, LLVisualParam *> 		visual_param_index_map_t;
@@ -286,6 +286,8 @@ private:
 	visual_param_name_map_t  					mVisualParamNameMap;
 
 	static LLStringTable sVisualParamNames;	
+
+	LLVector3 mHoverOffset;
 };
 
 #endif // LL_LLCHARACTER_H
diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp
index 89bec40323..5317e230c8 100755
--- a/indra/llcharacter/llkeyframemotion.cpp
+++ b/indra/llcharacter/llkeyframemotion.cpp
@@ -984,7 +984,7 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
 	{
 	case CONSTRAINT_TARGET_TYPE_GROUND:
 		target_pos = mCharacter->getPosAgentFromGlobal(constraint->mGroundPos);
-		target_pos += mCharacter->mHoverOffset;
+		target_pos += mCharacter->getHoverOffset();
 //		LL_INFOS() << "Target Pos " << constraint->mGroundPos << " on " << mCharacter->findCollisionVolume(shared_data->mSourceConstraintVolume)->getName() << LL_ENDL;
 		break;
 	case CONSTRAINT_TARGET_TYPE_BODY:
diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
index 7d0c011b74..8908626de6 100755
--- a/indra/newview/llfloaterhoverheight.cpp
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -51,9 +51,9 @@ void LLFloaterHoverHeight::syncFromPreferenceSetting(void *user_data)
 	if (isAgentAvatarValid())
 	{
 		LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z));
-		gAgentAvatarp->mHoverOffset = offset;
-		LL_INFOS("Avatar") << "set hover from preference setting" << offset[2] << LL_ENDL;
-		gAgentAvatarp->sendHoverHeight();
+		LL_INFOS("Avatar") << "setting hover from preference setting " << offset[2] << LL_ENDL;
+		gAgentAvatarp->setHoverOffset(offset);
+		//gAgentAvatarp->sendHoverHeight();
 	}
 }
 
@@ -84,18 +84,28 @@ BOOL LLFloaterHoverHeight::postBuild()
 	{
 		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") << "set hover from slider moved" << offset[2] << LL_ENDL;
-	gAgentAvatarp->mHoverOffset = offset;
+	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
@@ -105,6 +115,10 @@ 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()
diff --git a/indra/newview/llfloaterhoverheight.h b/indra/newview/llfloaterhoverheight.h
index 8809fc1bf8..ee065bc184 100755
--- a/indra/newview/llfloaterhoverheight.h
+++ b/indra/newview/llfloaterhoverheight.h
@@ -45,8 +45,8 @@ public:
 	void onSimulatorFeaturesReceived(const LLUUID &region_id);
 	void updateEditEnabled();
 
-
-	boost::signals2::connection                   mRegionChangedSlot;
+	/*virtual*/ void onClose(bool app_quitting);
+	boost::signals2::connection mRegionChangedSlot;
 };
 
 #endif
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index b5bf174045..38420a31bc 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -724,7 +724,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	mLastUpdateReceivedCOFVersion(-1)
 {
 	//VTResume();  // VTune
-	mHoverOffset = LLVector3(0.0, 0.0, 0.0);
+	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 );
@@ -3221,9 +3222,10 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 		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";
-		if (mHoverOffset[2] != 0.0)
+		const LLVector3& hover_offset = getHoverOffset();
+		if (hover_offset[2] != 0.0)
 		{
-			debug_line += llformat(" hov_z: %f", mHoverOffset[2]);
+			debug_line += llformat(" hov_z: %f", hover_offset[2]);
 		}
 		F32 elapsed = mLastAppearanceMessageTimer.getElapsedTimeF32();
 		static const char *elapsed_chars = "Xx*...";
@@ -3432,7 +3434,7 @@ 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;
-		root_pos += LLVector3d(mHoverOffset);
+		root_pos += LLVector3d(getHoverOffset());
 		
 		LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos);
 
@@ -3602,7 +3604,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 	else if (mDrawable.notNull())
 	{
 		LLVector3 pos = mDrawable->getPosition();
-		pos += mHoverOffset * mDrawable->getRotation();
+		pos += getHoverOffset() * mDrawable->getRotation();
 		mRoot->setPosition(pos);
 		mRoot->setRotation(mDrawable->getRotation());
 	}
@@ -7463,8 +7465,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 	{
 		// Got an update for some other avatar
 		// Ignore updates for self, because we have a more authoritative value in the preferences.
-		mHoverOffset = contents.mHoverOffset;
-		LL_INFOS("Avatar") << avString() << "setting hover from message" << mHoverOffset[2] << LL_ENDL;
+		setHoverOffset(contents.mHoverOffset);
+		LL_INFOS("Avatar") << avString() << "setting hover from message" << contents.mHoverOffset[2] << LL_ENDL;
 	}
 
 	if (!contents.mHoverOffsetWasSet && !isSelf())
@@ -7472,7 +7474,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 		// 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;
-		mHoverOffset = LLVector3(0.0, 0.0, 0.0);
+		setHoverOffset(LLVector3(0.0, 0.0, 0.0));
 	}
 
 	setCompositeUpdatesEnabled( TRUE );
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 5341c6f1c8..bd7ab41258 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -178,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;
 
@@ -253,12 +256,12 @@ void LLVOAvatarSelf::setHoverIfRegionEnabled()
 		if (getRegion()->avatarHoverHeightEnabled())
 		{
 			F32 hover_z = gSavedPerAccountSettings.getF32("AvatarHoverOffsetZ");
-			mHoverOffset = LLVector3(0.0, 0.0, llclamp(hover_z,MIN_HOVER_Z,MAX_HOVER_Z));
-			LL_INFOS("Avatar") << avString() << " set hover height from debug setting " << mHoverOffset[2] << LL_ENDL;
+			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 
 		{
-			mHoverOffset = LLVector3(0.0, 0.0, 0.0);
+			setHoverOffset(LLVector3(0.0, 0.0, 0.0));
 			LL_INFOS("Avatar") << avString() << " zeroing hover height, region does not support" << LL_ENDL;
 		}
 	}
@@ -2776,10 +2779,27 @@ void LLVOAvatarSelf::sendHoverHeight() const
 	if (!url.empty())
 	{
 		LLSD update = LLSD::emptyMap();
-		update["hover_height"] = mHoverOffset[2];
+		const LLVector3& hover_offset = getHoverOffset();
+		update["hover_height"] = hover_offset[2];
 
-		LL_DEBUGS("Avatar") << avString() << "sending hover height value " << mHoverOffset[2] << LL_ENDL;
+		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();
 	}
 }
 
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 6e585520da..6d190b5cfe 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -333,6 +333,10 @@ public:
 	// -- 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
  **                                                                            **
-- 
cgit v1.2.3


From 1c496b21b286f131652150eed4d13870127bd001 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 4 Mar 2015 14:29:41 -0500
Subject: MAINT-4858 FIX

---
 indra/llcharacter/llkeyframemotion.cpp |  1 -
 indra/newview/llvoavatar.cpp           | 73 ++++++++++++++++++++++++----------
 indra/newview/llvoavatar.h             |  1 +
 3 files changed, 53 insertions(+), 22 deletions(-)

diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp
index 5317e230c8..22aa4f1d2f 100755
--- a/indra/llcharacter/llkeyframemotion.cpp
+++ b/indra/llcharacter/llkeyframemotion.cpp
@@ -984,7 +984,6 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
 	{
 	case CONSTRAINT_TARGET_TYPE_GROUND:
 		target_pos = mCharacter->getPosAgentFromGlobal(constraint->mGroundPos);
-		target_pos += mCharacter->getHoverOffset();
 //		LL_INFOS() << "Target Pos " << constraint->mGroundPos << " on " << mCharacter->findCollisionVolume(shared_data->mSourceConstraintVolume)->getName() << LL_ENDL;
 		break;
 	case CONSTRAINT_TARGET_TYPE_BODY:
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 3f75131780..a90fade3c9 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -3178,12 +3178,8 @@ void	LLVOAvatar::forceUpdateVisualMuteSettings()
 }
 
 
-//------------------------------------------------------------------------
-// updateCharacter()
-// called on both your avatar and other avatars
-//------------------------------------------------------------------------
-BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
-{	
+void LLVOAvatar::updateDebugText()
+{
 	// clear debug text
 	mDebugText.clear();
 
@@ -3226,6 +3222,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 		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*...";
@@ -3241,7 +3239,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 		if (!mBakedTextureDebugText.empty())
 			addDebugText(mBakedTextureDebugText);
 	}
-				 
+
 	if (LLVOAvatar::sShowAnimationDebug)
 	{
 		for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin();
@@ -3270,6 +3268,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;
@@ -3378,9 +3397,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
@@ -3434,7 +3459,10 @@ 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;
-		root_pos += LLVector3d(getHoverOffset());
+		if (!mIsSitting && !was_sit_ground_constrained)
+		{
+			root_pos += LLVector3d(getHoverOffset());
+		}
 		
 		LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos);
 
@@ -3624,7 +3652,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();
 
@@ -3708,17 +3750,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;
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 82b95145e5..2e72633d39 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -233,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);
-- 
cgit v1.2.3


From bed810216db009a7c5b1e9eacfb8f0b1307d7a72 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 6 Mar 2015 13:51:12 -0500
Subject: MAINT-4967 FIX - log spam removed

---
 indra/newview/app_settings/logcontrol.xml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 6a798e1d42..de3732f339 100755
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -42,7 +42,6 @@
 						</array>
 					<key>tags</key>
 						<array>
-						     <string>Avatar</string>
 						<!-- sample entry for debugging specific items	
 						     <string>Avatar</string>
 						     <string>Inventory</string>
-- 
cgit v1.2.3


From 71942af3758c2c77c08a336406549a80b4580fbc Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 23 Mar 2015 14:32:13 -0400
Subject: Added tag 3.7.26-release for changeset 000e9dda4162

---
 .hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.hgtags b/.hgtags
index 6db0a64173..e73ba6a156 100755
--- a/.hgtags
+++ b/.hgtags
@@ -498,3 +498,4 @@ bc61801f614022c920cb5c3df1d7d67a9561ce1f 3.7.22-release
 3be800e1afad9615442159e388d6d137be7b951e 3.7.23-release
 d3d0101e980ec95043e0af9b7903045d3bc447e4 3.7.24-release
 9978a8c3a2ffce4a5e1c186256581c2ac139c9dc 3.7.25-release
+000e9dda4162cbf0a83ba88558b19473654a09a9 3.7.26-release
-- 
cgit v1.2.3


From c489f1f8647a77c8c7d5fb5b721433dd72cb49c8 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 23 Mar 2015 14:32:13 -0400
Subject: increment viewer version to 3.7.27

---
 indra/newview/VIEWER_VERSION.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index e5403775b2..0bbe2c1160 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.7.26
+3.7.27
-- 
cgit v1.2.3


From 794ae5cdcadcfaa655815bfa1e6c6823e03ee1f6 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 23 Mar 2015 22:34:34 -0400
Subject: correct merge error

---
 indra/newview/llvoavatarself.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index ff718b2c70..1e9945b514 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -177,8 +177,7 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id,
 	LLVOAvatar(id, pcode, regionp),
 	mScreenp(NULL),
 	mLastRegionHandle(0),
-	mRegionCrossingCount(0)
-	mInitialBakesLoaded(false),
+	mRegionCrossingCount(0),
 	// Value outside legal range, so will always be a mismatch the
 	// first time through.
 	mLastHoverOffsetSent(LLVector3(0.0f, 0.0f, -999.0f))
-- 
cgit v1.2.3


From 19e6455d830fe753a29e216fbd06db3c04d39a0d Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 27 Feb 2015 14:12:06 -0500
Subject: Remove viewer build dependency on Incredibuild. Specifically, change
 the 'BuildConsole' command to 'devenv', and fix command-line arguments
 appropriately.

---
 autobuild.xml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/autobuild.xml b/autobuild.xml
index e74825f945..52d750f64d 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -2727,11 +2727,11 @@
                   <string>SecondLife.sln</string>
                 </array>
                 <key>command</key>
-                <string>BuildConsole</string>
+                <string>devenv</string>
                 <key>options</key>
                 <array>
                   <string>/build</string>
-                  <string>"/cfg=RelWithDebInfo|Win32"</string>
+                  <string>"RelWithDebInfo|Win32"</string>
                 </array>
               </map>
               <key>configure</key>
@@ -2815,11 +2815,11 @@
                   <string>SecondLife.sln</string>
                 </array>
                 <key>command</key>
-                <string>BuildConsole</string>
+                <string>devenv</string>
                 <key>options</key>
                 <array>
                   <string>/build</string>
-                  <string>"/cfg=Release|Win32"</string>
+                  <string>"Release|Win32"</string>
                 </array>
               </map>
               <key>configure</key>
-- 
cgit v1.2.3


From 52d257f23432462bb4396dd851a9e0e8403a9d65 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 17 Mar 2015 16:32:44 -0400
Subject: MAINT-4995: fix stored favorites for login bar (close input files
 before opening them for writing)

---
 indra/newview/llfavoritesbar.cpp | 115 ++++++++++++++++++++++++++++-----------
 1 file changed, 84 insertions(+), 31 deletions(-)

diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 6c5b5be720..190ec4abe3 100755
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -480,7 +480,7 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 				const LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
 				if (item->getParentUUID() == favorites_id)
 				{
-					LL_WARNS() << "Attemt to copy a favorite item into the same folder." << LL_ENDL;
+					LL_WARNS("FavoritesBar") << "Attemt to copy a favorite item into the same folder." << LL_ENDL;
 					break;
 				}
 
@@ -632,7 +632,7 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con
 	//		landmarks to an empty favorites bar.
 	updateButtons();
 	
-	LL_INFOS() << "Copied inventory item #" << item->getUUID() << " to favorites." << LL_ENDL;
+	LL_INFOS("FavoritesBar") << "Copied inventory item #" << item->getUUID() << " to favorites." << LL_ENDL;
 }
 
 //virtual
@@ -871,7 +871,7 @@ LLButton* LLFavoritesBarCtrl::createButton(const LLPointer<LLViewerInventoryItem
 	fav_btn = LLUICtrlFactory::create<LLFavoriteLandmarkButton>(fav_btn_params);
 	if (NULL == fav_btn)
 	{
-		LL_WARNS() << "Unable to create LLFavoriteLandmarkButton widget: " << item->getName() << LL_ENDL;
+		LL_WARNS("FavoritesBar") << "Unable to create LLFavoriteLandmarkButton widget: " << item->getName() << LL_ENDL;
 		return NULL;
 	}
 	
@@ -1160,7 +1160,7 @@ bool LLFavoritesBarCtrl::enableSelected(const LLSD& userdata)
 void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata)
 {
 	std::string action = userdata.asString();
-	LL_INFOS() << "Action = " << action << " Item = " << mSelectedItemID.asString() << LL_ENDL;
+	LL_INFOS("FavoritesBar") << "Action = " << action << " Item = " << mSelectedItemID.asString() << LL_ENDL;
 	
 	LLViewerInventoryItem* item = gInventory.getItem(mSelectedItemID);
 	if (!item)
@@ -1444,6 +1444,7 @@ void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id)
 		boost::bind(&LLFavoritesOrderStorage::onLandmarkLoaded, this, asset_id, _1));
 	if (lm)
 	{
+        LL_DEBUGS("FavoritesBar") << "landmark for " << asset_id << " already loaded" << LL_ENDL;
 		onLandmarkLoaded(asset_id, lm);
 	}
 }
@@ -1459,7 +1460,11 @@ void LLFavoritesOrderStorage::destroyClass()
 	file.open(old_filename);
 	if (file.is_open())
 	{
+        file.close();
 		std::string new_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites_" + LLGridManager::getInstance()->getGrid() + ".xml");
+        LL_INFOS("FavoritesBar") << "moving favorites from old name '" << old_filename
+                                 << "' to new name '" << new_filename << "'"
+                                 << LL_ENDL;
 		LLFile::copy(old_filename,new_filename);
 		LLFile::remove(old_filename);
 	}
@@ -1485,7 +1490,15 @@ void LLFavoritesOrderStorage::load()
 	if (file.is_open())
 	{
 		LLSDSerialize::fromXML(settings_llsd, file);
+        LL_INFOS("FavoritesBar") << "loaded favorites order from '" << filename << "' "
+                                 << (settings_llsd.isMap() ? "" : "un") << "successfully"
+                                 << LL_ENDL;
+        file.close();
 	}
+    else
+    {
+        LL_WARNS("FavoritesBar") << "unable to open favorites order file at '" << filename << "'" << LL_ENDL;
+    }
 
 	for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
 		iter != settings_llsd.endMap(); ++iter)
@@ -1499,14 +1512,14 @@ void LLFavoritesOrderStorage::saveFavoritesSLURLs()
 	// Do not change the file if we are not logged in yet.
 	if (!LLLoginInstance::getInstance()->authSuccess())
 	{
-		LL_WARNS() << "Cannot save favorites: not logged in" << LL_ENDL;
+		LL_WARNS("FavoritesBar") << "Cannot save favorites: not logged in" << LL_ENDL;
 		return;
 	}
 
 	std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
 	if (user_dir.empty())
 	{
-		LL_WARNS() << "Cannot save favorites: empty user dir name" << LL_ENDL;
+		LL_WARNS("FavoritesBar") << "Cannot save favorites: empty user dir name" << LL_ENDL;
 		return;
 	}
 
@@ -1517,7 +1530,15 @@ void LLFavoritesOrderStorage::saveFavoritesSLURLs()
 	if (in_file.is_open())
 	{
 		LLSDSerialize::fromXML(fav_llsd, in_file);
+        LL_INFOS("FavoritesBar") << "loaded favorites from '" << filename << "' "
+                                 << (fav_llsd.isMap() ? "" : "un") << "successfully"
+                                 << LL_ENDL;
+        in_file.close();
 	}
+    else
+    {
+        LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL;
+    }
 
 	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
 	LLInventoryModel::cat_array_t cats;
@@ -1534,13 +1555,13 @@ void LLFavoritesOrderStorage::saveFavoritesSLURLs()
 		slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]);
 		if (slurl_iter != mSLURLs.end())
 		{
-			LL_DEBUGS() << "Saving favorite: idx=" << LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID()) << ", SLURL=" <<  slurl_iter->second << ", value=" << value << LL_ENDL;
+			LL_DEBUGS("FavoritesBar") << "Saving favorite: idx=" << LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID()) << ", SLURL=" <<  slurl_iter->second << ", value=" << value << LL_ENDL;
 			value["slurl"] = slurl_iter->second;
 			user_llsd[LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID())] = value;
 		}
 		else
 		{
-			LL_WARNS() << "Not saving favorite " << value["name"] << ": no matching SLURL" << LL_ENDL;
+			LL_WARNS("FavoritesBar") << "Not saving favorite " << value["name"] << ": no matching SLURL" << LL_ENDL;
 		}
 	}
 
@@ -1548,12 +1569,25 @@ void LLFavoritesOrderStorage::saveFavoritesSLURLs()
 	LLAvatarNameCache::get( gAgentID, &av_name );
 	// Note : use the "John Doe" and not the "john.doe" version of the name 
 	// as we'll compare it with the stored credentials in the login panel.
-	LL_DEBUGS() << "Saved favorites for " << av_name.getUserName() << LL_ENDL;
 	fav_llsd[av_name.getUserName()] = user_llsd;
 
 	llofstream file;
 	file.open(filename);
-	LLSDSerialize::toPrettyXML(fav_llsd, file);
+    if ( file.is_open() )
+    {
+        LLSDSerialize::toPrettyXML(fav_llsd, file);
+        LL_INFOS("FavoritesBar") << "saved favorites for '" << av_name.getUserName()
+                                 << "' to '" << filename << "' "
+                                 << LL_ENDL;
+        file.close();
+    }
+    else
+    {
+        LL_WARNS("FavoritesBar") << "unable to open favorites storage for '" << av_name.getUserName()
+                                 << "' at '" << filename << "' "
+                                 << LL_ENDL;
+    }
+
 }
 
 void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()
@@ -1562,29 +1596,38 @@ void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()
 	LLSD fav_llsd;
 	llifstream file;
 	file.open(filename);
-	if (!file.is_open()) return;
-	LLSDSerialize::fromXML(fav_llsd, file);
-
-	LLAvatarName av_name;
-	LLAvatarNameCache::get( gAgentID, &av_name );
-	// Note : use the "John Doe" and not the "john.doe" version of the name.
-	// See saveFavoritesSLURLs() here above for the reason why.
-	LL_DEBUGS() << "Removed favorites for " << av_name.getUserName() << LL_ENDL;
-	if (fav_llsd.has(av_name.getUserName()))
-	{
-		fav_llsd.erase(av_name.getUserName());
-	}
-
-	llofstream out_file;
-	out_file.open(filename);
-	LLSDSerialize::toPrettyXML(fav_llsd, out_file);
-
+	if (file.is_open())
+    {
+        LLSDSerialize::fromXML(fav_llsd, file);
+        file.close();
+        
+        LLAvatarName av_name;
+        LLAvatarNameCache::get( gAgentID, &av_name );
+        // Note : use the "John Doe" and not the "john.doe" version of the name.
+        // See saveFavoritesSLURLs() here above for the reason why.
+        if (fav_llsd.has(av_name.getUserName()))
+        {
+            LL_INFOS("FavoritesBar") << "Removed favorites for " << av_name.getUserName() << LL_ENDL;
+            fav_llsd.erase(av_name.getUserName());
+        }
+        
+        llofstream out_file;
+        out_file.open(filename);
+        if ( out_file.is_open() )
+        {
+            LLSDSerialize::toPrettyXML(fav_llsd, out_file);
+            LL_INFOS("FavoritesBar") << "saved favorites to '" << filename << "' "
+                                     << LL_ENDL;
+            out_file.close();
+        }
+    }
 }
 
 void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark)
 {
-	if (!landmark) return;
-
+	if (landmark)
+    {
+        LL_DEBUGS("FavoritesBar") << "landmark for " << asset_id << " loaded" << LL_ENDL;
 	LLVector3d pos_global;
 	if (!landmark->getGlobalPos(pos_global))
 	{
@@ -1595,14 +1638,16 @@ void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmar
 
 	if (!pos_global.isExactlyZero())
 	{
+        LL_DEBUGS("FavoritesBar") << "requestion slurl for landmark " << asset_id << LL_ENDL;
 		LLLandmarkActions::getSLURLfromPosGlobal(pos_global,
 			boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1));
 	}
+    }
 }
 
 void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl)
 {
-	LL_DEBUGS() << "Saving landmark SLURL: " << slurl << LL_ENDL;
+	LL_DEBUGS("FavoritesBar") << "Saving landmark SLURL '" << slurl << "' for " << asset_id << LL_ENDL;
 	mSLURLs[asset_id] = slurl;
 }
 
@@ -1627,7 +1672,15 @@ void LLFavoritesOrderStorage::save()
 
 		llofstream file;
 		file.open(filename);
-		LLSDSerialize::toPrettyXML(settings_llsd, file);
+        if ( file.is_open() )
+        {
+            LLSDSerialize::toPrettyXML(settings_llsd, file);
+            LL_INFOS("FavoritesBar") << "saved favorites order to '" << filename << "' " << LL_ENDL;
+        }
+        else
+        {
+            LL_WARNS("FavoritesBar") << "failed to open favorites order file '" << filename << "' " << LL_ENDL;
+        }
 	}
 }
 
-- 
cgit v1.2.3


From d3477b738881acbdf2bd1cc7bfaadaaae3890be6 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 17 Mar 2015 18:09:01 -0400
Subject: improve file name handling and clean up some error checks

---
 indra/newview/llfavoritesbar.cpp | 256 +++++++++++++++++++++------------------
 indra/newview/llfavoritesbar.h   |  18 +--
 2 files changed, 143 insertions(+), 131 deletions(-)

diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 190ec4abe3..3da162c5ef 100755
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -1449,6 +1449,19 @@ void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id)
 	}
 }
 
+// static
+std::string LLFavoritesOrderStorage::getStoredFavoritesFilename()
+{
+	std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
+
+    return (user_dir.empty() ? ""
+            : gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
+                                             "stored_favorites_"
+                                          + LLGridManager::getInstance()->getGrid()
+                                          + ".xml")
+            );
+}
+
 // static
 void LLFavoritesOrderStorage::destroyClass()
 {
@@ -1461,7 +1474,7 @@ void LLFavoritesOrderStorage::destroyClass()
 	if (file.is_open())
 	{
         file.close();
-		std::string new_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites_" + LLGridManager::getInstance()->getGrid() + ".xml");
+		std::string new_filename = getStoredFavoritesFilename();
         LL_INFOS("FavoritesBar") << "moving favorites from old name '" << old_filename
                                  << "' to new name '" << new_filename << "'"
                                  << LL_ENDL;
@@ -1479,10 +1492,19 @@ void LLFavoritesOrderStorage::destroyClass()
 	}
 }
 
+std::string LLFavoritesOrderStorage::getSavedOrderFileName()
+{
+	// If we quit from the login screen we will not have an SL account
+	// name.  Don't try to save, otherwise we'll dump a file in
+	// C:\Program Files\SecondLife\ or similar. JC
+	std::string user_dir = gDirUtilp->getLindenUserDir();
+    return (user_dir.empty() ? "" : gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME));
+}
+
 void LLFavoritesOrderStorage::load()
 {
 	// load per-resident sorting information
-	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME);
+	std::string filename = getSavedOrderFileName();
 
 	LLSD settings_llsd;
 	llifstream file;
@@ -1516,109 +1538,107 @@ void LLFavoritesOrderStorage::saveFavoritesSLURLs()
 		return;
 	}
 
-	std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
-	if (user_dir.empty())
-	{
-		LL_WARNS("FavoritesBar") << "Cannot save favorites: empty user dir name" << LL_ENDL;
-		return;
-	}
-
-	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites_" + LLGridManager::getInstance()->getGrid() + ".xml");
-	llifstream in_file;
-	in_file.open(filename);
-	LLSD fav_llsd;
-	if (in_file.is_open())
-	{
-		LLSDSerialize::fromXML(fav_llsd, in_file);
-        LL_INFOS("FavoritesBar") << "loaded favorites from '" << filename << "' "
-                                 << (fav_llsd.isMap() ? "" : "un") << "successfully"
-                                 << LL_ENDL;
-        in_file.close();
-	}
-    else
+	std::string filename = getStoredFavoritesFilename();
+    if (!filename.empty())
     {
-        LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL;
-    }
-
-	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
-	LLInventoryModel::cat_array_t cats;
-	LLInventoryModel::item_array_t items;
-	gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
+        llifstream in_file;
+        in_file.open(filename);
+        LLSD fav_llsd;
+        if (in_file.is_open())
+        {
+            LLSDSerialize::fromXML(fav_llsd, in_file);
+            LL_INFOS("FavoritesBar") << "loaded favorites from '" << filename << "' "
+                                     << (fav_llsd.isMap() ? "" : "un") << "successfully"
+                                     << LL_ENDL;
+            in_file.close();
+        }
+        else
+        {
+            LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL;
+        }
 
-	LLSD user_llsd;
-	for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++)
-	{
-		LLSD value;
-		value["name"] = (*it)->getName();
-		value["asset_id"] = (*it)->getAssetUUID();
+        const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+        LLInventoryModel::cat_array_t cats;
+        LLInventoryModel::item_array_t items;
+        gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
 
-		slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]);
-		if (slurl_iter != mSLURLs.end())
-		{
-			LL_DEBUGS("FavoritesBar") << "Saving favorite: idx=" << LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID()) << ", SLURL=" <<  slurl_iter->second << ", value=" << value << LL_ENDL;
-			value["slurl"] = slurl_iter->second;
-			user_llsd[LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID())] = value;
-		}
-		else
-		{
-			LL_WARNS("FavoritesBar") << "Not saving favorite " << value["name"] << ": no matching SLURL" << LL_ENDL;
-		}
-	}
+        LLSD user_llsd;
+        for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++)
+        {
+            LLSD value;
+            value["name"] = (*it)->getName();
+            value["asset_id"] = (*it)->getAssetUUID();
+
+            slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]);
+            if (slurl_iter != mSLURLs.end())
+            {
+                LL_DEBUGS("FavoritesBar") << "Saving favorite: idx=" << LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID()) << ", SLURL=" <<  slurl_iter->second << ", value=" << value << LL_ENDL;
+                value["slurl"] = slurl_iter->second;
+                user_llsd[LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID())] = value;
+            }
+            else
+            {
+                LL_WARNS("FavoritesBar") << "Not saving favorite " << value["name"] << ": no matching SLURL" << LL_ENDL;
+            }
+        }
 
-	LLAvatarName av_name;
-	LLAvatarNameCache::get( gAgentID, &av_name );
-	// Note : use the "John Doe" and not the "john.doe" version of the name 
-	// as we'll compare it with the stored credentials in the login panel.
-	fav_llsd[av_name.getUserName()] = user_llsd;
+        LLAvatarName av_name;
+        LLAvatarNameCache::get( gAgentID, &av_name );
+        // Note : use the "John Doe" and not the "john.doe" version of the name 
+        // as we'll compare it with the stored credentials in the login panel.
+        fav_llsd[av_name.getUserName()] = user_llsd;
 
-	llofstream file;
-	file.open(filename);
-    if ( file.is_open() )
-    {
-        LLSDSerialize::toPrettyXML(fav_llsd, file);
-        LL_INFOS("FavoritesBar") << "saved favorites for '" << av_name.getUserName()
-                                 << "' to '" << filename << "' "
-                                 << LL_ENDL;
-        file.close();
-    }
-    else
-    {
-        LL_WARNS("FavoritesBar") << "unable to open favorites storage for '" << av_name.getUserName()
-                                 << "' at '" << filename << "' "
-                                 << LL_ENDL;
+        llofstream file;
+        file.open(filename);
+        if ( file.is_open() )
+        {
+            LLSDSerialize::toPrettyXML(fav_llsd, file);
+            LL_INFOS("FavoritesBar") << "saved favorites for '" << av_name.getUserName()
+                                     << "' to '" << filename << "' "
+                                     << LL_ENDL;
+            file.close();
+        }
+        else
+        {
+            LL_WARNS("FavoritesBar") << "unable to open favorites storage for '" << av_name.getUserName()
+                                     << "' at '" << filename << "' "
+                                     << LL_ENDL;
+        }
     }
-
 }
 
 void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()
 {
-	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites_" + LLGridManager::getInstance()->getGrid() + ".xml");
-	LLSD fav_llsd;
-	llifstream file;
-	file.open(filename);
-	if (file.is_open())
+	std::string filename = getStoredFavoritesFilename();
+    if (!filename.empty())
     {
-        LLSDSerialize::fromXML(fav_llsd, file);
-        file.close();
-        
-        LLAvatarName av_name;
-        LLAvatarNameCache::get( gAgentID, &av_name );
-        // Note : use the "John Doe" and not the "john.doe" version of the name.
-        // See saveFavoritesSLURLs() here above for the reason why.
-        if (fav_llsd.has(av_name.getUserName()))
+        LLSD fav_llsd;
+        llifstream file;
+        file.open(filename);
+        if (file.is_open())
         {
-            LL_INFOS("FavoritesBar") << "Removed favorites for " << av_name.getUserName() << LL_ENDL;
-            fav_llsd.erase(av_name.getUserName());
-        }
+            LLSDSerialize::fromXML(fav_llsd, file);
+            file.close();
         
-        llofstream out_file;
-        out_file.open(filename);
-        if ( out_file.is_open() )
-        {
-            LLSDSerialize::toPrettyXML(fav_llsd, out_file);
-            LL_INFOS("FavoritesBar") << "saved favorites to '" << filename << "' "
-                                     << LL_ENDL;
-            out_file.close();
+            LLAvatarName av_name;
+            LLAvatarNameCache::get( gAgentID, &av_name );
+            // Note : use the "John Doe" and not the "john.doe" version of the name.
+            // See saveFavoritesSLURLs() here above for the reason why.
+            if (fav_llsd.has(av_name.getUserName()))
+            {
+                LL_INFOS("FavoritesBar") << "Removed favorites for " << av_name.getUserName() << LL_ENDL;
+                fav_llsd.erase(av_name.getUserName());
+            }
+        
+            llofstream out_file;
+            out_file.open(filename);
+            if ( out_file.is_open() )
+            {
+                LLSDSerialize::toPrettyXML(fav_llsd, out_file);
+                LL_INFOS("FavoritesBar") << "saved favorites to '" << filename << "' "
+                                         << LL_ENDL;
+                out_file.close();
+            }
         }
     }
 }
@@ -1638,7 +1658,7 @@ void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmar
 
 	if (!pos_global.isExactlyZero())
 	{
-        LL_DEBUGS("FavoritesBar") << "requestion slurl for landmark " << asset_id << LL_ENDL;
+        LL_DEBUGS("FavoritesBar") << "requesting slurl for landmark " << asset_id << LL_ENDL;
 		LLLandmarkActions::getSLURLfromPosGlobal(pos_global,
 			boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1));
 	}
@@ -1653,37 +1673,39 @@ void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::st
 
 void LLFavoritesOrderStorage::save()
 {
-	// nothing to save if clean
-	if (!mIsDirty) return;
-
-	// If we quit from the login screen we will not have an SL account
-	// name.  Don't try to save, otherwise we'll dump a file in
-	// C:\Program Files\SecondLife\ or similar. JC
-	std::string user_dir = gDirUtilp->getLindenUserDir();
-	if (!user_dir.empty())
-	{
-		std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME);
-		LLSD settings_llsd;
-
-		for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter)
-		{
-			settings_llsd[iter->first.asString()] = iter->second;
-		}
-
-		llofstream file;
-		file.open(filename);
-        if ( file.is_open() )
+	if (mIsDirty)
+    {
+        // something changed, so save it
+        std::string filename = LLFavoritesOrderStorage::getInstance()->getSavedOrderFileName();
+        if (!filename.empty())
         {
-            LLSDSerialize::toPrettyXML(settings_llsd, file);
-            LL_INFOS("FavoritesBar") << "saved favorites order to '" << filename << "' " << LL_ENDL;
+            LLSD settings_llsd;
+
+            for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter)
+            {
+                settings_llsd[iter->first.asString()] = iter->second;
+            }
+
+            llofstream file;
+            file.open(filename);
+            if ( file.is_open() )
+            {
+                LLSDSerialize::toPrettyXML(settings_llsd, file);
+                LL_INFOS("FavoritesBar") << "saved favorites order to '" << filename << "' " << LL_ENDL;
+            }
+            else
+            {
+                LL_WARNS("FavoritesBar") << "failed to open favorites order file '" << filename << "' " << LL_ENDL;
+            }
         }
         else
         {
-            LL_WARNS("FavoritesBar") << "failed to open favorites order file '" << filename << "' " << LL_ENDL;
+            LL_DEBUGS("FavoritesBar") << "no user directory available to store favorites order file" << LL_ENDL;
         }
-	}
+    }
 }
 
+
 void LLFavoritesOrderStorage::cleanup()
 {
 	// nothing to clean
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index 5ca1d3e8ed..a370724947 100755
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -162,19 +162,7 @@ private:
 
 	boost::signals2::connection mEndDragConnection;
 };
-/*
-class AddFavoriteLandmarkCallback : public LLInventoryCallback
-{
-public:
-	AddFavoriteLandmarkCallback() : mTargetLandmarkId(LLUUID::null) {}
-	void setTargetLandmarkId(const LLUUID& target_uuid) { mTargetLandmarkId = target_uuid; }
-
-private:
-	void fire(const LLUUID& inv_item);
 
-	LLUUID mTargetLandmarkId;
-};
-*/
 /**
  * Class to store sorting order of favorites landmarks in a local file. EXT-3985.
  * It replaced previously implemented solution to store sort index in landmark's name as a "<N>@" prefix.
@@ -222,14 +210,16 @@ private:
 	friend class LLSingleton<LLFavoritesOrderStorage>;
 	LLFavoritesOrderStorage() : mIsDirty(false) { load(); }
 	~LLFavoritesOrderStorage() { save(); }
-
+    
 	/**
 	 * Removes sort indexes for items which are not in Favorites bar for now.
 	 */
 	void cleanup();
 
 	const static std::string SORTING_DATA_FILE_NAME;
-
+    std::string getSavedOrderFileName();
+    static std::string getStoredFavoritesFilename();
+    
 	void load();
 	void save();
 
-- 
cgit v1.2.3


From 56a7c4af973ec3ba3e157a9f08632ddada1185f7 Mon Sep 17 00:00:00 2001
From: Cinder <cinder@sdf.org>
Date: Tue, 24 Mar 2015 12:17:07 -0600
Subject: BUG-8786 - Turn off fast math opts enforcing IEEE 754 floating point
 compliance

---
 indra/cmake/Variables.cmake | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index faca12c347..76d92d7a48 100755
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -138,7 +138,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
   set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0")
   set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL 3)
   set(CMAKE_XCODE_ATTRIBUTE_GCC_STRICT_ALIASING NO)
-  set(CMAKE_XCODE_ATTRIBUTE_GCC_FAST_MATH YES)
+  set(CMAKE_XCODE_ATTRIBUTE_GCC_FAST_MATH NO)
   set(CMAKE_XCODE_ATTRIBUTE_CLANG_X86_VECTOR_INSTRUCTIONS ssse3)
   set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libstdc++")
   set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT dwarf-with-dsym)
-- 
cgit v1.2.3


From ab30a44d9de332466841bfb40aa494ff0db1089a Mon Sep 17 00:00:00 2001
From: Cinder Biscuits <cinder@alchemyviewer.org>
Date: Wed, 25 Mar 2015 03:09:17 +0000
Subject: Add Cinder Roxley as contributor for BUG-8835

---
 doc/contributions.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 2923139405..f7041c538e 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -313,6 +313,7 @@ Ciaran Laval
 Cinder Roxley
     BUG-2326
     BUG-3863
+    BUG-8786
     OPEN-185
     OPEN-282
     STORM-1703
-- 
cgit v1.2.3