diff --git a/indra/llmath/llbbox.cpp b/indra/llmath/llbbox.cpp
index b46a6e03d2ed198ed9680e31b98bc711e9b172e1..3e2c05a6e6d4d861c6755213b88fb785e87ad0cb 100644
--- a/indra/llmath/llbbox.cpp
+++ b/indra/llmath/llbbox.cpp
@@ -89,6 +89,19 @@ void LLBBox::addBBoxAgent(const LLBBox& b)
 	}
 }
 
+LLBBox LLBBox::getAxisAligned() const
+{
+	// no rotation = axis aligned rotation
+	LLBBox aligned(mPosAgent, LLQuaternion(), LLVector3(), LLVector3());
+
+	// add the center point so that it's not empty
+	aligned.addPointAgent(mPosAgent);
+
+	// add our BBox
+	aligned.addBBoxAgent(*this);
+
+	return aligned;
+}
 
 void LLBBox::expand( F32 delta )
 {
@@ -147,6 +160,15 @@ BOOL LLBBox::containsPointAgent(const LLVector3& p) const
 	return containsPointLocal(point_local);
 }
 
+LLVector3 LLBBox::getMinAgent() const
+{
+	return localToAgent(mMinLocal);
+}
+
+LLVector3 LLBBox::getMaxAgent() const
+{
+	return localToAgent(mMaxLocal);
+}
 
 /*
 LLBBox operator*(const LLBBox &a, const LLMatrix4 &b)
diff --git a/indra/llmath/llbbox.h b/indra/llmath/llbbox.h
index 5b911793f0f4ae12289deff4e00540a8ea8a877a..28e69b75e122629aa680b83927463be3aefd52c9 100644
--- a/indra/llmath/llbbox.h
+++ b/indra/llmath/llbbox.h
@@ -51,9 +51,11 @@ class LLBBox
 	const LLVector3&	getPositionAgent() const			{ return mPosAgent; }
 	const LLQuaternion&	getRotation() const					{ return mRotation; }
 
+	LLVector3           getMinAgent() const;
 	const LLVector3&	getMinLocal() const					{ return mMinLocal; }
 	void				setMinLocal( const LLVector3& min )	{ mMinLocal = min; }
 
+	LLVector3           getMaxAgent() const;
 	const LLVector3&	getMaxLocal() const					{ return mMaxLocal; }
 	void				setMaxLocal( const LLVector3& max )	{ mMaxLocal = max; }
 
@@ -80,6 +82,8 @@ class LLBBox
 	LLVector3			localToAgentBasis(const LLVector3& v) const;
 	LLVector3			agentToLocalBasis(const LLVector3& v) const;
 
+	// Get the smallest possible axis aligned bbox that contains this bbox
+	LLBBox              getAxisAligned() const;
 
 //	friend LLBBox operator*(const LLBBox& a, const LLMatrix4& b);
 
diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h
index b9b974ec4f6a8109cbad4859b0c8f4671767654e..7b796a0fa875f92785ac0f0c376338c453188f97 100644
--- a/indra/llmessage/llregionflags.h
+++ b/indra/llmessage/llregionflags.h
@@ -42,9 +42,6 @@ const U32 REGION_FLAGS_RESET_HOME_ON_TELEPORT	= (1 << 3);
 // Does the sun move?
 const U32 REGION_FLAGS_SUN_FIXED				= (1 << 4);
 
-// Tax free zone (no taxes on objects, land, etc.)
-const U32 REGION_FLAGS_TAX_FREE					= (1 << 5);
-
 // Can't change the terrain heightfield, even on owned parcels,
 // but can plant trees and grass.
 const U32 REGION_FLAGS_BLOCK_TERRAFORM			= (1 << 6);
@@ -54,17 +51,12 @@ const U32 REGION_FLAGS_BLOCK_LAND_RESELL		= (1 << 7);
 
 // All content wiped once per night
 const U32 REGION_FLAGS_SANDBOX					= (1 << 8);
-const U32 REGION_FLAGS_NULL_LAYER				= (1 << 9);
-// const U32 REGION_FLAGS_SKIP_AGENT_ACTION		= (1 << 10);
-const U32 REGION_FLAGS_HARD_ALLOW_LAND_TRANSFER	= (1 << 10);	// Region allows land reselling
-// const U32 REGION_FLAGS_SKIP_UPDATE_INTEREST_LIST= (1 << 11);
-const U32 REGION_FLAGS_HARD_ALLOW_POST_CLASSIFIED	= (1 << 11);	// Region allows posting of classified ads
 const U32 REGION_FLAGS_SKIP_COLLISIONS			= (1 << 12); // Pin all non agent rigid bodies
 const U32 REGION_FLAGS_SKIP_SCRIPTS				= (1 << 13);
 const U32 REGION_FLAGS_SKIP_PHYSICS				= (1 << 14); // Skip all physics
 const U32 REGION_FLAGS_EXTERNALLY_VISIBLE		= (1 << 15);
-//const U32 REGION_FLAGS_MAINLAND_VISIBLE			= (1 << 16);
-const U32 REGION_FLAGS_PUBLIC_ALLOWED			= (1 << 17);
+const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT = (1 << 16);
+const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT = (1 << 17);
 const U32 REGION_FLAGS_BLOCK_DWELL				= (1 << 18);
 
 // Is flight allowed?
@@ -81,18 +73,13 @@ const U32 REGION_FLAGS_ESTATE_SKIP_SCRIPTS		= (1 << 21);
 const U32 REGION_FLAGS_RESTRICT_PUSHOBJECT		= (1 << 22);
 
 const U32 REGION_FLAGS_DENY_ANONYMOUS			= (1 << 23);
-// const U32 REGION_FLAGS_DENY_IDENTIFIED			= (1 << 24);
-// const U32 REGION_FLAGS_DENY_TRANSACTED			= (1 << 25);
 
 const U32 REGION_FLAGS_ALLOW_PARCEL_CHANGES		= (1 << 26);
 
-// const U32 REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER = (1 << 27); // We no longer support ELAR
-
 const U32 REGION_FLAGS_ALLOW_VOICE = (1 << 28);
 
 const U32 REGION_FLAGS_BLOCK_PARCEL_SEARCH = (1 << 29);
 const U32 REGION_FLAGS_DENY_AGEUNVERIFIED	= (1 << 30);
-const U32 REGION_FLAGS_SKIP_MONO_SCRIPTS	= (1 << 31);
 
 const U32 REGION_FLAGS_DEFAULT = REGION_FLAGS_ALLOW_LANDMARK |
 								 REGION_FLAGS_ALLOW_SET_HOME |
@@ -105,7 +92,6 @@ const U32 REGION_FLAGS_PRELUDE_UNSET = REGION_FLAGS_ALLOW_LANDMARK
 									   | REGION_FLAGS_ALLOW_SET_HOME;
 
 const U32 REGION_FLAGS_ESTATE_MASK = REGION_FLAGS_EXTERNALLY_VISIBLE
-									 | REGION_FLAGS_PUBLIC_ALLOWED	
 									 | REGION_FLAGS_SUN_FIXED
 									 | REGION_FLAGS_DENY_ANONYMOUS
 									 | REGION_FLAGS_DENY_AGEUNVERIFIED;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 9e16bf2fbb0fc362ceae59b1e2e7a523f4c3d07f..60b118284b18cc010bc6ad138d0e8e1885fd8494 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -557,7 +557,7 @@ class LLAdvancedCheckConsole : public view_listener_t
 			new_value = get_visibility( (void*)gDebugView->mMemoryView );
 		}
 #endif
-
+		
 		return new_value;
 	}
 };
@@ -4197,9 +4197,9 @@ class LLObjectEnableReturn : public view_listener_t
 					{
 						virtual bool apply(LLViewerObject* obj)
 						{
-							return (obj->isOverAgentOwnedLand() ||
-									obj->isOverGroupOwnedLand() ||
-									obj->permModify());
+							return 
+								obj->permModify() ||
+								obj->isReturnable();
 						}
 					} func;
 					const bool firstonly = true;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 1804fac1b3dbfc3765a4c8b0a2bc4254c29ebb74..18d6e4c8c87c3c79e9c1ea1994965aabff37770d 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -516,20 +516,23 @@ void LLViewerObject::setNameValueList(const std::string& name_value_list)
 
 // This method returns true if the object is over land owned by the
 // agent.
-BOOL LLViewerObject::isOverAgentOwnedLand() const
+bool LLViewerObject::isReturnable()
 {
-	return mRegionp
-		&& mRegionp->getParcelOverlay()
-		&& mRegionp->getParcelOverlay()->isOwnedSelf(getPositionRegion());
-}
+	if (isAttachment())
+	{
+		return false;
+	}
+	std::vector<LLBBox> boxes;
+	boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned());
+	for (child_list_t::iterator iter = mChildList.begin();
+		 iter != mChildList.end(); iter++)
+	{
+		LLViewerObject* child = *iter;
+		boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned());
+	}
 
-// This method returns true if the object is over land owned by the
-// agent.
-BOOL LLViewerObject::isOverGroupOwnedLand() const
-{
-	return mRegionp 
-		&& mRegionp->getParcelOverlay()
-		&& mRegionp->getParcelOverlay()->isOwnedGroup(getPositionRegion());
+	return mRegionp
+		&& mRegionp->objectIsReturnable(getPositionRegion(), boxes);
 }
 
 BOOL LLViewerObject::setParent(LLViewerObject* parent)
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index fe670f882716efb39b69fa24270660384143610d..5c1a34d5555c86c74dbed636a71b8cb02378dd6a 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -226,12 +226,9 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate
 	virtual BOOL hasLightTexture() const			{ return FALSE; }
 
 	// This method returns true if the object is over land owned by
-	// the agent.
-	BOOL isOverAgentOwnedLand() const;
-
-	// True if over land owned by group of which the agent is
-	// either officer or member.
-	BOOL isOverGroupOwnedLand() const;
+	// the agent, one of its groups, or it encroaches and 
+	// anti-encroachment is enabled
+	bool isReturnable();
 
 	/*
 	// This method will scan through this object, and then query the
diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp
index eee653b0c163775d9dd97a99734d5c0d5b3098fc..d07e06f6a7ed171e7864517bcc8b6eaa89f287cf 100644
--- a/indra/newview/llviewerparceloverlay.cpp
+++ b/indra/newview/llviewerparceloverlay.cpp
@@ -145,6 +145,35 @@ BOOL LLViewerParcelOverlay::isOwnedOther(const LLVector3& pos) const
 	return (PARCEL_OWNED == overlay || PARCEL_FOR_SALE == overlay);
 }
 
+bool LLViewerParcelOverlay::encroachesOwned(const std::vector<LLBBox>& boxes) const
+{
+	// boxes are expected to already be axis aligned
+	for (U32 i = 0; i < boxes.size(); ++i)
+	{
+		LLVector3 min = boxes[i].getMinAgent();
+		LLVector3 max = boxes[i].getMaxAgent();
+		
+		S32 left   = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+		S32 right  = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+		S32 top    = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+		S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+	
+		for (S32 row = top; row <= bottom; row++)
+		{
+			for (S32 column = left; column <= right; column++)
+			{
+				U8 type = ownership(row, column);
+				if ((PARCEL_SELF == type)
+					|| (PARCEL_GROUP == type))
+				{
+					return true;
+				}
+			}
+		}
+	}
+	return false;
+}
+
 BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const
 {
 	S32 row =    S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS);
diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h
index 61be2203121ff9d842a223a42c2ed21d84b4f38a..c80baedda6c6256d2fe12af5bee53a3476e1e746 100644
--- a/indra/newview/llviewerparceloverlay.h
+++ b/indra/newview/llviewerparceloverlay.h
@@ -30,6 +30,7 @@
 // The ownership data for land parcels.
 // One of these structures per region.
 
+#include "llbbox.h"
 #include "lldarray.h"
 #include "llframetimer.h"
 #include "lluuid.h"
@@ -54,6 +55,12 @@ class LLViewerParcelOverlay : public LLGLUpdate
 	BOOL			isOwnedSelf(const LLVector3& pos) const;
 	BOOL			isOwnedGroup(const LLVector3& pos) const;
 	BOOL			isOwnedOther(const LLVector3& pos) const;
+
+	// "encroaches" means the prim hangs over the parcel, but its center
+	// might be in another parcel. for now, we simply test axis aligned 
+	// bounding boxes which isn't perfect, but is close
+	bool encroachesOwned(const std::vector<LLBBox>& boxes) const;
+	
 	BOOL			isSoundLocal(const LLVector3& pos) const;
 
 	BOOL			isBuildCameraAllowed(const LLVector3& pos) const;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 551ba18dd549cbd5aa92ec01460d6a6915850c44..2a67d12b648d6ae985003f437183ae75b4632ddb 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1400,7 +1400,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 	capabilityNames.append("SendUserReportWithScreenshot");
 	capabilityNames.append("ServerReleaseNotes");
 	capabilityNames.append("SetDisplayName");
-	capabilityNames.append("SimConsole");
 	capabilityNames.append("SimConsoleAsync");
 	capabilityNames.append("StartGroupProposal");
 	capabilityNames.append("TextureStats");
@@ -1497,6 +1496,20 @@ LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)
 	return NULL;
 }
 
+// the viewer can not yet distinquish between normal- and estate-owned objects
+// so we collapse these two bits and enable the UI if either are set
+const U32 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT
+											| REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT;
+
+bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const
+{
+	return (mParcelOverlay != NULL)
+		&& (mParcelOverlay->isOwnedSelf(pos)
+			|| mParcelOverlay->isOwnedGroup(pos)
+			|| ((mRegionFlags & ALLOW_RETURN_ENCROACHING_OBJECT)
+				&& mParcelOverlay->encroachesOwned(boxes)) );
+}
+
 void LLViewerRegion::showReleaseNotes()
 {
 	std::string url = this->getCapability("ServerReleaseNotes");
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 8b71998f6054ddbaa7fccb8a1ee94ee317a5e093..3d3f1d62a6678ea280c0d70404ece557a3ef972e 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -33,6 +33,7 @@
 
 #include "lldarray.h"
 #include "llwind.h"
+#include "llbbox.h"
 #include "llcloud.h"
 #include "llstat.h"
 #include "v3dmath.h"
@@ -293,6 +294,8 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	std::string getHttpUrl() const { return mHttpUrl ;}
 
 	LLSpatialPartition* getSpatialPartition(U32 type);
+
+	bool objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const;
 public:
 	struct CompareDistance
 	{
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index bb4c5b180416adbbeb2429aa66fc6efcb6eeb87a..fd89044995aab28a4d7107f698ed147bfcec6581 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -2106,31 +2106,6 @@ void LLVOAvatar::computeBodySize()
 			gAgent.sendAgentSetAppearance();
 		}
 	}
-
-/* debug spam
-	std::cout << "skull = " << skull << std::endl;				// adebug
-	std::cout << "head = " << head << std::endl;				// adebug
-	std::cout << "head_scale = " << head_scale << std::endl;	// adebug
-	std::cout << "neck = " << neck << std::endl;				// adebug
-	std::cout << "neck_scale = " << neck_scale << std::endl;	// adebug
-	std::cout << "chest = " << chest << std::endl;				// adebug
-	std::cout << "chest_scale = " << chest_scale << std::endl;	// adebug
-	std::cout << "torso = " << torso << std::endl;				// adebug
-	std::cout << "torso_scale = " << torso_scale << std::endl;	// adebug
-	std::cout << std::endl;	// adebug
-
-	std::cout << "pelvis_scale = " << pelvis_scale << std::endl;// adebug
-	std::cout << std::endl;	// adebug
-
-	std::cout << "hip = " << hip << std::endl;					// adebug
-	std::cout << "hip_scale = " << hip_scale << std::endl;		// adebug
-	std::cout << "ankle = " << ankle << std::endl;				// adebug
-	std::cout << "ankle_scale = " << ankle_scale << std::endl;	// adebug
-	std::cout << "foot = " << foot << std::endl;				// adebug
-	std::cout << "mBodySize = " << mBodySize << std::endl;		// adebug
-	std::cout << "mPelvisToFoot = " << mPelvisToFoot << std::endl;	// adebug
-	std::cout << std::endl;		// adebug
-*/
 }
 
 //------------------------------------------------------------------------
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index d997a262a820dae84ff8332bbf921cf10661a09a..3d500c2371daf44fab9b230efea77770a4170e68 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2717,6 +2717,18 @@
                  function="Floater.Toggle"
                  parameter="region_debug_console" />
             </menu_item_check>
+            <menu_item_check
+             label="Region Debug Console"
+             name="Region Debug Console"
+             shortcut="control|shift|`"
+             use_mac_ctrl="true">
+                <menu_item_check.on_check
+                 function="Floater.Visible"
+                 parameter="region_debug_console" />
+                <menu_item_check.on_click
+                 function="Floater.Toggle"
+                 parameter="region_debug_console" />
+            </menu_item_check>
 
             <menu_item_separator />