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

Generated on Fri May 16 08:34:07 2008 for SecondLife by  doxygen 1.5.5