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

游戏引擎

开发平台:

C++ Builder

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