From a2241853e4ca3a77ffc354578835e32affc3d5c8 Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Sun, 11 Jul 2021 02:25:52 -0400
Subject: [PATCH] Fix build floater rotation spinners on attachments

---
 indra/newview/llpanelobject.cpp | 65 +++++++++++++++++++++++++++------
 1 file changed, 54 insertions(+), 11 deletions(-)

diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index 67639ac5fae..e1fa62ba20b 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -1732,7 +1732,7 @@ void LLPanelObject::sendRotation(BOOL btn_down)
 
 		if (mRootObject != mObject)
 		{
-			rotation = rotation * ~mRootObject->getRotationRegion();
+			rotation = rotation * (mObject->isAttachment() ? ~mRootObject->getRotationEdit() : ~mRootObject->getRotationRegion());
 		}
 
 		// To include avatars into movements and rotation
@@ -1808,15 +1808,25 @@ void LLPanelObject::sendPosition(BOOL btn_down)
 	if (mObject.isNull()) return;
 
 	LLVector3 newpos(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get());
+	LLVector3d new_pos_global;
 	LLViewerRegion* regionp = mObject->getRegion();
 
-	// Clamp the Z height
-	const F32 height = newpos.mV[VZ];
-	const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject, mObject->getPositionGlobal());
-	const F32 max_height = LLWorld::getInstance()->getRegionMaxHeight();
-
-	if (!mObject->isAttachment())
+	if (mObject->isAttachment())
+	{
+		newpos.clamp(LLVector3(-MAX_ATTACHMENT_DIST,-MAX_ATTACHMENT_DIST,-MAX_ATTACHMENT_DIST),LLVector3(MAX_ATTACHMENT_DIST,MAX_ATTACHMENT_DIST,MAX_ATTACHMENT_DIST));
+	}
+	else
 	{
+		// Clamp the Z height
+		const F32 height = newpos.mV[VZ];
+		LLVector3d height_check_pos = mObject->getPositionGlobal();
+		if (LLWorld::getInstance()->positionRegionValidGlobal(regionp->getPosGlobalFromRegion(newpos)))
+		{
+			height_check_pos = regionp->getPosGlobalFromRegion(newpos);
+		}
+		const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject, height_check_pos);
+		const F32 max_height = LLWorld::getInstance()->getRegionMaxHeight();
+
 		if ( height < min_height)
 		{
 			newpos.mV[VZ] = min_height;
@@ -1833,13 +1843,46 @@ void LLPanelObject::sendPosition(BOOL btn_down)
 		{
 			mCtrlPosZ->set(LLWorld::getInstance()->resolveLandHeightAgent(newpos) + 1.f);
 		}
+
+		// Make sure new position is in a valid region, so the object
+		// won't get dumped by the simulator.
+		new_pos_global = regionp->getPosGlobalFromRegion(newpos);
 	}
 
-	// Make sure new position is in a valid region, so the object
-	// won't get dumped by the simulator.
-	LLVector3d new_pos_global = regionp->getPosGlobalFromRegion(newpos);
+	if (mObject->isAttachment())
+	{	
+		const LLVector3& old_pos_local = mObject->getPosition();
 
-	if ( LLWorld::getInstance()->positionRegionValidGlobal(new_pos_global) )
+		if (mRootObject != mObject)
+		{
+			newpos = newpos - mRootObject->getPosition();
+			newpos = newpos * ~mRootObject->getRotation();
+			mObject->setPositionParent(newpos);
+		}
+		else
+		{
+			mObject->setPosition(newpos);
+		}
+
+		LLManip::rebuild(mObject);
+		gAgentAvatarp->clampAttachmentPositions();
+
+		// for individually selected roots, we need to counter-translate all unselected children
+		if (mObject->isRootEdit())
+		{
+			const LLVector3& delta = mObject->getPosition();
+			// counter-translate child objects if we are moving the root as an individual
+			mObject->resetChildrenPosition(old_pos_local - delta, TRUE);
+		}
+
+		if (!btn_down)
+		{
+			LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION);
+		}
+
+		LLSelectMgr::getInstance()->updateSelectionCenter();
+	}
+	else if ( LLWorld::getInstance()->positionRegionValidGlobal(new_pos_global) )
 	{
 		// send only if the position is changed, that is, the delta vector is not zero
 		LLVector3d old_pos_global = mObject->getPositionGlobal();
-- 
GitLab