diff options
author | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
---|---|---|
committer | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
commit | 420b91db29485df39fd6e724e782c449158811cb (patch) | |
tree | b471a94563af914d3ed3edd3e856d21cb1b69945 /indra/newview/lltoolgrab.cpp |
Print done when done.
Diffstat (limited to 'indra/newview/lltoolgrab.cpp')
-rw-r--r-- | indra/newview/lltoolgrab.cpp | 875 |
1 files changed, 875 insertions, 0 deletions
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp new file mode 100644 index 0000000000..898322d5ca --- /dev/null +++ b/indra/newview/lltoolgrab.cpp @@ -0,0 +1,875 @@ +/** + * @file lltoolgrab.cpp + * @brief LLToolGrab class implementation + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lltoolgrab.h" + +// library headers +#include "indra_constants.h" // for agent control flags +#include "llviewercontrol.h" +#include "llquaternion.h" +#include "llbox.h" +#include "message.h" +#include "llview.h" +#include "llfontgl.h" +#include "llui.h" + +// newview headers +#include "llagent.h" +//#include "llfloateravatarinfo.h" +#include "lldrawable.h" +#include "llfloatertools.h" +#include "llhudeffect.h" +#include "llhudmanager.h" +#include "llregionposition.h" +#include "llselectmgr.h" +#include "llstatusbar.h" +#include "lltoolmgr.h" +#include "lltoolpie.h" +#include "llviewercamera.h" +#include "llviewerobject.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llviewerwindow.h" +#include "llvoavatar.h" +#include "llworld.h" +#include "viewer.h" + +const S32 SLOP_DIST_SQ = 4; + +// Override modifier key behavior with these buttons +BOOL gGrabBtnVertical = FALSE; +BOOL gGrabBtnSpin = FALSE; +LLTool* gGrabTransientTool = NULL; +LLToolGrab *gToolGrab = NULL; +extern BOOL gDebugClicks; + +// +// Methods +// +LLToolGrab::LLToolGrab( LLToolComposite* composite ) +: LLTool( "Grab", composite ), + mMode( GRAB_INACTIVE ), + mVerticalDragging( FALSE ), + mHitLand(FALSE), + mHitObjectID(), + mGrabObject( NULL ), + mMouseDownX( -1 ), + mMouseDownY( -1 ), + mHasMoved( FALSE ), + mSpinGrabbing( FALSE ), + mSpinRotation(), + mHideBuildHighlight(FALSE) +{ } + +LLToolGrab::~LLToolGrab() +{ } + + +// virtual +void LLToolGrab::handleSelect() +{ + gFloaterTools->setStatusText("Drag to move objects, Ctrl to lift, Ctrl-Shift to spin"); + gGrabBtnVertical = FALSE; + gGrabBtnSpin = FALSE; +} + +void LLToolGrab::handleDeselect() +{ + if( hasMouseCapture() ) + { + setMouseCapture( FALSE ); + } + + gFloaterTools->setStatusText(""); +} + +BOOL LLToolGrab::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + if (gDebugClicks) + { + llinfos << "LLToolGrab handleDoubleClick (becoming mouseDown)" << llendl; + } + + return FALSE; +} + +BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask) +{ + if (gDebugClicks) + { + llinfos << "LLToolGrab handleMouseDown" << llendl; + } + + mHitLand = FALSE; + + // call the base class to propogate info to sim + LLTool::handleMouseDown(x, y, mask); + + if (!gAgent.leftButtonGrabbed()) + { + // can grab transparent objects (how touch event propagates, scripters rely on this) + gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback, TRUE); + } + return TRUE; +} + +void LLToolGrab::pickCallback(S32 x, S32 y, MASK mask) +{ + LLViewerObject *objectp = gObjectList.findObject( gLastHitObjectID ); + + BOOL extend_select = (mask & MASK_SHIFT); + + if (!extend_select && !gSelectMgr->isEmpty()) + { + gSelectMgr->deselectAll(); + gToolGrab->mDeselectedThisClick = TRUE; + } + else + { + gToolGrab->mDeselectedThisClick = FALSE; + } + + // if not over object, do nothing + if (!objectp) + { + gToolGrab->setMouseCapture(TRUE); + gToolGrab->mMode = GRAB_NOOBJECT; + gToolGrab->mHitObjectID.setNull(); + } + else + { + gToolGrab->handleObjectHit(objectp, x, y, mask); + } +} + +BOOL LLToolGrab::handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mask) +{ + mMouseDownX = x; + mMouseDownY = y; + mMouseMask = mask; + + if (gDebugClicks) + { + llinfos << "LLToolGrab handleObjectHit " << mMouseDownX << "," << mMouseDownY << llendl; + } + + if (objectp->isAvatar()) + { + if (gGrabTransientTool) + { + gBasicToolset->selectTool( gGrabTransientTool ); + gGrabTransientTool = NULL; + } + return TRUE; + } + + setMouseCapture( TRUE ); + + mHitObjectID = objectp->getID(); + + // Grabs always start from the root + // objectp = (LLViewerObject *)objectp->getRoot(); + + LLViewerObject* parent = objectp->getRootEdit(); + BOOL script_touch = (objectp && objectp->flagHandleTouch()) || (parent && parent->flagHandleTouch()); + + // Clicks on scripted or physical objects are temporary grabs, so + // not "Build mode" + mHideBuildHighlight = script_touch || objectp->usePhysics(); + + if (!objectp->usePhysics()) + { + // 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 (gAgent.cameraMouselook() && !script_touch) + { + mMode = GRAB_LOCKED; + } + else + { + mMode = GRAB_NONPHYSICAL; + } + gViewerWindow->hideCursor(); + gViewerWindow->moveCursorToCenter(); + // Don't bail out here, go on and grab so buttons can get + // their "touched" event. + } + else if( !objectp->permMove() ) + { + // 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 + + mAccumDeltaX = 0; + mAccumDeltaY = 0; + mHasMoved = FALSE; + mOutsideSlop = FALSE; + + mGrabObject = objectp; + + mGrabOffset.clearVec(); + + mVerticalDragging = (mask == MASK_VERTICAL) || gGrabBtnVertical; + + startGrab(x, y); + + if ((mask == MASK_SPIN) || gGrabBtnSpin) + { + startSpin(); + } + + gSelectMgr->updateSelectionCenter(); // update selection beam + + // update point at + LLViewerObject *edit_object = gObjectList.findObject(mHitObjectID); + if (edit_object) + { + LLVector3 local_edit_point = gAgent.getPosAgentFromGlobal(gLastHitNonFloraPosGlobal); + local_edit_point -= edit_object->getPositionAgent(); + local_edit_point = local_edit_point * ~edit_object->getRenderRotation(); + gAgent.setPointAt(POINTAT_TARGET_GRAB, edit_object, local_edit_point ); + gAgent.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; +} + + +void LLToolGrab::startSpin() +{ + mSpinGrabbing = TRUE; + + // Was saveSelectedObjectTransform() + LLViewerObject *root = (LLViewerObject *)mGrabObject->getRoot(); + mSpinRotation = root->getRotation(); + + LLMessageSystem *msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectSpinStart); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() ); + msg->sendMessage( mGrabObject->getRegion()->getHost() ); +} + + +void LLToolGrab::stopSpin() +{ + mSpinGrabbing = FALSE; + + LLMessageSystem *msg = gMessageSystem; + switch(mMode) + { + case GRAB_ACTIVE_CENTER: + case GRAB_NONPHYSICAL: + case GRAB_LOCKED: + msg->newMessageFast(_PREHASH_ObjectSpinStop); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() ); + msg->sendMessage( mGrabObject->getRegion()->getHost() ); + break; + + case GRAB_NOOBJECT: + case GRAB_INACTIVE: + default: + // do nothing + break; + } +} + + +void LLToolGrab::startGrab(S32 x, S32 y) +{ + // Compute grab_offset in the OBJECT's root's coordinate frame + // (sometimes root == object) + LLViewerObject *root = (LLViewerObject *)mGrabObject->getRoot(); + + // drag from center + LLVector3d grab_start_global = root->getPositionGlobal(); + + // Where the grab starts, relative to the center of the root object of the set. + // JC - This code looks wonky, but I believe it does the right thing. + // Otherwise, when you grab a linked object set, it "pops" on the start + // of the drag. + LLVector3d grab_offsetd = root->getPositionGlobal() - mGrabObject->getPositionGlobal(); + + LLVector3 grab_offset; + grab_offset.setVec(grab_offsetd); + + LLQuaternion rotation = root->getRotation(); + rotation.conjQuat(); + grab_offset = grab_offset * rotation; + + // This planar drag starts at the grab point + mDragStartPointGlobal = grab_start_global; + mDragStartFromCamera = grab_start_global - gAgent.getCameraPositionGlobal(); + + LLMessageSystem *msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectGrab); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_LocalID, mGrabObject->mLocalID); + msg->addVector3Fast(_PREHASH_GrabOffset, grab_offset ); + msg->sendMessage( mGrabObject->getRegion()->getHost()); + + mGrabOffsetFromCenterInitial = grab_offset; + mGrabHiddenOffsetFromCamera = mDragStartFromCamera; + + mGrabTimer.reset(); +} + + +BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask) +{ + mLastMouseX = x; + mLastMouseY = y; + + if (!gViewerWindow->getLeftMouseDown()) + { + gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB); + setMouseCapture(FALSE); + return TRUE; + } + + // Do the right hover based on mode + switch( mMode ) + { + case GRAB_ACTIVE_CENTER: + case GRAB_NONPHYSICAL: + handleHoverActive( x, y, mask ); // cursor hidden + break; + + case GRAB_INACTIVE: + handleHoverInactive( x, y, mask ); // cursor set here + break; + + case GRAB_NOOBJECT: + case GRAB_LOCKED: + handleHoverFailed( x, y, mask ); + break; + + } + + return TRUE; +} + + + + +// Dragging. +void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask) +{ + llassert( hasMouseCapture() ); + llassert( mGrabObject ); + if (mGrabObject->isDead()) + { + // Bail out of drag because object has been killed + setMouseCapture(FALSE); + return; + } + + //-------------------------------------------------- + // Toggle spinning + //-------------------------------------------------- + if (mSpinGrabbing && !(mask == MASK_SPIN) && !gGrabBtnSpin) + { + // user released ALT key, stop spinning + stopSpin(); + } + else if (!mSpinGrabbing && (mask == MASK_SPIN) ) + { + // user pressed ALT key, start spinning + startSpin(); + } + + //-------------------------------------------------- + // Toggle vertical dragging + //-------------------------------------------------- + if (mVerticalDragging && !(mask == MASK_VERTICAL) && !gGrabBtnVertical) + { + // ...switch to horizontal dragging + mVerticalDragging = FALSE; + + mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, mGrabObject); + mDragStartFromCamera = mDragStartPointGlobal - gAgent.getCameraPositionGlobal(); + } + else if (!mVerticalDragging && (mask == MASK_VERTICAL) ) + { + // ...switch to vertical dragging + mVerticalDragging = TRUE; + + mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, mGrabObject); + mDragStartFromCamera = mDragStartPointGlobal - gAgent.getCameraPositionGlobal(); + } + + const F32 RADIANS_PER_PIXEL_X = 0.01f; + const F32 RADIANS_PER_PIXEL_Y = 0.01f; + + const F32 SENSITIVITY_X = 0.0075f; + const F32 SENSITIVITY_Y = 0.0075f; + + S32 dx = x - (gViewerWindow->getWindowWidth() / 2); + S32 dy = y - (gViewerWindow->getWindowHeight() / 2); + + if (dx != 0 || dy != 0) + { + mAccumDeltaX += dx; + mAccumDeltaY += dy; + S32 dist_sq = mAccumDeltaX * mAccumDeltaX + mAccumDeltaY * mAccumDeltaY; + if (dist_sq > SLOP_DIST_SQ) + { + mOutsideSlop = TRUE; + } + + // mouse has moved outside center + mHasMoved = TRUE; + + if (mSpinGrabbing) + { + //------------------------------------------------------ + // Handle spinning + //------------------------------------------------------ + + // x motion maps to rotation around vertical axis + LLVector3 up(0.f, 0.f, 1.f); + LLQuaternion rotation_around_vertical( dx*RADIANS_PER_PIXEL_X, up ); + + // y motion maps to rotation around left axis + const LLVector3 &agent_left = gCamera->getLeftAxis(); + LLQuaternion rotation_around_left( dy*RADIANS_PER_PIXEL_Y, agent_left ); + + // compose with current rotation + mSpinRotation = mSpinRotation * rotation_around_vertical; + mSpinRotation = mSpinRotation * rotation_around_left; + + // TODO: Throttle these + LLMessageSystem *msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectSpinUpdate); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() ); + msg->addQuatFast(_PREHASH_Rotation, mSpinRotation ); + msg->sendMessage( mGrabObject->getRegion()->getHost() ); + } + else + { + //------------------------------------------------------ + // Handle grabbing + //------------------------------------------------------ + + LLVector3d x_part; + x_part.setVec(gCamera->getLeftAxis()); + x_part.mdV[VZ] = 0.0; + x_part.normVec(); + + LLVector3d y_part; + if( mVerticalDragging ) + { + y_part.setVec(gCamera->getUpAxis()); + // y_part.setVec(0.f, 0.f, 1.f); + } + else + { + // drag toward camera + y_part = x_part % LLVector3d::z_axis; + y_part.mdV[VZ] = 0.0; + y_part.normVec(); + } + + mGrabHiddenOffsetFromCamera = mGrabHiddenOffsetFromCamera + + (x_part * (-dx * SENSITIVITY_X)) + + (y_part * ( dy * SENSITIVITY_Y)); + + + // Send the message to the viewer. + F32 dt = mGrabTimer.getElapsedTimeAndResetF32(); + U32 dt_milliseconds = (U32) (1000.f * dt); + + // need to return offset from mGrabStartPoint + LLVector3d grab_point_global; + + grab_point_global = gAgent.getCameraPositionGlobal() + mGrabHiddenOffsetFromCamera; + + /* Snap to grid disabled for grab tool - very confusing + // Handle snapping to grid, but only when the tool is formally selected. + BOOL snap_on = gSavedSettings.getBOOL("SnapEnabled"); + if (snap_on && !gGrabTransientTool) + { + F64 snap_size = gSavedSettings.getF32("GridResolution"); + U8 snap_dimensions = (mVerticalDragging ? 3 : 2); + + for (U8 i = 0; i < snap_dimensions; i++) + { + grab_point_global.mdV[i] += snap_size / 2; + grab_point_global.mdV[i] -= fmod(grab_point_global.mdV[i], snap_size); + } + } + */ + + // Don't let object centers go underground. + F32 land_height = gWorldPointer->resolveLandHeightGlobal(grab_point_global); + + if (grab_point_global.mdV[VZ] < land_height) + { + grab_point_global.mdV[VZ] = land_height; + } + + // For safety, cap heights where objects can be dragged + if (grab_point_global.mdV[VZ] > MAX_OBJECT_Z) + { + grab_point_global.mdV[VZ] = MAX_OBJECT_Z; + } + + grab_point_global = gWorldp->clipToVisibleRegions(mDragStartPointGlobal, grab_point_global); + // propagate constrained grab point back to grab offset + mGrabHiddenOffsetFromCamera = grab_point_global - gAgent.getCameraPositionGlobal(); + + // Handle auto-rotation at screen edge. + LLVector3 grab_pos_agent = gAgent.getPosAgentFromGlobal( grab_point_global ); + + LLCoordGL grab_center_gl( gViewerWindow->getWindowWidth() / 2, gViewerWindow->getWindowHeight() / 2); + gCamera->projectPosAgentToScreen(grab_pos_agent, grab_center_gl); + + const S32 ROTATE_H_MARGIN = gViewerWindow->getWindowWidth() / 20; + const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD; + const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped; + // ...build mode moves camera about focus point + if (grab_center_gl.mX < ROTATE_H_MARGIN) + { + if (gAgent.getFocusOnAvatar()) + { + gAgent.yaw(rotate_angle); + } + else + { + gAgent.cameraOrbitAround(rotate_angle); + } + } + else if (grab_center_gl.mX > gViewerWindow->getWindowWidth() - ROTATE_H_MARGIN) + { + if (gAgent.getFocusOnAvatar()) + { + gAgent.yaw(-rotate_angle); + } + else + { + gAgent.cameraOrbitAround(-rotate_angle); + } + } + + // Don't move above top of screen or below bottom + if ((grab_center_gl.mY < gViewerWindow->getWindowHeight() - 6) + && (grab_center_gl.mY > 24)) + { + // Transmit update to simulator + LLVector3 grab_pos_region = mGrabObject->getRegion()->getPosRegionFromGlobal( grab_point_global ); + + LLMessageSystem *msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectGrabUpdate); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() ); + msg->addVector3Fast(_PREHASH_GrabOffsetInitial, mGrabOffsetFromCenterInitial ); + msg->addVector3Fast(_PREHASH_GrabPosition, grab_pos_region ); + msg->addU32Fast(_PREHASH_TimeSinceLast, dt_milliseconds ); + msg->sendMessage( mGrabObject->getRegion()->getHost() ); + } + } + + gViewerWindow->moveCursorToCenter(); + + gSelectMgr->updateSelectionCenter(); + + } + + // once we've initiated a drag, lock the camera down + if (mHasMoved) + { + if (!gAgent.cameraMouselook() && + !mGrabObject->isHUDAttachment() && + mGrabObject->getRoot() == gAgent.getAvatarObject()->getRoot()) + { + // force focus to point in space where we were looking previously + gAgent.setFocusGlobal(gAgent.calcFocusPositionTargetGlobal(), LLUUID::null); + gAgent.setFocusOnAvatar(FALSE, ANIMATE); + } + else + { + gAgent.clearFocusObject(); + } + } + + // HACK to avoid assert: error checking system makes sure that the cursor is set during every handleHover. This is actually a no-op since the cursor is hidden. + gViewerWindow->setCursor(UI_CURSOR_ARROW); + + lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (active) [cursor hidden]" << llendl; +} + + +// Not dragging. Just showing affordances +void LLToolGrab::handleHoverInactive(S32 x, S32 y, MASK mask) +{ + const F32 ROTATE_ANGLE_PER_SECOND = 40.f * DEG_TO_RAD; + const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped; + + // Look for cursor against the edge of the screen + // Only works in fullscreen + if (gSavedSettings.getBOOL("FullScreen")) + { + if (gAgent.cameraThirdPerson() ) + { + if (x == 0) + { + gAgent.yaw(rotate_angle); + //gAgent.setControlFlags(AGENT_CONTROL_YAW_POS); + } + else if (x == (gViewerWindow->getWindowWidth() - 1) ) + { + gAgent.yaw(-rotate_angle); + //gAgent.setControlFlags(AGENT_CONTROL_YAW_NEG); + } + } + } + + // JC - TODO - change cursor based on gGrabBtnVertical, gGrabBtnSpin + lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (inactive-not over editable object)" << llendl; + gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB); +} + +// User is trying to do something that's not allowed. +void LLToolGrab::handleHoverFailed(S32 x, S32 y, MASK mask) +{ + if( GRAB_NOOBJECT == mMode ) + { + gViewerWindow->setCursor(UI_CURSOR_NO); + lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (not on object)" << llendl; + } + else + { + S32 dist_sq = (x-mMouseDownX) * (x-mMouseDownX) + (y-mMouseDownY) * (y-mMouseDownY); + if( mOutsideSlop || dist_sq > SLOP_DIST_SQ ) + { + mOutsideSlop = TRUE; + + switch( mMode ) + { + case GRAB_LOCKED: + gViewerWindow->setCursor(UI_CURSOR_GRABLOCKED); + lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (grab failed, no move permission)" << llendl; + break; + +// Non physical now handled by handleHoverActive - CRO +// case GRAB_NONPHYSICAL: +// gViewerWindow->setCursor(UI_CURSOR_ARROW); +// lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (grab failed, nonphysical)" << llendl; +// break; + default: + llassert(0); + } + } + else + { + gViewerWindow->setCursor(UI_CURSOR_ARROW); + lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (grab failed but within slop)" << llendl; + } + } +} + + + + +BOOL LLToolGrab::handleMouseUp(S32 x, S32 y, MASK mask) +{ + // call the base class to propogate info to sim + LLTool::handleMouseUp(x, y, mask); + + if( hasMouseCapture() ) + { + setMouseCapture( FALSE ); + } + mMode = GRAB_INACTIVE; + + // HACK: Make some grabs temporary + if (gGrabTransientTool) + { + gBasicToolset->selectTool( gGrabTransientTool ); + gGrabTransientTool = NULL; + } + + //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject")); + + return TRUE; +} + +void LLToolGrab::stopEditing() +{ + if( hasMouseCapture() ) + { + setMouseCapture( FALSE ); + } +} + +void LLToolGrab::onMouseCaptureLost() +{ + // First, fix cursor placement + if( !gAgent.cameraMouselook() + && (GRAB_ACTIVE_CENTER == mMode || GRAB_NONPHYSICAL == mMode)) + { + llassert( mGrabObject ); + + if (mGrabObject->isHUDAttachment()) + { + // ...move cursor "naturally", as if it had moved when hidden + S32 x = mMouseDownX + mAccumDeltaX; + S32 y = mMouseDownY + mAccumDeltaY; + LLUI::setCursorPositionScreen(x, y); + } + else if (mHasMoved) + { + // ...move cursor back to the center of the object + LLVector3 grab_point_agent = mGrabObject->getRenderPosition(); + + LLCoordGL gl_point; + gCamera->projectPosAgentToScreen(grab_point_agent, gl_point); + + LLUI::setCursorPositionScreen(gl_point.mX, gl_point.mY); + } + else + { + // ...move cursor back to click position + LLUI::setCursorPositionScreen(mMouseDownX, mMouseDownY); + } + + gViewerWindow->showCursor(); + } + + stopGrab(); + stopSpin(); + mMode = GRAB_INACTIVE; + + mHideBuildHighlight = FALSE; + + mGrabObject = NULL; + + gSelectMgr->updateSelectionCenter(); + gAgent.setPointAt(POINTAT_TARGET_CLEAR); + gAgent.setLookAt(LOOKAT_TARGET_CLEAR); + + dialog_refresh_all(); +} + + +void LLToolGrab::stopGrab() +{ + // Next, send messages to simulator + LLMessageSystem *msg = gMessageSystem; + switch(mMode) + { + case GRAB_ACTIVE_CENTER: + case GRAB_NONPHYSICAL: + case GRAB_LOCKED: + msg->newMessageFast(_PREHASH_ObjectDeGrab); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_LocalID, mGrabObject->mLocalID); + msg->sendMessage(mGrabObject->getRegion()->getHost()); + + mVerticalDragging = FALSE; + mGrabOffset.clearVec(); + break; + + case GRAB_NOOBJECT: + case GRAB_INACTIVE: + default: + // do nothing + break; + } + + mHideBuildHighlight = FALSE; +} + + +void LLToolGrab::draw() +{ } + +void LLToolGrab::render() +{ } + +BOOL LLToolGrab::isEditing() +{ + // Can't just compare to null directly due to "smart" pointer. + LLViewerObject *obj = mGrabObject; + return (obj != NULL); +} + +LLViewerObject* LLToolGrab::getEditingObject() +{ + return mGrabObject; +} + + +LLVector3d LLToolGrab::getEditingPointGlobal() +{ + return getGrabPointGlobal(); +} + +LLVector3d LLToolGrab::getGrabPointGlobal() +{ + switch(mMode) + { + case GRAB_ACTIVE_CENTER: + case GRAB_NONPHYSICAL: + case GRAB_LOCKED: + return gAgent.getCameraPositionGlobal() + mGrabHiddenOffsetFromCamera; + + case GRAB_NOOBJECT: + case GRAB_INACTIVE: + default: + return gAgent.getPositionGlobal(); + } +} |