llmaniptranslate.cpp

Go to the documentation of this file.
00001 
00036 #include "llviewerprecompiledheaders.h"
00037 
00038 #include "llmaniptranslate.h"
00039 
00040 #include "llgl.h"
00041 
00042 #include "llagent.h"
00043 #include "llbbox.h"
00044 #include "llbox.h"
00045 #include "llviewercontrol.h"
00046 #include "llcriticaldamp.h"
00047 #include "llcylinder.h"
00048 #include "lldrawable.h"
00049 #include "llfloatertools.h"
00050 #include "llfontgl.h"
00051 #include "llglheaders.h"
00052 #include "llhudrender.h"
00053 #include "llresmgr.h"
00054 #include "llselectmgr.h"
00055 #include "llsphere.h"
00056 #include "llstatusbar.h"
00057 #include "lltoolmgr.h"
00058 #include "llviewercamera.h"
00059 #include "llviewerjoint.h"
00060 #include "llviewerobject.h"
00061 #include "llviewerwindow.h"
00062 #include "llvoavatar.h"
00063 #include "llworld.h"
00064 #include "viewer.h"
00065 #include "llui.h"
00066 #include "pipeline.h"
00067 
00068 const S32 NUM_AXES = 3;
00069 const S32 MOUSE_DRAG_SLOP = 2;       // pixels
00070 const F32 HANDLE_HIDE_ANGLE = 0.15f; // radians
00071 const F32 SELECTED_ARROW_SCALE = 1.3f;
00072 const F32 MANIPULATOR_HOTSPOT_START = 0.2f;
00073 const F32 MANIPULATOR_HOTSPOT_END = 1.2f;
00074 const F32 SNAP_GUIDE_SCREEN_SIZE = 0.7f;
00075 const F32 MIN_PLANE_MANIP_DOT_PRODUCT = 0.25f;
00076 const F32 PLANE_TICK_SIZE = 0.4f;
00077 const F32 MANIPULATOR_SCALE_HALF_LIFE = 0.07f;
00078 const F32 SNAP_ARROW_SCALE = 0.7f;
00079 
00080 static GLuint sGridTex = 0;
00081 
00082 const LLManip::EManipPart MANIPULATOR_IDS[9] = 
00083 {
00084         LLManip::LL_X_ARROW,
00085         LLManip::LL_Y_ARROW,
00086         LLManip::LL_Z_ARROW,
00087         LLManip::LL_X_ARROW,
00088         LLManip::LL_Y_ARROW,
00089         LLManip::LL_Z_ARROW,
00090         LLManip::LL_YZ_PLANE,
00091         LLManip::LL_XZ_PLANE,
00092         LLManip::LL_XY_PLANE
00093 };
00094 
00095 const U32 ARROW_TO_AXIS[4] = 
00096 {
00097         VX,
00098         VX,
00099         VY,
00100         VZ
00101 };
00102 
00103 BOOL sort_manip_by_end_z(LLManipTranslate::ManipulatorHandle *new_manip, LLManipTranslate::ManipulatorHandle *test_manip)
00104 {
00105         return (new_manip->mEndPosition.mV[VZ] < test_manip->mEndPosition.mV[VZ]);
00106 }
00107 
00108 LLManipTranslate::LLManipTranslate( LLToolComposite* composite )
00109 :       LLManip( "Move", composite ),
00110         mLastHoverMouseX(-1),
00111         mLastHoverMouseY(-1),
00112         mSendUpdateOnMouseUp(FALSE),
00113         mMouseOutsideSlop(FALSE),
00114         mCopyMadeThisDrag(FALSE),
00115         mMouseDownX(-1),
00116         mMouseDownY(-1),
00117         mAxisArrowLength(50),
00118         mConeSize(0),
00119         mArrowLengthMeters(0.f),
00120         mPlaneManipOffsetMeters(0.f),
00121         mManipPart(LL_NO_PART),
00122         mUpdateTimer(),
00123         mSnapOffsetMeters(0.f),
00124         mArrowScales(1.f, 1.f, 1.f),
00125         mPlaneScales(1.f, 1.f, 1.f),
00126         mPlaneManipPositions(1.f, 1.f, 1.f, 1.f)
00127 { 
00128         mProjectedManipulators.setInsertBefore(sort_manip_by_end_z);
00129 
00130         if (sGridTex == 0)
00131         { 
00132                 restoreGL();
00133         }
00134 }
00135 
00136 //static
00137 void LLManipTranslate::restoreGL()
00138 {
00139         //generate grid texture
00140         U32 rez = 512;
00141         U32 mip = 0;
00142 
00143         GLuint* d = new GLuint[rez*rez];
00144         LLGLEnable tex2d(GL_TEXTURE_2D);
00145         glGenTextures(1, &sGridTex);
00146         glBindTexture(GL_TEXTURE_2D, sGridTex);
00147         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00148         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00149 
00150         while (rez >= 1)
00151         {
00152                 for (U32 i = 0; i < rez*rez; i++)
00153                 {
00154                         d[i] = 0x00FFFFFF;
00155                 }
00156                 
00157                 U32 subcol = 0xFFFFFFFF;
00158                 if (rez >= 4)
00159                 {       //large grain grid
00160                         for (U32 i = 0; i < rez; i++)
00161                         {
00162                                 if (rez <= 16)
00163                                 {
00164                                         if (rez == 16)
00165                                         {
00166                                                 subcol = 0xA0FFFFFF;
00167                                         }
00168                                         else if (rez == 8)
00169                                         {
00170                                                 subcol = 0x80FFFFFF;
00171                                         }
00172                                         else
00173                                         {
00174                                                 subcol = 0x40FFFFFF;
00175                                         }
00176                                 }
00177                                 else
00178                                 {
00179                                         subcol = 0xFFFFFFFF;    
00180                                 }
00181                                 d[i                     *rez+ 0          ] = subcol;
00182                                 d[0                     *rez+ i          ] = subcol;                            
00183                                 if (rez >= 32)
00184                                 {
00185                                         d[i                     *rez+ (rez-1)] = subcol;
00186                                         d[(rez-1)       *rez+ i          ] = subcol;
00187                                 }
00188 
00189                                 if (rez >= 64)
00190                                 {
00191                                         subcol = 0xFFFFFFFF;
00192                                         
00193                                         if (i > 0 && i < (rez-1))
00194                                         {
00195                                                 d[i                     *rez+ 1          ] = subcol;
00196                                                 d[i                     *rez+ (rez-2)] = subcol;
00197                                                 d[1                     *rez+ i          ] = subcol;
00198                                                 d[(rez-2)       *rez+ i          ] = subcol;
00199                                         }
00200                                 }
00201                         }
00202                 }
00203 
00204                 subcol = 0x50A0A0A0;
00205                 if (rez >= 128)
00206                 { //small grain grid
00207                         for (U32 i = 8; i < rez; i+=8)
00208                         {
00209                                 for (U32 j = 2; j < rez-2; j++)
00210                                 {
00211                                         d[i     *rez+ j] = subcol;
00212                                         d[j     *rez+ i] = subcol;                      
00213                                 }
00214                         }
00215                 }
00216                 if (rez >= 64)
00217                 { //medium grain grid
00218                         if (rez == 64)
00219                         {
00220                                 subcol = 0x50A0A0A0;
00221                         }
00222                         else
00223                         {
00224                                 subcol = 0xA0D0D0D0;
00225                         }
00226 
00227                         for (U32 i = 32; i < rez; i+=32)
00228                         {
00229                                 U32 pi = i-1;
00230                                 for (U32 j = 2; j < rez-2; j++)
00231                                 {
00232                                         d[i             *rez+ j] = subcol;
00233                                         d[j             *rez+ i] = subcol;
00234 
00235                                         if (rez > 128)
00236                                         {
00237                                                 d[pi    *rez+ j] = subcol;
00238                                                 d[j             *rez+ pi] = subcol;                     
00239                                         }
00240                                 }
00241                         }
00242                 }
00243 #ifdef LL_WINDOWS
00244                 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, 0, GL_RGBA, GL_UNSIGNED_BYTE, d);
00245 #else
00246                 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, d);
00247 #endif
00248                 rez = rez >> 1;
00249                 mip++;
00250         }
00251         delete [] d;
00252 }
00253 
00254 
00255 LLManipTranslate::~LLManipTranslate()
00256 {
00257         mProjectedManipulators.deleteAllData();
00258 }
00259 
00260 
00261 void LLManipTranslate::handleSelect()
00262 {
00263         gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
00264         gFloaterTools->setStatusText("move");
00265         LLManip::handleSelect();
00266 }
00267 
00268 void LLManipTranslate::handleDeselect()
00269 {
00270         mHighlightedPart = LL_NO_PART;
00271         mManipPart = LL_NO_PART;
00272         LLManip::handleDeselect();
00273 }
00274 
00275 BOOL LLManipTranslate::handleMouseDown(S32 x, S32 y, MASK mask)
00276 {
00277         BOOL    handled = FALSE;
00278 
00279         // didn't click in any UI object, so must have clicked in the world
00280         LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
00281         if( hit_obj && 
00282                 (mHighlightedPart == LL_X_ARROW ||
00283                  mHighlightedPart == LL_Y_ARROW ||
00284                  mHighlightedPart == LL_Z_ARROW ||
00285                  mHighlightedPart == LL_YZ_PLANE ||
00286                  mHighlightedPart == LL_XZ_PLANE ||
00287                  mHighlightedPart == LL_XY_PLANE ) )
00288         {
00289                 handled = handleMouseDownOnPart( x, y, mask );
00290         }
00291 
00292         return handled;
00293 }
00294 
00295 // Assumes that one of the arrows on an object was hit.
00296 BOOL LLManipTranslate::handleMouseDownOnPart( S32 x, S32 y, MASK mask )
00297 {
00298         BOOL can_move = canAffectSelection();
00299         if (!can_move)
00300         {
00301                 return FALSE;
00302         }
00303 
00304         highlightManipulators(x, y);
00305         S32 hit_part = mHighlightedPart;
00306 
00307         if( (hit_part != LL_X_ARROW) && 
00308                 (hit_part != LL_Y_ARROW) &&
00309                 (hit_part != LL_Z_ARROW) &&
00310                 (hit_part != LL_YZ_PLANE) &&
00311                 (hit_part != LL_XZ_PLANE) &&
00312                 (hit_part != LL_XY_PLANE) )
00313         {
00314                 return TRUE;
00315         }
00316 
00317         mHelpTextTimer.reset();
00318         sNumTimesHelpTextShown++;
00319 
00320         gSelectMgr->getGrid(mGridOrigin, mGridRotation, mGridScale);
00321 
00322         gSelectMgr->enableSilhouette(FALSE);
00323 
00324         // we just started a drag, so save initial object positions
00325         gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_MOVE);
00326 
00327         mManipPart = (EManipPart)hit_part;
00328         mMouseDownX = x;
00329         mMouseDownY = y;
00330         mMouseOutsideSlop = FALSE;
00331 
00332         LLVector3               axis;
00333 
00334         LLSelectNode *selectNode = mObjectSelection->getFirstMoveableNode(TRUE);
00335 
00336         if (!selectNode)
00337         {
00338                 // didn't find the object in our selection...oh well
00339                 llwarns << "Trying to translate an unselected object" << llendl;
00340                 return TRUE;
00341         }
00342 
00343         LLViewerObject *selected_object = selectNode->getObject();
00344         if (!selected_object)
00345         {
00346                 // somehow we lost the object!
00347                 llwarns << "Translate manip lost the object, no selected object" << llendl;
00348                 gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
00349                 return TRUE;
00350         }
00351 
00352         // Compute unit vectors for arrow hit and a plane through that vector
00353         BOOL axis_exists = getManipAxis(selected_object, mManipPart, axis);
00354         getManipNormal(selected_object, mManipPart, mManipNormal);
00355 
00356         //LLVector3 select_center_agent = gAgent.getPosAgentFromGlobal(gSelectMgr->getSelectionCenterGlobal());
00357         // TomY: The above should (?) be identical to the below
00358         LLVector3 select_center_agent = getPivotPoint();
00359         mSubdivisions = llclamp(getSubdivisionLevel(select_center_agent, axis_exists ? axis : LLVector3::z_axis, getMinGridScale()), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
00360 
00361         // if we clicked on a planar manipulator, recenter mouse cursor
00362         if (mManipPart >= LL_YZ_PLANE && mManipPart <= LL_XY_PLANE)
00363         {
00364                 LLCoordGL mouse_pos;
00365                 if (!gCamera->projectPosAgentToScreen(select_center_agent, mouse_pos))
00366                 {
00367                         // mouse_pos may be nonsense
00368                         llwarns << "Failed to project object center to screen" << llendl;
00369                 }
00370                 else if (gSavedSettings.getBOOL("SnapToMouseCursor"))
00371                 {
00372                         LLUI::setCursorPositionScreen(mouse_pos.mX, mouse_pos.mY);
00373                         x = mouse_pos.mX;
00374                         y = mouse_pos.mY;
00375                 }
00376         }
00377 
00378         gSelectMgr->updateSelectionCenter();
00379         LLVector3d object_start_global = gAgent.getPosGlobalFromAgent(getPivotPoint());
00380         getMousePointOnPlaneGlobal(mDragCursorStartGlobal, x, y, object_start_global, mManipNormal);
00381         mDragSelectionStartGlobal = object_start_global;
00382         mCopyMadeThisDrag = FALSE;
00383 
00384         // Route future Mouse messages here preemptively.  (Release on mouse up.)
00385         setMouseCapture( TRUE );
00386 
00387         return TRUE;
00388 }
00389 
00390 BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
00391 {
00392         // Translation tool only works if mouse button is down.
00393         // Bail out if mouse not down.
00394         if( !hasMouseCapture() )
00395         {
00396                 lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (inactive)" << llendl;                
00397                 // Always show cursor
00398                 // gViewerWindow->setCursor(UI_CURSOR_ARROW);
00399                 gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
00400 
00401                 highlightManipulators(x, y);
00402                 return TRUE;
00403         }
00404         
00405         // Handle auto-rotation if necessary.
00406         const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD;
00407         const S32 ROTATE_H_MARGIN = gViewerWindow->getWindowWidth() / 20;
00408         const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped;
00409         BOOL rotated = FALSE;
00410 
00411         // ...build mode moves camera about focus point
00412         if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD)
00413         {
00414                 if (x < ROTATE_H_MARGIN)
00415                 {
00416                         gAgent.cameraOrbitAround(rotate_angle);
00417                         rotated = TRUE;
00418                 }
00419                 else if (x > gViewerWindow->getWindowWidth() - ROTATE_H_MARGIN)
00420                 {
00421                         gAgent.cameraOrbitAround(-rotate_angle);
00422                         rotated = TRUE;
00423                 }
00424         }
00425 
00426         // Suppress processing if mouse hasn't actually moved.
00427         // This may cause problems if the camera moves outside of the
00428         // rotation above.
00429         if( x == mLastHoverMouseX && y == mLastHoverMouseY && !rotated)
00430         {
00431                 lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (mouse unmoved)" << llendl;
00432                 gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
00433                 return TRUE;
00434         }
00435         mLastHoverMouseX = x;
00436         mLastHoverMouseY = y;
00437 
00438         // Suppress if mouse hasn't moved past the initial slop region
00439         // Reset once we start moving
00440         if( !mMouseOutsideSlop )
00441         {
00442                 if (abs(mMouseDownX - x) < MOUSE_DRAG_SLOP && abs(mMouseDownY - y) < MOUSE_DRAG_SLOP )
00443                 {
00444                         lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (mouse inside slop)" << llendl;
00445                         gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
00446                         return TRUE;
00447                 }
00448                 else
00449                 {
00450                         // ...just went outside the slop region
00451                         mMouseOutsideSlop = TRUE;
00452                         // If holding down shift, leave behind a copy.
00453                         if (mask == MASK_COPY)
00454                         {
00455                                 // ...we're trying to make a copy
00456                                 gSelectMgr->selectDuplicate(LLVector3::zero, FALSE);
00457                                 mCopyMadeThisDrag = TRUE;
00458 
00459                                 // When we make the copy, we don't want to do any other processing.
00460                                 // If so, the object will also be moved, and the copy will be offset.
00461                                 lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (made copy)" << llendl;
00462                                 gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
00463                         }
00464                 }
00465         }
00466 
00467         // Throttle updates to 10 per second.
00468         BOOL send_update = FALSE;
00469 
00470         LLVector3               axis_f;
00471         LLVector3d              axis_d;
00472 
00473         // pick the first object to constrain to grid w/ common origin
00474         // this is so we don't screw up groups
00475         LLSelectNode* selectNode = mObjectSelection->getFirstMoveableNode(TRUE);
00476         if (!selectNode)
00477         {
00478                 // somehow we lost the object!
00479                 llwarns << "Translate manip lost the object, no selectNode" << llendl;
00480                 gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
00481                 return TRUE;
00482         }
00483 
00484         LLViewerObject* object = selectNode->getObject();
00485         if (!object)
00486         {
00487                 // somehow we lost the object!
00488                 llwarns << "Translate manip lost the object, no object in selectNode" << llendl;
00489                 gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
00490                 return TRUE;
00491         }
00492 
00493         // Compute unit vectors for arrow hit and a plane through that vector
00494         BOOL axis_exists = getManipAxis(object, mManipPart, axis_f);            // TODO: move this
00495 
00496         axis_d.setVec(axis_f);
00497 
00498         gSelectMgr->updateSelectionCenter();
00499         LLVector3d current_pos_global = gAgent.getPosGlobalFromAgent(getPivotPoint());
00500 
00501         mSubdivisions = llclamp(getSubdivisionLevel(getPivotPoint(), axis_f, getMinGridScale()), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
00502 
00503         // Project the cursor onto that plane
00504         LLVector3d relative_move;
00505         getMousePointOnPlaneGlobal(relative_move, x, y, current_pos_global, mManipNormal);\
00506         relative_move -= mDragCursorStartGlobal;
00507 
00508         // You can't move more than some distance from your original mousedown point.
00509         if (gSavedSettings.getBOOL("LimitDragDistance"))
00510         {
00511                 F32 max_drag_distance = gSavedSettings.getF32("MaxDragDistance");
00512 
00513                 if (relative_move.magVecSquared() > max_drag_distance * max_drag_distance)
00514                 {
00515                         lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (too far)" << llendl;
00516                         gViewerWindow->setCursor(UI_CURSOR_NOLOCKED);
00517                         return TRUE;
00518                 }
00519         }
00520 
00521         F64 axis_magnitude = relative_move * axis_d;                                    // dot product
00522         LLVector3d cursor_point_snap_line;
00523         
00524         F64 off_axis_magnitude;
00525 
00526         getMousePointOnPlaneGlobal(cursor_point_snap_line, x, y, current_pos_global, mSnapOffsetAxis % axis_f);
00527         off_axis_magnitude = axis_exists ? llabs((cursor_point_snap_line - current_pos_global) * LLVector3d(mSnapOffsetAxis)) : 0.f;
00528 
00529         if (gSavedSettings.getBOOL("SnapEnabled"))
00530         {
00531                 if (off_axis_magnitude > mSnapOffsetMeters)
00532                 {
00533                         mInSnapRegime = TRUE;
00534                         LLVector3 mouse_down_offset(mDragCursorStartGlobal - mDragSelectionStartGlobal);
00535                         LLVector3 cursor_snap_agent = gAgent.getPosAgentFromGlobal(cursor_point_snap_line);
00536                         if (!gSavedSettings.getBOOL("SnapToMouseCursor"))
00537                         {
00538                                 cursor_snap_agent -= mouse_down_offset;
00539                         }
00540 
00541                         F32 cursor_grid_dist = (cursor_snap_agent - mGridOrigin) * axis_f;
00542                         
00543                         F32 snap_dist = getMinGridScale() / (2.f * mSubdivisions);
00544                         F32 relative_snap_dist = fmodf(llabs(cursor_grid_dist) + snap_dist, getMinGridScale() / mSubdivisions);
00545                         if (relative_snap_dist < snap_dist * 2.f)
00546                         {
00547                                 if (cursor_grid_dist > 0.f)
00548                                 {
00549                                         cursor_grid_dist -= relative_snap_dist - snap_dist;
00550                                 }
00551                                 else
00552                                 {
00553                                         cursor_grid_dist += relative_snap_dist - snap_dist;
00554                                 }
00555                         }
00556 
00557                         F32 object_start_on_axis = (gAgent.getPosAgentFromGlobal(mDragSelectionStartGlobal) - mGridOrigin) * axis_f;
00558                         axis_magnitude = cursor_grid_dist - object_start_on_axis;
00559                 }
00560                 else if (mManipPart >= LL_YZ_PLANE && mManipPart <= LL_XY_PLANE)
00561                 {
00562                         // subtract offset from object center
00563                         LLVector3d cursor_point_global;
00564                         getMousePointOnPlaneGlobal( cursor_point_global, x, y, current_pos_global, mManipNormal );
00565                         cursor_point_global -= (mDragCursorStartGlobal - mDragSelectionStartGlobal);
00566 
00567                         // snap to planar grid
00568                         LLVector3 cursor_point_agent = gAgent.getPosAgentFromGlobal(cursor_point_global);
00569                         LLVector3 camera_plane_projection = gCamera->getAtAxis();
00570                         camera_plane_projection -= projected_vec(camera_plane_projection, mManipNormal);
00571                         camera_plane_projection.normVec();
00572                         LLVector3 camera_projected_dir = camera_plane_projection;
00573                         camera_plane_projection.rotVec(~mGridRotation);
00574                         camera_plane_projection.scaleVec(mGridScale);
00575                         camera_plane_projection.abs();
00576                         F32 max_grid_scale;
00577                         if (camera_plane_projection.mV[VX] > camera_plane_projection.mV[VY] &&
00578                                 camera_plane_projection.mV[VX] > camera_plane_projection.mV[VZ])
00579                         {
00580                                 max_grid_scale = mGridScale.mV[VX];
00581                         }
00582                         else if (camera_plane_projection.mV[VY] > camera_plane_projection.mV[VZ])
00583                         {
00584                                 max_grid_scale = mGridScale.mV[VY];
00585                         }
00586                         else
00587                         {
00588                                 max_grid_scale = mGridScale.mV[VZ];
00589                         }
00590 
00591                         F32 num_subdivisions = llclamp(getSubdivisionLevel(getPivotPoint(), camera_projected_dir, max_grid_scale), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
00592 
00593                         F32 grid_scale_a;
00594                         F32 grid_scale_b;
00595                         LLVector3 cursor_point_grid = (cursor_point_agent - mGridOrigin) * ~mGridRotation;
00596 
00597                         switch (mManipPart)
00598                         {
00599                         case LL_YZ_PLANE:
00600                                 grid_scale_a = mGridScale.mV[VY] / num_subdivisions;
00601                                 grid_scale_b = mGridScale.mV[VZ] / num_subdivisions;
00602                                 cursor_point_grid.mV[VY] -= fmod(cursor_point_grid.mV[VY] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f;
00603                                 cursor_point_grid.mV[VZ] -= fmod(cursor_point_grid.mV[VZ] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f;
00604                                 break;
00605                         case LL_XZ_PLANE:
00606                                 grid_scale_a = mGridScale.mV[VX] / num_subdivisions;
00607                                 grid_scale_b = mGridScale.mV[VZ] / num_subdivisions;
00608                                 cursor_point_grid.mV[VX] -= fmod(cursor_point_grid.mV[VX] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f;
00609                                 cursor_point_grid.mV[VZ] -= fmod(cursor_point_grid.mV[VZ] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f;
00610                                 break;
00611                         case LL_XY_PLANE:
00612                                 grid_scale_a = mGridScale.mV[VX] / num_subdivisions;
00613                                 grid_scale_b = mGridScale.mV[VY] / num_subdivisions;
00614                                 cursor_point_grid.mV[VX] -= fmod(cursor_point_grid.mV[VX] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f;
00615                                 cursor_point_grid.mV[VY] -= fmod(cursor_point_grid.mV[VY] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f;
00616                                 break;
00617                         default:
00618                                 break;
00619                         }
00620                         cursor_point_agent = (cursor_point_grid * mGridRotation) + mGridOrigin;
00621                         relative_move.setVec(cursor_point_agent - gAgent.getPosAgentFromGlobal(mDragSelectionStartGlobal));
00622                         mInSnapRegime = TRUE;
00623                 }
00624                 else
00625                 {
00626                         mInSnapRegime = FALSE;
00627                 }
00628         }
00629         else
00630         {
00631                 mInSnapRegime = FALSE;
00632         }
00633 
00634         // Clamp to arrow direction
00635         // *FIX: does this apply anymore?
00636         if (!axis_exists)
00637         {
00638                 axis_magnitude = relative_move.normVec();
00639                 axis_d.setVec(relative_move);
00640                 axis_d.normVec();
00641                 axis_f.setVec(axis_d);
00642         }
00643 
00644         LLVector3d clamped_relative_move = axis_magnitude * axis_d;     // scalar multiply
00645         LLVector3 clamped_relative_move_f = (F32)axis_magnitude * axis_f; // scalar multiply
00646         
00647         for (LLObjectSelection::iterator iter = mObjectSelection->begin();
00648                  iter != mObjectSelection->end(); iter++)
00649         {
00650                 LLSelectNode* selectNode = *iter;
00651                 LLViewerObject* object = selectNode->getObject();
00652                 
00653                 // Only apply motion to root objects and objects selected
00654                 // as "individual".
00655                 if (!object->isRootEdit() && !selectNode->mIndividualSelection)
00656                 {
00657                         continue;
00658                 }
00659 
00660                 if (!object->isRootEdit())
00661                 {
00662                         // child objects should not update if parent is selected
00663                         LLViewerObject* editable_root = (LLViewerObject*)object->getParent();
00664                         if (editable_root->isSelected())
00665                         {
00666                                 // we will be moved properly by our parent, so skip
00667                                 continue;
00668                         }
00669                 }
00670 
00671                 if (object->permMove())
00672                 {
00673                         // handle attachments in local space
00674                         if (object->isAttachment() && object->mDrawable.notNull())
00675                         {
00676                                 // calculate local version of relative move
00677                                 LLQuaternion objWorldRotation = object->mDrawable->mXform.getParent()->getWorldRotation();
00678                                 objWorldRotation.transQuat();
00679 
00680                                 LLVector3 old_position_local = object->getPosition();
00681                                 LLVector3 new_position_local = selectNode->mSavedPositionLocal + (clamped_relative_move_f * objWorldRotation);
00682 
00683                                 // move and clamp root object first, before adjusting children
00684                                 if (new_position_local != old_position_local)
00685                                 {
00686                                         send_update = TRUE;
00687                                 }
00688                                 //RN: I forget, but we need to do this because of snapping which doesn't often result
00689                                 // in position changes even when the mouse moves
00690                                 object->setPosition(new_position_local);
00691                                 rebuild(object);
00692                                 gAgent.getAvatarObject()->clampAttachmentPositions();
00693                                 new_position_local = object->getPosition();
00694 
00695                                 if (selectNode->mIndividualSelection)
00696                                 {
00697                                         send_update = FALSE;
00698                                         LLVector3 child_offset = (old_position_local - new_position_local) * ~object->getRotation();
00699 
00700                                         // counter-translate child objects if we are moving the root as an individual
00701                                         for (U32 child_num = 0; child_num < object->mChildList.size(); child_num++)
00702                                         {
00703                                                 LLViewerObject* childp = object->mChildList[child_num];
00704 
00705                                                 if (!childp->isSelected())
00706                                                 {
00707                                                         childp->setPosition(childp->getPosition() + child_offset);
00708                                                         rebuild(childp);
00709                                                 }
00710                                         }
00711                                 }
00712                         }
00713                         else
00714                         {
00715                                 // compute new position to send to simulators, but don't set it yet.
00716                                 // We need the old position to know which simulator to send the move message to.
00717                                 LLVector3d new_position_global = selectNode->mSavedPositionGlobal + clamped_relative_move;
00718 
00719                                 // Don't let object centers go too far underground
00720                                 F64 min_height = gWorldp->getMinAllowedZ(object);
00721                                 if (new_position_global.mdV[VZ] < min_height)
00722                                 {
00723                                         new_position_global.mdV[VZ] = min_height;
00724                                 }
00725 
00726                                 // For safety, cap heights where objects can be dragged
00727                                 if (new_position_global.mdV[VZ] > MAX_OBJECT_Z)
00728                                 {
00729                                         new_position_global.mdV[VZ] = MAX_OBJECT_Z;
00730                                 }
00731 
00732                                 // Grass is always drawn on the ground, so clamp its position to the ground
00733                                 if (object->getPCode() == LL_PCODE_LEGACY_GRASS)
00734                                 {
00735                                         new_position_global.mdV[VZ] = gWorldp->resolveLandHeightGlobal(new_position_global) + 1.f;
00736                                 }
00737                                 
00738                                 if (object->isRootEdit())
00739                                 {
00740                                         new_position_global = gWorldp->clipToVisibleRegions(object->getPositionGlobal(), new_position_global);
00741                                 }
00742 
00743                                 // PR: Only update if changed
00744                                 LLVector3d old_position_global = object->getPositionGlobal();
00745                                 LLVector3 old_position_agent = object->getPositionAgent();
00746                                 LLVector3 new_position_agent = gAgent.getPosAgentFromGlobal(new_position_global);
00747                                 if (object->isRootEdit())
00748                                 {
00749                                         // finally, move parent object after children have calculated new offsets
00750                                         object->setPositionAgent(new_position_agent);
00751                                         rebuild(object);
00752                                 }
00753                                 else
00754                                 {
00755                                         LLViewerObject* root_object = object->getRootEdit();
00756                                         new_position_agent -= root_object->getPositionAgent();
00757                                         new_position_agent = new_position_agent * ~root_object->getRotation();
00758                                         object->setPositionParent(new_position_agent, FALSE);
00759                                         rebuild(object);
00760                                 }
00761 
00762                                 if (selectNode->mIndividualSelection)
00763                                 {
00764                                         LLVector3 parent_offset = (new_position_agent - old_position_agent) * ~object->getRotation();
00765 
00766                                         // counter-translate child objects if we are moving the root as an individual
00767                                         for (U32 child_num = 0; child_num < object->mChildList.size(); child_num++)
00768                                         {
00769                                                 LLViewerObject* childp = object->mChildList[child_num];
00770                                                 if (!childp->isSelected())
00771                                                 {
00772                                                         childp->setPosition(childp->getPosition() - parent_offset);
00773                                                         rebuild(childp);
00774                                                 }
00775                                         }
00776                                         send_update = FALSE;
00777                                 }
00778                                 else if (old_position_global != new_position_global)
00779                                 {
00780                                         send_update = TRUE;
00781                                 }
00782                         }
00783                         selectNode->mLastPositionLocal  = object->getPosition();
00784                 }
00785         }
00786 
00787         gSelectMgr->updateSelectionCenter();
00788         gAgent.clearFocusObject();
00789         dialog_refresh_all();           // ??? is this necessary?
00790 
00791         lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (active)" << llendl;
00792         gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
00793         return TRUE;
00794 }
00795 
00796 void LLManipTranslate::highlightManipulators(S32 x, S32 y)
00797 {
00798         mHighlightedPart = LL_NO_PART;
00799 
00800         if (!mObjectSelection->getObjectCount())
00801         {
00802                 return;
00803         }
00804         
00805         //LLBBox bbox = gSelectMgr->getBBoxOfSelection();
00806         LLMatrix4 projMatrix = gCamera->getProjection();
00807         LLMatrix4 modelView = gCamera->getModelview();
00808 
00809         LLVector3 object_position = getPivotPoint();
00810         
00811         LLVector3 grid_origin;
00812         LLVector3 grid_scale;
00813         LLQuaternion grid_rotation;
00814 
00815         gSelectMgr->getGrid(grid_origin, grid_rotation, grid_scale);
00816 
00817         LLVector3 relative_camera_dir;
00818 
00819         LLMatrix4 transform;
00820 
00821         if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
00822         {
00823                 relative_camera_dir = LLVector3(1.f, 0.f, 0.f) * ~grid_rotation;
00824                 LLVector4 translation(object_position);
00825                 transform.initRotTrans(grid_rotation, translation);
00826                 LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
00827                 transform *= cfr;
00828                 LLMatrix4 window_scale;
00829                 F32 zoom_level = 2.f * gAgent.getAvatarObject()->mHUDCurZoom;
00830                 window_scale.initAll(LLVector3(zoom_level / gCamera->getAspect(), zoom_level, 0.f),
00831                         LLQuaternion::DEFAULT,
00832                         LLVector3::zero);
00833                 transform *= window_scale;
00834         }
00835         else
00836         {
00837                 relative_camera_dir = (object_position - gCamera->getOrigin()) * ~grid_rotation;
00838                 relative_camera_dir.normVec();
00839 
00840                 transform.initRotTrans(grid_rotation, LLVector4(object_position));
00841                 transform *= modelView;
00842                 transform *= projMatrix;
00843         }
00844                 
00845         mProjectedManipulators.deleteAllData();
00846 
00847         S32 numManips = 0;
00848 
00849         // edges
00850         mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 0.f, 0.f, 1.f);
00851         mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 0.f, 0.f, 1.f);
00852 
00853         mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 0.f, 1.f);
00854         mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 0.f, 1.f);
00855 
00856         mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 1.f);
00857         mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 1.f);
00858 
00859         mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 0.f, 0.f, 1.f);
00860         mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 0.f, 0.f, 1.f);
00861 
00862         mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 0.f, 1.f);
00863         mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 0.f, 1.f);
00864 
00865         mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 1.f);
00866         mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 1.f);
00867 
00868         S32 num_arrow_manips = numManips;
00869 
00870         // planar manipulators
00871         BOOL planar_manip_yz_visible = FALSE;
00872         BOOL planar_manip_xz_visible = FALSE;
00873         BOOL planar_manip_xy_visible = FALSE;
00874 
00875         mManipulatorVertices[numManips] = LLVector4(0.f, mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 1.f);
00876         mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
00877         mManipulatorVertices[numManips] = LLVector4(0.f, mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 1.f);
00878         mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
00879         if (llabs(relative_camera_dir.mV[VX]) > MIN_PLANE_MANIP_DOT_PRODUCT)
00880         {
00881                 planar_manip_yz_visible = TRUE;
00882         }
00883 
00884         mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 0.f, mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 1.f);
00885         mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
00886         mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 0.f, mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 1.f);
00887         mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
00888         if (llabs(relative_camera_dir.mV[VY]) > MIN_PLANE_MANIP_DOT_PRODUCT)
00889         {
00890                 planar_manip_xz_visible = TRUE;
00891         }
00892 
00893         mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 0.f, 1.f);
00894         mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
00895         mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 0.f, 1.f);
00896         mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
00897         if (llabs(relative_camera_dir.mV[VZ]) > MIN_PLANE_MANIP_DOT_PRODUCT)
00898         {
00899                 planar_manip_xy_visible = TRUE;
00900         }
00901 
00902         for (S32 i = 0; i < num_arrow_manips; i+= 2)
00903         {
00904                 LLVector4 projected_start = mManipulatorVertices[i] * transform;
00905                 projected_start = projected_start * (1.f / projected_start.mV[VW]);
00906 
00907                 LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
00908                 projected_end = projected_end * (1.f / projected_end.mV[VW]);
00909 
00910                 ManipulatorHandle* projManipulator = 
00911                         new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), 
00912                                 LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), 
00913                                 MANIPULATOR_IDS[i / 2],
00914                                 10.f); // 10 pixel hotspot for arrows
00915                 mProjectedManipulators.addDataSorted(projManipulator);
00916         }
00917 
00918         if (planar_manip_yz_visible)
00919         {
00920                 S32 i = num_arrow_manips;
00921                 LLVector4 projected_start = mManipulatorVertices[i] * transform;
00922                 projected_start = projected_start * (1.f / projected_start.mV[VW]);
00923 
00924                 LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
00925                 projected_end = projected_end * (1.f / projected_end.mV[VW]);
00926 
00927                 ManipulatorHandle* projManipulator = 
00928                         new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), 
00929                                 LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), 
00930                                 MANIPULATOR_IDS[i / 2],
00931                                 20.f); // 20 pixels for planar manipulators
00932                 mProjectedManipulators.addDataSorted(projManipulator);
00933         }
00934 
00935         if (planar_manip_xz_visible)
00936         {
00937                 S32 i = num_arrow_manips + 2;
00938                 LLVector4 projected_start = mManipulatorVertices[i] * transform;
00939                 projected_start = projected_start * (1.f / projected_start.mV[VW]);
00940 
00941                 LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
00942                 projected_end = projected_end * (1.f / projected_end.mV[VW]);
00943 
00944                 ManipulatorHandle* projManipulator = 
00945                         new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), 
00946                                 LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), 
00947                                 MANIPULATOR_IDS[i / 2],
00948                                 20.f); // 20 pixels for planar manipulators
00949                 mProjectedManipulators.addDataSorted(projManipulator);
00950         }
00951 
00952         if (planar_manip_xy_visible)
00953         {
00954                 S32 i = num_arrow_manips + 4;
00955                 LLVector4 projected_start = mManipulatorVertices[i] * transform;
00956                 projected_start = projected_start * (1.f / projected_start.mV[VW]);
00957 
00958                 LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
00959                 projected_end = projected_end * (1.f / projected_end.mV[VW]);
00960 
00961                 ManipulatorHandle* projManipulator = 
00962                         new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), 
00963                                 LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), 
00964                                 MANIPULATOR_IDS[i / 2],
00965                                 20.f); // 20 pixels for planar manipulators
00966                 mProjectedManipulators.addDataSorted(projManipulator);
00967         }
00968 
00969         LLVector2 manip_start_2d;
00970         LLVector2 manip_end_2d;
00971         LLVector2 manip_dir;
00972         F32 half_width = gViewerWindow->getWindowWidth() / 2.f;
00973         F32 half_height = gViewerWindow->getWindowHeight() / 2.f;
00974         LLVector2 mousePos((F32)x - half_width, (F32)y - half_height);
00975         LLVector2 mouse_delta;
00976 
00977         for (ManipulatorHandle* manipulator = mProjectedManipulators.getFirstData();
00978                 manipulator;
00979                 manipulator = mProjectedManipulators.getNextData())
00980                 {
00981                         manip_start_2d.setVec(manipulator->mStartPosition.mV[VX] * half_width, manipulator->mStartPosition.mV[VY] * half_height);
00982                         manip_end_2d.setVec(manipulator->mEndPosition.mV[VX] * half_width, manipulator->mEndPosition.mV[VY] * half_height);
00983                         manip_dir = manip_end_2d - manip_start_2d;
00984 
00985                         mouse_delta = mousePos - manip_start_2d;
00986 
00987                         F32 manip_length = manip_dir.normVec();
00988 
00989                         F32 mouse_pos_manip = mouse_delta * manip_dir;
00990                         F32 mouse_dist_manip_squared = mouse_delta.magVecSquared() - (mouse_pos_manip * mouse_pos_manip);
00991 
00992                         if (mouse_pos_manip > 0.f &&
00993                                 mouse_pos_manip < manip_length &&
00994                                 mouse_dist_manip_squared < manipulator->mHotSpotRadius * manipulator->mHotSpotRadius)
00995                         {
00996                                 mHighlightedPart = manipulator->mManipID;
00997                                 break;
00998                         }
00999                 }
01000 }
01001 
01002 F32 LLManipTranslate::getMinGridScale()
01003 {
01004         F32 scale;
01005         switch (mManipPart)
01006         {
01007         case LL_NO_PART:
01008         default:
01009                 scale = 1.f;
01010                 break;
01011         case LL_X_ARROW:
01012                 scale = mGridScale.mV[VX];
01013                 break;
01014         case LL_Y_ARROW:
01015                 scale = mGridScale.mV[VY];
01016                 break;
01017         case LL_Z_ARROW:
01018                 scale = mGridScale.mV[VZ];
01019                 break;
01020         case LL_YZ_PLANE:
01021                 scale = llmin(mGridScale.mV[VY], mGridScale.mV[VZ]);
01022                 break;
01023         case LL_XZ_PLANE:
01024                 scale = llmin(mGridScale.mV[VX], mGridScale.mV[VZ]);
01025                 break;
01026         case LL_XY_PLANE:
01027                 scale = llmin(mGridScale.mV[VX], mGridScale.mV[VY]);
01028                 break;
01029         }
01030 
01031         return scale;
01032 }
01033 
01034 
01035 BOOL LLManipTranslate::handleMouseUp(S32 x, S32 y, MASK mask)
01036 {
01037         // first, perform normal processing in case this was a quick-click
01038         handleHover(x, y, mask);
01039 
01040         if(hasMouseCapture())
01041         {
01042                 // make sure arrow colors go back to normal
01043                 mManipPart = LL_NO_PART;
01044                 gSelectMgr->enableSilhouette(TRUE);
01045 
01046                 // Might have missed last update due to UPDATE_DELAY timing.
01047                 gSelectMgr->sendMultipleUpdate( UPD_POSITION );
01048                 
01049                 mInSnapRegime = FALSE;
01050                 gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
01051                 //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject"));
01052         }
01053 
01054         return LLManip::handleMouseUp(x, y, mask);
01055 }
01056 
01057 
01058 void LLManipTranslate::render()
01059 {
01060         glMatrixMode(GL_MODELVIEW);
01061         glPushMatrix();
01062         if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
01063         {
01064                 F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
01065                 glScalef(zoom, zoom, zoom);
01066         }
01067         {
01068                 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
01069                 renderGuidelines();
01070         }
01071         {
01072                 renderTranslationHandles();
01073                 renderSnapGuides();
01074         }
01075         glPopMatrix();
01076 
01077         renderText();
01078 }
01079 
01080 void LLManipTranslate::renderSnapGuides()
01081 {
01082         if (!gSavedSettings.getBOOL("SnapEnabled"))
01083         {
01084                 return;
01085         }
01086 
01087         F32 max_subdivisions = sGridMaxSubdivisionLevel;//(F32)gSavedSettings.getS32("GridSubdivision");
01088         F32 line_alpha = gSavedSettings.getF32("GridOpacity");
01089 
01090         LLGLSNoTexture gls_no_texture;
01091         LLGLDepthTest gls_depth(GL_TRUE);
01092         LLGLDisable gls_cull(GL_CULL_FACE);
01093         LLVector3 translate_axis;
01094 
01095         if (mManipPart == LL_NO_PART)
01096         {
01097                 return;
01098         }
01099 
01100         LLSelectNode *first_node = mObjectSelection->getFirstMoveableNode(TRUE);
01101         if (!first_node)
01102         {
01103                 return;
01104         }
01105         
01106         updateGridSettings();
01107 
01108         F32 smallest_grid_unit_scale = getMinGridScale() / max_subdivisions;
01109         LLVector3 grid_origin;
01110         LLVector3 grid_scale;
01111         LLQuaternion grid_rotation;
01112 
01113         gSelectMgr->getGrid(grid_origin, grid_rotation, grid_scale);
01114         LLVector3 saved_selection_center = getSavedPivotPoint(); //gSelectMgr->getSavedBBoxOfSelection().getCenterAgent();
01115         LLVector3 selection_center = getPivotPoint();
01116 
01117         LLViewerObject *first_object = first_node->getObject();
01118 
01119         //pick appropriate projection plane for snap rulers according to relative camera position
01120         if (mManipPart >= LL_X_ARROW && mManipPart <= LL_Z_ARROW)
01121         {
01122                 LLVector3 normal;
01123                 LLColor4 inner_color;
01124                 LLManip::EManipPart temp_manip = mManipPart;
01125                 switch (mManipPart)
01126                 {
01127                 case LL_X_ARROW:
01128                         normal.setVec(1,0,0);
01129                         inner_color.setVec(0,1,1,line_alpha);
01130                         mManipPart = LL_YZ_PLANE;
01131                         break;
01132                 case LL_Y_ARROW:
01133                         normal.setVec(0,1,0);
01134                         inner_color.setVec(1,0,1,line_alpha);
01135                         mManipPart = LL_XZ_PLANE;
01136                         break;
01137                 case LL_Z_ARROW:
01138                         normal.setVec(0,0,1);
01139                         inner_color.setVec(1,1,0,line_alpha);
01140                         mManipPart = LL_XY_PLANE;
01141                         break;
01142                 default:
01143                         break;
01144                 }
01145 
01146                 highlightIntersection(normal, selection_center, grid_rotation, inner_color);
01147                 mManipPart = temp_manip;
01148                 getManipAxis(first_object, mManipPart, translate_axis);
01149 
01150                 LLVector3 at_axis_abs;
01151                 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
01152                 {
01153                         at_axis_abs = LLVector3::x_axis * ~grid_rotation;
01154                 }
01155                 else
01156                 {
01157                         at_axis_abs = saved_selection_center - gCamera->getOrigin();
01158                         at_axis_abs.normVec();
01159 
01160                         at_axis_abs = at_axis_abs * ~grid_rotation;
01161                 }
01162                 at_axis_abs.abs();
01163 
01164                 if (at_axis_abs.mV[VX] > at_axis_abs.mV[VY] && at_axis_abs.mV[VX] > at_axis_abs.mV[VZ])
01165                 {
01166                         if (mManipPart == LL_Y_ARROW)
01167                         {
01168                                 mSnapOffsetAxis = LLVector3::z_axis;
01169                         }
01170                         else if (mManipPart == LL_Z_ARROW)
01171                         {
01172                                 mSnapOffsetAxis = LLVector3::y_axis;
01173                         }
01174                         else if (at_axis_abs.mV[VY] > at_axis_abs.mV[VZ])
01175                         {
01176                                 mSnapOffsetAxis = LLVector3::z_axis;
01177                         }
01178                         else
01179                         {
01180                                 mSnapOffsetAxis = LLVector3::y_axis;
01181                         }
01182                 }
01183                 else if (at_axis_abs.mV[VY] > at_axis_abs.mV[VZ])
01184                 {
01185                         if (mManipPart == LL_X_ARROW)
01186                         {
01187                                 mSnapOffsetAxis = LLVector3::z_axis;
01188                         }
01189                         else if (mManipPart == LL_Z_ARROW)
01190                         {
01191                                 mSnapOffsetAxis = LLVector3::x_axis;
01192                         }
01193                         else if (at_axis_abs.mV[VX] > at_axis_abs.mV[VZ])
01194                         {
01195                                 mSnapOffsetAxis = LLVector3::z_axis;
01196                         }
01197                         else
01198                         {
01199                                 mSnapOffsetAxis = LLVector3::x_axis;
01200                         }
01201                 }
01202                 else
01203                 {
01204                         if (mManipPart == LL_X_ARROW)
01205                         {
01206                                 mSnapOffsetAxis = LLVector3::y_axis;
01207                         }
01208                         else if (mManipPart == LL_Y_ARROW)
01209                         {
01210                                 mSnapOffsetAxis = LLVector3::x_axis;
01211                         }
01212                         else if (at_axis_abs.mV[VX] > at_axis_abs.mV[VY])
01213                         {
01214                                 mSnapOffsetAxis = LLVector3::y_axis;
01215                         }
01216                         else
01217                         {
01218                                 mSnapOffsetAxis = LLVector3::x_axis;
01219                         }
01220                 }
01221 
01222                 mSnapOffsetAxis = mSnapOffsetAxis * grid_rotation;
01223 
01224                 F32 guide_size_meters;
01225 
01226                 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
01227                 {
01228                         guide_size_meters = 1.f / gAgent.getAvatarObject()->mHUDCurZoom;
01229                         mSnapOffsetMeters = mArrowLengthMeters * 1.5f;
01230                 }
01231                 else
01232                 {
01233                         LLVector3 cam_to_selection = getPivotPoint() - gCamera->getOrigin();
01234                         F32 current_range = cam_to_selection.normVec();
01235                         guide_size_meters = SNAP_GUIDE_SCREEN_SIZE * gViewerWindow->getWindowHeight() * current_range / gCamera->getPixelMeterRatio();
01236         
01237                         F32 fraction_of_fov = mAxisArrowLength / (F32) gCamera->getViewHeightInPixels();
01238                         F32 apparent_angle = fraction_of_fov * gCamera->getView();  // radians
01239                         F32 offset_at_camera = tan(apparent_angle) * 1.5f;
01240                         F32 range = dist_vec(gAgent.getPosAgentFromGlobal(first_node->mSavedPositionGlobal), gCamera->getOrigin());
01241                         mSnapOffsetMeters = range * offset_at_camera;
01242                 }
01243 
01244                 LLVector3 tick_start;
01245                 LLVector3 tick_end;
01246 
01247                 // how far away from grid origin is the selection along the axis of translation?
01248                 F32 dist_grid_axis = (selection_center - mGridOrigin) * translate_axis;
01249                 // find distance to nearest smallest grid unit
01250                 F32 offset_nearest_grid_unit = fmodf(dist_grid_axis, smallest_grid_unit_scale);
01251                 // how many smallest grid units are we away from largest grid scale?
01252                 S32 sub_div_offset = llround(fmod(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() / sGridMinSubdivisionLevel) / smallest_grid_unit_scale);
01253                 S32 num_ticks_per_side = llmax(1, llfloor(0.5f * guide_size_meters / smallest_grid_unit_scale));
01254 
01255                 LLGLDepthTest gls_depth(GL_FALSE);
01256 
01257                 for (S32 pass = 0; pass < 3; pass++)
01258                 {
01259                         LLColor4 line_color = setupSnapGuideRenderPass(pass);
01260 
01261                         glBegin(GL_LINES);
01262                         {
01263                                 LLVector3 line_start = selection_center + (mSnapOffsetMeters * mSnapOffsetAxis) + (translate_axis * (guide_size_meters * 0.5f + offset_nearest_grid_unit));
01264                                 LLVector3 line_end = selection_center + (mSnapOffsetMeters * mSnapOffsetAxis) - (translate_axis * (guide_size_meters * 0.5f + offset_nearest_grid_unit));
01265                                 LLVector3 line_mid = (line_start + line_end) * 0.5f;
01266 
01267                                 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f);
01268                                 glVertex3fv(line_start.mV);
01269                                 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
01270                                 glVertex3fv(line_mid.mV);
01271                                 glVertex3fv(line_mid.mV);
01272                                 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f);
01273                                 glVertex3fv(line_end.mV);
01274 
01275                                 line_start.setVec(selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) + (translate_axis * guide_size_meters * 0.5f));
01276                                 line_end.setVec(selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) - (translate_axis * guide_size_meters * 0.5f));
01277                                 line_mid = (line_start + line_end) * 0.5f;
01278 
01279                                 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f);
01280                                 glVertex3fv(line_start.mV);
01281                                 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
01282                                 glVertex3fv(line_mid.mV);
01283                                 glVertex3fv(line_mid.mV);
01284                                 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f);
01285                                 glVertex3fv(line_end.mV);
01286 
01287                                 for (S32 i = -num_ticks_per_side; i <= num_ticks_per_side; i++)
01288                                 {
01289                                         tick_start = selection_center + (translate_axis * (smallest_grid_unit_scale * (F32)i - offset_nearest_grid_unit));
01290 
01291                                         F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_start, translate_axis, getMinGridScale()), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
01292 
01293                                         if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / cur_subdivisions)) != 0.f)
01294                                         {
01295                                                 continue;
01296                                         }
01297 
01298                                         // add in off-axis offset
01299                                         tick_start += (mSnapOffsetAxis * mSnapOffsetMeters);
01300 
01301                                         BOOL is_sub_tick = FALSE;
01302                                         F32 tick_scale = 1.f;
01303                                         for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f)
01304                                         {
01305                                                 if (fmodf((F32)(i + sub_div_offset), division_level) == 0.f)
01306                                                 {
01307                                                         break;
01308                                                 }
01309                                                 tick_scale *= 0.7f;
01310                                                 is_sub_tick = TRUE;
01311                                         }
01312 
01313 //                                      S32 num_ticks_to_fade = is_sub_tick ? num_ticks_per_side / 2 : num_ticks_per_side;
01314 //                                      F32 alpha = line_alpha * (1.f - (0.8f *  ((F32)llabs(i) / (F32)num_ticks_to_fade)));
01315 
01316                                         tick_end = tick_start + (mSnapOffsetAxis * mSnapOffsetMeters * tick_scale);
01317 
01318                                         glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
01319                                         glVertex3fv(tick_start.mV);
01320                                         glVertex3fv(tick_end.mV);
01321 
01322                                         tick_start = selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) +
01323                                                 (translate_axis * (getMinGridScale() / (F32)(max_subdivisions) * (F32)i - offset_nearest_grid_unit));
01324                                         tick_end = tick_start - (mSnapOffsetAxis * mSnapOffsetMeters * tick_scale);
01325 
01326                                         glVertex3fv(tick_start.mV);
01327                                         glVertex3fv(tick_end.mV);
01328                                 }
01329                         }
01330                         glEnd();
01331 
01332                         if (mInSnapRegime)
01333                         {
01334                                 LLVector3 line_start = selection_center - mSnapOffsetAxis * mSnapOffsetMeters;
01335                                 LLVector3 line_end = selection_center + mSnapOffsetAxis * mSnapOffsetMeters;
01336 
01337                                 glBegin(GL_LINES);
01338                                 {
01339                                         glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
01340 
01341                                         glVertex3fv(line_start.mV);
01342                                         glVertex3fv(line_end.mV);
01343                                 }
01344                                 glEnd();
01345 
01346                                 // draw snap guide arrow
01347                                 glBegin(GL_TRIANGLES);
01348                                 {
01349                                         glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
01350 
01351                                         LLVector3 arrow_dir;
01352                                         LLVector3 arrow_span = translate_axis;
01353 
01354                                         arrow_dir = -mSnapOffsetAxis;
01355                                         glVertex3fv((line_start + arrow_dir * mConeSize * SNAP_ARROW_SCALE).mV);
01356                                         glVertex3fv((line_start + arrow_span * mConeSize * SNAP_ARROW_SCALE).mV);
01357                                         glVertex3fv((line_start - arrow_span * mConeSize * SNAP_ARROW_SCALE).mV);
01358 
01359                                         arrow_dir = mSnapOffsetAxis;
01360                                         glVertex3fv((line_end + arrow_dir * mConeSize * SNAP_ARROW_SCALE).mV);
01361                                         glVertex3fv((line_end + arrow_span * mConeSize * SNAP_ARROW_SCALE).mV);
01362                                         glVertex3fv((line_end - arrow_span * mConeSize * SNAP_ARROW_SCALE).mV);
01363                                 }
01364                                 glEnd();
01365                         }
01366                 }
01367 
01368                 sub_div_offset = llround(fmod(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() * 32.f) / smallest_grid_unit_scale);
01369 
01370                 LLVector2 screen_translate_axis(llabs(translate_axis * gCamera->getLeftAxis()), llabs(translate_axis * gCamera->getUpAxis()));
01371                 screen_translate_axis.normVec();
01372 
01373                 S32 tick_label_spacing = llround(screen_translate_axis * sTickLabelSpacing);
01374         
01375                 // render tickmark values
01376                 for (S32 i = -num_ticks_per_side; i <= num_ticks_per_side; i++)
01377                 {
01378                         LLVector3 tick_pos = selection_center + (translate_axis * ((smallest_grid_unit_scale * (F32)i) - offset_nearest_grid_unit));
01379                         F32 alpha = line_alpha * (1.f - (0.5f *  ((F32)llabs(i) / (F32)num_ticks_per_side)));
01380 
01381                         F32 tick_scale = 1.f;
01382                         for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f)
01383                         {
01384                                 if (fmodf((F32)(i + sub_div_offset), division_level) == 0.f)
01385                                 {
01386                                         break;
01387                                 }
01388                                 tick_scale *= 0.7f;
01389                         }
01390 
01391                         if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / llmin(sGridMaxSubdivisionLevel, getSubdivisionLevel(tick_pos, translate_axis, getMinGridScale(), tick_label_spacing)))) == 0.f)
01392                         {
01393                                 F32 snap_offset_meters;
01394 
01395                                 if (mSnapOffsetAxis * gCamera->getUpAxis() > 0.f)
01396                                 {
01397                                         snap_offset_meters = mSnapOffsetMeters;                 
01398                                 }
01399                                 else
01400                                 {
01401                                         snap_offset_meters = -mSnapOffsetMeters;
01402                                 }
01403                                 LLVector3 text_origin = selection_center + 
01404                                                 (translate_axis * ((smallest_grid_unit_scale * (F32)i) - offset_nearest_grid_unit)) + 
01405                                                         (mSnapOffsetAxis * snap_offset_meters * (1.f + tick_scale));
01406                                 
01407                                 LLVector3 tick_offset = (tick_pos - mGridOrigin) * ~mGridRotation;
01408                                 F32 offset_val = 0.5f * tick_offset.mV[ARROW_TO_AXIS[mManipPart]] / getMinGridScale();
01409                                 EGridMode grid_mode = gSelectMgr->getGridMode();
01410                                 F32 text_highlight = 0.8f;
01411                                 if(i - llround(offset_nearest_grid_unit / smallest_grid_unit_scale) == 0 && mInSnapRegime)
01412                                 {
01413                                         text_highlight = 1.f;
01414                                 }
01415                                 
01416                                 if (grid_mode == GRID_MODE_WORLD)
01417                                 {
01418                                         // rescale units to meters from multiple of grid scale
01419                                         offset_val *= 2.f * grid_scale[ARROW_TO_AXIS[mManipPart]];
01420                                         renderTickValue(text_origin, offset_val, "m", LLColor4(text_highlight, text_highlight, text_highlight, alpha));
01421                                 }
01422                                 else
01423                                 {
01424                                         renderTickValue(text_origin, offset_val, "x", LLColor4(text_highlight, text_highlight, text_highlight, alpha));
01425                                 }
01426                         }
01427                 }
01428                 if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD)
01429                 {
01430                         // render helpful text
01431                         if (mHelpTextTimer.getElapsedTimeF32() < sHelpTextVisibleTime + sHelpTextFadeTime && sNumTimesHelpTextShown < sMaxTimesShowHelpText)
01432                         {
01433                                 F32 snap_offset_meters_up;
01434                                 if (mSnapOffsetAxis * gCamera->getUpAxis() > 0.f)
01435                                 {
01436                                         snap_offset_meters_up = mSnapOffsetMeters;                      
01437                                 }
01438                                 else
01439                                 {
01440                                         snap_offset_meters_up = -mSnapOffsetMeters;
01441                                 }
01442 
01443                                 LLVector3 selection_center_start = getSavedPivotPoint();//gSelectMgr->getSavedBBoxOfSelection().getCenterAgent();
01444 
01445                                 LLVector3 help_text_pos = selection_center_start + (snap_offset_meters_up * 3.f * mSnapOffsetAxis);
01446                                 const LLFontGL* big_fontp = LLFontGL::sSansSerif;
01447 
01448                                 LLGLSTexture gls_texture;
01449                                 std::string help_text = "Move mouse cursor over ruler to snap";
01450                                 LLColor4 help_text_color = LLColor4::white;
01451                                 help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, line_alpha, 0.f);
01452                                 hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
01453                                 help_text = "to snap to grid";
01454                                 help_text_pos -= gCamera->getUpAxis() * mSnapOffsetMeters * 0.2f;
01455                                 hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
01456                         }
01457                 }
01458         }
01459         else
01460         {
01461                 // render gridlines for planar snapping
01462 
01463                 F32 u = 0, v = 0;
01464         LLColor4 inner_color;
01465                 LLVector3 normal;
01466                 LLVector3 grid_center = selection_center - grid_origin;
01467                 F32 usc = 1;
01468                 F32 vsc = 1;
01469                 
01470                 grid_center *= ~grid_rotation;
01471 
01472                 switch (mManipPart)
01473                 {
01474                 case LL_YZ_PLANE:
01475                         u = grid_center.mV[VY];
01476                         v = grid_center.mV[VZ];
01477                         usc = grid_scale.mV[VY];
01478                         vsc = grid_scale.mV[VZ];
01479                         inner_color.setVec(0,1,1,line_alpha);
01480                         normal.setVec(1,0,0);
01481                         break;
01482                 case LL_XZ_PLANE:
01483                         u = grid_center.mV[VX];
01484                         v = grid_center.mV[VZ];
01485                         usc = grid_scale.mV[VX];
01486                         vsc = grid_scale.mV[VZ];
01487                         inner_color.setVec(1,0,1,line_alpha);
01488                         normal.setVec(0,1,0);
01489                         break;
01490                 case LL_XY_PLANE:
01491                         u = grid_center.mV[VX];
01492                         v = grid_center.mV[VY];
01493                         usc = grid_scale.mV[VX];
01494                         vsc = grid_scale.mV[VY];
01495                         inner_color.setVec(1,1,0,line_alpha);
01496                         normal.setVec(0,0,1);
01497                         break;
01498                 default:
01499                         break;
01500                 }
01501 
01502                 highlightIntersection(normal, selection_center, grid_rotation, inner_color);
01503 
01504                 glPushMatrix();
01505 
01506                 F32 x,y,z,angle_radians;
01507                 grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z);
01508                 glTranslatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]);
01509                 glRotatef(angle_radians * RAD_TO_DEG, x, y, z);
01510                 
01511                 F32 sz = mGridSizeMeters;
01512                 F32 tiles = sz;
01513                 glMatrixMode(GL_TEXTURE);
01514                 glPushMatrix();
01515                 usc = 1.0f/usc;
01516                 vsc = 1.0f/vsc;
01517                 
01518                 while (usc > vsc*4.0f)
01519                 {
01520                         usc *= 0.5f;
01521                 }
01522                 while (vsc > usc * 4.0f)
01523                 {
01524                         vsc *= 0.5f;
01525                 }
01526 
01527                 glScalef(usc, vsc, 1.0f);
01528                 glTranslatef(u, v, 0);
01529                 
01530                 float a = line_alpha;
01531 
01532                 LLColor4 col = gColors.getColor("SilhouetteChildColor");
01533                 {
01534                         //draw grid behind objects
01535                         LLGLSTexture tex2d;
01536                         LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
01537 
01538                         {
01539                                 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER);
01540                                 glBindTexture(GL_TEXTURE_2D, sGridTex);
01541                                 glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
01542                                 renderGrid(u,v,tiles,0.9f, 0.9f, 0.9f,a*0.15f);
01543                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01544                         }
01545                         
01546                         {
01547                                 LLGLDisable alpha_test(GL_ALPHA_TEST);
01548                                 //draw black overlay
01549                                 glBindTexture(GL_TEXTURE_2D, 0);
01550                                 renderGrid(u,v,tiles,0.0f, 0.0f, 0.0f,a*0.16f);
01551 
01552                                 //draw grid top
01553                                 glBindTexture(GL_TEXTURE_2D, sGridTex);
01554                                 renderGrid(u,v,tiles,1,1,1,a);
01555 
01556                                 glPopMatrix();
01557                                 glMatrixMode(GL_MODELVIEW);
01558                                 glPopMatrix();
01559 
01560                                 {
01561                                         LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
01562                                         renderGuidelines();
01563                                 }
01564 
01565                                 {
01566                                         LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER);
01567                                         LLGLEnable stipple(GL_LINE_STIPPLE);
01568                                         glLineStipple(1, 0x3333);
01569                 
01570                                         switch (mManipPart)
01571                                         {
01572                                           case LL_YZ_PLANE:
01573                                                 renderGuidelines(FALSE, TRUE, TRUE);
01574                                                 break;
01575                                           case LL_XZ_PLANE:
01576                                                 renderGuidelines(TRUE, FALSE, TRUE);
01577                                                 break;
01578                                           case LL_XY_PLANE:
01579                                                 renderGuidelines(TRUE, TRUE, FALSE);
01580                                                 break;
01581                                           default:
01582                                                 break;
01583                                         }
01584                                 }
01585                         }
01586                 }
01587         }
01588 }
01589 
01590 void LLManipTranslate::renderGrid(F32 x, F32 y, F32 size, F32 r, F32 g, F32 b, F32 a)
01591 {
01592         F32 d = size*0.5f;
01593 
01594         for (F32 xx = -size-d; xx < size+d; xx += d)
01595         {
01596                 glBegin(GL_TRIANGLE_STRIP);
01597                 for (F32 yy = -size-d; yy < size+d; yy += d)
01598                 {
01599                         float dx, dy, da;
01600 
01601                         dx = xx; dy = yy;
01602                         da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a;
01603                         glTexCoord2f(dx, dy);
01604                         renderGridVert(dx,dy,r,g,b,da);
01605 
01606                         dx = xx+d; dy = yy;
01607                         da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a;
01608                         glTexCoord2f(dx, dy);
01609                         renderGridVert(dx,dy,r,g,b,da);
01610                         
01611                         dx = xx; dy = yy+d;
01612                         da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a;
01613                         glTexCoord2f(dx, dy);
01614                         renderGridVert(dx,dy,r,g,b,da);
01615 
01616                         dx = xx+d; dy = yy+d;
01617                         da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a;
01618                         glTexCoord2f(dx, dy);
01619                         renderGridVert(dx,dy,r,g,b,da);
01620                 }
01621                 glEnd();
01622         }
01623 
01624         
01625 }
01626 
01627 void LLManipTranslate::highlightIntersection(LLVector3 normal, 
01628                                                                                          LLVector3 selection_center, 
01629                                                                                          LLQuaternion grid_rotation, 
01630                                                                                          LLColor4 inner_color)
01631 {
01632         if (!gSavedSettings.getBOOL("GridCrossSections"))
01633         {
01634                 return;
01635         }
01636         
01637         U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT };
01638 
01639         GLuint stencil_mask = 0xFFFFFFFF;
01640         //stencil in volumes
01641         {
01642                 glStencilMask(stencil_mask);
01643                 glClearStencil(1);
01644                 glClear(GL_STENCIL_BUFFER_BIT);
01645                 LLGLEnable cull_face(GL_CULL_FACE);
01646                 LLGLEnable stencil(GL_STENCIL_TEST);
01647                 LLGLDepthTest depth (GL_TRUE, GL_FALSE, GL_ALWAYS);
01648                 glStencilFunc(GL_ALWAYS, 0, stencil_mask);
01649 
01650                 //********UMICH 3D LAB********
01651                 // protect the color mask change for correct anaglyph render
01652                 GLboolean mask[4];
01653                 glGetBooleanv(GL_COLOR_WRITEMASK,mask);
01654                 //********UMICH 3D LAB********
01655 
01656                 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
01657         LLGLDisable tex(GL_TEXTURE_2D);
01658                 glColor4f(1,1,1,1);
01659 
01660                 //setup clip plane
01661                 normal = normal * grid_rotation;
01662                 if (normal * (gCamera->getOrigin()-selection_center) < 0)
01663                 {
01664                         normal = -normal;
01665                 }
01666                 F32 d = -(selection_center * normal);
01667                 F64 plane[] = { normal.mV[0], normal.mV[1], normal.mV[2], d };
01668                 LLGLEnable clip(GL_CLIP_PLANE0);
01669                 glClipPlane(GL_CLIP_PLANE0, plane);
01670 
01671                 BOOL particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
01672                 BOOL clouds = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS);
01673                 
01674                 if (particles)
01675                 {
01676                         LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
01677                 }
01678                 if (clouds)
01679                 {
01680                         LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS);
01681                 }
01682                 
01683                 //stencil in volumes
01684                 glStencilOp(GL_INCR, GL_INCR, GL_INCR);
01685                 glCullFace(GL_FRONT);
01686                 for (U32 i = 0; i < 3; i++)
01687                 {
01688                         gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
01689                 }
01690 
01691                 glStencilOp(GL_DECR, GL_DECR, GL_DECR);
01692                 glCullFace(GL_BACK);
01693                 for (U32 i = 0; i < 3; i++)
01694                 {
01695                         gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
01696                 }
01697                 
01698                 if (particles)
01699                 {
01700                         LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
01701                 }
01702                 if (clouds)
01703                 {
01704                         LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS);
01705                 }
01706 
01707                 //********UMICH 3D LAB********
01708                 glColorMask(mask[0], mask[1], mask[2], mask[3]);
01709                 //********UMICH 3D LAB********
01710         }
01711 
01712         glPushMatrix();
01713 
01714         F32 x,y,z,angle_radians;
01715         grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z);
01716         glTranslatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]);
01717         glRotatef(angle_radians * RAD_TO_DEG, x, y, z);
01718         
01719         F32 sz = mGridSizeMeters;
01720         F32 tiles = sz;
01721 
01722         //draw volume/plane intersections
01723         {
01724                 LLGLDisable tex(GL_TEXTURE_2D);
01725                 LLGLDepthTest depth(GL_FALSE);
01726                 LLGLEnable stencil(GL_STENCIL_TEST);
01727                 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
01728                 glStencilFunc(GL_EQUAL, 0, stencil_mask);
01729                 renderGrid(0,0,tiles,inner_color.mV[0], inner_color.mV[1], inner_color.mV[2], 0.25f);
01730         }
01731 
01732         glPopMatrix();
01733 }
01734 
01735 void LLManipTranslate::renderText()
01736 {
01737         if (mObjectSelection->getRootObjectCount() && !mObjectSelection->isAttachment())
01738         {
01739                 LLVector3 pos = getPivotPoint();
01740                 renderXYZ(pos);
01741         }
01742         else
01743         {
01744                 const BOOL children_ok = TRUE;
01745                 LLViewerObject* objectp = mObjectSelection->getFirstRootObject(children_ok);
01746                 if (objectp)
01747                 {
01748                         renderXYZ(objectp->getPositionEdit());
01749                 }
01750         }
01751 }
01752 
01753 void LLManipTranslate::renderTranslationHandles()
01754 {
01755         LLVector3 grid_origin;
01756         LLVector3 grid_scale;
01757         LLQuaternion grid_rotation;
01758         LLGLDepthTest gls_depth(GL_FALSE);
01759         
01760         gSelectMgr->getGrid(grid_origin, grid_rotation, grid_scale);
01761         LLVector3 at_axis;
01762         if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
01763         {
01764                 at_axis = LLVector3::x_axis * ~grid_rotation;
01765         }
01766         else
01767         {
01768                 at_axis = gCamera->getAtAxis() * ~grid_rotation;
01769         }
01770 
01771         if (at_axis.mV[VX] > 0.f)
01772         {
01773                 mPlaneManipPositions.mV[VX] = 1.f;
01774         }
01775         else
01776         {
01777                 mPlaneManipPositions.mV[VX] = -1.f;
01778         }
01779 
01780         if (at_axis.mV[VY] > 0.f)
01781         {
01782                 mPlaneManipPositions.mV[VY] = 1.f;
01783         }
01784         else
01785         {
01786                 mPlaneManipPositions.mV[VY] = -1.f;
01787         }
01788 
01789         if (at_axis.mV[VZ] > 0.f)
01790         {
01791                 mPlaneManipPositions.mV[VZ] = 1.f;
01792         }
01793         else
01794         {
01795                 mPlaneManipPositions.mV[VZ] = -1.f;
01796         }
01797 
01798         LLViewerObject *first_object = mObjectSelection->getFirstMoveableObject(TRUE);
01799         if (!first_object) return;
01800 
01801         LLVector3 selection_center = getPivotPoint();
01802 
01803         // Drag handles         
01804         if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
01805         {
01806                 mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWindowHeight();
01807                 mArrowLengthMeters /= gAgent.getAvatarObject()->mHUDCurZoom;
01808         }
01809         else
01810         {
01811                 LLVector3 camera_pos_agent = gAgent.getCameraPositionAgent();
01812                 F32 range = dist_vec(camera_pos_agent, selection_center);
01813                 F32 range_from_agent = dist_vec(gAgent.getPositionAgent(), selection_center);
01814                 
01815                 // Don't draw handles if you're too far away
01816                 if (gSavedSettings.getBOOL("LimitSelectDistance"))
01817                 {
01818                         if (range_from_agent > gSavedSettings.getF32("MaxSelectDistance"))
01819                         {
01820                                 return;
01821                         }
01822                 }
01823 
01824                 if (range > 0.001f)
01825                 {
01826                         // range != zero
01827                         F32 fraction_of_fov = mAxisArrowLength / (F32) gCamera->getViewHeightInPixels();
01828                         F32 apparent_angle = fraction_of_fov * gCamera->getView();  // radians
01829                         mArrowLengthMeters = range * tan(apparent_angle);
01830                 }
01831                 else
01832                 {
01833                         // range == zero
01834                         mArrowLengthMeters = 1.0f;
01835                 }
01836         }
01837 
01838         mPlaneManipOffsetMeters = mArrowLengthMeters * 1.8f;
01839         mGridSizeMeters = gSavedSettings.getF32("GridDrawSize");
01840         mConeSize = mArrowLengthMeters / 4.f;
01841 
01842         glMatrixMode(GL_MODELVIEW);
01843         glPushMatrix();
01844         {
01845                 glTranslatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]);
01846 
01847                 F32 angle_radians, x, y, z;
01848                 grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z);
01849 
01850                 glRotatef(angle_radians * RAD_TO_DEG, x, y, z);
01851 
01852                 LLQuaternion invRotation = grid_rotation;
01853                 invRotation.conjQuat();
01854 
01855                 LLVector3 relative_camera_dir;
01856                 
01857                 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
01858                 {
01859                         relative_camera_dir = LLVector3::x_axis * invRotation;
01860                 }
01861                 else
01862                 {
01863                         relative_camera_dir = (selection_center - gCamera->getOrigin()) * invRotation;
01864                 }
01865                 relative_camera_dir.normVec();
01866 
01867                 {
01868                         LLGLSNoTexture gls_ui_no_texture;
01869                         LLGLDisable cull_face(GL_CULL_FACE);
01870 
01871                         LLColor4 color1;
01872                         LLColor4 color2;
01873 
01874                         // update manipulator sizes
01875                         for (S32 index = 0; index < 3; index++)
01876                         {
01877                                 if (index == mManipPart - LL_X_ARROW || index == mHighlightedPart - LL_X_ARROW)
01878                                 {
01879                                         mArrowScales.mV[index] = lerp(mArrowScales.mV[index], SELECTED_ARROW_SCALE, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
01880                                         mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
01881                                 }
01882                                 else if (index == mManipPart - LL_YZ_PLANE || index == mHighlightedPart - LL_YZ_PLANE)
01883                                 {
01884                                         mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
01885                                         mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], SELECTED_ARROW_SCALE, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
01886                                 }
01887                                 else
01888                                 {
01889                                         mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
01890                                         mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
01891                                 }
01892                         }
01893 
01894                         if ((mManipPart == LL_NO_PART || mManipPart == LL_YZ_PLANE) && llabs(relative_camera_dir.mV[VX]) > MIN_PLANE_MANIP_DOT_PRODUCT)
01895                         {
01896                                 // render YZ plane manipulator
01897                                 glPushMatrix();
01898                                 glScalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]);
01899                                 glTranslatef(0.f, mPlaneManipOffsetMeters, mPlaneManipOffsetMeters);
01900                                 glScalef(mPlaneScales.mV[VX], mPlaneScales.mV[VX], mPlaneScales.mV[VX]);
01901                                 if (mHighlightedPart == LL_YZ_PLANE)
01902                                 {
01903                                         color1.setVec(0.f, 1.f, 0.f, 1.f);
01904                                         color2.setVec(0.f, 0.f, 1.f, 1.f);
01905                                 }
01906                                 else
01907                                 {
01908                                         color1.setVec(0.f, 1.f, 0.f, 0.6f);
01909                                         color2.setVec(0.f, 0.f, 1.f, 0.6f);
01910                                 }
01911                                 glBegin(GL_TRIANGLES);
01912                                 {
01913                                         glColor4fv(color1.mV);
01914                                         glVertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f));
01915                                         glVertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f));
01916                                         glVertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
01917 
01918                                         glColor4fv(color2.mV);
01919                                         glVertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
01920                                         glVertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
01921                                         glVertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f));
01922                                 }
01923                                 glEnd();
01924 
01925                                 LLUI::setLineWidth(3.0f);
01926                                 glBegin(GL_LINES);
01927                                 {
01928                                         glColor4f(0.f, 0.f, 0.f, 0.3f);
01929                                         glVertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f,  mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
01930                                         glVertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE  * 0.25f,  mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
01931                                         glVertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE  * 0.25f,  mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
01932                                         glVertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE  * 0.1f,   mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f);
01933                                         glVertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE  * 0.25f,  mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
01934                                         glVertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE  * 0.1f,   mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f);
01935 
01936                                         glVertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
01937                                         glVertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
01938                                         glVertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
01939                                         glVertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f,  mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f);
01940                                         glVertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
01941                                         glVertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f,  mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f);
01942                                 }
01943                                 glEnd();
01944                                 LLUI::setLineWidth(1.0f);
01945                                 glPopMatrix();
01946                         }
01947 
01948                         if ((mManipPart == LL_NO_PART || mManipPart == LL_XZ_PLANE) && llabs(relative_camera_dir.mV[VY]) > MIN_PLANE_MANIP_DOT_PRODUCT)
01949                         {
01950                                 // render XZ plane manipulator
01951                                 glPushMatrix();
01952                                 glScalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]);
01953                                 glTranslatef(mPlaneManipOffsetMeters, 0.f, mPlaneManipOffsetMeters);
01954                                 glScalef(mPlaneScales.mV[VY], mPlaneScales.mV[VY], mPlaneScales.mV[VY]);
01955                                 if (mHighlightedPart == LL_XZ_PLANE)
01956                                 {
01957                                         color1.setVec(0.f, 0.f, 1.f, 1.f);
01958                                         color2.setVec(1.f, 0.f, 0.f, 1.f);
01959                                 }
01960                                 else
01961                                 {
01962                                         color1.setVec(0.f, 0.f, 1.f, 0.6f);
01963                                         color2.setVec(1.f, 0.f, 0.f, 0.6f);
01964                                 }
01965 
01966                                 glBegin(GL_TRIANGLES);
01967                                 {
01968                                         glColor4fv(color1.mV);
01969                                         glVertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
01970                                         glVertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
01971                                         glVertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f));
01972 
01973                                         glColor4fv(color2.mV);
01974                                         glVertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f));
01975                                         glVertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f));
01976                                         glVertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
01977                                 }
01978                                 glEnd();
01979 
01980                                 LLUI::setLineWidth(3.0f);
01981                                 glBegin(GL_LINES);
01982                                 {
01983                                         glColor4f(0.f, 0.f, 0.f, 0.3f);
01984                                         glVertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f,  0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
01985                                         glVertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE  * 0.25f,  0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
01986                                         glVertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE  * 0.25f,  0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
01987                                         glVertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE  * 0.1f,   0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f);
01988                                         glVertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE  * 0.25f,  0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
01989                                         glVertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE  * 0.1f,   0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f);
01990                                                                                                                                                                 
01991                                         glVertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f,  0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
01992                                         glVertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f,  0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
01993                                         glVertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f,  0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
01994                                         glVertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f,   0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f);
01995                                         glVertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f,  0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
01996                                         glVertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f,   0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f);
01997                                 }
01998                                 glEnd();
01999                                 LLUI::setLineWidth(1.0f);
02000 
02001                                 glPopMatrix();
02002                         }
02003 
02004                         if ((mManipPart == LL_NO_PART || mManipPart == LL_XY_PLANE) && llabs(relative_camera_dir.mV[VZ]) > MIN_PLANE_MANIP_DOT_PRODUCT)
02005                         {
02006                                 // render XY plane manipulator
02007                                 glPushMatrix();
02008                                 glScalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]);
02009                                 
02010 /*                                                        Y
02011                                                           ^
02012                                                           v1
02013                                                           |  \ 
02014                                                           |<- v0
02015                                                           |  /| \ 
02016                                                           v2__v__v3 > X
02017 */
02018                                         LLVector3 v0,v1,v2,v3;
02019 #if 0
02020                                         // This should theoretically work but looks off; could be tuned later -SJB
02021                                         glTranslatef(-mPlaneManipOffsetMeters, -mPlaneManipOffsetMeters, 0.f);
02022                                         v0 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f);
02023                                         v1 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.75f), 0.f);
02024                                         v2 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f);
02025                                         v3 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f);
02026 #else
02027                                         glTranslatef(mPlaneManipOffsetMeters, mPlaneManipOffsetMeters, 0.f);
02028                                         v0 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f);
02029                                         v1 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), 0.f);
02030                                         v2 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f);
02031                                         v3 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f);
02032 #endif
02033                                         glScalef(mPlaneScales.mV[VZ], mPlaneScales.mV[VZ], mPlaneScales.mV[VZ]);
02034                                         if (mHighlightedPart == LL_XY_PLANE)
02035                                         {
02036                                                 color1.setVec(1.f, 0.f, 0.f, 1.f);
02037                                                 color2.setVec(0.f, 1.f, 0.f, 1.f);
02038                                         }
02039                                         else
02040                                         {
02041                                                 color1.setVec(0.8f, 0.f, 0.f, 0.6f);
02042                                                 color2.setVec(0.f, 0.8f, 0.f, 0.6f);
02043                                         }
02044                                 
02045                                         glBegin(GL_TRIANGLES);
02046                                         {
02047                                                 glColor4fv(color1.mV);
02048                                                 glVertex3fv(v0.mV);
02049                                                 glVertex3fv(v1.mV);
02050                                                 glVertex3fv(v2.mV);
02051 
02052                                                 glColor4fv(color2.mV);
02053                                                 glVertex3fv(v2.mV);
02054                                                 glVertex3fv(v3.mV);
02055                                                 glVertex3fv(v0.mV);
02056                                         }
02057                                         glEnd();
02058 
02059                                         LLUI::setLineWidth(3.0f);
02060                                         glBegin(GL_LINES);
02061                                         {
02062                                                 glColor4f(0.f, 0.f, 0.f, 0.3f);
02063                                                 LLVector3 v12 = (v1 + v2) * .5f;
02064                                                 glVertex3fv(v0.mV);
02065                                                 glVertex3fv(v12.mV);
02066                                                 glVertex3fv(v12.mV);
02067                                                 glVertex3fv((v12 + (v0-v12)*.3f + (v2-v12)*.3f).mV);
02068                                                 glVertex3fv(v12.mV);
02069                                                 glVertex3fv((v12 + (v0-v12)*.3f + (v1-v12)*.3f).mV);
02070 
02071                                                 LLVector3 v23 = (v2 + v3) * .5f;
02072                                                 glVertex3fv(v0.mV);
02073                                                 glVertex3fv(v23.mV);
02074                                                 glVertex3fv(v23.mV);
02075                                                 glVertex3fv((v23 + (v0-v23)*.3f + (v3-v23)*.3f).mV);
02076                                                 glVertex3fv(v23.mV);
02077                                                 glVertex3fv((v23 + (v0-v23)*.3f + (v2-v23)*.3f).mV);
02078                                         }
02079                                         glEnd();
02080                                         LLUI::setLineWidth(1.0f);
02081 
02082                                 glPopMatrix();
02083                         }
02084                 }
02085                 {
02086                         LLGLSNoTexture gls_ui_no_texture;
02087 
02088                         // Since we draw handles with depth testing off, we need to draw them in the 
02089                         // proper depth order.
02090 
02091                         // Copied from LLDrawable::updateGeometry
02092                         LLVector3 pos_agent     = first_object->getPositionAgent();
02093                         LLVector3 camera_agent  = gAgent.getCameraPositionAgent();
02094                         LLVector3 headPos               = pos_agent - camera_agent;
02095 
02096                         LLVector3 orientWRTHead    = headPos * invRotation;
02097 
02098                         // Find nearest vertex
02099                         U32 nearest = (orientWRTHead.mV[0] < 0.0f ? 1 : 0) + 
02100                                 (orientWRTHead.mV[1] < 0.0f ? 2 : 0) + 
02101                                 (orientWRTHead.mV[2] < 0.0f ? 4 : 0);
02102 
02103                         // opposite faces on Linden cubes:
02104                         // 0 & 5
02105                         // 1 & 3
02106                         // 2 & 4
02107 
02108                         // Table of order to draw faces, based on nearest vertex
02109                         static U32 face_list[8][NUM_AXES*2] = { 
02110                                 { 2,0,1, 4,5,3 }, // v6  F201 F453
02111                                 { 2,0,3, 4,5,1 }, // v7  F203 F451
02112                                 { 4,0,1, 2,5,3 }, // v5  F401 F253
02113                                 { 4,0,3, 2,5,1 }, // v4  F403 F251
02114                                 { 2,5,1, 4,0,3 }, // v2  F251 F403
02115                                 { 2,5,3, 4,0,1 }, // v3  F253 F401
02116                                 { 4,5,1, 2,0,3 }, // v1  F451 F203
02117                                 { 4,5,3, 2,0,1 }, // v0  F453 F201
02118                         };
02119                         static const EManipPart which_arrow[6] = {
02120                                 LL_Z_ARROW,
02121                                 LL_X_ARROW,
02122                                 LL_Y_ARROW,
02123                                 LL_X_ARROW,
02124                                 LL_Y_ARROW,
02125                                 LL_Z_ARROW};
02126 
02127                         // draw arrows for deeper faces first, closer faces last
02128                         LLVector3 camera_axis;
02129                         if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
02130                         {
02131                                 camera_axis = LLVector3::x_axis;
02132                         }
02133                         else
02134                         {
02135                                 camera_axis.setVec(gAgent.getCameraPositionAgent() - first_object->getPositionAgent());
02136                         }
02137 
02138                         for (U32 i = 0; i < NUM_AXES*2; i++)
02139                         {                               
02140                                 U32 face = face_list[nearest][i];
02141 
02142                                 LLVector3 arrow_axis;
02143                                 getManipAxis(first_object, which_arrow[face], arrow_axis);
02144 
02145                                 if (fabs(angle_between(camera_axis, arrow_axis) - F_PI_BY_TWO) < F_PI_BY_TWO - HANDLE_HIDE_ANGLE)
02146                                 {
02147                                         renderArrow(which_arrow[face],
02148                                                                 mManipPart,
02149                                                                 (face >= 3) ? -mConeSize : mConeSize,
02150                                                                 (face >= 3) ? -mArrowLengthMeters : mArrowLengthMeters,
02151                                                                 mConeSize,
02152                                                                 FALSE);
02153                                 }
02154                         }
02155                 }
02156         }
02157         glPopMatrix();
02158 }
02159 
02160 
02161 void LLManipTranslate::renderArrow(S32 which_arrow, S32 selected_arrow, F32 box_size, F32 arrow_size, F32 handle_size, BOOL reverse_direction)
02162 {
02163         LLGLSNoTexture gls_ui_no_texture;
02164         LLGLEnable gls_blend(GL_BLEND);
02165         LLGLEnable gls_color_material(GL_COLOR_MATERIAL);
02166         
02167         for (S32 pass = 1; pass <= 2; pass++)
02168         {       
02169                 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, pass == 1 ? GL_LEQUAL : GL_GREATER);
02170                 glPushMatrix();
02171                         
02172                 S32 index = 0;
02173         
02174                 index = ARROW_TO_AXIS[which_arrow];
02175                 
02176                 // assign a color for this arrow
02177                 LLColor4 color;  // black
02178                 if (which_arrow == selected_arrow || which_arrow == mHighlightedPart)
02179                 {
02180                         color.mV[index] = (pass == 1) ? 1.f : 0.5f;
02181                 }
02182                 else if (selected_arrow != LL_NO_PART)
02183                 {
02184                         color.mV[VALPHA] = 0.f;
02185                 }
02186                 else 
02187                 {
02188                         color.mV[index] = pass == 1 ? .8f : .35f ;                      // red, green, or blue
02189                         color.mV[VALPHA] = 0.6f;
02190                 }
02191                 glColor4fv( color.mV );
02192 
02193                 LLVector3 vec;
02194 
02195                 {
02196 //                      Stipple looks OK, but not great - SJB
02197 //                      LLGLEnable stipple(GL_LINE_STIPPLE);
02198 //                      glLineStipple(1, 0x3333);
02199 
02200                         LLUI::setLineWidth(2.0f);
02201                         glBegin(GL_LINES);
02202                                 vec.mV[index] = box_size;
02203                                 glVertex3f(vec.mV[0], vec.mV[1], vec.mV[2]);
02204 
02205                                 vec.mV[index] = arrow_size;
02206                                 glVertex3f(vec.mV[0], vec.mV[1], vec.mV[2]);
02207                         glEnd();
02208                         LLUI::setLineWidth(1.0f);
02209                 }
02210                 
02211                 glTranslatef(vec.mV[0], vec.mV[1], vec.mV[2]);
02212                 glScalef(handle_size, handle_size, handle_size);
02213 
02214                 F32 rot = 0.0f;
02215                 LLVector3 axis;
02216 
02217                 switch(which_arrow)
02218                 {
02219                 case LL_X_ARROW:
02220                         rot = reverse_direction ? -90.0f : 90.0f;
02221                         axis.mV[1] = 1.0f;
02222                         break;
02223                 case LL_Y_ARROW:
02224                         rot = reverse_direction ? 90.0f : -90.0f;
02225                         axis.mV[0] = 1.0f;
02226                         break;
02227                 case LL_Z_ARROW:
02228                         rot = reverse_direction ? 180.0f : 0.0f;
02229                         axis.mV[0] = 1.0f;
02230                         break;
02231                 default:
02232                         llerrs << "renderArrow called with bad arrow " << which_arrow << llendl;
02233                         break;
02234                 }
02235 
02236                 glRotatef(rot, axis.mV[0], axis.mV[1], axis.mV[2]);
02237                 glScalef(mArrowScales.mV[index], mArrowScales.mV[index], mArrowScales.mV[index] * 1.5f);
02238 
02239                 gCone.render(CONE_LOD_HIGHEST);
02240 
02241                 glPopMatrix();
02242         }
02243 }
02244 
02245 void LLManipTranslate::renderGridVert(F32 x_trans, F32 y_trans, F32 r, F32 g, F32 b, F32 alpha)
02246 {
02247         glColor4f(r, g, b, alpha);
02248         switch (mManipPart)
02249         {
02250         case LL_YZ_PLANE:
02251                 glVertex3f(0, x_trans, y_trans);
02252                 break;
02253         case LL_XZ_PLANE:
02254                 glVertex3f(x_trans, 0, y_trans);
02255                 break;
02256         case LL_XY_PLANE:
02257                 glVertex3f(x_trans, y_trans, 0);
02258                 break;
02259         default:
02260                 glVertex3f(0,0,0);
02261                 break;
02262         }
02263 
02264 }
02265 
02266 // virtual
02267 BOOL LLManipTranslate::canAffectSelection()
02268 {
02269         BOOL can_move = mObjectSelection->getObjectCount() != 0;
02270         if (can_move)
02271         {
02272                 struct f : public LLSelectedObjectFunctor
02273                 {
02274                         virtual bool apply(LLViewerObject* objectp)
02275                         {
02276                                 return objectp->permMove() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts"));
02277                         }
02278                 } func;
02279                 can_move = mObjectSelection->applyToObjects(&func);
02280         }
02281         return can_move;
02282 }

Generated on Thu Jul 1 06:08:51 2010 for Second Life Viewer by  doxygen 1.4.7