BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info)
{
	mGrabPick = info;
	LLViewerObject* objectp = mGrabPick.getObject();

	if (gDebugClicks)
	{
		llinfos << "LLToolGrab handleObjectHit " << info.mMousePt.mX << "," << info.mMousePt.mY << llendl;
	}

	if (NULL == objectp) // unexpected
	{
		llwarns << "objectp was NULL; returning FALSE" << llendl;
		return FALSE;
	}

	if (objectp->isAvatar())
	{
		if (gGrabTransientTool)
		{
			gBasicToolset->selectTool( gGrabTransientTool );
			gGrabTransientTool = NULL;
		}
		return TRUE;
	}

	setMouseCapture( TRUE );

	// Grabs always start from the root
	// objectp = (LLViewerObject *)objectp->getRoot();

	LLViewerObject* parent = objectp->getRootEdit();
	BOOL script_touch = (objectp->flagHandleTouch()) || (parent && parent->flagHandleTouch());

	// Clicks on scripted or physical objects are temporary grabs, so
	// not "Build mode"
	mHideBuildHighlight = script_touch || objectp->flagUsePhysics();

	if (!objectp->flagUsePhysics())
	{
		if (script_touch)
		{
			mMode = GRAB_NONPHYSICAL;  // if it has a script, use the non-physical grab
		}
		else
		{
			// In mouselook, we shouldn't be able to grab non-physical, 
			// non-touchable objects.  If it has a touch handler, we
			// do grab it (so llDetectedGrab works), but movement is
			// blocked on the server side. JC
			if (gAgentCamera.cameraMouselook())
			{
				mMode = GRAB_LOCKED;
				gViewerWindow->hideCursor();
				gViewerWindow->moveCursorToCenter();
			}
			else if (objectp->permMove() && !objectp->isPermanentEnforced())
			{
				mMode = GRAB_ACTIVE_CENTER;
				gViewerWindow->hideCursor();
				gViewerWindow->moveCursorToCenter();
			}
			else
			{
				mMode = GRAB_LOCKED;
			}

			
		}
	}
	else if( objectp->flagCharacter() || !objectp->permMove() || objectp->isPermanentEnforced())
	{
		// if mouse is over a physical object without move permission, show feedback if user tries to move it.
		mMode = GRAB_LOCKED;

		// Don't bail out here, go on and grab so buttons can get
		// their "touched" event.
	}
	else
	{
		// if mouse is over a physical object with move permission, 
		// select it and enter "grab" mode (hiding cursor, etc.)

		mMode = GRAB_ACTIVE_CENTER;

		gViewerWindow->hideCursor();
		gViewerWindow->moveCursorToCenter();
	}

	// Always send "touched" message

	mLastMouseX = gViewerWindow->getCurrentMouseX();
	mLastMouseY = gViewerWindow->getCurrentMouseY();
	mAccumDeltaX = 0;
	mAccumDeltaY = 0;
	mHasMoved = FALSE;
	mOutsideSlop = FALSE;

	mVerticalDragging = (info.mKeyMask == MASK_VERTICAL) || gGrabBtnVertical;

	startGrab();

	if ((info.mKeyMask == MASK_SPIN) || gGrabBtnSpin)
	{
		startSpin();
	}

	LLSelectMgr::getInstance()->updateSelectionCenter();		// update selection beam

	// update point at
	LLViewerObject *edit_object = info.getObject();
	if (edit_object && info.mPickType != LLPickInfo::PICK_FLORA)
	{
		LLVector3 local_edit_point = gAgent.getPosAgentFromGlobal(info.mPosGlobal);
		local_edit_point -= edit_object->getPositionAgent();
		local_edit_point = local_edit_point * ~edit_object->getRenderRotation();
		gAgentCamera.setPointAt(POINTAT_TARGET_GRAB, edit_object, local_edit_point );
		gAgentCamera.setLookAt(LOOKAT_TARGET_SELECT, edit_object, local_edit_point );
	}

	// on transient grabs (clicks on world objects), kill the grab immediately
	if (!gViewerWindow->getLeftMouseDown() 
		&& gGrabTransientTool 
		&& (mMode == GRAB_NONPHYSICAL || mMode == GRAB_LOCKED))
	{
		gBasicToolset->selectTool( gGrabTransientTool );
		gGrabTransientTool = NULL;
	}

	return TRUE;
}