lltoolgrab.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "lltoolgrab.h"
00035  
00036 // library headers
00037 #include "indra_constants.h"            // for agent control flags
00038 #include "llviewercontrol.h"
00039 #include "llquaternion.h"
00040 #include "llbox.h"
00041 #include "message.h"
00042 #include "llview.h"
00043 #include "llfontgl.h"
00044 #include "llui.h"
00045 
00046 // newview headers
00047 #include "llagent.h"
00048 //#include "llfloateravatarinfo.h"
00049 #include "lldrawable.h"
00050 #include "llfloatertools.h"
00051 #include "llhudeffect.h"
00052 #include "llhudmanager.h"
00053 #include "llregionposition.h"
00054 #include "llselectmgr.h"
00055 #include "llstatusbar.h"
00056 #include "lltoolmgr.h"
00057 #include "lltoolpie.h"
00058 #include "llviewercamera.h"
00059 #include "llviewerobject.h"
00060 #include "llviewerobjectlist.h" 
00061 #include "llviewerregion.h"
00062 #include "llviewerwindow.h"
00063 #include "llvoavatar.h"
00064 #include "llworld.h"
00065 #include "viewer.h"
00066 
00067 const S32 SLOP_DIST_SQ = 4;
00068 
00069 // Override modifier key behavior with these buttons
00070 BOOL gGrabBtnVertical = FALSE;
00071 BOOL gGrabBtnSpin = FALSE;
00072 LLTool* gGrabTransientTool = NULL;
00073 LLToolGrab *gToolGrab = NULL;
00074 extern BOOL gDebugClicks;
00075 
00076 //
00077 // Methods
00078 //
00079 LLToolGrab::LLToolGrab( LLToolComposite* composite )
00080 :       LLTool( "Grab", composite ),
00081         mMode( GRAB_INACTIVE ),
00082         mVerticalDragging( FALSE ),
00083         mHitLand(FALSE),
00084         mHitObjectID(),
00085         mGrabObject( NULL ),
00086         mMouseDownX( -1 ),
00087         mMouseDownY( -1 ),
00088         mHasMoved( FALSE ),
00089         mSpinGrabbing( FALSE ),
00090         mSpinRotation(),
00091         mHideBuildHighlight(FALSE)
00092 { }
00093 
00094 LLToolGrab::~LLToolGrab()
00095 { }
00096 
00097 
00098 // virtual
00099 void LLToolGrab::handleSelect()
00100 {
00101         if(gFloaterTools)
00102         {
00103                 // viewer can crash during startup if we don't check.
00104                 gFloaterTools->setStatusText("grab");
00105         }
00106         gGrabBtnVertical = FALSE;
00107         gGrabBtnSpin = FALSE;
00108 }
00109 
00110 void LLToolGrab::handleDeselect()
00111 {
00112         if( hasMouseCapture() )
00113         {
00114                 setMouseCapture( FALSE );
00115         }
00116 
00117 }
00118 
00119 BOOL LLToolGrab::handleDoubleClick(S32 x, S32 y, MASK mask)
00120 {
00121         if (gDebugClicks)
00122         {
00123                 llinfos << "LLToolGrab handleDoubleClick (becoming mouseDown)" << llendl;
00124         }
00125 
00126         return FALSE;
00127 }
00128 
00129 BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask)
00130 {
00131         if (gDebugClicks)
00132         {
00133                 llinfos << "LLToolGrab handleMouseDown" << llendl;
00134         }
00135 
00136         mHitLand = FALSE;
00137 
00138         // call the base class to propogate info to sim
00139         LLTool::handleMouseDown(x, y, mask);
00140         
00141         if (!gAgent.leftButtonGrabbed())
00142         {
00143                 // can grab transparent objects (how touch event propagates, scripters rely on this)
00144                 gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback, TRUE);
00145         }
00146         return TRUE;
00147 }
00148 
00149 void LLToolGrab::pickCallback(S32 x, S32 y, MASK mask)
00150 {
00151         LLViewerObject  *objectp = gObjectList.findObject( gLastHitObjectID );
00152 
00153         BOOL extend_select = (mask & MASK_SHIFT);
00154 
00155         if (!extend_select && !gSelectMgr->getSelection()->isEmpty())
00156         {
00157                 gSelectMgr->deselectAll();
00158                 gToolGrab->mDeselectedThisClick = TRUE;
00159         }
00160         else
00161         {
00162                 gToolGrab->mDeselectedThisClick = FALSE;
00163         }
00164 
00165         // if not over object, do nothing
00166         if (!objectp)
00167         {
00168                 gToolGrab->setMouseCapture(TRUE);
00169                 gToolGrab->mMode = GRAB_NOOBJECT;
00170                 gToolGrab->mHitObjectID.setNull();
00171         }
00172         else
00173         {
00174                 gToolGrab->handleObjectHit(objectp, x, y, mask);
00175         }
00176 }
00177 
00178 BOOL LLToolGrab::handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mask)
00179 {
00180         mMouseDownX = x;
00181         mMouseDownY = y;
00182         mMouseMask = mask;
00183 
00184         if (gDebugClicks)
00185         {
00186                 llinfos << "LLToolGrab handleObjectHit " << mMouseDownX << "," << mMouseDownY << llendl;
00187         }
00188 
00189         if (NULL == objectp) // unexpected
00190         {
00191                 llwarns << "objectp was NULL; returning FALSE" << llendl;
00192                 return FALSE;
00193         }
00194 
00195         if (objectp->isAvatar())
00196         {
00197                 if (gGrabTransientTool)
00198                 {
00199                         gBasicToolset->selectTool( gGrabTransientTool );
00200                         gGrabTransientTool = NULL;
00201                 }
00202                 return TRUE;
00203         }
00204 
00205         setMouseCapture( TRUE );
00206 
00207         mHitObjectID = objectp->getID();
00208 
00209         // Grabs always start from the root
00210         // objectp = (LLViewerObject *)objectp->getRoot();
00211 
00212         LLViewerObject* parent = objectp->getRootEdit();
00213         BOOL script_touch = (objectp->flagHandleTouch()) || (parent && parent->flagHandleTouch());
00214 
00215         // Clicks on scripted or physical objects are temporary grabs, so
00216         // not "Build mode"
00217         mHideBuildHighlight = script_touch || objectp->usePhysics();
00218 
00219         if (!objectp->usePhysics())
00220         {
00221                 // In mouselook, we shouldn't be able to grab non-physical, 
00222                 // non-touchable objects.  If it has a touch handler, we
00223                 // do grab it (so llDetectedGrab works), but movement is
00224                 // blocked on the server side. JC
00225                 if (gAgent.cameraMouselook() && !script_touch)
00226                 {
00227                         mMode = GRAB_LOCKED;
00228                 }
00229                 else
00230                 {
00231                         mMode = GRAB_NONPHYSICAL;
00232                 }
00233                 gViewerWindow->hideCursor();
00234                 gViewerWindow->moveCursorToCenter();
00235                 // Don't bail out here, go on and grab so buttons can get
00236                 // their "touched" event.
00237         }
00238         else if( !objectp->permMove() )
00239         {
00240                 // if mouse is over a physical object without move permission, show feedback if user tries to move it.
00241                 mMode = GRAB_LOCKED;
00242 
00243                 // Don't bail out here, go on and grab so buttons can get
00244                 // their "touched" event.
00245         }
00246         else
00247         {
00248                 // if mouse is over a physical object with move permission, 
00249                 // select it and enter "grab" mode (hiding cursor, etc.)
00250 
00251                 mMode = GRAB_ACTIVE_CENTER;
00252 
00253                 gViewerWindow->hideCursor();
00254                 gViewerWindow->moveCursorToCenter();
00255         }
00256 
00257         // Always send "touched" message
00258 
00259         mAccumDeltaX = 0;
00260         mAccumDeltaY = 0;
00261         mHasMoved = FALSE;
00262         mOutsideSlop = FALSE;
00263 
00264         mGrabObject = objectp;
00265 
00266         mGrabOffset.clearVec();
00267 
00268         mVerticalDragging = (mask == MASK_VERTICAL) || gGrabBtnVertical;
00269 
00270         startGrab(x, y);
00271 
00272         if ((mask == MASK_SPIN) || gGrabBtnSpin)
00273         {
00274                 startSpin();
00275         }
00276 
00277         gSelectMgr->updateSelectionCenter();            // update selection beam
00278 
00279         // update point at
00280         LLViewerObject *edit_object = gObjectList.findObject(mHitObjectID);
00281         if (edit_object)
00282         {
00283                 LLVector3 local_edit_point = gAgent.getPosAgentFromGlobal(gLastHitNonFloraPosGlobal);
00284                 local_edit_point -= edit_object->getPositionAgent();
00285                 local_edit_point = local_edit_point * ~edit_object->getRenderRotation();
00286                 gAgent.setPointAt(POINTAT_TARGET_GRAB, edit_object, local_edit_point );
00287                 gAgent.setLookAt(LOOKAT_TARGET_SELECT, edit_object, local_edit_point );
00288         }
00289 
00290         // on transient grabs (clicks on world objects), kill the grab immediately
00291         if (!gViewerWindow->getLeftMouseDown() 
00292                 && gGrabTransientTool 
00293                 && (mMode == GRAB_NONPHYSICAL || mMode == GRAB_LOCKED))
00294         {
00295                 gBasicToolset->selectTool( gGrabTransientTool );
00296                 gGrabTransientTool = NULL;
00297         }
00298 
00299         return TRUE;
00300 }
00301 
00302 
00303 void LLToolGrab::startSpin()
00304 {
00305         mSpinGrabbing = TRUE;
00306 
00307         // Was saveSelectedObjectTransform()
00308         LLViewerObject *root = (LLViewerObject *)mGrabObject->getRoot();
00309         mSpinRotation = root->getRotation();
00310 
00311         LLMessageSystem *msg = gMessageSystem;
00312         msg->newMessageFast(_PREHASH_ObjectSpinStart);
00313         msg->nextBlockFast(_PREHASH_AgentData);
00314         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
00315         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00316         msg->nextBlockFast(_PREHASH_ObjectData);
00317         msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() );
00318         msg->sendMessage( mGrabObject->getRegion()->getHost() );
00319 }
00320 
00321 
00322 void LLToolGrab::stopSpin()
00323 {
00324         mSpinGrabbing = FALSE;
00325 
00326         LLMessageSystem *msg = gMessageSystem;
00327         switch(mMode)
00328         {
00329         case GRAB_ACTIVE_CENTER:
00330         case GRAB_NONPHYSICAL:
00331         case GRAB_LOCKED:
00332                 msg->newMessageFast(_PREHASH_ObjectSpinStop);
00333                 msg->nextBlockFast(_PREHASH_AgentData);
00334                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
00335                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00336                 msg->nextBlockFast(_PREHASH_ObjectData);
00337                 msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() );
00338                 msg->sendMessage( mGrabObject->getRegion()->getHost() );
00339                 break;
00340 
00341         case GRAB_NOOBJECT:
00342         case GRAB_INACTIVE:
00343         default:
00344                 // do nothing
00345                 break;
00346         }
00347 }
00348 
00349 
00350 void LLToolGrab::startGrab(S32 x, S32 y)
00351 {
00352         // Compute grab_offset in the OBJECT's root's coordinate frame
00353         // (sometimes root == object)
00354         LLViewerObject *root = (LLViewerObject *)mGrabObject->getRoot();
00355 
00356         // drag from center
00357         LLVector3d grab_start_global = root->getPositionGlobal();
00358 
00359         // Where the grab starts, relative to the center of the root object of the set.
00360         // JC - This code looks wonky, but I believe it does the right thing.
00361         // Otherwise, when you grab a linked object set, it "pops" on the start
00362         // of the drag.
00363         LLVector3d grab_offsetd = root->getPositionGlobal() - mGrabObject->getPositionGlobal();
00364 
00365         LLVector3 grab_offset;
00366         grab_offset.setVec(grab_offsetd);
00367 
00368         LLQuaternion rotation = root->getRotation();
00369         rotation.conjQuat();
00370         grab_offset = grab_offset * rotation;
00371 
00372         // This planar drag starts at the grab point
00373         mDragStartPointGlobal = grab_start_global;
00374         mDragStartFromCamera = grab_start_global - gAgent.getCameraPositionGlobal();
00375 
00376         LLMessageSystem *msg = gMessageSystem;
00377         msg->newMessageFast(_PREHASH_ObjectGrab);
00378         msg->nextBlockFast(_PREHASH_AgentData);
00379         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00380         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00381         msg->nextBlockFast(_PREHASH_ObjectData);
00382         msg->addU32Fast(_PREHASH_LocalID, mGrabObject->mLocalID);
00383         msg->addVector3Fast(_PREHASH_GrabOffset, grab_offset );
00384         msg->sendMessage( mGrabObject->getRegion()->getHost());
00385 
00386         mGrabOffsetFromCenterInitial = grab_offset;
00387         mGrabHiddenOffsetFromCamera = mDragStartFromCamera;
00388 
00389         mGrabTimer.reset();
00390 }
00391 
00392 
00393 BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask)
00394 {
00395         mLastMouseX = x;
00396         mLastMouseY = y;
00397 
00398         if (!gViewerWindow->getLeftMouseDown())
00399         {
00400                 gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
00401                 setMouseCapture(FALSE);
00402                 return TRUE;
00403         }
00404 
00405         // Do the right hover based on mode
00406         switch( mMode )
00407         {
00408         case GRAB_ACTIVE_CENTER:
00409         case GRAB_NONPHYSICAL:
00410                 handleHoverActive( x, y, mask );        // cursor hidden
00411                 break;
00412 
00413         case GRAB_INACTIVE:
00414                 handleHoverInactive( x, y, mask );  // cursor set here
00415                 break;
00416 
00417         case GRAB_NOOBJECT:
00418         case GRAB_LOCKED:
00419                 handleHoverFailed( x, y, mask );
00420                 break;
00421 
00422         }
00423 
00424         return TRUE;
00425 }
00426 
00427 
00428 
00429                 
00430 // Dragging.
00431 void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
00432 {
00433         llassert( hasMouseCapture() );
00434         llassert( mGrabObject );
00435         if (mGrabObject->isDead())
00436         {
00437                 // Bail out of drag because object has been killed
00438                 setMouseCapture(FALSE);
00439                 return;
00440         }
00441 
00442         //--------------------------------------------------
00443         // Toggle spinning
00444         //--------------------------------------------------
00445         if (mSpinGrabbing && !(mask == MASK_SPIN) && !gGrabBtnSpin)
00446         {
00447                 // user released ALT key, stop spinning
00448                 stopSpin();
00449         }
00450         else if (!mSpinGrabbing && (mask == MASK_SPIN) )
00451         {
00452                 // user pressed ALT key, start spinning
00453                 startSpin();
00454         }
00455 
00456         //--------------------------------------------------
00457         // Toggle vertical dragging
00458         //--------------------------------------------------
00459         if (mVerticalDragging && !(mask == MASK_VERTICAL) && !gGrabBtnVertical)
00460         {
00461                 // ...switch to horizontal dragging
00462                 mVerticalDragging = FALSE;
00463 
00464                 mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, mGrabObject);
00465                 mDragStartFromCamera = mDragStartPointGlobal - gAgent.getCameraPositionGlobal();
00466         }
00467         else if (!mVerticalDragging && (mask == MASK_VERTICAL) )
00468         {
00469                 // ...switch to vertical dragging
00470                 mVerticalDragging = TRUE;
00471 
00472                 mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, mGrabObject);
00473                 mDragStartFromCamera = mDragStartPointGlobal - gAgent.getCameraPositionGlobal();
00474         }
00475 
00476         const F32 RADIANS_PER_PIXEL_X = 0.01f;
00477         const F32 RADIANS_PER_PIXEL_Y = 0.01f;
00478 
00479         const F32 SENSITIVITY_X = 0.0075f;
00480         const F32 SENSITIVITY_Y = 0.0075f;
00481 
00482         S32 dx = x - (gViewerWindow->getWindowWidth() / 2);
00483         S32 dy = y - (gViewerWindow->getWindowHeight() / 2);
00484 
00485         if (dx != 0 || dy != 0)
00486         {
00487                 mAccumDeltaX += dx;
00488                 mAccumDeltaY += dy;
00489                 S32 dist_sq = mAccumDeltaX * mAccumDeltaX + mAccumDeltaY * mAccumDeltaY;
00490                 if (dist_sq > SLOP_DIST_SQ)
00491                 {
00492                         mOutsideSlop = TRUE;
00493                 }
00494 
00495                 // mouse has moved outside center
00496                 mHasMoved = TRUE;
00497                 
00498                 if (mSpinGrabbing)
00499                 {
00500                         //------------------------------------------------------
00501                         // Handle spinning
00502                         //------------------------------------------------------
00503 
00504                         // x motion maps to rotation around vertical axis
00505                         LLVector3 up(0.f, 0.f, 1.f);
00506                         LLQuaternion rotation_around_vertical( dx*RADIANS_PER_PIXEL_X, up );
00507 
00508                         // y motion maps to rotation around left axis
00509                         const LLVector3 &agent_left = gCamera->getLeftAxis();
00510                         LLQuaternion rotation_around_left( dy*RADIANS_PER_PIXEL_Y, agent_left );
00511 
00512                         // compose with current rotation
00513                         mSpinRotation = mSpinRotation * rotation_around_vertical;
00514                         mSpinRotation = mSpinRotation * rotation_around_left;
00515 
00516                         // TODO: Throttle these
00517                         LLMessageSystem *msg = gMessageSystem;
00518                         msg->newMessageFast(_PREHASH_ObjectSpinUpdate);
00519                         msg->nextBlockFast(_PREHASH_AgentData);
00520                         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
00521                         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00522                         msg->nextBlockFast(_PREHASH_ObjectData);
00523                         msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() );
00524                         msg->addQuatFast(_PREHASH_Rotation, mSpinRotation );
00525                         msg->sendMessage( mGrabObject->getRegion()->getHost() );
00526                 }
00527                 else
00528                 {
00529                         //------------------------------------------------------
00530                         // Handle grabbing
00531                         //------------------------------------------------------
00532 
00533                         LLVector3d x_part;
00534                         x_part.setVec(gCamera->getLeftAxis());
00535                         x_part.mdV[VZ] = 0.0;
00536                         x_part.normVec();
00537 
00538                         LLVector3d y_part;
00539                         if( mVerticalDragging )
00540                         {
00541                                 y_part.setVec(gCamera->getUpAxis());
00542                                 // y_part.setVec(0.f, 0.f, 1.f);
00543                         }
00544                         else
00545                         {
00546                                 // drag toward camera
00547                                 y_part = x_part % LLVector3d::z_axis;
00548                                 y_part.mdV[VZ] = 0.0;
00549                                 y_part.normVec();
00550                         }
00551 
00552                         mGrabHiddenOffsetFromCamera = mGrabHiddenOffsetFromCamera 
00553                                 + (x_part * (-dx * SENSITIVITY_X)) 
00554                                 + (y_part * ( dy * SENSITIVITY_Y));
00555 
00556 
00557                         // Send the message to the viewer.
00558                         F32 dt = mGrabTimer.getElapsedTimeAndResetF32();
00559                         U32 dt_milliseconds = (U32) (1000.f * dt);
00560 
00561                         // need to return offset from mGrabStartPoint
00562                         LLVector3d grab_point_global;
00563 
00564                         grab_point_global = gAgent.getCameraPositionGlobal() + mGrabHiddenOffsetFromCamera;
00565 
00566                         /* Snap to grid disabled for grab tool - very confusing
00567                         // Handle snapping to grid, but only when the tool is formally selected.
00568                         BOOL snap_on = gSavedSettings.getBOOL("SnapEnabled");
00569                         if (snap_on && !gGrabTransientTool)
00570                         {
00571                                 F64     snap_size = gSavedSettings.getF32("GridResolution");
00572                                 U8 snap_dimensions = (mVerticalDragging ? 3 : 2);
00573 
00574                                 for (U8 i = 0; i < snap_dimensions; i++)
00575                                 {
00576                                         grab_point_global.mdV[i] += snap_size / 2;
00577                                         grab_point_global.mdV[i] -= fmod(grab_point_global.mdV[i], snap_size);
00578                                 }
00579                         }
00580                         */
00581 
00582                         // Don't let object centers go underground.
00583                         F32 land_height = gWorldPointer->resolveLandHeightGlobal(grab_point_global);
00584 
00585                         if (grab_point_global.mdV[VZ] < land_height)
00586                         {
00587                                 grab_point_global.mdV[VZ] = land_height;
00588                         }
00589 
00590                         // For safety, cap heights where objects can be dragged
00591                         if (grab_point_global.mdV[VZ] > MAX_OBJECT_Z)
00592                         {
00593                                 grab_point_global.mdV[VZ] = MAX_OBJECT_Z;
00594                         }
00595 
00596                         grab_point_global = gWorldp->clipToVisibleRegions(mDragStartPointGlobal, grab_point_global);
00597                         // propagate constrained grab point back to grab offset
00598                         mGrabHiddenOffsetFromCamera = grab_point_global - gAgent.getCameraPositionGlobal();
00599 
00600                         // Handle auto-rotation at screen edge.
00601                         LLVector3 grab_pos_agent = gAgent.getPosAgentFromGlobal( grab_point_global );
00602 
00603                         LLCoordGL grab_center_gl( gViewerWindow->getWindowWidth() / 2, gViewerWindow->getWindowHeight() / 2);
00604                         gCamera->projectPosAgentToScreen(grab_pos_agent, grab_center_gl);
00605 
00606                         const S32 ROTATE_H_MARGIN = gViewerWindow->getWindowWidth() / 20;
00607                         const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD;
00608                         const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped;
00609                         // ...build mode moves camera about focus point
00610                         if (grab_center_gl.mX < ROTATE_H_MARGIN)
00611                         {
00612                                 if (gAgent.getFocusOnAvatar())
00613                                 {
00614                                         gAgent.yaw(rotate_angle);
00615                                 }
00616                                 else
00617                                 {
00618                                         gAgent.cameraOrbitAround(rotate_angle);
00619                                 }
00620                         }
00621                         else if (grab_center_gl.mX > gViewerWindow->getWindowWidth() - ROTATE_H_MARGIN)
00622                         {
00623                                 if (gAgent.getFocusOnAvatar())
00624                                 {
00625                                         gAgent.yaw(-rotate_angle);
00626                                 }
00627                                 else
00628                                 {
00629                                         gAgent.cameraOrbitAround(-rotate_angle);
00630                                 }
00631                         }
00632 
00633                         // Don't move above top of screen or below bottom
00634                         if ((grab_center_gl.mY < gViewerWindow->getWindowHeight() - 6)
00635                                 && (grab_center_gl.mY > 24))
00636                         {
00637                                 // Transmit update to simulator
00638                                 LLVector3 grab_pos_region = mGrabObject->getRegion()->getPosRegionFromGlobal( grab_point_global );
00639 
00640                                 LLMessageSystem *msg = gMessageSystem;
00641                                 msg->newMessageFast(_PREHASH_ObjectGrabUpdate);
00642                                 msg->nextBlockFast(_PREHASH_AgentData);
00643                                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00644                                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00645                                 msg->nextBlockFast(_PREHASH_ObjectData);
00646                                 msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() );
00647                                 msg->addVector3Fast(_PREHASH_GrabOffsetInitial, mGrabOffsetFromCenterInitial );
00648                                 msg->addVector3Fast(_PREHASH_GrabPosition, grab_pos_region );
00649                                 msg->addU32Fast(_PREHASH_TimeSinceLast, dt_milliseconds );
00650                                 msg->sendMessage( mGrabObject->getRegion()->getHost() );
00651                         }
00652                 }
00653 
00654                 gViewerWindow->moveCursorToCenter();
00655 
00656                 gSelectMgr->updateSelectionCenter();
00657 
00658         }
00659 
00660         // once we've initiated a drag, lock the camera down
00661         if (mHasMoved)
00662         {
00663                 if (!gAgent.cameraMouselook() && 
00664                         !mGrabObject->isHUDAttachment() && 
00665                         mGrabObject->getRoot() == gAgent.getAvatarObject()->getRoot())
00666                 {
00667                         // force focus to point in space where we were looking previously
00668                         gAgent.setFocusGlobal(gAgent.calcFocusPositionTargetGlobal(), LLUUID::null);
00669                         gAgent.setFocusOnAvatar(FALSE, ANIMATE);
00670                 }
00671                 else
00672                 {
00673                         gAgent.clearFocusObject();
00674                 }
00675         }
00676 
00677         // 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.
00678         gViewerWindow->setCursor(UI_CURSOR_ARROW);  
00679 
00680         lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (active) [cursor hidden]" << llendl;                
00681 }
00682  
00683 
00684 // Not dragging.  Just showing affordances
00685 void LLToolGrab::handleHoverInactive(S32 x, S32 y, MASK mask)
00686 {
00687         const F32 ROTATE_ANGLE_PER_SECOND = 40.f * DEG_TO_RAD;
00688         const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped;
00689 
00690         // Look for cursor against the edge of the screen
00691         // Only works in fullscreen
00692         if (gSavedSettings.getBOOL("FullScreen"))
00693         {
00694                 if (gAgent.cameraThirdPerson() )
00695                 {
00696                         if (x == 0)
00697                         {
00698                                 gAgent.yaw(rotate_angle);
00699                                 //gAgent.setControlFlags(AGENT_CONTROL_YAW_POS);
00700                         }
00701                         else if (x == (gViewerWindow->getWindowWidth() - 1) )
00702                         {
00703                                 gAgent.yaw(-rotate_angle);
00704                                 //gAgent.setControlFlags(AGENT_CONTROL_YAW_NEG);
00705                         }
00706                 }
00707         }
00708 
00709         // JC - TODO - change cursor based on gGrabBtnVertical, gGrabBtnSpin
00710         lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (inactive-not over editable object)" << llendl;             
00711         gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
00712 }
00713 
00714 // User is trying to do something that's not allowed.
00715 void LLToolGrab::handleHoverFailed(S32 x, S32 y, MASK mask)
00716 {
00717         if( GRAB_NOOBJECT == mMode )
00718         {
00719                 gViewerWindow->setCursor(UI_CURSOR_NO);
00720                 lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (not on object)" << llendl;         
00721         }
00722         else
00723         {
00724                 S32 dist_sq = (x-mMouseDownX) * (x-mMouseDownX) + (y-mMouseDownY) * (y-mMouseDownY);
00725                 if( mOutsideSlop || dist_sq > SLOP_DIST_SQ )
00726                 {
00727                         mOutsideSlop = TRUE;
00728 
00729                         switch( mMode )
00730                         {
00731                         case GRAB_LOCKED:
00732                                 gViewerWindow->setCursor(UI_CURSOR_GRABLOCKED);
00733                                 lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (grab failed, no move permission)" << llendl;               
00734                                 break;
00735 
00736 //  Non physical now handled by handleHoverActive - CRO                         
00737 //                      case GRAB_NONPHYSICAL:
00738 //                              gViewerWindow->setCursor(UI_CURSOR_ARROW);
00739 //                              lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (grab failed, nonphysical)" << llendl;              
00740 //                              break;
00741                         default:
00742                                 llassert(0);
00743                         }
00744                 }
00745                 else
00746                 {
00747                         gViewerWindow->setCursor(UI_CURSOR_ARROW);
00748                         lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (grab failed but within slop)" << llendl;           
00749                 }
00750         }
00751 }
00752 
00753 
00754 
00755 
00756 BOOL LLToolGrab::handleMouseUp(S32 x, S32 y, MASK mask)
00757 {
00758         // call the base class to propogate info to sim
00759         LLTool::handleMouseUp(x, y, mask);
00760 
00761         if( hasMouseCapture() )
00762         {
00763                 setMouseCapture( FALSE );
00764         }
00765         mMode = GRAB_INACTIVE;
00766 
00767         // HACK: Make some grabs temporary
00768         if (gGrabTransientTool)
00769         {
00770                 gBasicToolset->selectTool( gGrabTransientTool );
00771                 gGrabTransientTool = NULL;
00772         }
00773 
00774         //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject"));
00775 
00776         return TRUE;
00777 } 
00778 
00779 void LLToolGrab::stopEditing()
00780 {
00781         if( hasMouseCapture() )
00782         {
00783                 setMouseCapture( FALSE );
00784         }
00785 }
00786 
00787 void LLToolGrab::onMouseCaptureLost()
00788 {
00789         // First, fix cursor placement
00790         if( !gAgent.cameraMouselook() 
00791                 && (GRAB_ACTIVE_CENTER == mMode || GRAB_NONPHYSICAL == mMode))
00792         {
00793                 llassert( mGrabObject ); 
00794 
00795                 if (mGrabObject->isHUDAttachment())
00796                 {
00797                         // ...move cursor "naturally", as if it had moved when hidden
00798                         S32 x = mMouseDownX + mAccumDeltaX;
00799                         S32 y = mMouseDownY + mAccumDeltaY;
00800                         LLUI::setCursorPositionScreen(x, y);
00801                 }
00802                 else if (mHasMoved)
00803                 {
00804                         // ...move cursor back to the center of the object
00805                         LLVector3 grab_point_agent = mGrabObject->getRenderPosition();
00806 
00807                         LLCoordGL gl_point;
00808                         if (gCamera->projectPosAgentToScreen(grab_point_agent, gl_point))
00809                         {
00810                                 LLUI::setCursorPositionScreen(gl_point.mX, gl_point.mY);
00811                         }
00812                 }
00813                 else
00814                 {
00815                         // ...move cursor back to click position
00816                         LLUI::setCursorPositionScreen(mMouseDownX, mMouseDownY);
00817                 }
00818 
00819                 gViewerWindow->showCursor();
00820         }
00821 
00822         stopGrab();
00823         stopSpin();
00824         mMode = GRAB_INACTIVE;
00825 
00826         mHideBuildHighlight = FALSE;
00827 
00828         mGrabObject = NULL;
00829 
00830         gSelectMgr->updateSelectionCenter();
00831         gAgent.setPointAt(POINTAT_TARGET_CLEAR);
00832         gAgent.setLookAt(LOOKAT_TARGET_CLEAR);
00833 
00834         dialog_refresh_all();
00835 }
00836 
00837 
00838 void LLToolGrab::stopGrab()
00839 {
00840         // Next, send messages to simulator
00841         LLMessageSystem *msg = gMessageSystem;
00842         switch(mMode)
00843         {
00844         case GRAB_ACTIVE_CENTER:
00845         case GRAB_NONPHYSICAL:
00846         case GRAB_LOCKED:
00847                 msg->newMessageFast(_PREHASH_ObjectDeGrab);
00848                 msg->nextBlockFast(_PREHASH_AgentData);
00849                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00850                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00851                 msg->nextBlockFast(_PREHASH_ObjectData);
00852                 msg->addU32Fast(_PREHASH_LocalID, mGrabObject->mLocalID);
00853                 msg->sendMessage(mGrabObject->getRegion()->getHost());
00854 
00855                 mVerticalDragging = FALSE;
00856                 mGrabOffset.clearVec();
00857                 break;
00858 
00859         case GRAB_NOOBJECT:
00860         case GRAB_INACTIVE:
00861         default:
00862                 // do nothing
00863                 break;
00864         }
00865 
00866         mHideBuildHighlight = FALSE;
00867 }
00868 
00869 
00870 void LLToolGrab::draw()
00871 { }
00872 
00873 void LLToolGrab::render()
00874 { }
00875 
00876 BOOL LLToolGrab::isEditing()
00877 {
00878         // Can't just compare to null directly due to "smart" pointer.
00879         LLViewerObject *obj = mGrabObject;
00880         return (obj != NULL);
00881 }
00882 
00883 LLViewerObject* LLToolGrab::getEditingObject()
00884 {
00885         return mGrabObject;
00886 }
00887 
00888 
00889 LLVector3d LLToolGrab::getEditingPointGlobal()
00890 {
00891         return getGrabPointGlobal();
00892 }
00893 
00894 LLVector3d LLToolGrab::getGrabPointGlobal()
00895 {
00896         switch(mMode)
00897         {
00898         case GRAB_ACTIVE_CENTER:
00899         case GRAB_NONPHYSICAL:
00900         case GRAB_LOCKED:
00901                 return gAgent.getCameraPositionGlobal() + mGrabHiddenOffsetFromCamera;
00902 
00903         case GRAB_NOOBJECT:
00904         case GRAB_INACTIVE:
00905         default:
00906                 return gAgent.getPositionGlobal();
00907         }
00908 }

Generated on Thu Jul 1 06:09:21 2010 for Second Life Viewer by  doxygen 1.4.7