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

Generated on Fri May 16 08:33:47 2008 for SecondLife by  doxygen 1.5.5