lltoolgrab.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:31k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lltoolgrab.cpp
  3.  * @brief LLToolGrab class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "lltoolgrab.h"
  34.  
  35. // library headers
  36. #include "indra_constants.h" // for agent control flags
  37. #include "llviewercontrol.h"
  38. #include "llquaternion.h"
  39. #include "llbox.h"
  40. #include "message.h"
  41. #include "llview.h"
  42. #include "llfontgl.h"
  43. #include "llui.h"
  44. // newview headers
  45. #include "llagent.h"
  46. #include "lldrawable.h"
  47. #include "llfloatertools.h"
  48. #include "llhudeffect.h"
  49. #include "llhudmanager.h"
  50. #include "llregionposition.h"
  51. #include "llselectmgr.h"
  52. #include "llstatusbar.h"
  53. #include "lltoolmgr.h"
  54. #include "lltoolpie.h"
  55. #include "llviewercamera.h"
  56. #include "llviewerobject.h"
  57. #include "llviewerobjectlist.h" 
  58. #include "llviewerregion.h"
  59. #include "llviewerwindow.h"
  60. #include "llvoavatarself.h"
  61. #include "llworld.h"
  62. const S32 SLOP_DIST_SQ = 4;
  63. // Override modifier key behavior with these buttons
  64. BOOL gGrabBtnVertical = FALSE;
  65. BOOL gGrabBtnSpin = FALSE;
  66. LLTool* gGrabTransientTool = NULL;
  67. extern BOOL gDebugClicks;
  68. //
  69. // Methods
  70. //
  71. LLToolGrab::LLToolGrab( LLToolComposite* composite )
  72. : LLTool( std::string("Grab"), composite ),
  73. mMode( GRAB_INACTIVE ),
  74. mVerticalDragging( FALSE ),
  75. mHitLand(FALSE),
  76. mLastMouseX(0),
  77. mLastMouseY(0),
  78. mAccumDeltaX(0),
  79. mAccumDeltaY(0),
  80. mHasMoved( FALSE ),
  81. mOutsideSlop(FALSE),
  82. mDeselectedThisClick(FALSE),
  83. mLastFace(0),
  84. mSpinGrabbing( FALSE ),
  85. mSpinRotation(),
  86. mHideBuildHighlight(FALSE)
  87. { }
  88. LLToolGrab::~LLToolGrab()
  89. { }
  90. // virtual
  91. void LLToolGrab::handleSelect()
  92. {
  93. if(gFloaterTools)
  94. {
  95. // viewer can crash during startup if we don't check.
  96. gFloaterTools->setStatusText("grab");
  97. }
  98. gGrabBtnVertical = FALSE;
  99. gGrabBtnSpin = FALSE;
  100. }
  101. void LLToolGrab::handleDeselect()
  102. {
  103. if( hasMouseCapture() )
  104. {
  105. setMouseCapture( FALSE );
  106. }
  107. }
  108. BOOL LLToolGrab::handleDoubleClick(S32 x, S32 y, MASK mask)
  109. {
  110. if (gDebugClicks)
  111. {
  112. llinfos << "LLToolGrab handleDoubleClick (becoming mouseDown)" << llendl;
  113. }
  114. return FALSE;
  115. }
  116. BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask)
  117. {
  118. if (gDebugClicks)
  119. {
  120. llinfos << "LLToolGrab handleMouseDown" << llendl;
  121. }
  122. // call the base class to propogate info to sim
  123. LLTool::handleMouseDown(x, y, mask);
  124. if (!gAgent.leftButtonGrabbed())
  125. {
  126. // can grab transparent objects (how touch event propagates, scripters rely on this)
  127. gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE);
  128. }
  129. return TRUE;
  130. }
  131. void LLToolGrab::pickCallback(const LLPickInfo& pick_info)
  132. {
  133. LLToolGrab::getInstance()->mGrabPick = pick_info;
  134. LLViewerObject *objectp = pick_info.getObject();
  135. BOOL extend_select = (pick_info.mKeyMask & MASK_SHIFT);
  136. if (!extend_select && !LLSelectMgr::getInstance()->getSelection()->isEmpty())
  137. {
  138. LLSelectMgr::getInstance()->deselectAll();
  139. LLToolGrab::getInstance()->mDeselectedThisClick = TRUE;
  140. }
  141. else
  142. {
  143. LLToolGrab::getInstance()->mDeselectedThisClick = FALSE;
  144. }
  145. // if not over object, do nothing
  146. if (!objectp)
  147. {
  148. LLToolGrab::getInstance()->setMouseCapture(TRUE);
  149. LLToolGrab::getInstance()->mMode = GRAB_NOOBJECT;
  150. LLToolGrab::getInstance()->mGrabPick.mObjectID.setNull();
  151. }
  152. else
  153. {
  154. LLToolGrab::getInstance()->handleObjectHit(LLToolGrab::getInstance()->mGrabPick);
  155. }
  156. }
  157. BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info)
  158. {
  159. mGrabPick = info;
  160. LLViewerObject* objectp = mGrabPick.getObject();
  161. if (gDebugClicks)
  162. {
  163. llinfos << "LLToolGrab handleObjectHit " << info.mMousePt.mX << "," << info.mMousePt.mY << llendl;
  164. }
  165. if (NULL == objectp) // unexpected
  166. {
  167. llwarns << "objectp was NULL; returning FALSE" << llendl;
  168. return FALSE;
  169. }
  170. if (objectp->isAvatar())
  171. {
  172. if (gGrabTransientTool)
  173. {
  174. gBasicToolset->selectTool( gGrabTransientTool );
  175. gGrabTransientTool = NULL;
  176. }
  177. return TRUE;
  178. }
  179. setMouseCapture( TRUE );
  180. // Grabs always start from the root
  181. // objectp = (LLViewerObject *)objectp->getRoot();
  182. LLViewerObject* parent = objectp->getRootEdit();
  183. BOOL script_touch = (objectp->flagHandleTouch()) || (parent && parent->flagHandleTouch());
  184. // Clicks on scripted or physical objects are temporary grabs, so
  185. // not "Build mode"
  186. mHideBuildHighlight = script_touch || objectp->usePhysics();
  187. if (!objectp->usePhysics())
  188. {
  189. if (script_touch)
  190. {
  191. mMode = GRAB_NONPHYSICAL;  // if it has a script, use the non-physical grab
  192. }
  193. else
  194. {
  195. // In mouselook, we shouldn't be able to grab non-physical, 
  196. // non-touchable objects.  If it has a touch handler, we
  197. // do grab it (so llDetectedGrab works), but movement is
  198. // blocked on the server side. JC
  199. if (gAgent.cameraMouselook())
  200. {
  201. mMode = GRAB_LOCKED;
  202. }
  203. else
  204. {
  205. mMode = GRAB_ACTIVE_CENTER;
  206. }
  207. gViewerWindow->hideCursor();
  208. gViewerWindow->moveCursorToCenter();
  209. }
  210. }
  211. else if( !objectp->permMove() )
  212. {
  213. // if mouse is over a physical object without move permission, show feedback if user tries to move it.
  214. mMode = GRAB_LOCKED;
  215. // Don't bail out here, go on and grab so buttons can get
  216. // their "touched" event.
  217. }
  218. else
  219. {
  220. // if mouse is over a physical object with move permission, 
  221. // select it and enter "grab" mode (hiding cursor, etc.)
  222. mMode = GRAB_ACTIVE_CENTER;
  223. gViewerWindow->hideCursor();
  224. gViewerWindow->moveCursorToCenter();
  225. }
  226. // Always send "touched" message
  227. mLastMouseX = gViewerWindow->getCurrentMouseX();
  228. mLastMouseY = gViewerWindow->getCurrentMouseY();
  229. mAccumDeltaX = 0;
  230. mAccumDeltaY = 0;
  231. mHasMoved = FALSE;
  232. mOutsideSlop = FALSE;
  233. mVerticalDragging = (info.mKeyMask == MASK_VERTICAL) || gGrabBtnVertical;
  234. startGrab();
  235. if ((info.mKeyMask == MASK_SPIN) || gGrabBtnSpin)
  236. {
  237. startSpin();
  238. }
  239. LLSelectMgr::getInstance()->updateSelectionCenter(); // update selection beam
  240. // update point at
  241. LLViewerObject *edit_object = info.getObject();
  242. if (edit_object && info.mPickType != LLPickInfo::PICK_FLORA)
  243. {
  244. LLVector3 local_edit_point = gAgent.getPosAgentFromGlobal(info.mPosGlobal);
  245. local_edit_point -= edit_object->getPositionAgent();
  246. local_edit_point = local_edit_point * ~edit_object->getRenderRotation();
  247. gAgent.setPointAt(POINTAT_TARGET_GRAB, edit_object, local_edit_point );
  248. gAgent.setLookAt(LOOKAT_TARGET_SELECT, edit_object, local_edit_point );
  249. }
  250. // on transient grabs (clicks on world objects), kill the grab immediately
  251. if (!gViewerWindow->getLeftMouseDown() 
  252. && gGrabTransientTool 
  253. && (mMode == GRAB_NONPHYSICAL || mMode == GRAB_LOCKED))
  254. {
  255. gBasicToolset->selectTool( gGrabTransientTool );
  256. gGrabTransientTool = NULL;
  257. }
  258. return TRUE;
  259. }
  260. void LLToolGrab::startSpin()
  261. {
  262. LLViewerObject* objectp = mGrabPick.getObject();
  263. if (!objectp)
  264. {
  265. return;
  266. }
  267. mSpinGrabbing = TRUE;
  268. // Was saveSelectedObjectTransform()
  269. LLViewerObject *root = (LLViewerObject *)objectp->getRoot();
  270. mSpinRotation = root->getRotation();
  271. LLMessageSystem *msg = gMessageSystem;
  272. msg->newMessageFast(_PREHASH_ObjectSpinStart);
  273. msg->nextBlockFast(_PREHASH_AgentData);
  274. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  275. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  276. msg->nextBlockFast(_PREHASH_ObjectData);
  277. msg->addUUIDFast(_PREHASH_ObjectID, mGrabPick.mObjectID );
  278. msg->sendMessage( objectp->getRegion()->getHost() );
  279. }
  280. void LLToolGrab::stopSpin()
  281. {
  282. mSpinGrabbing = FALSE;
  283. LLViewerObject* objectp = mGrabPick.getObject();
  284. if (!objectp)
  285. {
  286. return;
  287. }
  288. LLMessageSystem *msg = gMessageSystem;
  289. switch(mMode)
  290. {
  291. case GRAB_ACTIVE_CENTER:
  292. case GRAB_NONPHYSICAL:
  293. case GRAB_LOCKED:
  294. msg->newMessageFast(_PREHASH_ObjectSpinStop);
  295. msg->nextBlockFast(_PREHASH_AgentData);
  296. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  297. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  298. msg->nextBlockFast(_PREHASH_ObjectData);
  299. msg->addUUIDFast(_PREHASH_ObjectID, objectp->getID() );
  300. msg->sendMessage( objectp->getRegion()->getHost() );
  301. break;
  302. case GRAB_NOOBJECT:
  303. case GRAB_INACTIVE:
  304. default:
  305. // do nothing
  306. break;
  307. }
  308. }
  309. void LLToolGrab::startGrab()
  310. {
  311. // Compute grab_offset in the OBJECT's root's coordinate frame
  312. // (sometimes root == object)
  313. LLViewerObject* objectp = mGrabPick.getObject();
  314. if (!objectp)
  315. {
  316. return;
  317. }
  318. LLViewerObject *root = (LLViewerObject *)objectp->getRoot();
  319. // drag from center
  320. LLVector3d grab_start_global = root->getPositionGlobal();
  321. // Where the grab starts, relative to the center of the root object of the set.
  322. // JC - This code looks wonky, but I believe it does the right thing.
  323. // Otherwise, when you grab a linked object set, it "pops" on the start
  324. // of the drag.
  325. LLVector3d grab_offsetd = root->getPositionGlobal() - objectp->getPositionGlobal();
  326. LLVector3 grab_offset;
  327. grab_offset.setVec(grab_offsetd);
  328. LLQuaternion rotation = root->getRotation();
  329. rotation.conjQuat();
  330. grab_offset = grab_offset * rotation;
  331. // This planar drag starts at the grab point
  332. mDragStartPointGlobal = grab_start_global;
  333. mDragStartFromCamera = grab_start_global - gAgent.getCameraPositionGlobal();
  334. LLMessageSystem *msg = gMessageSystem;
  335. msg->newMessageFast(_PREHASH_ObjectGrab);
  336. msg->nextBlockFast(_PREHASH_AgentData);
  337. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  338. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  339. msg->nextBlockFast(_PREHASH_ObjectData);
  340. msg->addU32Fast(_PREHASH_LocalID, objectp->mLocalID);
  341. msg->addVector3Fast(_PREHASH_GrabOffset, grab_offset );
  342. msg->nextBlock("SurfaceInfo");
  343. msg->addVector3("UVCoord", LLVector3(mGrabPick.mUVCoords));
  344. msg->addVector3("STCoord", LLVector3(mGrabPick.mSTCoords));
  345. msg->addS32Fast(_PREHASH_FaceIndex, mGrabPick.mObjectFace);
  346. msg->addVector3("Position", mGrabPick.mIntersection);
  347. msg->addVector3("Normal", mGrabPick.mNormal);
  348. msg->addVector3("Binormal", mGrabPick.mBinormal);
  349. msg->sendMessage( objectp->getRegion()->getHost());
  350. mGrabOffsetFromCenterInitial = grab_offset;
  351. mGrabHiddenOffsetFromCamera = mDragStartFromCamera;
  352. mGrabTimer.reset();
  353. mLastUVCoords = mGrabPick.mUVCoords;
  354. mLastSTCoords = mGrabPick.mSTCoords;
  355. mLastFace = mGrabPick.mObjectFace;
  356. mLastIntersection = mGrabPick.mIntersection;
  357. mLastNormal = mGrabPick.mNormal;
  358. mLastBinormal = mGrabPick.mBinormal;
  359. mLastGrabPos = LLVector3(-1.f, -1.f, -1.f);
  360. }
  361. BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask)
  362. {
  363. if (!gViewerWindow->getLeftMouseDown())
  364. {
  365. gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
  366. setMouseCapture(FALSE);
  367. return TRUE;
  368. }
  369. // Do the right hover based on mode
  370. switch( mMode )
  371. {
  372. case GRAB_ACTIVE_CENTER:
  373. handleHoverActive( x, y, mask ); // cursor hidden
  374. break;
  375. case GRAB_NONPHYSICAL:
  376. handleHoverNonPhysical(x, y, mask);
  377. break;
  378. case GRAB_INACTIVE:
  379. handleHoverInactive( x, y, mask );  // cursor set here
  380. break;
  381. case GRAB_NOOBJECT:
  382. case GRAB_LOCKED:
  383. handleHoverFailed( x, y, mask );
  384. break;
  385. }
  386. mLastMouseX = x;
  387. mLastMouseY = y;
  388. return TRUE;
  389. }
  390. const F32 GRAB_SENSITIVITY_X = 0.0075f;
  391. const F32 GRAB_SENSITIVITY_Y = 0.0075f;
  392. // Dragging.
  393. void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
  394. {
  395. LLViewerObject* objectp = mGrabPick.getObject();
  396. if (!objectp || !hasMouseCapture() ) return;
  397. if (objectp->isDead())
  398. {
  399. // Bail out of drag because object has been killed
  400. setMouseCapture(FALSE);
  401. return;
  402. }
  403. //--------------------------------------------------
  404. // Toggle spinning
  405. //--------------------------------------------------
  406. if (mSpinGrabbing && !(mask == MASK_SPIN) && !gGrabBtnSpin)
  407. {
  408. // user released ALT key, stop spinning
  409. stopSpin();
  410. }
  411. else if (!mSpinGrabbing && (mask == MASK_SPIN) )
  412. {
  413. // user pressed ALT key, start spinning
  414. startSpin();
  415. }
  416. //--------------------------------------------------
  417. // Toggle vertical dragging
  418. //--------------------------------------------------
  419. if (mVerticalDragging && !(mask == MASK_VERTICAL) && !gGrabBtnVertical)
  420. {
  421. // ...switch to horizontal dragging
  422. mVerticalDragging = FALSE;
  423. mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, objectp);
  424. mDragStartFromCamera = mDragStartPointGlobal - gAgent.getCameraPositionGlobal();
  425. }
  426. else if (!mVerticalDragging && (mask == MASK_VERTICAL) )
  427. {
  428. // ...switch to vertical dragging
  429. mVerticalDragging = TRUE;
  430. mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, objectp);
  431. mDragStartFromCamera = mDragStartPointGlobal - gAgent.getCameraPositionGlobal();
  432. }
  433. const F32 RADIANS_PER_PIXEL_X = 0.01f;
  434. const F32 RADIANS_PER_PIXEL_Y = 0.01f;
  435. S32 dx = x - (gViewerWindow->getWorldViewWidthScaled() / 2);
  436. S32 dy = y - (gViewerWindow->getWorldViewHeightScaled() / 2);
  437. if (dx != 0 || dy != 0)
  438. {
  439. mAccumDeltaX += dx;
  440. mAccumDeltaY += dy;
  441. S32 dist_sq = mAccumDeltaX * mAccumDeltaX + mAccumDeltaY * mAccumDeltaY;
  442. if (dist_sq > SLOP_DIST_SQ)
  443. {
  444. mOutsideSlop = TRUE;
  445. }
  446. // mouse has moved outside center
  447. mHasMoved = TRUE;
  448. if (mSpinGrabbing)
  449. {
  450. //------------------------------------------------------
  451. // Handle spinning
  452. //------------------------------------------------------
  453. // x motion maps to rotation around vertical axis
  454. LLVector3 up(0.f, 0.f, 1.f);
  455. LLQuaternion rotation_around_vertical( dx*RADIANS_PER_PIXEL_X, up );
  456. // y motion maps to rotation around left axis
  457. const LLVector3 &agent_left = LLViewerCamera::getInstance()->getLeftAxis();
  458. LLQuaternion rotation_around_left( dy*RADIANS_PER_PIXEL_Y, agent_left );
  459. // compose with current rotation
  460. mSpinRotation = mSpinRotation * rotation_around_vertical;
  461. mSpinRotation = mSpinRotation * rotation_around_left;
  462. // TODO: Throttle these
  463. LLMessageSystem *msg = gMessageSystem;
  464. msg->newMessageFast(_PREHASH_ObjectSpinUpdate);
  465. msg->nextBlockFast(_PREHASH_AgentData);
  466. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  467. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  468. msg->nextBlockFast(_PREHASH_ObjectData);
  469. msg->addUUIDFast(_PREHASH_ObjectID, objectp->getID() );
  470. msg->addQuatFast(_PREHASH_Rotation, mSpinRotation );
  471. msg->sendMessage( objectp->getRegion()->getHost() );
  472. }
  473. else
  474. {
  475. //------------------------------------------------------
  476. // Handle grabbing
  477. //------------------------------------------------------
  478. LLVector3d x_part;
  479. x_part.setVec(LLViewerCamera::getInstance()->getLeftAxis());
  480. x_part.mdV[VZ] = 0.0;
  481. x_part.normVec();
  482. LLVector3d y_part;
  483. if( mVerticalDragging )
  484. {
  485. y_part.setVec(LLViewerCamera::getInstance()->getUpAxis());
  486. // y_part.setVec(0.f, 0.f, 1.f);
  487. }
  488. else
  489. {
  490. // drag toward camera
  491. y_part = x_part % LLVector3d::z_axis;
  492. y_part.mdV[VZ] = 0.0;
  493. y_part.normVec();
  494. }
  495. mGrabHiddenOffsetFromCamera = mGrabHiddenOffsetFromCamera 
  496. + (x_part * (-dx * GRAB_SENSITIVITY_X)) 
  497. + (y_part * ( dy * GRAB_SENSITIVITY_Y));
  498. // Send the message to the viewer.
  499. F32 dt = mGrabTimer.getElapsedTimeAndResetF32();
  500. U32 dt_milliseconds = (U32) (1000.f * dt);
  501. // need to return offset from mGrabStartPoint
  502. LLVector3d grab_point_global;
  503. grab_point_global = gAgent.getCameraPositionGlobal() + mGrabHiddenOffsetFromCamera;
  504. /* Snap to grid disabled for grab tool - very confusing
  505. // Handle snapping to grid, but only when the tool is formally selected.
  506. BOOL snap_on = gSavedSettings.getBOOL("SnapEnabled");
  507. if (snap_on && !gGrabTransientTool)
  508. {
  509. F64 snap_size = gSavedSettings.getF32("GridResolution");
  510. U8 snap_dimensions = (mVerticalDragging ? 3 : 2);
  511. for (U8 i = 0; i < snap_dimensions; i++)
  512. {
  513. grab_point_global.mdV[i] += snap_size / 2;
  514. grab_point_global.mdV[i] -= fmod(grab_point_global.mdV[i], snap_size);
  515. }
  516. }
  517. */
  518. // Don't let object centers go underground.
  519. F32 land_height = LLWorld::getInstance()->resolveLandHeightGlobal(grab_point_global);
  520. if (grab_point_global.mdV[VZ] < land_height)
  521. {
  522. grab_point_global.mdV[VZ] = land_height;
  523. }
  524. // For safety, cap heights where objects can be dragged
  525. if (grab_point_global.mdV[VZ] > MAX_OBJECT_Z)
  526. {
  527. grab_point_global.mdV[VZ] = MAX_OBJECT_Z;
  528. }
  529. grab_point_global = LLWorld::getInstance()->clipToVisibleRegions(mDragStartPointGlobal, grab_point_global);
  530. // propagate constrained grab point back to grab offset
  531. mGrabHiddenOffsetFromCamera = grab_point_global - gAgent.getCameraPositionGlobal();
  532. // Handle auto-rotation at screen edge.
  533. LLVector3 grab_pos_agent = gAgent.getPosAgentFromGlobal( grab_point_global );
  534. LLCoordGL grab_center_gl( gViewerWindow->getWorldViewWidthScaled() / 2, gViewerWindow->getWorldViewHeightScaled() / 2);
  535. LLViewerCamera::getInstance()->projectPosAgentToScreen(grab_pos_agent, grab_center_gl);
  536. const S32 ROTATE_H_MARGIN = gViewerWindow->getWorldViewWidthScaled() / 20;
  537. const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD;
  538. const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped;
  539. // ...build mode moves camera about focus point
  540. if (grab_center_gl.mX < ROTATE_H_MARGIN)
  541. {
  542. if (gAgent.getFocusOnAvatar())
  543. {
  544. gAgent.yaw(rotate_angle);
  545. }
  546. else
  547. {
  548. gAgent.cameraOrbitAround(rotate_angle);
  549. }
  550. }
  551. else if (grab_center_gl.mX > gViewerWindow->getWorldViewWidthScaled() - ROTATE_H_MARGIN)
  552. {
  553. if (gAgent.getFocusOnAvatar())
  554. {
  555. gAgent.yaw(-rotate_angle);
  556. }
  557. else
  558. {
  559. gAgent.cameraOrbitAround(-rotate_angle);
  560. }
  561. }
  562. // Don't move above top of screen or below bottom
  563. if ((grab_center_gl.mY < gViewerWindow->getWorldViewHeightScaled() - 6)
  564. && (grab_center_gl.mY > 24))
  565. {
  566. // Transmit update to simulator
  567. LLVector3 grab_pos_region = objectp->getRegion()->getPosRegionFromGlobal( grab_point_global );
  568. LLMessageSystem *msg = gMessageSystem;
  569. msg->newMessageFast(_PREHASH_ObjectGrabUpdate);
  570. msg->nextBlockFast(_PREHASH_AgentData);
  571. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  572. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  573. msg->nextBlockFast(_PREHASH_ObjectData);
  574. msg->addUUIDFast(_PREHASH_ObjectID, objectp->getID() );
  575. msg->addVector3Fast(_PREHASH_GrabOffsetInitial, mGrabOffsetFromCenterInitial );
  576. msg->addVector3Fast(_PREHASH_GrabPosition, grab_pos_region );
  577. msg->addU32Fast(_PREHASH_TimeSinceLast, dt_milliseconds );
  578. msg->nextBlock("SurfaceInfo");
  579. msg->addVector3("UVCoord", LLVector3(mGrabPick.mUVCoords));
  580. msg->addVector3("STCoord", LLVector3(mGrabPick.mSTCoords));
  581. msg->addS32Fast(_PREHASH_FaceIndex, mGrabPick.mObjectFace);
  582. msg->addVector3("Position", mGrabPick.mIntersection);
  583. msg->addVector3("Normal", mGrabPick.mNormal);
  584. msg->addVector3("Binormal", mGrabPick.mBinormal);
  585. msg->sendMessage( objectp->getRegion()->getHost() );
  586. }
  587. }
  588. gViewerWindow->moveCursorToCenter();
  589. LLSelectMgr::getInstance()->updateSelectionCenter();
  590. }
  591. // once we've initiated a drag, lock the camera down
  592. if (mHasMoved)
  593. {
  594. if (!gAgent.cameraMouselook() && 
  595. !objectp->isHUDAttachment() && 
  596. objectp->getRoot() == gAgent.getAvatarObject()->getRoot())
  597. {
  598. // force focus to point in space where we were looking previously
  599. gAgent.setFocusGlobal(gAgent.calcFocusPositionTargetGlobal(), LLUUID::null);
  600. gAgent.setFocusOnAvatar(FALSE, ANIMATE);
  601. }
  602. else
  603. {
  604. gAgent.clearFocusObject();
  605. }
  606. }
  607. // 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.
  608. gViewerWindow->setCursor(UI_CURSOR_ARROW);  
  609. lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (active) [cursor hidden]" << llendl;
  610. }
  611.  
  612. void LLToolGrab::handleHoverNonPhysical(S32 x, S32 y, MASK mask)
  613. {
  614. LLViewerObject* objectp = mGrabPick.getObject();
  615. if (!objectp || !hasMouseCapture() ) return;
  616. if (objectp->isDead())
  617. {
  618. // Bail out of drag because object has been killed
  619. setMouseCapture(FALSE);
  620. return;
  621. }
  622. LLPickInfo pick = mGrabPick;
  623. pick.mMousePt = LLCoordGL(x, y);
  624. pick.getSurfaceInfo();
  625. // compute elapsed time
  626. F32 dt = mGrabTimer.getElapsedTimeAndResetF32();
  627. U32 dt_milliseconds = (U32) (1000.f * dt);
  628. // i'm not a big fan of the following code - it's been culled from the physical grab case.
  629. // ideally these two would be nicely integrated - but the code in that method is a serious
  630. // mess of spaghetti.  so here we go:
  631. LLVector3 grab_pos_region(0,0,0);
  632. const BOOL SUPPORT_LLDETECTED_GRAB = TRUE;
  633. if (SUPPORT_LLDETECTED_GRAB)
  634. {
  635. //--------------------------------------------------
  636. // Toggle vertical dragging
  637. //--------------------------------------------------
  638. if (mVerticalDragging && !(mask == MASK_VERTICAL) && !gGrabBtnVertical)
  639. {
  640. mVerticalDragging = FALSE;
  641. }
  642. else if (!mVerticalDragging && (mask == MASK_VERTICAL) )
  643. {
  644. mVerticalDragging = TRUE;
  645. }
  646. S32 dx = x - mLastMouseX;
  647. S32 dy = y - mLastMouseY;
  648. if (dx != 0 || dy != 0)
  649. {
  650. mAccumDeltaX += dx;
  651. mAccumDeltaY += dy;
  652. S32 dist_sq = mAccumDeltaX * mAccumDeltaX + mAccumDeltaY * mAccumDeltaY;
  653. if (dist_sq > SLOP_DIST_SQ)
  654. {
  655. mOutsideSlop = TRUE;
  656. }
  657. // mouse has moved 
  658. mHasMoved = TRUE;
  659. //------------------------------------------------------
  660. // Handle grabbing
  661. //------------------------------------------------------
  662. LLVector3d x_part;
  663. x_part.setVec(LLViewerCamera::getInstance()->getLeftAxis());
  664. x_part.mdV[VZ] = 0.0;
  665. x_part.normVec();
  666. LLVector3d y_part;
  667. if( mVerticalDragging )
  668. {
  669. y_part.setVec(LLViewerCamera::getInstance()->getUpAxis());
  670. // y_part.setVec(0.f, 0.f, 1.f);
  671. }
  672. else
  673. {
  674. // drag toward camera
  675. y_part = x_part % LLVector3d::z_axis;
  676. y_part.mdV[VZ] = 0.0;
  677. y_part.normVec();
  678. }
  679. mGrabHiddenOffsetFromCamera = mGrabHiddenOffsetFromCamera 
  680. + (x_part * (-dx * GRAB_SENSITIVITY_X)) 
  681. + (y_part * ( dy * GRAB_SENSITIVITY_Y));
  682. }
  683. // need to return offset from mGrabStartPoint
  684. LLVector3d grab_point_global = gAgent.getCameraPositionGlobal() + mGrabHiddenOffsetFromCamera;
  685. grab_pos_region = objectp->getRegion()->getPosRegionFromGlobal( grab_point_global );
  686. }
  687. // only send message if something has changed since last message
  688. BOOL changed_since_last_update = FALSE;
  689. // test if touch data needs to be updated
  690. if ((pick.mObjectFace != mLastFace) ||
  691. (pick.mUVCoords != mLastUVCoords) ||
  692. (pick.mSTCoords != mLastSTCoords) ||
  693. (pick.mIntersection != mLastIntersection) ||
  694. (pick.mNormal != mLastNormal) ||
  695. (pick.mBinormal != mLastBinormal) ||
  696. (grab_pos_region != mLastGrabPos))
  697. {
  698. changed_since_last_update = TRUE;
  699. }
  700. if (changed_since_last_update)
  701. {
  702. LLMessageSystem *msg = gMessageSystem;
  703. msg->newMessageFast(_PREHASH_ObjectGrabUpdate);
  704. msg->nextBlockFast(_PREHASH_AgentData);
  705. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  706. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  707. msg->nextBlockFast(_PREHASH_ObjectData);
  708. msg->addUUIDFast(_PREHASH_ObjectID, objectp->getID() );
  709. msg->addVector3Fast(_PREHASH_GrabOffsetInitial, mGrabOffsetFromCenterInitial );
  710. msg->addVector3Fast(_PREHASH_GrabPosition, grab_pos_region );
  711. msg->addU32Fast(_PREHASH_TimeSinceLast, dt_milliseconds );
  712. msg->nextBlock("SurfaceInfo");
  713. msg->addVector3("UVCoord", LLVector3(pick.mUVCoords));
  714. msg->addVector3("STCoord", LLVector3(pick.mSTCoords));
  715. msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace);
  716. msg->addVector3("Position", pick.mIntersection);
  717. msg->addVector3("Normal", pick.mNormal);
  718. msg->addVector3("Binormal", pick.mBinormal);
  719. msg->sendMessage( objectp->getRegion()->getHost() );
  720. mLastUVCoords = pick.mUVCoords;
  721. mLastSTCoords = pick.mSTCoords;
  722. mLastFace = pick.mObjectFace;
  723. mLastIntersection = pick.mIntersection;
  724. mLastNormal= pick.mNormal;
  725. mLastBinormal= pick.mBinormal;
  726. mLastGrabPos = grab_pos_region;
  727. }
  728. // update point-at / look-at
  729. if (pick.mObjectFace != -1) // if the intersection was on the surface of the obejct
  730. {
  731. LLVector3 local_edit_point = pick.mIntersection;
  732. local_edit_point -= objectp->getPositionAgent();
  733. local_edit_point = local_edit_point * ~objectp->getRenderRotation();
  734. gAgent.setPointAt(POINTAT_TARGET_GRAB, objectp, local_edit_point );
  735. gAgent.setLookAt(LOOKAT_TARGET_SELECT, objectp, local_edit_point );
  736. }
  737. gViewerWindow->setCursor(UI_CURSOR_HAND);  
  738. }
  739.  
  740. // Not dragging.  Just showing affordances
  741. void LLToolGrab::handleHoverInactive(S32 x, S32 y, MASK mask)
  742. {
  743. const F32 ROTATE_ANGLE_PER_SECOND = 40.f * DEG_TO_RAD;
  744. const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped;
  745. // Look for cursor against the edge of the screen
  746. // Only works in fullscreen
  747. if (gSavedSettings.getBOOL("WindowFullScreen"))
  748. {
  749. if (gAgent.cameraThirdPerson() )
  750. {
  751. if (x == 0)
  752. {
  753. gAgent.yaw(rotate_angle);
  754. //gAgent.setControlFlags(AGENT_CONTROL_YAW_POS);
  755. }
  756. else if (x == (gViewerWindow->getWorldViewWidthScaled() - 1) )
  757. {
  758. gAgent.yaw(-rotate_angle);
  759. //gAgent.setControlFlags(AGENT_CONTROL_YAW_NEG);
  760. }
  761. }
  762. }
  763. // JC - TODO - change cursor based on gGrabBtnVertical, gGrabBtnSpin
  764. lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (inactive-not over editable object)" << llendl;
  765. gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
  766. }
  767. // User is trying to do something that's not allowed.
  768. void LLToolGrab::handleHoverFailed(S32 x, S32 y, MASK mask)
  769. {
  770. if( GRAB_NOOBJECT == mMode )
  771. {
  772. gViewerWindow->setCursor(UI_CURSOR_NO);
  773. lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (not on object)" << llendl;
  774. }
  775. else
  776. {
  777. S32 dist_sq = (x-mGrabPick.mMousePt.mX) * (x-mGrabPick.mMousePt.mX) + (y-mGrabPick.mMousePt.mY) * (y-mGrabPick.mMousePt.mY);
  778. if( mOutsideSlop || dist_sq > SLOP_DIST_SQ )
  779. {
  780. mOutsideSlop = TRUE;
  781. switch( mMode )
  782. {
  783. case GRAB_LOCKED:
  784. gViewerWindow->setCursor(UI_CURSOR_GRABLOCKED);
  785. lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (grab failed, no move permission)" << llendl;
  786. break;
  787. //  Non physical now handled by handleHoverActive - CRO
  788. // case GRAB_NONPHYSICAL:
  789. // gViewerWindow->setCursor(UI_CURSOR_ARROW);
  790. // lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (grab failed, nonphysical)" << llendl;
  791. // break;
  792. default:
  793. llassert(0);
  794. }
  795. }
  796. else
  797. {
  798. gViewerWindow->setCursor(UI_CURSOR_ARROW);
  799. lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolGrab (grab failed but within slop)" << llendl;
  800. }
  801. }
  802. }
  803. BOOL LLToolGrab::handleMouseUp(S32 x, S32 y, MASK mask)
  804. {
  805. // call the base class to propogate info to sim
  806. LLTool::handleMouseUp(x, y, mask);
  807. if( hasMouseCapture() )
  808. {
  809. setMouseCapture( FALSE );
  810. }
  811. mMode = GRAB_INACTIVE;
  812. // HACK: Make some grabs temporary
  813. if (gGrabTransientTool)
  814. {
  815. gBasicToolset->selectTool( gGrabTransientTool );
  816. gGrabTransientTool = NULL;
  817. }
  818. //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject"));
  819. return TRUE;
  820. void LLToolGrab::stopEditing()
  821. {
  822. if( hasMouseCapture() )
  823. {
  824. setMouseCapture( FALSE );
  825. }
  826. }
  827. void LLToolGrab::onMouseCaptureLost()
  828. {
  829. LLViewerObject* objectp = mGrabPick.getObject();
  830. if (!objectp)
  831. {
  832. gViewerWindow->showCursor();
  833. return;
  834. }
  835. // First, fix cursor placement
  836. if( !gAgent.cameraMouselook() 
  837. && (GRAB_ACTIVE_CENTER == mMode))
  838. {
  839. if (objectp->isHUDAttachment())
  840. {
  841. // ...move cursor "naturally", as if it had moved when hidden
  842. S32 x = mGrabPick.mMousePt.mX + mAccumDeltaX;
  843. S32 y = mGrabPick.mMousePt.mY + mAccumDeltaY;
  844. LLUI::setMousePositionScreen(x, y);
  845. }
  846. else if (mHasMoved)
  847. {
  848. // ...move cursor back to the center of the object
  849. LLVector3 grab_point_agent = objectp->getRenderPosition();
  850. LLCoordGL gl_point;
  851. if (LLViewerCamera::getInstance()->projectPosAgentToScreen(grab_point_agent, gl_point))
  852. {
  853. LLUI::setMousePositionScreen(gl_point.mX, gl_point.mY);
  854. }
  855. }
  856. else
  857. {
  858. // ...move cursor back to click position
  859. LLUI::setMousePositionScreen(mGrabPick.mMousePt.mX, mGrabPick.mMousePt.mY);
  860. }
  861. gViewerWindow->showCursor();
  862. }
  863. stopGrab();
  864. if (mSpinGrabbing)
  865. stopSpin();
  866. mMode = GRAB_INACTIVE;
  867. mHideBuildHighlight = FALSE;
  868. mGrabPick.mObjectID.setNull();
  869. LLSelectMgr::getInstance()->updateSelectionCenter();
  870. gAgent.setPointAt(POINTAT_TARGET_CLEAR);
  871. gAgent.setLookAt(LOOKAT_TARGET_CLEAR);
  872. dialog_refresh_all();
  873. }
  874. void LLToolGrab::stopGrab()
  875. {
  876. LLViewerObject* objectp = mGrabPick.getObject();
  877. if (!objectp)
  878. {
  879. return;
  880. }
  881. LLPickInfo pick = mGrabPick;
  882. if (mMode == GRAB_NONPHYSICAL)
  883. {
  884. // for non-physical (touch) grabs,
  885. // gather surface info for this degrab (mouse-up)
  886. S32 x = gViewerWindow->getCurrentMouseX();
  887. S32 y = gViewerWindow->getCurrentMouseY();
  888. pick.mMousePt = LLCoordGL(x, y);
  889. pick.getSurfaceInfo();
  890. }
  891. // Next, send messages to simulator
  892. LLMessageSystem *msg = gMessageSystem;
  893. switch(mMode)
  894. {
  895. case GRAB_ACTIVE_CENTER:
  896. case GRAB_NONPHYSICAL:
  897. case GRAB_LOCKED:
  898. msg->newMessageFast(_PREHASH_ObjectDeGrab);
  899. msg->nextBlockFast(_PREHASH_AgentData);
  900. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  901. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  902. msg->nextBlockFast(_PREHASH_ObjectData);
  903. msg->addU32Fast(_PREHASH_LocalID, objectp->mLocalID);
  904. msg->nextBlock("SurfaceInfo");
  905. msg->addVector3("UVCoord", LLVector3(pick.mUVCoords));
  906. msg->addVector3("STCoord", LLVector3(pick.mSTCoords));
  907. msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace);
  908. msg->addVector3("Position", pick.mIntersection);
  909. msg->addVector3("Normal", pick.mNormal);
  910. msg->addVector3("Binormal", pick.mBinormal);
  911. msg->sendMessage(objectp->getRegion()->getHost());
  912. mVerticalDragging = FALSE;
  913. break;
  914. case GRAB_NOOBJECT:
  915. case GRAB_INACTIVE:
  916. default:
  917. // do nothing
  918. break;
  919. }
  920. mHideBuildHighlight = FALSE;
  921. }
  922. void LLToolGrab::draw()
  923. { }
  924. void LLToolGrab::render()
  925. { }
  926. BOOL LLToolGrab::isEditing()
  927. {
  928. return (mGrabPick.getObject().notNull());
  929. }
  930. LLViewerObject* LLToolGrab::getEditingObject()
  931. {
  932. return mGrabPick.getObject();
  933. }
  934. LLVector3d LLToolGrab::getEditingPointGlobal()
  935. {
  936. return getGrabPointGlobal();
  937. }
  938. LLVector3d LLToolGrab::getGrabPointGlobal()
  939. {
  940. switch(mMode)
  941. {
  942. case GRAB_ACTIVE_CENTER:
  943. case GRAB_NONPHYSICAL:
  944. case GRAB_LOCKED:
  945. return gAgent.getCameraPositionGlobal() + mGrabHiddenOffsetFromCamera;
  946. case GRAB_NOOBJECT:
  947. case GRAB_INACTIVE:
  948. default:
  949. return gAgent.getPositionGlobal();
  950. }
  951. }