PageRenderTime 32ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/newview/llmaniptranslate.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2007 lines | 1604 code | 278 blank | 125 comment | 239 complexity | e78d1541749553c330ad50f9c1a0bab2 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llmaniptranslate.cpp
  3. * @brief LLManipTranslate class implementation
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. /**
  27. * Positioning tool
  28. */
  29. #include "llviewerprecompiledheaders.h"
  30. #include "llmaniptranslate.h"
  31. #include "llgl.h"
  32. #include "llrender.h"
  33. #include "llagent.h"
  34. #include "llagentcamera.h"
  35. #include "llbbox.h"
  36. #include "llbox.h"
  37. #include "llviewercontrol.h"
  38. #include "llcriticaldamp.h"
  39. #include "llcylinder.h"
  40. #include "lldrawable.h"
  41. #include "llfloatertools.h"
  42. #include "llfontgl.h"
  43. #include "llglheaders.h"
  44. #include "llhudrender.h"
  45. #include "llresmgr.h"
  46. #include "llselectmgr.h"
  47. #include "llrendersphere.h"
  48. #include "llstatusbar.h"
  49. #include "lltoolmgr.h"
  50. #include "llviewercamera.h"
  51. #include "llviewerjoint.h"
  52. #include "llviewerobject.h"
  53. #include "llviewerwindow.h"
  54. #include "llvoavatarself.h"
  55. #include "llworld.h"
  56. #include "llui.h"
  57. #include "pipeline.h"
  58. const S32 NUM_AXES = 3;
  59. const S32 MOUSE_DRAG_SLOP = 2; // pixels
  60. const F32 HANDLE_HIDE_ANGLE = 0.15f; // radians
  61. const F32 SELECTED_ARROW_SCALE = 1.3f;
  62. const F32 MANIPULATOR_HOTSPOT_START = 0.2f;
  63. const F32 MANIPULATOR_HOTSPOT_END = 1.2f;
  64. const F32 SNAP_GUIDE_SCREEN_SIZE = 0.7f;
  65. const F32 MIN_PLANE_MANIP_DOT_PRODUCT = 0.25f;
  66. const F32 PLANE_TICK_SIZE = 0.4f;
  67. const F32 MANIPULATOR_SCALE_HALF_LIFE = 0.07f;
  68. const F32 SNAP_ARROW_SCALE = 0.7f;
  69. static LLPointer<LLViewerTexture> sGridTex = NULL ;
  70. const LLManip::EManipPart MANIPULATOR_IDS[9] =
  71. {
  72. LLManip::LL_X_ARROW,
  73. LLManip::LL_Y_ARROW,
  74. LLManip::LL_Z_ARROW,
  75. LLManip::LL_X_ARROW,
  76. LLManip::LL_Y_ARROW,
  77. LLManip::LL_Z_ARROW,
  78. LLManip::LL_YZ_PLANE,
  79. LLManip::LL_XZ_PLANE,
  80. LLManip::LL_XY_PLANE
  81. };
  82. const U32 ARROW_TO_AXIS[4] =
  83. {
  84. VX,
  85. VX,
  86. VY,
  87. VZ
  88. };
  89. // Sort manipulator handles by their screen-space projection
  90. struct ClosestToCamera
  91. {
  92. bool operator()(const LLManipTranslate::ManipulatorHandle& a,
  93. const LLManipTranslate::ManipulatorHandle& b) const
  94. {
  95. return a.mEndPosition.mV[VZ] < b.mEndPosition.mV[VZ];
  96. }
  97. };
  98. LLManipTranslate::LLManipTranslate( LLToolComposite* composite )
  99. : LLManip( std::string("Move"), composite ),
  100. mLastHoverMouseX(-1),
  101. mLastHoverMouseY(-1),
  102. mSendUpdateOnMouseUp(FALSE),
  103. mMouseOutsideSlop(FALSE),
  104. mCopyMadeThisDrag(FALSE),
  105. mMouseDownX(-1),
  106. mMouseDownY(-1),
  107. mAxisArrowLength(50),
  108. mConeSize(0),
  109. mArrowLengthMeters(0.f),
  110. mGridSizeMeters(1.f),
  111. mPlaneManipOffsetMeters(0.f),
  112. mUpdateTimer(),
  113. mSnapOffsetMeters(0.f),
  114. mSubdivisions(10.f),
  115. mInSnapRegime(FALSE),
  116. mSnapped(FALSE),
  117. mArrowScales(1.f, 1.f, 1.f),
  118. mPlaneScales(1.f, 1.f, 1.f),
  119. mPlaneManipPositions(1.f, 1.f, 1.f, 1.f)
  120. {
  121. if (sGridTex.isNull())
  122. {
  123. restoreGL();
  124. }
  125. }
  126. //static
  127. U32 LLManipTranslate::getGridTexName()
  128. {
  129. if(sGridTex.isNull())
  130. {
  131. restoreGL() ;
  132. }
  133. return sGridTex.isNull() ? 0 : sGridTex->getTexName() ;
  134. }
  135. //static
  136. void LLManipTranslate::destroyGL()
  137. {
  138. if (sGridTex)
  139. {
  140. sGridTex = NULL ;
  141. }
  142. }
  143. //static
  144. void LLManipTranslate::restoreGL()
  145. {
  146. //generate grid texture
  147. U32 rez = 512;
  148. U32 mip = 0;
  149. destroyGL() ;
  150. sGridTex = LLViewerTextureManager::getLocalTexture() ;
  151. if(!sGridTex->createGLTexture())
  152. {
  153. sGridTex = NULL ;
  154. return ;
  155. }
  156. GLuint* d = new GLuint[rez*rez];
  157. gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex->getTexName(), true);
  158. gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
  159. while (rez >= 1)
  160. {
  161. for (U32 i = 0; i < rez*rez; i++)
  162. {
  163. d[i] = 0x00FFFFFF;
  164. }
  165. U32 subcol = 0xFFFFFFFF;
  166. if (rez >= 4)
  167. { //large grain grid
  168. for (U32 i = 0; i < rez; i++)
  169. {
  170. if (rez <= 16)
  171. {
  172. if (rez == 16)
  173. {
  174. subcol = 0xA0FFFFFF;
  175. }
  176. else if (rez == 8)
  177. {
  178. subcol = 0x80FFFFFF;
  179. }
  180. else
  181. {
  182. subcol = 0x40FFFFFF;
  183. }
  184. }
  185. else
  186. {
  187. subcol = 0xFFFFFFFF;
  188. }
  189. d[i *rez+ 0 ] = subcol;
  190. d[0 *rez+ i ] = subcol;
  191. if (rez >= 32)
  192. {
  193. d[i *rez+ (rez-1)] = subcol;
  194. d[(rez-1) *rez+ i ] = subcol;
  195. }
  196. if (rez >= 64)
  197. {
  198. subcol = 0xFFFFFFFF;
  199. if (i > 0 && i < (rez-1))
  200. {
  201. d[i *rez+ 1 ] = subcol;
  202. d[i *rez+ (rez-2)] = subcol;
  203. d[1 *rez+ i ] = subcol;
  204. d[(rez-2) *rez+ i ] = subcol;
  205. }
  206. }
  207. }
  208. }
  209. subcol = 0x50A0A0A0;
  210. if (rez >= 128)
  211. { //small grain grid
  212. for (U32 i = 8; i < rez; i+=8)
  213. {
  214. for (U32 j = 2; j < rez-2; j++)
  215. {
  216. d[i *rez+ j] = subcol;
  217. d[j *rez+ i] = subcol;
  218. }
  219. }
  220. }
  221. if (rez >= 64)
  222. { //medium grain grid
  223. if (rez == 64)
  224. {
  225. subcol = 0x50A0A0A0;
  226. }
  227. else
  228. {
  229. subcol = 0xA0D0D0D0;
  230. }
  231. for (U32 i = 32; i < rez; i+=32)
  232. {
  233. U32 pi = i-1;
  234. for (U32 j = 2; j < rez-2; j++)
  235. {
  236. d[i *rez+ j] = subcol;
  237. d[j *rez+ i] = subcol;
  238. if (rez > 128)
  239. {
  240. d[pi *rez+ j] = subcol;
  241. d[j *rez+ pi] = subcol;
  242. }
  243. }
  244. }
  245. }
  246. #ifdef LL_WINDOWS
  247. LLImageGL::setManualImage(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, GL_RGBA, GL_UNSIGNED_BYTE, d);
  248. #else
  249. LLImageGL::setManualImage(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, d);
  250. #endif
  251. rez = rez >> 1;
  252. mip++;
  253. }
  254. delete [] d;
  255. }
  256. LLManipTranslate::~LLManipTranslate()
  257. {
  258. }
  259. void LLManipTranslate::handleSelect()
  260. {
  261. LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
  262. gFloaterTools->setStatusText("move");
  263. LLManip::handleSelect();
  264. }
  265. BOOL LLManipTranslate::handleMouseDown(S32 x, S32 y, MASK mask)
  266. {
  267. BOOL handled = FALSE;
  268. // didn't click in any UI object, so must have clicked in the world
  269. if( (mHighlightedPart == LL_X_ARROW ||
  270. mHighlightedPart == LL_Y_ARROW ||
  271. mHighlightedPart == LL_Z_ARROW ||
  272. mHighlightedPart == LL_YZ_PLANE ||
  273. mHighlightedPart == LL_XZ_PLANE ||
  274. mHighlightedPart == LL_XY_PLANE ) )
  275. {
  276. handled = handleMouseDownOnPart( x, y, mask );
  277. }
  278. return handled;
  279. }
  280. // Assumes that one of the arrows on an object was hit.
  281. BOOL LLManipTranslate::handleMouseDownOnPart( S32 x, S32 y, MASK mask )
  282. {
  283. BOOL can_move = canAffectSelection();
  284. if (!can_move)
  285. {
  286. return FALSE;
  287. }
  288. highlightManipulators(x, y);
  289. S32 hit_part = mHighlightedPart;
  290. if( (hit_part != LL_X_ARROW) &&
  291. (hit_part != LL_Y_ARROW) &&
  292. (hit_part != LL_Z_ARROW) &&
  293. (hit_part != LL_YZ_PLANE) &&
  294. (hit_part != LL_XZ_PLANE) &&
  295. (hit_part != LL_XY_PLANE) )
  296. {
  297. return TRUE;
  298. }
  299. mHelpTextTimer.reset();
  300. sNumTimesHelpTextShown++;
  301. LLSelectMgr::getInstance()->getGrid(mGridOrigin, mGridRotation, mGridScale);
  302. LLSelectMgr::getInstance()->enableSilhouette(FALSE);
  303. // we just started a drag, so save initial object positions
  304. LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_MOVE);
  305. mManipPart = (EManipPart)hit_part;
  306. mMouseDownX = x;
  307. mMouseDownY = y;
  308. mMouseOutsideSlop = FALSE;
  309. LLVector3 axis;
  310. LLSelectNode *selectNode = mObjectSelection->getFirstMoveableNode(TRUE);
  311. if (!selectNode)
  312. {
  313. // didn't find the object in our selection...oh well
  314. llwarns << "Trying to translate an unselected object" << llendl;
  315. return TRUE;
  316. }
  317. LLViewerObject *selected_object = selectNode->getObject();
  318. if (!selected_object)
  319. {
  320. // somehow we lost the object!
  321. llwarns << "Translate manip lost the object, no selected object" << llendl;
  322. gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
  323. return TRUE;
  324. }
  325. // Compute unit vectors for arrow hit and a plane through that vector
  326. BOOL axis_exists = getManipAxis(selected_object, mManipPart, axis);
  327. getManipNormal(selected_object, mManipPart, mManipNormal);
  328. //LLVector3 select_center_agent = gAgent.getPosAgentFromGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal());
  329. // TomY: The above should (?) be identical to the below
  330. LLVector3 select_center_agent = getPivotPoint();
  331. mSubdivisions = llclamp(getSubdivisionLevel(select_center_agent, axis_exists ? axis : LLVector3::z_axis, getMinGridScale()), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
  332. // if we clicked on a planar manipulator, recenter mouse cursor
  333. if (mManipPart >= LL_YZ_PLANE && mManipPart <= LL_XY_PLANE)
  334. {
  335. LLCoordGL mouse_pos;
  336. if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(select_center_agent, mouse_pos))
  337. {
  338. // mouse_pos may be nonsense
  339. llwarns << "Failed to project object center to screen" << llendl;
  340. }
  341. else if (gSavedSettings.getBOOL("SnapToMouseCursor"))
  342. {
  343. LLUI::setMousePositionScreen(mouse_pos.mX, mouse_pos.mY);
  344. x = mouse_pos.mX;
  345. y = mouse_pos.mY;
  346. }
  347. }
  348. LLSelectMgr::getInstance()->updateSelectionCenter();
  349. LLVector3d object_start_global = gAgent.getPosGlobalFromAgent(getPivotPoint());
  350. getMousePointOnPlaneGlobal(mDragCursorStartGlobal, x, y, object_start_global, mManipNormal);
  351. mDragSelectionStartGlobal = object_start_global;
  352. mCopyMadeThisDrag = FALSE;
  353. // Route future Mouse messages here preemptively. (Release on mouse up.)
  354. setMouseCapture( TRUE );
  355. return TRUE;
  356. }
  357. BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
  358. {
  359. // Translation tool only works if mouse button is down.
  360. // Bail out if mouse not down.
  361. if( !hasMouseCapture() )
  362. {
  363. lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (inactive)" << llendl;
  364. // Always show cursor
  365. // gViewerWindow->setCursor(UI_CURSOR_ARROW);
  366. gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
  367. highlightManipulators(x, y);
  368. return TRUE;
  369. }
  370. // Handle auto-rotation if necessary.
  371. LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
  372. const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD;
  373. const S32 ROTATE_H_MARGIN = world_rect.getWidth() / 20;
  374. const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped;
  375. BOOL rotated = FALSE;
  376. // ...build mode moves camera about focus point
  377. if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD)
  378. {
  379. if (x < ROTATE_H_MARGIN)
  380. {
  381. gAgentCamera.cameraOrbitAround(rotate_angle);
  382. rotated = TRUE;
  383. }
  384. else if (x > world_rect.getWidth() - ROTATE_H_MARGIN)
  385. {
  386. gAgentCamera.cameraOrbitAround(-rotate_angle);
  387. rotated = TRUE;
  388. }
  389. }
  390. // Suppress processing if mouse hasn't actually moved.
  391. // This may cause problems if the camera moves outside of the
  392. // rotation above.
  393. if( x == mLastHoverMouseX && y == mLastHoverMouseY && !rotated)
  394. {
  395. lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (mouse unmoved)" << llendl;
  396. gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
  397. return TRUE;
  398. }
  399. mLastHoverMouseX = x;
  400. mLastHoverMouseY = y;
  401. // Suppress if mouse hasn't moved past the initial slop region
  402. // Reset once we start moving
  403. if( !mMouseOutsideSlop )
  404. {
  405. if (abs(mMouseDownX - x) < MOUSE_DRAG_SLOP && abs(mMouseDownY - y) < MOUSE_DRAG_SLOP )
  406. {
  407. lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (mouse inside slop)" << llendl;
  408. gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
  409. return TRUE;
  410. }
  411. else
  412. {
  413. // ...just went outside the slop region
  414. mMouseOutsideSlop = TRUE;
  415. // If holding down shift, leave behind a copy.
  416. if (mask == MASK_COPY)
  417. {
  418. // ...we're trying to make a copy
  419. LLSelectMgr::getInstance()->selectDuplicate(LLVector3::zero, FALSE);
  420. mCopyMadeThisDrag = TRUE;
  421. // When we make the copy, we don't want to do any other processing.
  422. // If so, the object will also be moved, and the copy will be offset.
  423. lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (made copy)" << llendl;
  424. gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
  425. }
  426. }
  427. }
  428. // Throttle updates to 10 per second.
  429. BOOL send_update = FALSE;
  430. LLVector3 axis_f;
  431. LLVector3d axis_d;
  432. // pick the first object to constrain to grid w/ common origin
  433. // this is so we don't screw up groups
  434. LLSelectNode* selectNode = mObjectSelection->getFirstMoveableNode(TRUE);
  435. if (!selectNode)
  436. {
  437. // somehow we lost the object!
  438. llwarns << "Translate manip lost the object, no selectNode" << llendl;
  439. gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
  440. return TRUE;
  441. }
  442. LLViewerObject* object = selectNode->getObject();
  443. if (!object)
  444. {
  445. // somehow we lost the object!
  446. llwarns << "Translate manip lost the object, no object in selectNode" << llendl;
  447. gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
  448. return TRUE;
  449. }
  450. // Compute unit vectors for arrow hit and a plane through that vector
  451. BOOL axis_exists = getManipAxis(object, mManipPart, axis_f); // TODO: move this
  452. axis_d.setVec(axis_f);
  453. LLSelectMgr::getInstance()->updateSelectionCenter();
  454. LLVector3d current_pos_global = gAgent.getPosGlobalFromAgent(getPivotPoint());
  455. mSubdivisions = llclamp(getSubdivisionLevel(getPivotPoint(), axis_f, getMinGridScale()), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
  456. // Project the cursor onto that plane
  457. LLVector3d relative_move;
  458. getMousePointOnPlaneGlobal(relative_move, x, y, current_pos_global, mManipNormal);\
  459. relative_move -= mDragCursorStartGlobal;
  460. // You can't move more than some distance from your original mousedown point.
  461. if (gSavedSettings.getBOOL("LimitDragDistance"))
  462. {
  463. F32 max_drag_distance = gSavedSettings.getF32("MaxDragDistance");
  464. if (relative_move.magVecSquared() > max_drag_distance * max_drag_distance)
  465. {
  466. lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (too far)" << llendl;
  467. gViewerWindow->setCursor(UI_CURSOR_NOLOCKED);
  468. return TRUE;
  469. }
  470. }
  471. F64 axis_magnitude = relative_move * axis_d; // dot product
  472. LLVector3d cursor_point_snap_line;
  473. F64 off_axis_magnitude;
  474. getMousePointOnPlaneGlobal(cursor_point_snap_line, x, y, current_pos_global, mSnapOffsetAxis % axis_f);
  475. off_axis_magnitude = axis_exists ? llabs((cursor_point_snap_line - current_pos_global) * LLVector3d(mSnapOffsetAxis)) : 0.f;
  476. if (gSavedSettings.getBOOL("SnapEnabled"))
  477. {
  478. if (off_axis_magnitude > mSnapOffsetMeters)
  479. {
  480. mInSnapRegime = TRUE;
  481. LLVector3 mouse_down_offset(mDragCursorStartGlobal - mDragSelectionStartGlobal);
  482. LLVector3 cursor_snap_agent = gAgent.getPosAgentFromGlobal(cursor_point_snap_line);
  483. if (!gSavedSettings.getBOOL("SnapToMouseCursor"))
  484. {
  485. cursor_snap_agent -= mouse_down_offset;
  486. }
  487. F32 cursor_grid_dist = (cursor_snap_agent - mGridOrigin) * axis_f;
  488. F32 snap_dist = getMinGridScale() / (2.f * mSubdivisions);
  489. F32 relative_snap_dist = fmodf(llabs(cursor_grid_dist) + snap_dist, getMinGridScale() / mSubdivisions);
  490. if (relative_snap_dist < snap_dist * 2.f)
  491. {
  492. if (cursor_grid_dist > 0.f)
  493. {
  494. cursor_grid_dist -= relative_snap_dist - snap_dist;
  495. }
  496. else
  497. {
  498. cursor_grid_dist += relative_snap_dist - snap_dist;
  499. }
  500. }
  501. F32 object_start_on_axis = (gAgent.getPosAgentFromGlobal(mDragSelectionStartGlobal) - mGridOrigin) * axis_f;
  502. axis_magnitude = cursor_grid_dist - object_start_on_axis;
  503. }
  504. else if (mManipPart >= LL_YZ_PLANE && mManipPart <= LL_XY_PLANE)
  505. {
  506. // subtract offset from object center
  507. LLVector3d cursor_point_global;
  508. getMousePointOnPlaneGlobal( cursor_point_global, x, y, current_pos_global, mManipNormal );
  509. cursor_point_global -= (mDragCursorStartGlobal - mDragSelectionStartGlobal);
  510. // snap to planar grid
  511. LLVector3 cursor_point_agent = gAgent.getPosAgentFromGlobal(cursor_point_global);
  512. LLVector3 camera_plane_projection = LLViewerCamera::getInstance()->getAtAxis();
  513. camera_plane_projection -= projected_vec(camera_plane_projection, mManipNormal);
  514. camera_plane_projection.normVec();
  515. LLVector3 camera_projected_dir = camera_plane_projection;
  516. camera_plane_projection.rotVec(~mGridRotation);
  517. camera_plane_projection.scaleVec(mGridScale);
  518. camera_plane_projection.abs();
  519. F32 max_grid_scale;
  520. if (camera_plane_projection.mV[VX] > camera_plane_projection.mV[VY] &&
  521. camera_plane_projection.mV[VX] > camera_plane_projection.mV[VZ])
  522. {
  523. max_grid_scale = mGridScale.mV[VX];
  524. }
  525. else if (camera_plane_projection.mV[VY] > camera_plane_projection.mV[VZ])
  526. {
  527. max_grid_scale = mGridScale.mV[VY];
  528. }
  529. else
  530. {
  531. max_grid_scale = mGridScale.mV[VZ];
  532. }
  533. F32 num_subdivisions = llclamp(getSubdivisionLevel(getPivotPoint(), camera_projected_dir, max_grid_scale), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
  534. F32 grid_scale_a;
  535. F32 grid_scale_b;
  536. LLVector3 cursor_point_grid = (cursor_point_agent - mGridOrigin) * ~mGridRotation;
  537. switch (mManipPart)
  538. {
  539. case LL_YZ_PLANE:
  540. grid_scale_a = mGridScale.mV[VY] / num_subdivisions;
  541. grid_scale_b = mGridScale.mV[VZ] / num_subdivisions;
  542. cursor_point_grid.mV[VY] -= fmod(cursor_point_grid.mV[VY] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f;
  543. cursor_point_grid.mV[VZ] -= fmod(cursor_point_grid.mV[VZ] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f;
  544. break;
  545. case LL_XZ_PLANE:
  546. grid_scale_a = mGridScale.mV[VX] / num_subdivisions;
  547. grid_scale_b = mGridScale.mV[VZ] / num_subdivisions;
  548. cursor_point_grid.mV[VX] -= fmod(cursor_point_grid.mV[VX] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f;
  549. cursor_point_grid.mV[VZ] -= fmod(cursor_point_grid.mV[VZ] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f;
  550. break;
  551. case LL_XY_PLANE:
  552. grid_scale_a = mGridScale.mV[VX] / num_subdivisions;
  553. grid_scale_b = mGridScale.mV[VY] / num_subdivisions;
  554. cursor_point_grid.mV[VX] -= fmod(cursor_point_grid.mV[VX] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f;
  555. cursor_point_grid.mV[VY] -= fmod(cursor_point_grid.mV[VY] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f;
  556. break;
  557. default:
  558. break;
  559. }
  560. cursor_point_agent = (cursor_point_grid * mGridRotation) + mGridOrigin;
  561. relative_move.setVec(cursor_point_agent - gAgent.getPosAgentFromGlobal(mDragSelectionStartGlobal));
  562. mInSnapRegime = TRUE;
  563. }
  564. else
  565. {
  566. mInSnapRegime = FALSE;
  567. }
  568. }
  569. else
  570. {
  571. mInSnapRegime = FALSE;
  572. }
  573. // Clamp to arrow direction
  574. // *FIX: does this apply anymore?
  575. if (!axis_exists)
  576. {
  577. axis_magnitude = relative_move.normVec();
  578. axis_d.setVec(relative_move);
  579. axis_d.normVec();
  580. axis_f.setVec(axis_d);
  581. }
  582. LLVector3d clamped_relative_move = axis_magnitude * axis_d; // scalar multiply
  583. LLVector3 clamped_relative_move_f = (F32)axis_magnitude * axis_f; // scalar multiply
  584. for (LLObjectSelection::iterator iter = mObjectSelection->begin();
  585. iter != mObjectSelection->end(); iter++)
  586. {
  587. LLSelectNode* selectNode = *iter;
  588. LLViewerObject* object = selectNode->getObject();
  589. // Only apply motion to root objects and objects selected
  590. // as "individual".
  591. if (!object->isRootEdit() && !selectNode->mIndividualSelection)
  592. {
  593. continue;
  594. }
  595. if (!object->isRootEdit())
  596. {
  597. // child objects should not update if parent is selected
  598. LLViewerObject* editable_root = (LLViewerObject*)object->getParent();
  599. if (editable_root->isSelected())
  600. {
  601. // we will be moved properly by our parent, so skip
  602. continue;
  603. }
  604. }
  605. if (object->permMove())
  606. {
  607. // handle attachments in local space
  608. if (object->isAttachment() && object->mDrawable.notNull())
  609. {
  610. // calculate local version of relative move
  611. LLQuaternion objWorldRotation = object->mDrawable->mXform.getParent()->getWorldRotation();
  612. objWorldRotation.transQuat();
  613. LLVector3 old_position_local = object->getPosition();
  614. LLVector3 new_position_local = selectNode->mSavedPositionLocal + (clamped_relative_move_f * objWorldRotation);
  615. // move and clamp root object first, before adjusting children
  616. if (new_position_local != old_position_local)
  617. {
  618. send_update = TRUE;
  619. }
  620. //RN: I forget, but we need to do this because of snapping which doesn't often result
  621. // in position changes even when the mouse moves
  622. object->setPosition(new_position_local);
  623. rebuild(object);
  624. gAgentAvatarp->clampAttachmentPositions();
  625. new_position_local = object->getPosition();
  626. if (selectNode->mIndividualSelection)
  627. {
  628. send_update = FALSE;
  629. // counter-translate child objects if we are moving the root as an individual
  630. object->resetChildrenPosition(old_position_local - new_position_local, TRUE) ;
  631. }
  632. }
  633. else
  634. {
  635. // compute new position to send to simulators, but don't set it yet.
  636. // We need the old position to know which simulator to send the move message to.
  637. LLVector3d new_position_global = selectNode->mSavedPositionGlobal + clamped_relative_move;
  638. // Don't let object centers go too far underground
  639. F64 min_height = LLWorld::getInstance()->getMinAllowedZ(object, object->getPositionGlobal());
  640. if (new_position_global.mdV[VZ] < min_height)
  641. {
  642. new_position_global.mdV[VZ] = min_height;
  643. }
  644. // For safety, cap heights where objects can be dragged
  645. if (new_position_global.mdV[VZ] > MAX_OBJECT_Z)
  646. {
  647. new_position_global.mdV[VZ] = MAX_OBJECT_Z;
  648. }
  649. // Grass is always drawn on the ground, so clamp its position to the ground
  650. if (object->getPCode() == LL_PCODE_LEGACY_GRASS)
  651. {
  652. new_position_global.mdV[VZ] = LLWorld::getInstance()->resolveLandHeightGlobal(new_position_global) + 1.f;
  653. }
  654. if (object->isRootEdit())
  655. {
  656. new_position_global = LLWorld::getInstance()->clipToVisibleRegions(object->getPositionGlobal(), new_position_global);
  657. }
  658. // PR: Only update if changed
  659. LLVector3d old_position_global = object->getPositionGlobal();
  660. LLVector3 old_position_agent = object->getPositionAgent();
  661. LLVector3 new_position_agent = gAgent.getPosAgentFromGlobal(new_position_global);
  662. if (object->isRootEdit())
  663. {
  664. // finally, move parent object after children have calculated new offsets
  665. object->setPositionAgent(new_position_agent);
  666. rebuild(object);
  667. }
  668. else
  669. {
  670. LLViewerObject* root_object = object->getRootEdit();
  671. new_position_agent -= root_object->getPositionAgent();
  672. new_position_agent = new_position_agent * ~root_object->getRotation();
  673. object->setPositionParent(new_position_agent, FALSE);
  674. rebuild(object);
  675. }
  676. if (selectNode->mIndividualSelection)
  677. {
  678. // counter-translate child objects if we are moving the root as an individual
  679. object->resetChildrenPosition(old_position_agent - new_position_agent, TRUE) ;
  680. send_update = FALSE;
  681. }
  682. else if (old_position_global != new_position_global)
  683. {
  684. send_update = TRUE;
  685. }
  686. }
  687. selectNode->mLastPositionLocal = object->getPosition();
  688. }
  689. }
  690. LLSelectMgr::getInstance()->updateSelectionCenter();
  691. gAgentCamera.clearFocusObject();
  692. dialog_refresh_all(); // ??? is this necessary?
  693. lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (active)" << llendl;
  694. gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
  695. return TRUE;
  696. }
  697. void LLManipTranslate::highlightManipulators(S32 x, S32 y)
  698. {
  699. mHighlightedPart = LL_NO_PART;
  700. if (!mObjectSelection->getObjectCount())
  701. {
  702. return;
  703. }
  704. //LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();
  705. LLMatrix4 projMatrix = LLViewerCamera::getInstance()->getProjection();
  706. LLMatrix4 modelView = LLViewerCamera::getInstance()->getModelview();
  707. LLVector3 object_position = getPivotPoint();
  708. LLVector3 grid_origin;
  709. LLVector3 grid_scale;
  710. LLQuaternion grid_rotation;
  711. LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale);
  712. LLVector3 relative_camera_dir;
  713. LLMatrix4 transform;
  714. if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
  715. {
  716. relative_camera_dir = LLVector3(1.f, 0.f, 0.f) * ~grid_rotation;
  717. LLVector4 translation(object_position);
  718. transform.initRotTrans(grid_rotation, translation);
  719. LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
  720. transform *= cfr;
  721. LLMatrix4 window_scale;
  722. F32 zoom_level = 2.f * gAgentCamera.mHUDCurZoom;
  723. window_scale.initAll(LLVector3(zoom_level / LLViewerCamera::getInstance()->getAspect(), zoom_level, 0.f),
  724. LLQuaternion::DEFAULT,
  725. LLVector3::zero);
  726. transform *= window_scale;
  727. }
  728. else
  729. {
  730. relative_camera_dir = (object_position - LLViewerCamera::getInstance()->getOrigin()) * ~grid_rotation;
  731. relative_camera_dir.normVec();
  732. transform.initRotTrans(grid_rotation, LLVector4(object_position));
  733. transform *= modelView;
  734. transform *= projMatrix;
  735. }
  736. S32 numManips = 0;
  737. // edges
  738. mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 0.f, 0.f, 1.f);
  739. mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 0.f, 0.f, 1.f);
  740. mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 0.f, 1.f);
  741. mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 0.f, 1.f);
  742. mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 1.f);
  743. mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 1.f);
  744. mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 0.f, 0.f, 1.f);
  745. mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 0.f, 0.f, 1.f);
  746. mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 0.f, 1.f);
  747. mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 0.f, 1.f);
  748. mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 1.f);
  749. mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 1.f);
  750. S32 num_arrow_manips = numManips;
  751. // planar manipulators
  752. BOOL planar_manip_yz_visible = FALSE;
  753. BOOL planar_manip_xz_visible = FALSE;
  754. BOOL planar_manip_xy_visible = FALSE;
  755. mManipulatorVertices[numManips] = LLVector4(0.f, mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 1.f);
  756. mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
  757. mManipulatorVertices[numManips] = LLVector4(0.f, mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 1.f);
  758. mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
  759. if (llabs(relative_camera_dir.mV[VX]) > MIN_PLANE_MANIP_DOT_PRODUCT)
  760. {
  761. planar_manip_yz_visible = TRUE;
  762. }
  763. mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 0.f, mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 1.f);
  764. mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
  765. mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 0.f, mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 1.f);
  766. mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
  767. if (llabs(relative_camera_dir.mV[VY]) > MIN_PLANE_MANIP_DOT_PRODUCT)
  768. {
  769. planar_manip_xz_visible = TRUE;
  770. }
  771. mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 0.f, 1.f);
  772. mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
  773. mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 0.f, 1.f);
  774. mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
  775. if (llabs(relative_camera_dir.mV[VZ]) > MIN_PLANE_MANIP_DOT_PRODUCT)
  776. {
  777. planar_manip_xy_visible = TRUE;
  778. }
  779. // Project up to 9 manipulators to screen space 2*X, 2*Y, 2*Z, 3*planes
  780. std::vector<ManipulatorHandle> projected_manipulators;
  781. projected_manipulators.reserve(9);
  782. for (S32 i = 0; i < num_arrow_manips; i+= 2)
  783. {
  784. LLVector4 projected_start = mManipulatorVertices[i] * transform;
  785. projected_start = projected_start * (1.f / projected_start.mV[VW]);
  786. LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
  787. projected_end = projected_end * (1.f / projected_end.mV[VW]);
  788. ManipulatorHandle projected_manip(
  789. LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
  790. LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]),
  791. MANIPULATOR_IDS[i / 2],
  792. 10.f); // 10 pixel hotspot for arrows
  793. projected_manipulators.push_back(projected_manip);
  794. }
  795. if (planar_manip_yz_visible)
  796. {
  797. S32 i = num_arrow_manips;
  798. LLVector4 projected_start = mManipulatorVertices[i] * transform;
  799. projected_start = projected_start * (1.f / projected_start.mV[VW]);
  800. LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
  801. projected_end = projected_end * (1.f / projected_end.mV[VW]);
  802. ManipulatorHandle projected_manip(
  803. LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
  804. LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]),
  805. MANIPULATOR_IDS[i / 2],
  806. 20.f); // 20 pixels for planar manipulators
  807. projected_manipulators.push_back(projected_manip);
  808. }
  809. if (planar_manip_xz_visible)
  810. {
  811. S32 i = num_arrow_manips + 2;
  812. LLVector4 projected_start = mManipulatorVertices[i] * transform;
  813. projected_start = projected_start * (1.f / projected_start.mV[VW]);
  814. LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
  815. projected_end = projected_end * (1.f / projected_end.mV[VW]);
  816. ManipulatorHandle projected_manip(
  817. LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
  818. LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]),
  819. MANIPULATOR_IDS[i / 2],
  820. 20.f); // 20 pixels for planar manipulators
  821. projected_manipulators.push_back(projected_manip);
  822. }
  823. if (planar_manip_xy_visible)
  824. {
  825. S32 i = num_arrow_manips + 4;
  826. LLVector4 projected_start = mManipulatorVertices[i] * transform;
  827. projected_start = projected_start * (1.f / projected_start.mV[VW]);
  828. LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
  829. projected_end = projected_end * (1.f / projected_end.mV[VW]);
  830. ManipulatorHandle projected_manip(
  831. LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
  832. LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]),
  833. MANIPULATOR_IDS[i / 2],
  834. 20.f); // 20 pixels for planar manipulators
  835. projected_manipulators.push_back(projected_manip);
  836. }
  837. LLVector2 manip_start_2d;
  838. LLVector2 manip_end_2d;
  839. LLVector2 manip_dir;
  840. LLRect world_view_rect = gViewerWindow->getWorldViewRectScaled();
  841. F32 half_width = (F32)world_view_rect.getWidth() / 2.f;
  842. F32 half_height = (F32)world_view_rect.getHeight() / 2.f;
  843. LLVector2 mousePos((F32)x - half_width, (F32)y - half_height);
  844. LLVector2 mouse_delta;
  845. // Keep order consistent with insertion via stable_sort
  846. std::stable_sort( projected_manipulators.begin(),
  847. projected_manipulators.end(),
  848. ClosestToCamera() );
  849. std::vector<ManipulatorHandle>::iterator it = projected_manipulators.begin();
  850. for ( ; it != projected_manipulators.end(); ++it)
  851. {
  852. ManipulatorHandle& manipulator = *it;
  853. {
  854. manip_start_2d.setVec(manipulator.mStartPosition.mV[VX] * half_width, manipulator.mStartPosition.mV[VY] * half_height);
  855. manip_end_2d.setVec(manipulator.mEndPosition.mV[VX] * half_width, manipulator.mEndPosition.mV[VY] * half_height);
  856. manip_dir = manip_end_2d - manip_start_2d;
  857. mouse_delta = mousePos - manip_start_2d;
  858. F32 manip_length = manip_dir.normVec();
  859. F32 mouse_pos_manip = mouse_delta * manip_dir;
  860. F32 mouse_dist_manip_squared = mouse_delta.magVecSquared() - (mouse_pos_manip * mouse_pos_manip);
  861. if (mouse_pos_manip > 0.f &&
  862. mouse_pos_manip < manip_length &&
  863. mouse_dist_manip_squared < manipulator.mHotSpotRadius * manipulator.mHotSpotRadius)
  864. {
  865. mHighlightedPart = manipulator.mManipID;
  866. break;
  867. }
  868. }
  869. }
  870. }
  871. F32 LLManipTranslate::getMinGridScale()
  872. {
  873. F32 scale;
  874. switch (mManipPart)
  875. {
  876. case LL_NO_PART:
  877. default:
  878. scale = 1.f;
  879. break;
  880. case LL_X_ARROW:
  881. scale = mGridScale.mV[VX];
  882. break;
  883. case LL_Y_ARROW:
  884. scale = mGridScale.mV[VY];
  885. break;
  886. case LL_Z_ARROW:
  887. scale = mGridScale.mV[VZ];
  888. break;
  889. case LL_YZ_PLANE:
  890. scale = llmin(mGridScale.mV[VY], mGridScale.mV[VZ]);
  891. break;
  892. case LL_XZ_PLANE:
  893. scale = llmin(mGridScale.mV[VX], mGridScale.mV[VZ]);
  894. break;
  895. case LL_XY_PLANE:
  896. scale = llmin(mGridScale.mV[VX], mGridScale.mV[VY]);
  897. break;
  898. }
  899. return scale;
  900. }
  901. BOOL LLManipTranslate::handleMouseUp(S32 x, S32 y, MASK mask)
  902. {
  903. // first, perform normal processing in case this was a quick-click
  904. handleHover(x, y, mask);
  905. if(hasMouseCapture())
  906. {
  907. // make sure arrow colors go back to normal
  908. mManipPart = LL_NO_PART;
  909. LLSelectMgr::getInstance()->enableSilhouette(TRUE);
  910. // Might have missed last update due to UPDATE_DELAY timing.
  911. LLSelectMgr::getInstance()->sendMultipleUpdate( UPD_POSITION );
  912. mInSnapRegime = FALSE;
  913. LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
  914. //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject"));
  915. }
  916. return LLManip::handleMouseUp(x, y, mask);
  917. }
  918. void LLManipTranslate::render()
  919. {
  920. gGL.matrixMode(LLRender::MM_MODELVIEW);
  921. gGL.pushMatrix();
  922. if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
  923. {
  924. F32 zoom = gAgentCamera.mHUDCurZoom;
  925. gGL.scalef(zoom, zoom, zoom);
  926. }
  927. {
  928. LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
  929. renderGuidelines();
  930. }
  931. {
  932. renderTranslationHandles();
  933. renderSnapGuides();
  934. }
  935. gGL.popMatrix();
  936. renderText();
  937. }
  938. void LLManipTranslate::renderSnapGuides()
  939. {
  940. if (!gSavedSettings.getBOOL("SnapEnabled"))
  941. {
  942. return;
  943. }
  944. F32 max_subdivisions = sGridMaxSubdivisionLevel;//(F32)gSavedSettings.getS32("GridSubdivision");
  945. F32 line_alpha = gSavedSettings.getF32("GridOpacity");
  946. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  947. LLGLDepthTest gls_depth(GL_TRUE);
  948. LLGLDisable gls_cull(GL_CULL_FACE);
  949. LLVector3 translate_axis;
  950. if (mManipPart == LL_NO_PART)
  951. {
  952. return;
  953. }
  954. LLSelectNode *first_node = mObjectSelection->getFirstMoveableNode(TRUE);
  955. if (!first_node)
  956. {
  957. return;
  958. }
  959. updateGridSettings();
  960. F32 smallest_grid_unit_scale = getMinGridScale() / max_subdivisions;
  961. LLVector3 grid_origin;
  962. LLVector3 grid_scale;
  963. LLQuaternion grid_rotation;
  964. LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale);
  965. LLVector3 saved_selection_center = getSavedPivotPoint(); //LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent();
  966. LLVector3 selection_center = getPivotPoint();
  967. LLViewerObject *first_object = first_node->getObject();
  968. //pick appropriate projection plane for snap rulers according to relative camera position
  969. if (mManipPart >= LL_X_ARROW && mManipPart <= LL_Z_ARROW)
  970. {
  971. LLVector3 normal;
  972. LLColor4 inner_color;
  973. LLManip::EManipPart temp_manip = mManipPart;
  974. switch (mManipPart)
  975. {
  976. case LL_X_ARROW:
  977. normal.setVec(1,0,0);
  978. inner_color.setVec(0,1,1,line_alpha);
  979. mManipPart = LL_YZ_PLANE;
  980. break;
  981. case LL_Y_ARROW:
  982. normal.setVec(0,1,0);
  983. inner_color.setVec(1,0,1,line_alpha);
  984. mManipPart = LL_XZ_PLANE;
  985. break;
  986. case LL_Z_ARROW:
  987. normal.setVec(0,0,1);
  988. inner_color.setVec(1,1,0,line_alpha);
  989. mManipPart = LL_XY_PLANE;
  990. break;
  991. default:
  992. break;
  993. }
  994. highlightIntersection(normal, selection_center, grid_rotation, inner_color);
  995. mManipPart = temp_manip;
  996. getManipAxis(first_object, mManipPart, translate_axis);
  997. LLVector3 at_axis_abs;
  998. if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
  999. {
  1000. at_axis_abs = LLVector3::x_axis * ~grid_rotation;
  1001. }
  1002. else
  1003. {
  1004. at_axis_abs = saved_selection_center - LLViewerCamera::getInstance()->getOrigin();
  1005. at_axis_abs.normVec();
  1006. at_axis_abs = at_axis_abs * ~grid_rotation;
  1007. }
  1008. at_axis_abs.abs();
  1009. if (at_axis_abs.mV[VX] > at_axis_abs.mV[VY] && at_axis_abs.mV[VX] > at_axis_abs.mV[VZ])
  1010. {
  1011. if (mManipPart == LL_Y_ARROW)
  1012. {
  1013. mSnapOffsetAxis = LLVector3::z_axis;
  1014. }
  1015. else if (mManipPart == LL_Z_ARROW)
  1016. {
  1017. mSnapOffsetAxis = LLVector3::y_axis;
  1018. }
  1019. else if (at_axis_abs.mV[VY] > at_axis_abs.mV[VZ])
  1020. {
  1021. mSnapOffsetAxis = LLVector3::z_axis;
  1022. }
  1023. else
  1024. {
  1025. mSnapOffsetAxis = LLVector3::y_axis;
  1026. }
  1027. }
  1028. else if (at_axis_abs.mV[VY] > at_axis_abs.mV[VZ])
  1029. {
  1030. if (mManipPart == LL_X_ARROW)
  1031. {
  1032. mSnapOffsetAxis = LLVector3::z_axis;
  1033. }
  1034. else if (mManipPart == LL_Z_ARROW)
  1035. {
  1036. mSnapOffsetAxis = LLVector3::x_axis;
  1037. }
  1038. else if (at_axis_abs.mV[VX] > at_axis_abs.mV[VZ])
  1039. {
  1040. mSnapOffsetAxis = LLVector3::z_axis;
  1041. }
  1042. else
  1043. {
  1044. mSnapOffsetAxis = LLVector3::x_axis;
  1045. }
  1046. }
  1047. else
  1048. {
  1049. if (mManipPart == LL_X_ARROW)
  1050. {
  1051. mSnapOffsetAxis = LLVector3::y_axis;
  1052. }
  1053. else if (mManipPart == LL_Y_ARROW)
  1054. {
  1055. mSnapOffsetAxis = LLVector3::x_axis;
  1056. }
  1057. else if (at_axis_abs.mV[VX] > at_axis_abs.mV[VY])
  1058. {
  1059. mSnapOffsetAxis = LLVector3::y_axis;
  1060. }
  1061. else
  1062. {
  1063. mSnapOffsetAxis = LLVector3::x_axis;
  1064. }
  1065. }
  1066. mSnapOffsetAxis = mSnapOffsetAxis * grid_rotation;
  1067. F32 guide_size_meters;
  1068. if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
  1069. {
  1070. guide_size_meters = 1.f / gAgentCamera.mHUDCurZoom;
  1071. mSnapOffsetMeters = mArrowLengthMeters * 1.5f;
  1072. }
  1073. else
  1074. {
  1075. LLVector3 cam_to_selection = getPivotPoint() - LLViewerCamera::getInstance()->getOrigin();
  1076. F32 current_range = cam_to_selection.normVec();
  1077. guide_size_meters = SNAP_GUIDE_SCREEN_SIZE * gViewerWindow->getWorldViewHeightRaw() * current_range / LLViewerCamera::getInstance()->getPixelMeterRatio();
  1078. F32 fraction_of_fov = mAxisArrowLength / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels();
  1079. F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians
  1080. F32 offset_at_camera = tan(apparent_angle) * 1.5f;
  1081. F32 range = dist_vec(gAgent.getPosAgentFromGlobal(first_node->mSavedPositionGlobal), LLViewerCamera::getInstance()->getOrigin());
  1082. mSnapOffsetMeters = range * offset_at_camera;
  1083. }
  1084. LLVector3 tick_start;
  1085. LLVector3 tick_end;
  1086. // how far away from grid origin is the selection along the axis of translation?
  1087. F32 dist_grid_axis = (selection_center - mGridOrigin) * translate_axis;
  1088. // find distance to nearest smallest grid unit
  1089. F32 offset_nearest_grid_unit = fmodf(dist_grid_axis, smallest_grid_unit_scale);
  1090. // how many smallest grid units are we away from largest grid scale?
  1091. S32 sub_div_offset = llround(fmod(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() / sGridMinSubdivisionLevel) / smallest_grid_unit_scale);
  1092. S32 num_ticks_per_side = llmax(1, llfloor(0.5f * guide_size_meters / smallest_grid_unit_scale));
  1093. LLGLDepthTest gls_depth(GL_FALSE);
  1094. for (S32 pass = 0; pass < 3; pass++)
  1095. {
  1096. LLColor4 line_color = setupSnapGuideRenderPass(pass);
  1097. gGL.begin(LLRender::LINES);
  1098. {
  1099. LLVector3 line_start = selection_center + (mSnapOffsetMeters * mSnapOffsetAxis) + (translate_axis * (guide_size_meters * 0.5f + offset_nearest_grid_unit));
  1100. LLVector3 line_end = selection_center + (mSnapOffsetMeters * mSnapOffsetAxis) - (translate_axis * (guide_size_meters * 0.5f + offset_nearest_grid_unit));
  1101. LLVector3 line_mid = (line_start + line_end) * 0.5f;
  1102. gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f);
  1103. gGL.vertex3fv(line_start.mV);
  1104. gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
  1105. gGL.vertex3fv(line_mid.mV);
  1106. gGL.vertex3fv(line_mid.mV);
  1107. gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f);
  1108. gGL.vertex3fv(line_end.mV);
  1109. line_start.setVec(selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) + (translate_axis * guide_size_meters * 0.5f));
  1110. line_end.setVec(selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) - (translate_axis * guide_size_meters * 0.5f));
  1111. line_mid = (line_start + line_end) * 0.5f;
  1112. gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f);
  1113. gGL.vertex3fv(line_start.mV);
  1114. gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
  1115. gGL.vertex3fv(line_mid.mV);
  1116. gGL.vertex3fv(line_mid.mV);
  1117. gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f);
  1118. gGL.vertex3fv(line_end.mV);
  1119. for (S32 i = -num_ticks_per_side; i <= num_ticks_per_side; i++)
  1120. {
  1121. tick_start = selection_center + (translate_axis * (smallest_grid_unit_scale * (F32)i - offset_nearest_grid_unit));
  1122. F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_start, translate_axis, getMinGridScale()), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
  1123. if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / cur_subdivisions)) != 0.f)
  1124. {
  1125. continue;
  1126. }
  1127. // add in off-axis offset
  1128. tick_start += (mSnapOffsetAxis * mSnapOffsetMeters);
  1129. BOOL is_sub_tick = FALSE;
  1130. F32 tick_scale = 1.f;
  1131. for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f)
  1132. {
  1133. if (fmodf((F32)(i + sub_div_offset), division_level) == 0.f)
  1134. {
  1135. break;
  1136. }
  1137. tick_scale *= 0.7f;
  1138. is_sub_tick = TRUE;
  1139. }
  1140. // S32 num_ticks_to_fade = is_sub_tick ? num_ticks_per_side / 2 : num_ticks_per_side;
  1141. // F32 alpha = line_alpha * (1.f - (0.8f * ((F32)llabs(i) / (F32)num_ticks_to_fade)));
  1142. tick_end = tick_start + (mSnapOffsetAxis * mSnapOffsetMeters * tick_scale);
  1143. gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
  1144. gGL.vertex3fv(tick_start.mV);
  1145. gGL.vertex3fv(tick_end.mV);
  1146. tick_start = selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) +
  1147. (translate_axis * (getMinGridScale() / (F32)(max_subdivisions) * (F32)i - offset_nearest_grid_unit));
  1148. tick_end = tick_start - (mSnapOffsetAxis * mSnapOffsetMeters * tick_scale);
  1149. gGL.vertex3fv(tick_start.mV);
  1150. gGL.vertex3fv(tick_end.mV);
  1151. }
  1152. }
  1153. gGL.end();
  1154. if (mInSnapRegime)
  1155. {
  1156. LLVector3 line_start = selection_center - mSnapOffsetAxis * mSnapOffsetMeters;
  1157. LLVector3 line_end = selection_center + mSnapOffsetAxis * mSnapOffsetMeters;
  1158. gGL.begin(LLRender::LINES);
  1159. {
  1160. gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
  1161. gGL.vertex3fv(line_start.mV);
  1162. gGL.vertex3fv(line_end.mV);
  1163. }
  1164. gGL.end();
  1165. // draw snap guide arrow
  1166. gGL.begin(LLRender::TRIANGLES);
  1167. {
  1168. gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
  1169. LLVector3 arrow_dir;
  1170. LLVector3 arrow_span = translate_axis;
  1171. arrow_dir = -mSnapOffsetAxis;
  1172. gGL.vertex3fv((line_start + arrow_dir * mConeSize * SNAP_ARROW_SCALE).mV);
  1173. gGL.vertex3fv((line_start + arrow_span * mConeSize * SNAP_ARROW_SCALE).mV);
  1174. gGL.vertex3fv((line_start - arrow_span * mConeSize * SNAP_ARROW_SCALE).mV);
  1175. arrow_dir = mSnapOffsetAxis;
  1176. gGL.vertex3fv((line_end + arrow_dir * mConeSize * SNAP_ARROW_SCALE).mV);
  1177. gGL.vertex3fv((line_end + arrow_span * mConeSize * SNAP_ARROW_SCALE).mV);
  1178. gGL.vertex3fv((line_end - arrow_span * mConeSize * SNAP_ARROW_SCALE).mV);
  1179. }
  1180. gGL.end();
  1181. }
  1182. }
  1183. sub_div_offset = llround(fmod(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() * 32.f) / smallest_grid_unit_scale);
  1184. LLVector2 screen_translate_axis(llabs(translate_axis * LLViewerCamera::getInstance()->getLeftAxis()), llabs(translate_axis * LLViewerCamera::getInstance()->getUpAxis()));
  1185. screen_translate_axis.normVec();
  1186. S32 tick_label_spacing = llround(screen_translate_axis * sTickLabelSpacing);
  1187. // render tickmark values
  1188. for (S32 i = -num_ticks_per_side; i <= num_ticks_per_side; i++)
  1189. {
  1190. LLVector3 tick_pos = selection_center + (translate_axis * ((smallest_grid_unit_scale * (F32)i) - offset_nearest_grid_unit));
  1191. F32 alpha = line_alpha * (1.f - (0.5f * ((F32)llabs(i) / (F32)num_ticks_per_side)));
  1192. F32 tick_scale = 1.f;
  1193. for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f)
  1194. {
  1195. if (fmodf((F32)(i + sub_div_offset), division_level) == 0.f)
  1196. {
  1197. break;
  1198. }
  1199. tick_scale *= 0.7f;
  1200. }
  1201. if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / llmin(sGridMaxSubdivisionLevel, getSubdivisionLevel(tick_pos, translate_axis, getMinGridScale(), tick_label_spacing)))) == 0.f)
  1202. {
  1203. F32 snap_offset_meters;
  1204. if (mSnapOffsetAxis * LLViewerCamera::getInstance()->getUpAxis() > 0.f)
  1205. {
  1206. snap_offset_meters = mSnapOffsetMeters;
  1207. }
  1208. else
  1209. {
  1210. snap_offset_meters = -mSnapOffsetMeters;
  1211. }
  1212. LLVector3 text_origin = selection_center +
  1213. (translate_axis * ((smallest_grid_unit_scale * (F32)i) - offset_nearest_grid_unit)) +
  1214. (mSnapOffsetAxis * snap_offset_meters * (1.f + tick_scale));
  1215. LLVector3 tick_offset = (tick_pos - mGridOrigin) * ~mGridRotation;
  1216. F32 offset_val = 0.5f * tick_offset.mV[ARROW_TO_AXIS[mManipPart]] / getMinGridScale();
  1217. EGridMode grid_mode = LLSelectMgr::getInstance()->getGridMode();
  1218. F32 text_highlight = 0.8f;
  1219. if(i - llround(offset_nearest_grid_unit / smallest_grid_unit_scale) == 0 && mInSnapRegime)
  1220. {
  1221. text_highlight = 1.f;
  1222. }
  1223. if (grid_mode == GRID_MODE_WORLD)
  1224. {
  1225. // rescale units to meters from multiple of grid scale
  1226. offset_val *= 2.f * grid_scale[ARROW_TO_AXIS[mManipPart]];
  1227. renderTickValue(text_origin, offset_val, std::string("m"), LLColor4(text_highlight, text_highlight, text_highlight, alpha));
  1228. }
  1229. else
  1230. {
  1231. renderTickValue(text_origin, offset_val, std::string("x"), LLColor4(text_highlight, text_highlight, text_highlight, alpha));
  1232. }
  1233. }
  1234. }
  1235. if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD)
  1236. {
  1237. // render helpful text
  1238. if (mHelpTextTimer.getElapsedTimeF32() < sHelpTextVisibleTime + sHelpTextFadeTime && sNumTimesHelpTextShown < sMaxTimesShowHelpText)
  1239. {
  1240. F32 snap_offset_meters_up;
  1241. if (mSnapOffsetAxis * LLViewerCamera::getInstance()->getUpAxis() > 0.f)
  1242. {
  1243. snap_offset_meters_up = mSnapOffsetMeters;
  1244. }
  1245. else
  1246. {
  1247. snap_offset_meters_up = -mSnapOffsetMeters;
  1248. }
  1249. LLVector3 selection_center_start = getSavedPivotPoint();//LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent();
  1250. LLVector3 help_text_pos = selection_center_start + (snap_offset_meters_up * 3.f * mSnapOffsetAxis);
  1251. const LLFontGL* big_fontp = LLFontGL::getFontSansSerif();
  1252. std::string help_text = "Move mouse cursor over ruler";
  1253. LLColor4 help_text_color = LLColor4::white;
  1254. help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, line_alpha, 0.f);
  1255. hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
  1256. help_text = "to snap to grid";
  1257. help_text_pos -= LLViewerCamera::getInstance()->getUpAxis() * mSnapOffsetMeters * 0.2f;
  1258. hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
  1259. }
  1260. }
  1261. }
  1262. else
  1263. {
  1264. // render gridlines for planar snapping
  1265. F32 u = 0, v = 0;
  1266. LLColor4 inner_color;
  1267. LLVector3 normal;
  1268. LLVector3 grid_center = selection_center - grid_origin;
  1269. F32 usc = 1;
  1270. F32 vsc = 1;
  1271. grid_center *= ~grid_rotation;
  1272. switch (mManipPart)
  1273. {
  1274. case LL_YZ_PLANE:
  1275. u = grid_center.mV[VY];
  1276. v = grid_center.mV[VZ];
  1277. usc = grid_scale.mV[VY];
  1278. vsc = grid_scale.mV[VZ];
  1279. inner_color.setVec(0,1,1,line_alpha);
  1280. normal.setVec(1,0,0);
  1281. break;
  1282. case LL_XZ_PLANE:
  1283. u = grid_center.mV[VX];
  1284. v = grid_center.mV[VZ];
  1285. usc = grid_scale.mV[VX];
  1286. vsc = grid_scale.mV[VZ];
  1287. inner_color.setVec(1,0,1,line_alpha);
  1288. normal.setVec(0,1,0);
  1289. break;
  1290. case LL_XY_PLANE:
  1291. u = grid_center.mV[VX];
  1292. v = grid_center.mV[VY];
  1293. usc = grid_scale.mV[VX];
  1294. vsc = grid_scale.mV[VY];
  1295. inner_color.setVec(1,1,0,line_alpha);
  1296. normal.setVec(0,0,1);
  1297. break;
  1298. default:
  1299. break;
  1300. }
  1301. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  1302. highlightIntersection(normal, selection_center, grid_rotation, inner_color);
  1303. gGL.pushMatrix();
  1304. F32 x,y,z,angle_radians;
  1305. grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z);
  1306. gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]);
  1307. gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z);
  1308. F32 sz = mGridSizeMeters;
  1309. F32 tiles = sz;
  1310. gGL.matrixMode(LLRender::MM_TEXTURE);
  1311. gGL.pushMatrix();
  1312. usc = 1.0f/usc;
  1313. vsc = 1.0f/vsc;
  1314. while (usc > vsc*4.0f)
  1315. {
  1316. usc *= 0.5f;
  1317. }
  1318. while (vsc > usc * 4.0f)
  1319. {
  1320. vsc *= 0.5f;
  1321. }
  1322. gGL.scalef(usc, vsc, 1.0f);
  1323. gGL.translatef(u, v, 0);
  1324. float a = line_alpha;
  1325. LLColor4 col = LLUIColorTable::instance().getColor("SilhouetteChildColor");
  1326. {
  1327. //draw grid behind objects
  1328. LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
  1329. {
  1330. LLGLDisable stencil(GL_STENCIL_TEST);
  1331. {
  1332. LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER);
  1333. gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getGridTexName());
  1334. gGL.flush();
  1335. gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
  1336. renderGrid(u,v,tiles,0.9f, 0.9f, 0.9f,a*0.15f);
  1337. gGL.flush();
  1338. gGL.setSceneBlendType(LLRender::BT_ALPHA);
  1339. }
  1340. {
  1341. LLGLDisable alpha_test(GL_ALPHA_TEST);
  1342. //draw black overlay
  1343. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  1344. renderGrid(u,v,tiles,0.0f, 0.0f, 0.0f,a*0.16f);
  1345. //draw grid top
  1346. gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getGridTexName());
  1347. renderGrid(u,v,tiles,1,1,1,a);
  1348. gGL.popMatrix();
  1349. gGL.matrixMode(LLRender::MM_MODELVIEW);
  1350. gGL.popMatrix();
  1351. }
  1352. {
  1353. LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
  1354. renderGuidelines();
  1355. }
  1356. {
  1357. LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER);
  1358. LLGLEnable stipple(GL_LINE_STIPPLE);
  1359. gGL.flush();
  1360. glLineStipple(1, 0x3333);
  1361. switch (mManipPart)
  1362. {
  1363. case LL_YZ_PLANE:
  1364. renderGuidelines(FALSE, TRUE, TRUE);
  1365. break;
  1366. case LL_XZ_PLANE:
  1367. renderGuidelines(TRUE, FALSE, TRUE);
  1368. break;
  1369. case LL_XY_PLANE:
  1370. renderGuidelines(TRUE, TRUE, FALSE);
  1371. break;
  1372. default:
  1373. break;
  1374. }
  1375. gGL.flush();
  1376. }
  1377. }
  1378. }
  1379. }
  1380. }
  1381. void LLManipTranslate::renderGrid(F32 x, F32 y, F32 size, F32 r, F32 g, F32 b, F32 a)
  1382. {
  1383. F32 d = size*0.5f;
  1384. for (F32 xx = -size-d; xx < size+d; xx += d)
  1385. {
  1386. gGL.begin(LLRender::TRIANGLE_STRIP);
  1387. for (F32 yy = -size-d; yy < size+d; yy += d)
  1388. {
  1389. float dx, dy, da;
  1390. dx = xx; dy = yy;
  1391. da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a;
  1392. gGL.texCoord2f(dx, dy);
  1393. renderGridVert(dx,dy,r,g,b,da);
  1394. dx = xx+d; dy = yy;
  1395. da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a;
  1396. gGL.texCoord2f(dx, dy);
  1397. renderGridVert(dx,dy,r,g,b,da);
  1398. dx = xx; dy = yy+d;
  1399. da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a;
  1400. gGL.texCoord2f(dx, dy);
  1401. renderGridVert(dx,dy,r,g,b,da);
  1402. dx = xx+d; dy = yy+d;
  1403. da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a;
  1404. gGL.texCoord2f(dx, dy);
  1405. renderGridVert(dx,dy,r,g,b,da);
  1406. }
  1407. gGL.end();
  1408. }
  1409. }
  1410. void LLManipTranslate::highlightIntersection(LLVector3 normal,
  1411. LLVector3 selection_center,
  1412. LLQuaternion grid_rotation,
  1413. LLColor4 inner_color)
  1414. {
  1415. if (!gSavedSettings.getBOOL("GridCrossSections"))
  1416. {
  1417. return;
  1418. }
  1419. U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY };
  1420. U32 num_types = LL_ARRAY_SIZE(types);
  1421. GLuint stencil_mask = 0xFFFFFFFF;
  1422. //stencil in volumes
  1423. gGL.flush();
  1424. {
  1425. glStencilMask(stencil_mask);
  1426. glClearStencil(1);
  1427. glClear(GL_STENCIL_BUFFER_BIT);
  1428. LLGLEnable cull_face(GL_CULL_FACE);
  1429. LLGLEnable stencil(GL_STENCIL_TEST);
  1430. LLGLDepthTest depth (GL_TRUE, GL_FALSE, GL_ALWAYS);
  1431. glStencilFunc(GL_ALWAYS, 0, stencil_mask);
  1432. gGL.setColorMask(false, false);
  1433. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  1434. gGL.diffuseColor4f(1,1,1,1);
  1435. //setup clip plane
  1436. normal = normal * grid_rotation;
  1437. if (normal * (LLViewerCamera::getInstance()->getOrigin()-selection_center) < 0)
  1438. {
  1439. normal = -normal;
  1440. }
  1441. F32 d = -(selection_center * normal);
  1442. F64 plane[] = { normal.mV[0], normal.mV[1], normal.mV[2], d };
  1443. LLGLEnable clip(GL_CLIP_PLANE0);
  1444. glClipPlane(GL_CLIP_PLANE0, plane);
  1445. BOOL particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
  1446. BOOL clouds = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS);
  1447. if (particles)
  1448. {
  1449. LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
  1450. }
  1451. if (clouds)
  1452. {
  1453. LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS);
  1454. }
  1455. //stencil in volumes
  1456. glStencilOp(GL_INCR, GL_INCR, GL_INCR);
  1457. glCullFace(GL_FRONT);
  1458. for (U32 i = 0; i < num_types; i++)
  1459. {
  1460. gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
  1461. }
  1462. glStencilOp(GL_DECR, GL_DECR, GL_DECR);
  1463. glCullFace(GL_BACK);
  1464. for (U32 i = 0; i < num_types; i++)
  1465. {
  1466. gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
  1467. }
  1468. if (particles)
  1469. {
  1470. LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
  1471. }
  1472. if (clouds)
  1473. {
  1474. LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS);
  1475. }
  1476. gGL.setColorMask(true, false);
  1477. }
  1478. gGL.color4f(1,1,1,1);
  1479. gGL.pushMatrix();
  1480. F32 x,y,z,angle_radians;
  1481. grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z);
  1482. gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]);
  1483. gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z);
  1484. F32 sz = mGridSizeMeters;
  1485. F32 tiles = sz;
  1486. //draw volume/plane intersections
  1487. {
  1488. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  1489. LLGLDepthTest depth(GL_FALSE);
  1490. LLGLEnable stencil(GL_STENCIL_TEST);
  1491. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  1492. glStencilFunc(GL_EQUAL, 0, stencil_mask);
  1493. renderGrid(0,0,tiles,inner_color.mV[0], inner_color.mV[1], inner_color.mV[2], 0.25f);
  1494. }
  1495. glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF);
  1496. glStencilMask(0xFFFFFFFF);
  1497. glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  1498. gGL.popMatrix();
  1499. }
  1500. void LLManipTranslate::renderText()
  1501. {
  1502. if (mObjectSelection->getRootObjectCount() && !mObjectSelection->isAttachment())
  1503. {
  1504. LLVector3 pos = getPivotPoint();
  1505. renderXYZ(pos);
  1506. }
  1507. else
  1508. {
  1509. const BOOL children_ok = TRUE;
  1510. LLViewerObject* objectp = mObjectSelection->getFirstRootObject(children_ok);
  1511. if (objectp)
  1512. {
  1513. renderXYZ(objectp->getPositionEdit());
  1514. }
  1515. }
  1516. }
  1517. void LLManipTranslate::renderTranslationHandles()
  1518. {
  1519. LLVector3 grid_origin;
  1520. LLVector3 grid_scale;
  1521. LLQuaternion grid_rotation;
  1522. LLGLDepthTest gls_depth(GL_FALSE);
  1523. LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale);
  1524. LLVector3 at_axis;
  1525. if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
  1526. {
  1527. at_axis = LLVector3::x_axis * ~grid_rotation;
  1528. }
  1529. else
  1530. {
  1531. at_axis = LLViewerCamera::getInstance()->getAtAxis() * ~grid_rotation;
  1532. }
  1533. if (at_axis.mV[VX] > 0.f)
  1534. {
  1535. mPlaneManipPositions.mV[VX] = 1.f;
  1536. }
  1537. else
  1538. {
  1539. mPlaneManipPositions.mV[VX] = -1.f;
  1540. }
  1541. if (at_axis.mV[VY] > 0.f)
  1542. {
  1543. mPlaneManipPositions.mV[VY] = 1.f;
  1544. }
  1545. else
  1546. {
  1547. mPlaneManipPositions.mV[VY] = -1.f;
  1548. }
  1549. if (at_axis.mV[VZ] > 0.f)
  1550. {
  1551. mPlaneManipPositions.mV[VZ] = 1.f;
  1552. }
  1553. else
  1554. {
  1555. mPlaneManipPositions.mV[VZ] = -1.f;
  1556. }
  1557. LLViewerObject *first_object = mObjectSelection->getFirstMoveableObject(TRUE);
  1558. if (!first_object) return;
  1559. LLVector3 selection_center = getPivotPoint();
  1560. // Drag handles
  1561. if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
  1562. {
  1563. mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWorldViewHeightRaw();
  1564. mArrowLengthMeters /= gAgentCamera.mHUDCurZoom;
  1565. }
  1566. else
  1567. {
  1568. LLVector3 camera_pos_agent = gAgentCamera.getCameraPositionAgent();
  1569. F32 range = dist_vec(camera_pos_agent, selection_center);
  1570. F32 range_from_agent = dist_vec(gAgent.getPositionAgent(), selection_center);
  1571. // Don't draw handles if you're too far away
  1572. if (gSavedSettings.getBOOL("LimitSelectDistance"))
  1573. {
  1574. if (range_from_agent > gSavedSettings.getF32("MaxSelectDistance"))
  1575. {
  1576. return;
  1577. }
  1578. }
  1579. if (range > 0.001f)
  1580. {
  1581. // range != zero
  1582. F32 fraction_of_fov = mAxisArrowLength / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels();
  1583. F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians
  1584. mArrowLengthMeters = range * tan(apparent_angle);
  1585. }
  1586. else
  1587. {
  1588. // range == zero
  1589. mArrowLengthMeters = 1.0f;
  1590. }
  1591. }
  1592. mPlaneManipOffsetMeters = mArrowLengthMeters * 1.8f;
  1593. mGridSizeMeters = gSavedSettings.getF32("GridDrawSize");
  1594. mConeSize = mArrowLengthMeters / 4.f;
  1595. gGL.matrixMode(LLRender::MM_MODELVIEW);
  1596. gGL.pushMatrix();
  1597. {
  1598. gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]);
  1599. F32 angle_radians, x, y, z;
  1600. grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z);
  1601. gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z);
  1602. LLQuaternion invRotation = grid_rotation;
  1603. invRotation.conjQuat();
  1604. LLVector3 relative_camera_dir;
  1605. if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
  1606. {
  1607. relative_camera_dir = LLVector3::x_axis * invRotation;
  1608. }
  1609. else
  1610. {
  1611. relative_camera_dir = (selection_center - LLViewerCamera::getInstance()->getOrigin()) * invRotation;
  1612. }
  1613. relative_camera_dir.normVec();
  1614. {
  1615. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  1616. LLGLDisable cull_face(GL_CULL_FACE);
  1617. LLColor4 color1;
  1618. LLColor4 color2;
  1619. // update manipulator sizes
  1620. for (S32 index = 0; index < 3; index++)
  1621. {
  1622. if (index == mManipPart - LL_X_ARROW || index == mHighlightedPart - LL_X_ARROW)
  1623. {
  1624. mArrowScales.mV[index] = lerp(mArrowScales.mV[index], SELECTED_ARROW_SCALE, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
  1625. mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
  1626. }
  1627. else if (index == mManipPart - LL_YZ_PLANE || index == mHighlightedPart - LL_YZ_PLANE)
  1628. {
  1629. mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
  1630. mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], SELECTED_ARROW_SCALE, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
  1631. }
  1632. else
  1633. {
  1634. mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
  1635. mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
  1636. }
  1637. }
  1638. if ((mManipPart == LL_NO_PART || mManipPart == LL_YZ_PLANE) && llabs(relative_camera_dir.mV[VX]) > MIN_PLANE_MANIP_DOT_PRODUCT)
  1639. {
  1640. // render YZ plane manipulator
  1641. gGL.pushMatrix();
  1642. gGL.scalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]);
  1643. gGL.translatef(0.f, mPlaneManipOffsetMeters, mPlaneManipOffsetMeters);
  1644. gGL.scalef(mPlaneScales.mV[VX], mPlaneScales.mV[VX], mPlaneScales.mV[VX]);
  1645. if (mHighlightedPart == LL_YZ_PLANE)
  1646. {
  1647. color1.setVec(0.f, 1.f, 0.f, 1.f);
  1648. color2.setVec(0.f, 0.f, 1.f, 1.f);
  1649. }
  1650. else
  1651. {
  1652. color1.setVec(0.f, 1.f, 0.f, 0.6f);
  1653. color2.setVec(0.f, 0.f, 1.f, 0.6f);
  1654. }
  1655. gGL.begin(LLRender::TRIANGLES);
  1656. {
  1657. gGL.color4fv(color1.mV);
  1658. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f));
  1659. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f));
  1660. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
  1661. gGL.color4fv(color2.mV);
  1662. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
  1663. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
  1664. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f));
  1665. }
  1666. gGL.end();
  1667. LLUI::setLineWidth(3.0f);
  1668. gGL.begin(LLRender::LINES);
  1669. {
  1670. gGL.color4f(0.f, 0.f, 0.f, 0.3f);
  1671. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
  1672. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
  1673. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
  1674. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f);
  1675. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
  1676. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f);
  1677. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
  1678. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
  1679. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
  1680. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f);
  1681. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
  1682. gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f);
  1683. }
  1684. gGL.end();
  1685. LLUI::setLineWidth(1.0f);
  1686. gGL.popMatrix();
  1687. }
  1688. if ((mManipPart == LL_NO_PART || mManipPart == LL_XZ_PLANE) && llabs(relative_camera_dir.mV[VY]) > MIN_PLANE_MANIP_DOT_PRODUCT)
  1689. {
  1690. // render XZ plane manipulator
  1691. gGL.pushMatrix();
  1692. gGL.scalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]);
  1693. gGL.translatef(mPlaneManipOffsetMeters, 0.f, mPlaneManipOffsetMeters);
  1694. gGL.scalef(mPlaneScales.mV[VY], mPlaneScales.mV[VY], mPlaneScales.mV[VY]);
  1695. if (mHighlightedPart == LL_XZ_PLANE)
  1696. {
  1697. color1.setVec(0.f, 0.f, 1.f, 1.f);
  1698. color2.setVec(1.f, 0.f, 0.f, 1.f);
  1699. }
  1700. else
  1701. {
  1702. color1.setVec(0.f, 0.f, 1.f, 0.6f);
  1703. color2.setVec(1.f, 0.f, 0.f, 0.6f);
  1704. }
  1705. gGL.begin(LLRender::TRIANGLES);
  1706. {
  1707. gGL.color4fv(color1.mV);
  1708. gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
  1709. gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
  1710. gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f));
  1711. gGL.color4fv(color2.mV);
  1712. gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f));
  1713. gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f));
  1714. gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
  1715. }
  1716. gGL.end();
  1717. LLUI::setLineWidth(3.0f);
  1718. gGL.begin(LLRender::LINES);
  1719. {
  1720. gGL.color4f(0.f, 0.f, 0.f, 0.3f);
  1721. gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
  1722. gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
  1723. gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
  1724. gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f);
  1725. gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
  1726. gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f);
  1727. gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
  1728. gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
  1729. gGL.vertex3f(mPla