00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llmanipscale.h"
00035
00036
00037 #include "llmath.h"
00038 #include "v3math.h"
00039 #include "llquaternion.h"
00040 #include "llgl.h"
00041 #include "v4color.h"
00042 #include "llprimitive.h"
00043
00044
00045 #include "llagent.h"
00046 #include "llbbox.h"
00047 #include "llbox.h"
00048 #include "llviewercontrol.h"
00049 #include "llcriticaldamp.h"
00050 #include "llcylinder.h"
00051 #include "lldrawable.h"
00052 #include "llfloatertools.h"
00053 #include "llglheaders.h"
00054 #include "llselectmgr.h"
00055 #include "llstatusbar.h"
00056 #include "llui.h"
00057 #include "llviewercamera.h"
00058 #include "llviewerobject.h"
00059 #include "llviewerwindow.h"
00060 #include "llhudrender.h"
00061 #include "llworld.h"
00062 #include "v2math.h"
00063 #include "llvoavatar.h"
00064
00065
00066 const F32 MAX_MANIP_SELECT_DISTANCE_SQUARED = 11.f * 11.f;
00067 const F32 SNAP_GUIDE_SCREEN_OFFSET = 0.05f;
00068 const F32 SNAP_GUIDE_SCREEN_LENGTH = 0.7f;
00069 const F32 SELECTED_MANIPULATOR_SCALE = 1.2f;
00070 const F32 MANIPULATOR_SCALE_HALF_LIFE = 0.07f;
00071 const S32 NUM_MANIPULATORS = 14;
00072
00073 const LLManip::EManipPart MANIPULATOR_IDS[NUM_MANIPULATORS] =
00074 {
00075 LLManip::LL_CORNER_NNN,
00076 LLManip::LL_CORNER_NNP,
00077 LLManip::LL_CORNER_NPN,
00078 LLManip::LL_CORNER_NPP,
00079 LLManip::LL_CORNER_PNN,
00080 LLManip::LL_CORNER_PNP,
00081 LLManip::LL_CORNER_PPN,
00082 LLManip::LL_CORNER_PPP,
00083 LLManip::LL_FACE_POSZ,
00084 LLManip::LL_FACE_POSX,
00085 LLManip::LL_FACE_POSY,
00086 LLManip::LL_FACE_NEGX,
00087 LLManip::LL_FACE_NEGY,
00088 LLManip::LL_FACE_NEGZ
00089 };
00090
00091
00092
00093
00094 void LLManipScale::setUniform(BOOL b)
00095 {
00096 gSavedSettings.setBOOL("ScaleUniform", b);
00097 }
00098
00099
00100 void LLManipScale::setShowAxes(BOOL b)
00101 {
00102 gSavedSettings.setBOOL("ScaleShowAxes", b);
00103 }
00104
00105
00106 void LLManipScale::setStretchTextures(BOOL b)
00107 {
00108 gSavedSettings.setBOOL("ScaleStretchTextures", b);
00109 }
00110
00111
00112 BOOL LLManipScale::getUniform()
00113 {
00114 return gSavedSettings.getBOOL("ScaleUniform");
00115 }
00116
00117
00118 BOOL LLManipScale::getShowAxes()
00119 {
00120 return gSavedSettings.getBOOL("ScaleShowAxes");
00121 }
00122
00123
00124 BOOL LLManipScale::getStretchTextures()
00125 {
00126 return gSavedSettings.getBOOL("ScaleStretchTextures");
00127 }
00128
00129 inline void LLManipScale::conditionalHighlight( U32 part, const LLColor4* highlight, const LLColor4* normal )
00130 {
00131 LLColor4 default_highlight( 1.f, 1.f, 1.f, 1.f );
00132 LLColor4 default_normal( 0.7f, 0.7f, 0.7f, 0.6f );
00133 LLColor4 invisible(0.f, 0.f, 0.f, 0.f);
00134 F32 manipulator_scale = 1.f;
00135
00136 for (S32 i = 0; i < NUM_MANIPULATORS; i++)
00137 {
00138 if((U32)MANIPULATOR_IDS[i] == part)
00139 {
00140 manipulator_scale = mManipulatorScales[i];
00141 break;
00142 }
00143 }
00144
00145 mScaledBoxHandleSize = mBoxHandleSize * manipulator_scale;
00146 if (mManipPart != (S32)LL_NO_PART && mManipPart != (S32)part)
00147 {
00148 glColor4fv( invisible.mV );
00149 }
00150 else if( mHighlightedPart == (S32)part )
00151 {
00152 glColor4fv( highlight ? highlight->mV : default_highlight.mV );
00153 }
00154 else
00155 {
00156 glColor4fv( normal ? normal->mV : default_normal.mV );
00157 }
00158 }
00159
00160 void LLManipScale::handleSelect()
00161 {
00162 LLBBox bbox = gSelectMgr->getBBoxOfSelection();
00163 updateSnapGuides(bbox);
00164 gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
00165 gFloaterTools->setStatusText("scale");
00166 LLManip::handleSelect();
00167 }
00168
00169 void LLManipScale::handleDeselect()
00170 {
00171 mHighlightedPart = LL_NO_PART;
00172 mManipPart = LL_NO_PART;
00173 LLManip::handleDeselect();
00174 }
00175
00176 BOOL sort_manip_by_z(LLManipScale::ManipulatorHandle *new_manip, LLManipScale::ManipulatorHandle *test_manip)
00177 {
00178 return ((new_manip->mType < test_manip->mType) || (new_manip->mPosition.mV[VZ] < test_manip->mPosition.mV[VZ]));
00179 }
00180
00181 LLManipScale::LLManipScale( LLToolComposite* composite )
00182 :
00183 LLManip( "Scale", composite ),
00184 mBoxHandleSize( 1.f ),
00185 mScaledBoxHandleSize( 1.f ),
00186 mManipPart( LL_NO_PART ),
00187 mLastMouseX( -1 ),
00188 mLastMouseY( -1 ),
00189 mSendUpdateOnMouseUp( FALSE ),
00190 mLastUpdateFlags( 0 ),
00191 mScaleSnapUnit1(1.f),
00192 mScaleSnapUnit2(1.f),
00193 mSnapRegimeOffset(0.f),
00194 mSnapGuideLength(0.f),
00195 mScaleSnapValue(0.f)
00196 {
00197 mProjectedManipulators.setInsertBefore(sort_manip_by_z);
00198 mManipulatorScales = new F32[NUM_MANIPULATORS];
00199 for (S32 i = 0; i < NUM_MANIPULATORS; i++)
00200 {
00201 mManipulatorScales[i] = 1.f;
00202 }
00203 }
00204
00205 LLManipScale::~LLManipScale()
00206 {
00207 delete []mManipulatorScales;
00208 }
00209
00210 void LLManipScale::render()
00211 {
00212 LLGLSUIDefault gls_ui;
00213 LLGLSNoTexture gls_no_texture;
00214 LLGLDepthTest gls_depth(GL_TRUE);
00215 LLGLEnable gl_blend(GL_BLEND);
00216 LLGLEnable gls_alpha_test(GL_ALPHA_TEST);
00217
00218 if( canAffectSelection() )
00219 {
00220 glMatrixMode(GL_MODELVIEW);
00221 glPushMatrix();
00222 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
00223 {
00224 F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
00225 glScalef(zoom, zoom, zoom);
00226 }
00227
00229
00230
00231 const F32 BOX_HANDLE_BASE_SIZE = 50.0f;
00232 const F32 BOX_HANDLE_BASE_FACTOR = 0.2f;
00233
00234 LLVector3 center_agent = gAgent.getPosAgentFromGlobal(gSelectMgr->getSelectionCenterGlobal());
00235
00236 F32 range;
00237 F32 range_from_agent;
00238 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
00239 {
00240 mBoxHandleSize = BOX_HANDLE_BASE_SIZE * BOX_HANDLE_BASE_FACTOR / (F32) gCamera->getViewHeightInPixels();
00241 mBoxHandleSize /= gAgent.getAvatarObject()->mHUDCurZoom;
00242 }
00243 else
00244 {
00245 range = dist_vec(gAgent.getCameraPositionAgent(), center_agent);
00246 range_from_agent = dist_vec(gAgent.getPositionAgent(), center_agent);
00247
00248
00249 if (gSavedSettings.getBOOL("LimitSelectDistance"))
00250 {
00251 F32 max_select_distance = gSavedSettings.getF32("MaxSelectDistance");
00252 if (range_from_agent > max_select_distance)
00253 {
00254 return;
00255 }
00256 }
00257
00258 if (range > 0.001f)
00259 {
00260
00261 F32 fraction_of_fov = BOX_HANDLE_BASE_SIZE / (F32) gCamera->getViewHeightInPixels();
00262 F32 apparent_angle = fraction_of_fov * gCamera->getView();
00263 mBoxHandleSize = range * tan(apparent_angle) * BOX_HANDLE_BASE_FACTOR;
00264 }
00265 else
00266 {
00267
00268 mBoxHandleSize = BOX_HANDLE_BASE_FACTOR;
00269 }
00270 }
00271
00273
00274
00275 LLBBox bbox = gSelectMgr->getBBoxOfSelection();
00276 LLVector3 pos_agent = bbox.getPositionAgent();
00277 LLQuaternion rot = bbox.getRotation();
00278
00279 glMatrixMode(GL_MODELVIEW);
00280 glPushMatrix();
00281 {
00282 glTranslatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ]);
00283
00284 F32 angle_radians, x, y, z;
00285 rot.getAngleAxis(&angle_radians, &x, &y, &z);
00286 glRotatef(angle_radians * RAD_TO_DEG, x, y, z);
00287
00288
00289 {
00290 LLGLEnable poly_offset(GL_POLYGON_OFFSET_FILL);
00291 glPolygonOffset( -2.f, -2.f);
00292
00293
00294
00295
00296
00297 renderCorners( bbox );
00298 renderFaces( bbox );
00299
00300 if (mManipPart != LL_NO_PART)
00301 {
00302 renderGuidelinesPart( bbox );
00303 }
00304
00305 glPolygonOffset( 0.f, 0.f);
00306 }
00307 }
00308 glPopMatrix();
00309
00310 if (mManipPart != LL_NO_PART)
00311 {
00312 renderSnapGuides(bbox);
00313 }
00314 glPopMatrix();
00315
00316 renderXYZ(bbox.getExtentLocal());
00317 }
00318 }
00319
00320 BOOL LLManipScale::handleMouseDown(S32 x, S32 y, MASK mask)
00321 {
00322 BOOL handled = FALSE;
00323
00324 LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
00325 if( hit_obj ||
00326 (mHighlightedPart != LL_NO_PART) )
00327 {
00328 handled = handleMouseDownOnPart( x, y, mask );
00329 }
00330
00331 return handled;
00332 }
00333
00334
00335 BOOL LLManipScale::handleMouseDownOnPart( S32 x, S32 y, MASK mask )
00336 {
00337 BOOL can_scale = canAffectSelection();
00338 if (!can_scale)
00339 {
00340 return FALSE;
00341 }
00342
00343 highlightManipulators(x, y);
00344 S32 hit_part = mHighlightedPart;
00345
00346 gSelectMgr->enableSilhouette(FALSE);
00347 mManipPart = (EManipPart)hit_part;
00348
00349 LLBBox bbox = gSelectMgr->getBBoxOfSelection();
00350 LLVector3 box_center_agent = bbox.getCenterAgent();
00351 LLVector3 box_corner_agent = bbox.localToAgent( unitVectorToLocalBBoxExtent( partToUnitVector( mManipPart ), bbox ) );
00352
00353 updateSnapGuides(bbox);
00354
00355 mDragStartPointGlobal = gAgent.getPosGlobalFromAgent(box_corner_agent);
00356 mDragStartCenterGlobal = gAgent.getPosGlobalFromAgent(box_center_agent);
00357 LLVector3 far_corner_agent = bbox.localToAgent( unitVectorToLocalBBoxExtent( -1.f * partToUnitVector( mManipPart ), bbox ) );
00358 mDragFarHitGlobal = gAgent.getPosGlobalFromAgent(far_corner_agent);
00359 mDragPointGlobal = mDragStartPointGlobal;
00360
00361
00362 gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_SCALE);
00363
00364 setMouseCapture( TRUE );
00365
00366 mHelpTextTimer.reset();
00367 sNumTimesHelpTextShown++;
00368 return TRUE;
00369 }
00370
00371
00372 BOOL LLManipScale::handleMouseUp(S32 x, S32 y, MASK mask)
00373 {
00374
00375 handleHover(x, y, mask);
00376
00377 if( hasMouseCapture() )
00378 {
00379 if( (LL_FACE_MIN <= (S32)mManipPart)
00380 && ((S32)mManipPart <= LL_FACE_MAX) )
00381 {
00382 sendUpdates(TRUE,TRUE,FALSE);
00383 }
00384 else
00385 if( (LL_CORNER_MIN <= (S32)mManipPart)
00386 && ((S32)mManipPart <= LL_CORNER_MAX) )
00387 {
00388 sendUpdates(TRUE,TRUE,TRUE);
00389 }
00390
00391
00392 gSelectMgr->adjustTexturesByScale(TRUE, getStretchTextures());
00393
00394 gSelectMgr->enableSilhouette(TRUE);
00395 mManipPart = LL_NO_PART;
00396
00397
00398 gSelectMgr->sendMultipleUpdate( mLastUpdateFlags );
00399
00400
00401 gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
00402 }
00403 return LLManip::handleMouseUp(x, y, mask);
00404 }
00405
00406
00407 BOOL LLManipScale::handleHover(S32 x, S32 y, MASK mask)
00408 {
00409 if( hasMouseCapture() )
00410 {
00411 if( mObjectSelection->isEmpty() )
00412 {
00413
00414 setMouseCapture( FALSE );
00415 }
00416 else
00417 {
00418 drag( x, y );
00419 }
00420 lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipScale (active)" << llendl;
00421 }
00422 else
00423 {
00424 mInSnapRegime = FALSE;
00425
00426 highlightManipulators(x, y);
00427 }
00428
00429
00430 gSelectMgr->adjustTexturesByScale(FALSE, getStretchTextures());
00431
00432 gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLSCALE);
00433 return TRUE;
00434 }
00435
00436 void LLManipScale::highlightManipulators(S32 x, S32 y)
00437 {
00438 mHighlightedPart = LL_NO_PART;
00439
00440
00441
00442 LLBBox bbox = gSelectMgr->getBBoxOfSelection();
00443
00444 if( canAffectSelection() )
00445 {
00446 LLMatrix4 transform;
00447 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
00448 {
00449 LLVector4 translation(bbox.getPositionAgent());
00450 transform.initRotTrans(bbox.getRotation(), translation);
00451 LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
00452 transform *= cfr;
00453 LLMatrix4 window_scale;
00454 F32 zoom_level = 2.f * gAgent.getAvatarObject()->mHUDCurZoom;
00455 window_scale.initAll(LLVector3(zoom_level / gCamera->getAspect(), zoom_level, 0.f),
00456 LLQuaternion::DEFAULT,
00457 LLVector3::zero);
00458 transform *= window_scale;
00459 }
00460 else
00461 {
00462 LLMatrix4 projMatrix = gCamera->getProjection();
00463 LLMatrix4 modelView = gCamera->getModelview();
00464 transform.initAll(LLVector3(1.f, 1.f, 1.f), bbox.getRotation(), bbox.getPositionAgent());
00465
00466 transform *= modelView;
00467 transform *= projMatrix;
00468 }
00469
00470 LLVector3 min = bbox.getMinLocal();
00471 LLVector3 max = bbox.getMaxLocal();
00472 LLVector3 ctr = bbox.getCenterLocal();
00473
00474 mProjectedManipulators.deleteAllData();
00475
00476 S32 numManips = 0;
00477
00478 mManipulatorVertices[numManips++] = LLVector4(min.mV[VX], min.mV[VY], min.mV[VZ], 1.f);
00479 mManipulatorVertices[numManips++] = LLVector4(min.mV[VX], min.mV[VY], max.mV[VZ], 1.f);
00480 mManipulatorVertices[numManips++] = LLVector4(min.mV[VX], max.mV[VY], min.mV[VZ], 1.f);
00481 mManipulatorVertices[numManips++] = LLVector4(min.mV[VX], max.mV[VY], max.mV[VZ], 1.f);
00482 mManipulatorVertices[numManips++] = LLVector4(max.mV[VX], min.mV[VY], min.mV[VZ], 1.f);
00483 mManipulatorVertices[numManips++] = LLVector4(max.mV[VX], min.mV[VY], max.mV[VZ], 1.f);
00484 mManipulatorVertices[numManips++] = LLVector4(max.mV[VX], max.mV[VY], min.mV[VZ], 1.f);
00485 mManipulatorVertices[numManips++] = LLVector4(max.mV[VX], max.mV[VY], max.mV[VZ], 1.f);
00486
00487
00488 if( mObjectSelection->getObjectCount() == 1 )
00489 {
00490
00491 mManipulatorVertices[numManips++] = LLVector4(ctr.mV[VX], ctr.mV[VY], max.mV[VZ], 1.f);
00492 mManipulatorVertices[numManips++] = LLVector4(max.mV[VX], ctr.mV[VY], ctr.mV[VZ], 1.f);
00493 mManipulatorVertices[numManips++] = LLVector4(ctr.mV[VX], max.mV[VY], ctr.mV[VZ], 1.f);
00494 mManipulatorVertices[numManips++] = LLVector4(min.mV[VX], ctr.mV[VY], ctr.mV[VZ], 1.f);
00495 mManipulatorVertices[numManips++] = LLVector4(ctr.mV[VX], min.mV[VY], ctr.mV[VZ], 1.f);
00496 mManipulatorVertices[numManips++] = LLVector4(ctr.mV[VX], ctr.mV[VY], min.mV[VZ], 1.f);
00497 }
00498
00499 for (S32 i = 0; i < numManips; i++)
00500 {
00501 LLVector4 projectedVertex = mManipulatorVertices[i] * transform;
00502 projectedVertex = projectedVertex * (1.f / projectedVertex.mV[VW]);
00503
00504 ManipulatorHandle* projManipulator = new ManipulatorHandle(LLVector3(projectedVertex.mV[VX], projectedVertex.mV[VY],
00505 projectedVertex.mV[VZ]), MANIPULATOR_IDS[i], (i < 7) ? SCALE_MANIP_CORNER : SCALE_MANIP_FACE);
00506 mProjectedManipulators.addDataSorted(projManipulator);
00507 }
00508
00509 F32 half_width = (F32)gViewerWindow->getWindowWidth() / 2.f;
00510 F32 half_height = (F32)gViewerWindow->getWindowHeight() / 2.f;
00511 LLVector2 manip2d;
00512 LLVector2 mousePos((F32)x - half_width, (F32)y - half_height);
00513 LLVector2 delta;
00514
00515 mHighlightedPart = LL_NO_PART;
00516
00517 for (ManipulatorHandle* manipulator = mProjectedManipulators.getFirstData();
00518 manipulator;
00519 manipulator = mProjectedManipulators.getNextData())
00520 {
00521 manip2d.setVec(manipulator->mPosition.mV[VX] * half_width, manipulator->mPosition.mV[VY] * half_height);
00522
00523 delta = manip2d - mousePos;
00524 if (delta.magVecSquared() < MAX_MANIP_SELECT_DISTANCE_SQUARED)
00525 {
00526 mHighlightedPart = manipulator->mManipID;
00527
00528
00529 break;
00530 }
00531 }
00532 }
00533
00534 for (S32 i = 0; i < NUM_MANIPULATORS; i++)
00535 {
00536 if (mHighlightedPart == MANIPULATOR_IDS[i])
00537 {
00538 mManipulatorScales[i] = lerp(mManipulatorScales[i], SELECTED_MANIPULATOR_SCALE, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE));
00539 }
00540 else
00541 {
00542 mManipulatorScales[i] = lerp(mManipulatorScales[i], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE));
00543 }
00544 }
00545
00546 lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipScale (inactive)" << llendl;
00547 }
00548
00549
00550 void LLManipScale::renderFaces( const LLBBox& bbox )
00551 {
00552
00553
00554 if ( mObjectSelection->getObjectCount() > 1 )
00555 {
00556 return;
00557 }
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 LLColor4 highlight_color( 1.f, 1.f, 1.f, 0.5f);
00584 LLColor4 normal_color( 1.f, 1.f, 1.f, 0.3f);
00585
00586 LLColor4 x_highlight_color( 1.f, 0.2f, 0.2f, 1.0f);
00587 LLColor4 x_normal_color( 0.6f, 0.f, 0.f, 0.4f);
00588
00589 LLColor4 y_highlight_color( 0.2f, 1.f, 0.2f, 1.0f);
00590 LLColor4 y_normal_color( 0.f, 0.6f, 0.f, 0.4f);
00591
00592 LLColor4 z_highlight_color( 0.2f, 0.2f, 1.f, 1.0f);
00593 LLColor4 z_normal_color( 0.f, 0.f, 0.6f, 0.4f);
00594
00595 LLColor4 default_normal_color( 0.7f, 0.7f, 0.7f, 0.15f );
00596
00597 const LLVector3& min = bbox.getMinLocal();
00598 const LLVector3& max = bbox.getMaxLocal();
00599 LLVector3 ctr = bbox.getCenterLocal();
00600
00601 if (mManipPart == LL_NO_PART)
00602 {
00603 glColor4fv( default_normal_color.mV );
00604 LLGLDepthTest gls_depth(GL_FALSE);
00605 glBegin(GL_QUADS);
00606 {
00607
00608 glVertex3f(min.mV[VX], max.mV[VY], max.mV[VZ]);
00609 glVertex3f(min.mV[VX], min.mV[VY], max.mV[VZ]);
00610 glVertex3f(max.mV[VX], min.mV[VY], max.mV[VZ]);
00611 glVertex3f(max.mV[VX], max.mV[VY], max.mV[VZ]);
00612
00613
00614 glVertex3f(max.mV[VX], min.mV[VY], max.mV[VZ]);
00615 glVertex3f(max.mV[VX], min.mV[VY], min.mV[VZ]);
00616 glVertex3f(max.mV[VX], max.mV[VY], min.mV[VZ]);
00617 glVertex3f(max.mV[VX], max.mV[VY], max.mV[VZ]);
00618
00619
00620 glVertex3f(min.mV[VX], max.mV[VY], min.mV[VZ]);
00621 glVertex3f(min.mV[VX], max.mV[VY], max.mV[VZ]);
00622 glVertex3f(max.mV[VX], max.mV[VY], max.mV[VZ]);
00623 glVertex3f(max.mV[VX], max.mV[VY], min.mV[VZ]);
00624
00625
00626 glVertex3f(min.mV[VX], max.mV[VY], max.mV[VZ]);
00627 glVertex3f(min.mV[VX], max.mV[VY], min.mV[VZ]);
00628 glVertex3f(min.mV[VX], min.mV[VY], min.mV[VZ]);
00629 glVertex3f(min.mV[VX], min.mV[VY], max.mV[VZ]);
00630
00631
00632 glVertex3f(min.mV[VX], min.mV[VY], max.mV[VZ]);
00633 glVertex3f(min.mV[VX], min.mV[VY], min.mV[VZ]);
00634 glVertex3f(max.mV[VX], min.mV[VY], min.mV[VZ]);
00635 glVertex3f(max.mV[VX], min.mV[VY], max.mV[VZ]);
00636
00637
00638 glVertex3f(min.mV[VX], min.mV[VY], min.mV[VZ]);
00639 glVertex3f(min.mV[VX], max.mV[VY], min.mV[VZ]);
00640 glVertex3f(max.mV[VX], max.mV[VY], min.mV[VZ]);
00641 glVertex3f(max.mV[VX], min.mV[VY], min.mV[VZ]);
00642 }
00643 glEnd();
00644 }
00645
00646
00647 LLVector3 orientWRTHead = bbox.agentToLocalBasis( bbox.getCenterAgent() - gAgent.getCameraPositionAgent() );
00648 U32 nearest =
00649 (orientWRTHead.mV[0] < 0.0f ? 1 : 0) +
00650 (orientWRTHead.mV[1] < 0.0f ? 2 : 0) +
00651 (orientWRTHead.mV[2] < 0.0f ? 4 : 0);
00652
00653
00654
00655
00656
00657
00658
00659 static U32 face_list[8][6] = {
00660 { 2,0,1, 4,5,3 },
00661 { 2,0,3, 4,5,1 },
00662 { 4,0,1, 2,5,3 },
00663 { 4,0,3, 2,5,1 },
00664 { 2,5,1, 4,0,3 },
00665 { 2,5,3, 4,0,1 },
00666 { 4,5,1, 2,0,3 },
00667 { 4,5,3, 2,0,1 }
00668 };
00669
00670 {
00671 LLGLDepthTest gls_depth(GL_FALSE);
00672
00673 for (S32 i = 0; i < 6; i++)
00674 {
00675 U32 face = face_list[nearest][i];
00676 switch( face )
00677 {
00678 case 0:
00679 conditionalHighlight( LL_FACE_POSZ, &z_highlight_color, &z_normal_color );
00680 renderAxisHandle( ctr, LLVector3( ctr.mV[VX], ctr.mV[VY], max.mV[VZ] ) );
00681 break;
00682
00683 case 1:
00684 conditionalHighlight( LL_FACE_POSX, &x_highlight_color, &x_normal_color );
00685 renderAxisHandle( ctr, LLVector3( max.mV[VX], ctr.mV[VY], ctr.mV[VZ] ) );
00686 break;
00687
00688 case 2:
00689 conditionalHighlight( LL_FACE_POSY, &y_highlight_color, &y_normal_color );
00690 renderAxisHandle( ctr, LLVector3( ctr.mV[VX], max.mV[VY], ctr.mV[VZ] ) );
00691 break;
00692
00693 case 3:
00694 conditionalHighlight( LL_FACE_NEGX, &x_highlight_color, &x_normal_color );
00695 renderAxisHandle( ctr, LLVector3( min.mV[VX], ctr.mV[VY], ctr.mV[VZ] ) );
00696 break;
00697
00698 case 4:
00699 conditionalHighlight( LL_FACE_NEGY, &y_highlight_color, &y_normal_color );
00700 renderAxisHandle( ctr, LLVector3( ctr.mV[VX], min.mV[VY], ctr.mV[VZ] ) );
00701 break;
00702
00703 case 5:
00704 conditionalHighlight( LL_FACE_NEGZ, &z_highlight_color, &z_normal_color );
00705 renderAxisHandle( ctr, LLVector3( ctr.mV[VX], ctr.mV[VY], min.mV[VZ] ) );
00706 break;
00707 }
00708 }
00709 }
00710 }
00711
00712 void LLManipScale::renderEdges( const LLBBox& bbox )
00713 {
00714 LLVector3 extent = bbox.getExtentLocal();
00715 F32 edge_width = mBoxHandleSize * .6f;
00716
00717 for( U32 part = LL_EDGE_MIN; part <= LL_EDGE_MAX; part++ )
00718 {
00719 LLVector3 direction = edgeToUnitVector( part );
00720 LLVector3 center_to_edge = unitVectorToLocalBBoxExtent( direction, bbox );
00721
00722 glPushMatrix();
00723 {
00724 glTranslatef( center_to_edge.mV[0], center_to_edge.mV[1], center_to_edge.mV[2] );
00725 conditionalHighlight( part );
00726 glScalef(
00727 direction.mV[0] ? edge_width : extent.mV[VX],
00728 direction.mV[1] ? edge_width : extent.mV[VY],
00729 direction.mV[2] ? edge_width : extent.mV[VZ] );
00730 gBox.render();
00731 }
00732 glPopMatrix();
00733 }
00734 }
00735
00736
00737 void LLManipScale::renderCorners( const LLBBox& bbox )
00738 {
00739 U32 part = LL_CORNER_NNN;
00740
00741 F32 x_offset = bbox.getMinLocal().mV[VX];
00742 for( S32 i=0; i < 2; i++ )
00743 {
00744 F32 y_offset = bbox.getMinLocal().mV[VY];
00745 for( S32 j=0; j < 2; j++ )
00746 {
00747 F32 z_offset = bbox.getMinLocal().mV[VZ];
00748 for( S32 k=0; k < 2; k++ )
00749 {
00750 conditionalHighlight( part );
00751 renderBoxHandle( x_offset, y_offset, z_offset );
00752 part++;
00753
00754 z_offset = bbox.getMaxLocal().mV[VZ];
00755
00756 }
00757 y_offset = bbox.getMaxLocal().mV[VY];
00758 }
00759 x_offset = bbox.getMaxLocal().mV[VX];
00760 }
00761 }
00762
00763
00764 void LLManipScale::renderBoxHandle( F32 x, F32 y, F32 z )
00765 {
00766 LLGLDisable gls_tex(GL_TEXTURE_2D);
00767 LLGLDepthTest gls_depth(GL_FALSE);
00768
00769 glPushMatrix();
00770 {
00771 glTranslatef( x, y, z );
00772 glScalef( mScaledBoxHandleSize, mScaledBoxHandleSize, mScaledBoxHandleSize );
00773 gBox.render();
00774 }
00775 glPopMatrix();
00776 }
00777
00778
00779 void LLManipScale::renderAxisHandle( const LLVector3& start, const LLVector3& end )
00780 {
00781 if( getShowAxes() )
00782 {
00783
00784 LLVector3 offset_start = end - start;
00785 offset_start.normVec();
00786 offset_start = start + mBoxHandleSize * offset_start;
00787
00788 LLVector3 delta = end - offset_start;
00789 LLVector3 pos = offset_start + 0.5f * delta;
00790
00791 glPushMatrix();
00792 {
00793 glTranslatef( pos.mV[VX], pos.mV[VY], pos.mV[VZ] );
00794 glScalef(
00795 mBoxHandleSize + llabs(delta.mV[VX]),
00796 mBoxHandleSize + llabs(delta.mV[VY]),
00797 mBoxHandleSize + llabs(delta.mV[VZ]));
00798 gBox.render();
00799 }
00800 glPopMatrix();
00801 }
00802 else
00803 {
00804 renderBoxHandle( end.mV[VX], end.mV[VY], end.mV[VZ] );
00805 }
00806 }
00807
00808
00809 void LLManipScale::drag( S32 x, S32 y )
00810 {
00811 if( (LL_FACE_MIN <= (S32)mManipPart)
00812 && ((S32)mManipPart <= LL_FACE_MAX) )
00813 {
00814 dragFace( x, y );
00815 }
00816 else
00817 if( (LL_CORNER_MIN <= (S32)mManipPart)
00818 && ((S32)mManipPart <= LL_CORNER_MAX) )
00819 {
00820 dragCorner( x, y );
00821 }
00822
00823
00824 for (LLObjectSelection::iterator iter = gSelectMgr->getSelection()->begin();
00825 iter != gSelectMgr->getSelection()->end(); iter++)
00826 {
00827 LLSelectNode* selectNode = *iter;
00828 LLViewerObject*cur = selectNode->getObject();
00829 if( cur->permModify() && cur->permMove() && !cur->isAvatar())
00830 {
00831 selectNode->mLastScale = cur->getScale();
00832 selectNode->mLastPositionLocal = cur->getPosition();
00833 }
00834 }
00835
00836 gSelectMgr->updateSelectionCenter();
00837 gAgent.clearFocusObject();
00838 }
00839
00840
00841 void LLManipScale::dragCorner( S32 x, S32 y )
00842 {
00843 LLBBox bbox = gSelectMgr->getBBoxOfSelection();
00844
00845
00846 if (x == mLastMouseX && y == mLastMouseY)
00847 {
00848
00849 return;
00850 }
00851
00852 mLastMouseX = x;
00853 mLastMouseY = y;
00854
00855 LLVector3d drag_start_point_global = mDragStartPointGlobal;
00856 LLVector3d drag_start_center_global = mDragStartCenterGlobal;
00857 LLVector3 drag_start_point_agent = gAgent.getPosAgentFromGlobal(drag_start_point_global);
00858 LLVector3 drag_start_center_agent = gAgent.getPosAgentFromGlobal(drag_start_center_global);
00859
00860 LLVector3d drag_start_dir_d;
00861 drag_start_dir_d.setVec(drag_start_point_global - drag_start_center_global);
00862 LLVector3 drag_start_dir_f;
00863 drag_start_dir_f.setVec(drag_start_dir_d);
00864
00865 F32 s = 0;
00866 F32 t = 0;
00867
00868 nearestPointOnLineFromMouse(x, y,
00869 drag_start_center_agent,
00870 drag_start_point_agent,
00871 s, t );
00872
00873 F32 drag_start_dist = dist_vec(drag_start_point_agent, drag_start_center_agent);
00874
00875 if( s <= 0 )
00876 {
00877 return;
00878 }
00879
00880 LLVector3d drag_point_global = drag_start_center_global + t * drag_start_dir_d;
00881
00882 F32 scale_factor = t;
00883
00884 BOOL uniform = LLManipScale::getUniform();
00885
00886 if( !uniform )
00887 {
00888 scale_factor = 0.5f + (scale_factor * 0.5f);
00889 }
00890
00891
00892 LLVector3 drag_center_agent = gAgent.getPosAgentFromGlobal(drag_point_global);
00893 LLVector3 mouse_on_plane1;
00894 getMousePointOnPlaneAgent(mouse_on_plane1, x, y, drag_center_agent, mScalePlaneNormal1);
00895 LLVector3 mouse_on_plane2;
00896 getMousePointOnPlaneAgent(mouse_on_plane2, x, y, drag_center_agent, mScalePlaneNormal2);
00897 LLVector3 mouse_dir_1 = mouse_on_plane1 - mScaleCenter;
00898 LLVector3 mouse_dir_2 = mouse_on_plane2 - mScaleCenter;
00899 LLVector3 mouse_to_scale_line_1 = mouse_dir_1 - projected_vec(mouse_dir_1, mScaleDir);
00900 LLVector3 mouse_to_scale_line_2 = mouse_dir_2 - projected_vec(mouse_dir_2, mScaleDir);
00901 LLVector3 mouse_to_scale_line_dir_1 = mouse_to_scale_line_1;
00902 mouse_to_scale_line_dir_1.normVec();
00903 if (mouse_to_scale_line_dir_1 * mSnapGuideDir1 < 0.f)
00904 {
00905
00906 mouse_to_scale_line_dir_1 *= -1.f;
00907 }
00908 LLVector3 mouse_to_scale_line_dir_2 = mouse_to_scale_line_2;
00909 mouse_to_scale_line_dir_2.normVec();
00910 if (mouse_to_scale_line_dir_2 * mSnapGuideDir2 < 0.f)
00911 {
00912
00913 mouse_to_scale_line_dir_2 *= -1.f;
00914 }
00915
00916 F32 snap_dir_dot_mouse_offset1 = mSnapGuideDir1 * mouse_to_scale_line_dir_1;
00917 F32 snap_dir_dot_mouse_offset2 = mSnapGuideDir2 * mouse_to_scale_line_dir_2;
00918
00919 F32 dist_from_scale_line_1 = mouse_to_scale_line_1 * mouse_to_scale_line_dir_1;
00920 F32 dist_from_scale_line_2 = mouse_to_scale_line_2 * mouse_to_scale_line_dir_2;
00921
00922 F32 max_scale = partToMaxScale(mManipPart, bbox);
00923 F32 min_scale = partToMinScale(mManipPart, bbox);
00924
00925 BOOL snap_enabled = gSavedSettings.getBOOL("SnapEnabled");
00926 if (snap_enabled && dist_from_scale_line_1 > mSnapRegimeOffset * snap_dir_dot_mouse_offset1)
00927 {
00928 mInSnapRegime = TRUE;
00929 LLVector3 projected_drag_pos = mouse_on_plane1 - (dist_from_scale_line_1 / snap_dir_dot_mouse_offset1) * mSnapGuideDir1;
00930 F32 drag_dist = (projected_drag_pos - mScaleCenter) * mScaleDir;
00931
00932 F32 cur_subdivisions = llclamp(getSubdivisionLevel(projected_drag_pos, mScaleDir, mScaleSnapUnit1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
00933 F32 snap_dist = mScaleSnapUnit1 / (2.f * cur_subdivisions);
00934 F32 relative_snap_dist = fmodf(drag_dist + snap_dist, mScaleSnapUnit1 / cur_subdivisions);
00935
00936 mScaleSnapValue = llclamp((drag_dist - (relative_snap_dist - snap_dist)), min_scale, max_scale);
00937
00938 scale_factor = mScaleSnapValue / drag_start_dist;
00939 if( !uniform )
00940 {
00941 scale_factor *= 0.5f;
00942 }
00943 }
00944 else if (snap_enabled && dist_from_scale_line_2 > mSnapRegimeOffset * snap_dir_dot_mouse_offset2)
00945 {
00946 mInSnapRegime = TRUE;
00947 LLVector3 projected_drag_pos = mouse_on_plane2 - (dist_from_scale_line_2 / snap_dir_dot_mouse_offset2) * mSnapGuideDir2;
00948 F32 drag_dist = (projected_drag_pos - mScaleCenter) * mScaleDir;
00949
00950 F32 cur_subdivisions = llclamp(getSubdivisionLevel(projected_drag_pos, mScaleDir, mScaleSnapUnit2), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
00951 F32 snap_dist = mScaleSnapUnit2 / (2.f * cur_subdivisions);
00952 F32 relative_snap_dist = fmodf(drag_dist + snap_dist, mScaleSnapUnit2 / cur_subdivisions);
00953
00954 mScaleSnapValue = llclamp((drag_dist - (relative_snap_dist - snap_dist)), min_scale, max_scale);
00955
00956 scale_factor = mScaleSnapValue / drag_start_dist;
00957 if( !uniform )
00958 {
00959 scale_factor *= 0.5f;
00960 }
00961 }
00962 else
00963 {
00964 mInSnapRegime = FALSE;
00965 }
00966
00967 F32 max_scale_factor = MAX_OBJECT_SCALE / MIN_OBJECT_SCALE;
00968 F32 min_scale_factor = MIN_OBJECT_SCALE / MAX_OBJECT_SCALE;
00969
00970
00971 for (LLObjectSelection::iterator iter = mObjectSelection->begin();
00972 iter != mObjectSelection->end(); iter++)
00973 {
00974 LLSelectNode* selectNode = *iter;
00975 LLViewerObject* cur = selectNode->getObject();
00976 if( cur->permModify() && cur->permMove() && !cur->isAvatar() )
00977 {
00978 const LLVector3& scale = selectNode->mSavedScale;
00979
00980 F32 cur_max_scale_factor = llmin( MAX_OBJECT_SCALE / scale.mV[VX], MAX_OBJECT_SCALE / scale.mV[VY], MAX_OBJECT_SCALE / scale.mV[VZ] );
00981 max_scale_factor = llmin( max_scale_factor, cur_max_scale_factor );
00982
00983 F32 cur_min_scale_factor = llmax( MIN_OBJECT_SCALE / scale.mV[VX], MIN_OBJECT_SCALE / scale.mV[VY], MIN_OBJECT_SCALE / scale.mV[VZ] );
00984 min_scale_factor = llmax( min_scale_factor, cur_min_scale_factor );
00985 }
00986 }
00987
00988 scale_factor = llclamp( scale_factor, min_scale_factor, max_scale_factor );
00989
00990 LLVector3d drag_global = uniform ? mDragStartCenterGlobal : mDragFarHitGlobal;
00991
00992
00993 for (LLObjectSelection::iterator iter = mObjectSelection->begin();
00994 iter != mObjectSelection->end(); iter++)
00995 {
00996 LLSelectNode* selectNode = *iter;
00997 LLViewerObject* cur = selectNode->getObject();
00998 if( cur->permModify() && cur->permMove() && !cur->isAvatar() && cur->isRootEdit() )
00999 {
01000 const LLVector3& scale = selectNode->mSavedScale;
01001 cur->setScale( scale_factor * scale );
01002
01003 LLVector3 delta_pos;
01004 LLVector3 original_pos = cur->getPositionEdit();
01005 LLVector3d new_pos_global = drag_global + (selectNode->mSavedPositionGlobal - drag_global) * scale_factor;
01006 if (!cur->isAttachment())
01007 {
01008 new_pos_global = gWorldp->clipToVisibleRegions(selectNode->mSavedPositionGlobal, new_pos_global);
01009 }
01010 cur->setPositionAbsoluteGlobal( new_pos_global );
01011 rebuild(cur);
01012
01013 delta_pos = cur->getPositionEdit() - original_pos;
01014
01015 if (selectNode->mIndividualSelection)
01016 {
01017
01018 for (U32 child_num = 0; child_num < cur->mChildList.size(); child_num++)
01019 {
01020 LLViewerObject* childp = cur->mChildList[child_num];
01021
01022 if (cur->isAttachment())
01023 {
01024 LLVector3 child_pos = childp->getPosition() - (delta_pos * ~cur->getRotationEdit());
01025 childp->setPosition(child_pos);
01026 }
01027 else
01028 {
01029 LLVector3d child_pos_delta(delta_pos);
01030
01031 childp->setPositionAbsoluteGlobal(childp->getPositionGlobal() - child_pos_delta);
01032 }
01033 rebuild(childp);
01034 }
01035 }
01036 }
01037 }
01038
01039 for (LLObjectSelection::iterator iter = mObjectSelection->begin();
01040 iter != mObjectSelection->end(); iter++)
01041 {
01042 LLSelectNode* selectNode = *iter;
01043 LLViewerObject*cur = selectNode->getObject();
01044 if( cur->permModify() && cur->permMove() && !cur->isAvatar() && !cur->isRootEdit() )
01045 {
01046 const LLVector3& scale = selectNode->mSavedScale;
01047 cur->setScale( scale_factor * scale, FALSE );
01048
01049 if (!selectNode->mIndividualSelection)
01050 {
01051 cur->setPosition(selectNode->mSavedPositionLocal * scale_factor);
01052 }
01053
01054 rebuild(cur);
01055 }
01056 }
01057
01058
01059
01060 mDragPointGlobal = drag_point_global;
01061 }
01062
01063
01064 void LLManipScale::dragFace( S32 x, S32 y )
01065 {
01066
01067 if (x == mLastMouseX && y == mLastMouseY)
01068 {
01069
01070 return;
01071 }
01072
01073 mLastMouseX = x;
01074 mLastMouseY = y;
01075
01076 LLVector3d drag_start_point_global = mDragStartPointGlobal;
01077 LLVector3d drag_start_center_global = mDragStartCenterGlobal;
01078 LLVector3 drag_start_point_agent = gAgent.getPosAgentFromGlobal(drag_start_point_global);
01079 LLVector3 drag_start_center_agent = gAgent.getPosAgentFromGlobal(drag_start_center_global);
01080
01081 LLVector3d drag_start_dir_d;
01082 drag_start_dir_d.setVec(drag_start_point_global - drag_start_center_global);
01083 LLVector3 drag_start_dir_f;
01084 drag_start_dir_f.setVec(drag_start_dir_d);
01085
01086 LLBBox bbox = gSelectMgr->getBBoxOfSelection();
01087
01088 F32 s = 0;
01089 F32 t = 0;
01090
01091 nearestPointOnLineFromMouse(x,
01092 y,
01093 drag_start_center_agent,
01094 drag_start_point_agent,
01095 s, t );
01096
01097 if( s <= 0 )
01098 {
01099 return;
01100 }
01101
01102 LLVector3d drag_point_global = drag_start_center_global + t * drag_start_dir_d;
01103 LLVector3 part_dir_local = partToUnitVector( mManipPart );
01104
01105
01106 LLVector3 mouse_on_plane;
01107 getMousePointOnPlaneAgent(mouse_on_plane, x, y, mScaleCenter, mScalePlaneNormal1 );
01108
01109 LLVector3 mouse_on_scale_line = mScaleCenter + projected_vec(mouse_on_plane - mScaleCenter, mScaleDir);
01110 LLVector3 drag_delta(mouse_on_scale_line - drag_start_point_agent);
01111 F32 max_drag_dist = partToMaxScale(mManipPart, bbox);
01112 F32 min_drag_dist = partToMinScale(mManipPart, bbox);
01113
01114 BOOL uniform = LLManipScale::getUniform();
01115 if( uniform )
01116 {
01117 drag_delta *= 2.f;
01118 }
01119
01120 LLVector3 scale_center_to_mouse = mouse_on_plane - mScaleCenter;
01121 F32 dist_from_scale_line = dist_vec(scale_center_to_mouse, (mouse_on_scale_line - mScaleCenter));
01122 F32 dist_along_scale_line = scale_center_to_mouse * mScaleDir;
01123
01124 BOOL snap_enabled = gSavedSettings.getBOOL("SnapEnabled");
01125
01126 if (snap_enabled && dist_from_scale_line > mSnapRegimeOffset)
01127 {
01128 mInSnapRegime = TRUE;
01129
01130 if (dist_along_scale_line > max_drag_dist)
01131 {
01132 mScaleSnapValue = max_drag_dist;
01133
01134 LLVector3 clamp_point = mScaleCenter + max_drag_dist * mScaleDir;
01135 drag_delta.setVec(clamp_point - drag_start_point_agent);
01136 }
01137 else if (dist_along_scale_line < min_drag_dist)
01138 {
01139 mScaleSnapValue = min_drag_dist;
01140
01141 LLVector3 clamp_point = mScaleCenter + min_drag_dist * mScaleDir;
01142 drag_delta.setVec(clamp_point - drag_start_point_agent);
01143 }
01144 else
01145 {
01146 F32 drag_dist = scale_center_to_mouse * mScaleDir;
01147 F32 cur_subdivisions = llclamp(getSubdivisionLevel(mScaleCenter + mScaleDir * drag_dist, mScaleDir, mScaleSnapUnit1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
01148 F32 snap_dist = mScaleSnapUnit1 / (2.f * cur_subdivisions);
01149 F32 relative_snap_dist = fmodf(drag_dist + snap_dist, mScaleSnapUnit1 / cur_subdivisions);
01150 relative_snap_dist -= snap_dist;
01151
01152
01153
01154
01155
01156
01157 relative_snap_dist = llclamp(relative_snap_dist,
01158 drag_dist - max_drag_dist,
01159 drag_dist - min_drag_dist);
01160
01161 mScaleSnapValue = drag_dist - relative_snap_dist;
01162
01163 if (llabs(relative_snap_dist) < snap_dist)
01164 {
01165 LLVector3 drag_correction = relative_snap_dist * mScaleDir;
01166 if (uniform)
01167 {
01168 drag_correction *= 2.f;
01169 }
01170
01171 drag_delta -= drag_correction;
01172 }
01173 }
01174 }
01175 else
01176 {
01177 mInSnapRegime = FALSE;
01178 }
01179
01180 BOOL send_scale_update = FALSE;
01181 BOOL send_position_update = FALSE;
01182
01183 LLVector3 dir_agent;
01184 if( part_dir_local.mV[VX] )
01185 {
01186 dir_agent = bbox.localToAgentBasis( LLVector3::x_axis );
01187 }
01188 else if( part_dir_local.mV[VY] )
01189 {
01190 dir_agent = bbox.localToAgentBasis( LLVector3::y_axis );
01191 }
01192 else if( part_dir_local.mV[VZ] )
01193 {
01194 dir_agent = bbox.localToAgentBasis( LLVector3::z_axis );
01195 }
01196 stretchFace(
01197 projected_vec(drag_start_dir_f, dir_agent) + drag_start_center_agent,
01198 projected_vec(drag_delta, dir_agent));
01199 send_position_update = TRUE;
01200 send_scale_update = TRUE;
01201
01202 mDragPointGlobal = drag_point_global;
01203 }
01204
01205 void LLManipScale::sendUpdates( BOOL send_position_update, BOOL send_scale_update, BOOL corner )
01206 {
01207
01208 static LLTimer update_timer;
01209 F32 elapsed_time = update_timer.getElapsedTimeF32();
01210 const F32 UPDATE_DELAY = 0.1f;
01211
01212 if( send_scale_update || send_position_update )
01213 {
01214 U32 update_flags = UPD_NONE;
01215 if (send_position_update) update_flags |= UPD_POSITION;
01216 if (send_scale_update) update_flags |= UPD_SCALE;
01217
01218
01219 if (corner)
01220 {
01221 update_flags |= UPD_UNIFORM;
01222 }
01223
01224 mLastUpdateFlags = update_flags;
01225
01226
01227 if( elapsed_time > UPDATE_DELAY && !gSavedSettings.getBOOL("EditLinkedParts") )
01228 {
01229 gSelectMgr->sendMultipleUpdate( update_flags );
01230 update_timer.reset();
01231 mSendUpdateOnMouseUp = FALSE;
01232 }
01233 else
01234 {
01235 mSendUpdateOnMouseUp = TRUE;
01236 }
01237 dialog_refresh_all();
01238 }
01239 }
01240
01241
01242
01243 void LLManipScale::stretchFace( const LLVector3& drag_start_agent, const LLVector3& drag_delta_agent )
01244 {
01245 LLVector3 drag_start_center_agent = gAgent.getPosAgentFromGlobal(mDragStartCenterGlobal);
01246
01247 for (LLObjectSelection::iterator iter = mObjectSelection->begin();
01248 iter != mObjectSelection->end(); iter++)
01249 {
01250 LLSelectNode* selectNode = *iter;
01251 LLViewerObject*cur = selectNode->getObject();
01252 if( cur->permModify() && cur->permMove() && !cur->isAvatar() )
01253 {
01254 LLBBox cur_bbox = cur->getBoundingBoxAgent();
01255 LLVector3 start_local = cur_bbox.agentToLocal( drag_start_agent );
01256 LLVector3 end_local = cur_bbox.agentToLocal( drag_start_agent + drag_delta_agent);
01257 LLVector3 start_center_local = cur_bbox.agentToLocal( drag_start_center_agent );
01258 LLVector3 axis = nearestAxis( start_local - start_center_local );
01259 S32 axis_index = axis.mV[0] ? 0 : (axis.mV[1] ? 1 : 2 );
01260
01261 LLVector3 delta_local = end_local - start_local;
01262 F32 delta_local_mag = delta_local.magVec();
01263 LLVector3 dir_local;
01264 if (delta_local_mag == 0.f)
01265 {
01266 dir_local = axis;
01267 }
01268 else
01269 {
01270 dir_local = delta_local / delta_local_mag;
01271 }
01272
01273 F32 denom = axis * dir_local;
01274 F32 desired_delta_size = is_approx_zero(denom) ? 0.f : (delta_local_mag / denom);
01275 F32 desired_scale = llclamp(selectNode->mSavedScale.mV[axis_index] + desired_delta_size, MIN_OBJECT_SCALE, MAX_OBJECT_SCALE);
01276
01277 desired_delta_size = desired_scale - selectNode->mSavedScale.mV[axis_index];
01278
01279 LLVector3 scale = cur->getScale();
01280 scale.mV[axis_index] = desired_scale;
01281 cur->setScale(scale, FALSE);
01282 rebuild(cur);
01283 LLVector3 delta_pos;
01284 if( !getUniform() )
01285 {
01286 LLVector3 delta_pos_local = axis * (0.5f * desired_delta_size);
01287 LLVector3d delta_pos_global;
01288 delta_pos_global.setVec(cur_bbox.localToAgent( delta_pos_local ) - cur_bbox.getCenterAgent());
01289 LLVector3 cur_pos = cur->getPositionEdit();
01290
01291 if (cur->isRootEdit() && !cur->isAttachment())
01292 {
01293 LLVector3d new_pos_global = gWorldp->clipToVisibleRegions(selectNode->mSavedPositionGlobal, selectNode->mSavedPositionGlobal + delta_pos_global);
01294 cur->setPositionGlobal( new_pos_global );
01295 }
01296 else
01297 {
01298 LLXform* parent_xform = cur->mDrawable->getXform()->getParent();
01299 LLVector3 new_pos_local;
01300
01301 if (parent_xform)
01302 {
01303 new_pos_local = selectNode->mSavedPositionLocal + (LLVector3(delta_pos_global) * ~parent_xform->getWorldRotation());
01304 }
01305 else
01306 {
01307 new_pos_local = selectNode->mSavedPositionLocal + LLVector3(delta_pos_global);
01308 }
01309 cur->setPosition(new_pos_local);
01310 }
01311 delta_pos = cur->getPositionEdit() - cur_pos;
01312 }
01313 if (cur->isRootEdit() && selectNode->mIndividualSelection)
01314 {
01315
01316 for (U32 child_num = 0; child_num < cur->mChildList.size(); child_num++)
01317 {
01318 LLViewerObject* childp = cur->mChildList[child_num];
01319 if (!getUniform())
01320 {
01321 LLVector3 child_pos = childp->getPosition() - (delta_pos * ~cur->getRotationEdit());
01322 childp->setPosition(child_pos);
01323 rebuild(childp);
01324 }
01325 }
01326 }
01327 }
01328 }
01329 }
01330
01331
01332 void LLManipScale::renderGuidelinesPart( const LLBBox& bbox )
01333 {
01334 LLVector3 guideline_start = bbox.getCenterLocal();
01335
01336 LLVector3 guideline_end = unitVectorToLocalBBoxExtent( partToUnitVector( mManipPart ), bbox );
01337
01338 if (!getUniform())
01339 {
01340 guideline_start = unitVectorToLocalBBoxExtent( -partToUnitVector( mManipPart ), bbox );
01341 }
01342
01343 guideline_end -= guideline_start;
01344 guideline_end.normVec();
01345 guideline_end *= gWorldPointer->getRegionWidthInMeters();
01346 guideline_end += guideline_start;
01347
01348 {
01349 LLGLDepthTest gls_depth(GL_TRUE);
01350 gl_stippled_line_3d( guideline_start, guideline_end, LLColor4(1.f, 1.f, 1.f, 0.5f) );
01351 }
01352 {
01353 LLGLDepthTest gls_depth(GL_FALSE);
01354 gl_stippled_line_3d( guideline_start, guideline_end, LLColor4(1.f, 1.f, 1.f, 0.25f) );
01355 }
01356 }
01357
01358 void LLManipScale::updateSnapGuides(const LLBBox& bbox)
01359 {
01360 LLVector3 grid_origin;
01361 LLVector3 grid_scale;
01362 LLQuaternion grid_rotation;
01363 gSelectMgr->getGrid(grid_origin, grid_rotation, grid_scale);
01364
01365 LLVector3 box_corner_agent = bbox.localToAgent(unitVectorToLocalBBoxExtent( partToUnitVector( mManipPart ), bbox ));
01366 mScaleCenter = getUniform() ? bbox.getCenterAgent() : bbox.localToAgent(unitVectorToLocalBBoxExtent( -1.f * partToUnitVector( mManipPart ), bbox ));
01367 mScaleDir = box_corner_agent - mScaleCenter;
01368 mScaleDir.normVec();
01369
01370 if(mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
01371 {
01372 mSnapRegimeOffset = SNAP_GUIDE_SCREEN_OFFSET / gAgent.getAvatarObject()->mHUDCurZoom;
01373
01374 }
01375 else
01376 {
01377 F32 object_distance = dist_vec(mScaleCenter, gCamera->getOrigin());
01378 mSnapRegimeOffset = (SNAP_GUIDE_SCREEN_OFFSET * gViewerWindow->getWindowWidth() * object_distance) / gCamera->getPixelMeterRatio();
01379 }
01380 LLVector3 cam_at_axis;
01381 F32 snap_guide_length;
01382 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
01383 {
01384 cam_at_axis.setVec(1.f, 0.f, 0.f);
01385 snap_guide_length = SNAP_GUIDE_SCREEN_LENGTH / gAgent.getAvatarObject()->mHUDCurZoom;
01386 }
01387 else
01388 {
01389 cam_at_axis = gCamera->getAtAxis();
01390 F32 manipulator_distance = dist_vec(box_corner_agent, gCamera->getOrigin());
01391 snap_guide_length = (SNAP_GUIDE_SCREEN_LENGTH * gViewerWindow->getWindowWidth() * manipulator_distance) / gCamera->getPixelMeterRatio();
01392 }
01393
01394 mSnapGuideLength = snap_guide_length / llmax(0.1f, (llmin(mSnapGuideDir1 * cam_at_axis, mSnapGuideDir2 * cam_at_axis)));
01395
01396 LLVector3 off_axis_dir = mScaleDir % cam_at_axis;
01397 off_axis_dir.normVec();
01398
01399 if( (LL_FACE_MIN <= (S32)mManipPart) && ((S32)mManipPart <= LL_FACE_MAX) )
01400 {
01401 LLVector3 object_scale = bbox.getMaxLocal();
01402 object_scale.scaleVec(off_axis_dir * ~bbox.getRotation());
01403 object_scale.abs();
01404 if (object_scale.mV[VX] > object_scale.mV[VY] && object_scale.mV[VX] > object_scale.mV[VZ])
01405 {
01406 mSnapGuideDir1 = LLVector3::x_axis * bbox.getRotation();
01407 }
01408 else if (object_scale.mV[VY] > object_scale.mV[VZ])
01409 {
01410 mSnapGuideDir1 = LLVector3::y_axis * bbox.getRotation();
01411 }
01412 else
01413 {
01414 mSnapGuideDir1 = LLVector3::z_axis * bbox.getRotation();
01415 }
01416
01417 LLVector3 scale_snap = grid_scale;
01418 mScaleSnapUnit1 = scale_snap.scaleVec(partToUnitVector( mManipPart )).magVec();
01419 mScaleSnapUnit2 = mScaleSnapUnit1;
01420 mSnapGuideDir1 *= mSnapGuideDir1 * gCamera->getUpAxis() > 0.f ? 1.f : -1.f;
01421 mSnapGuideDir2 = mSnapGuideDir1 * -1.f;
01422 mSnapDir1 = mScaleDir;
01423 mSnapDir2 = mScaleDir;
01424 }
01425 else if( (LL_CORNER_MIN <= (S32)mManipPart) && ((S32)mManipPart <= LL_CORNER_MAX) )
01426 {
01427 LLVector3 local_scale_dir = partToUnitVector( mManipPart );
01428 LLVector3 local_camera_dir;
01429 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
01430 {
01431 local_camera_dir = LLVector3(-1.f, 0.f, 0.f) * ~bbox.getRotation();
01432 }
01433 else
01434 {
01435 local_camera_dir = (gCamera->getOrigin() - bbox.getCenterAgent()) * ~bbox.getRotation();
01436 local_camera_dir.normVec();
01437 }
01438 local_scale_dir -= projected_vec(local_scale_dir, local_camera_dir);
01439 local_scale_dir.normVec();
01440 LLVector3 x_axis_proj_camera = LLVector3::x_axis - projected_vec(LLVector3::x_axis, local_camera_dir);
01441 x_axis_proj_camera.normVec();
01442 LLVector3 y_axis_proj_camera = LLVector3::y_axis - projected_vec(LLVector3::y_axis, local_camera_dir);
01443 y_axis_proj_camera.normVec();
01444 LLVector3 z_axis_proj_camera = LLVector3::z_axis - projected_vec(LLVector3::z_axis, local_camera_dir);
01445 z_axis_proj_camera.normVec();
01446 F32 x_axis_proj = llabs(local_scale_dir * x_axis_proj_camera);
01447 F32 y_axis_proj = llabs(local_scale_dir * y_axis_proj_camera);
01448 F32 z_axis_proj = llabs(local_scale_dir * z_axis_proj_camera);
01449
01450 if (x_axis_proj > y_axis_proj && x_axis_proj > z_axis_proj)
01451 {
01452 mSnapGuideDir1 = LLVector3::y_axis;
01453 mScaleSnapUnit2 = grid_scale.mV[VY];
01454 mSnapGuideDir2 = LLVector3::z_axis;
01455 mScaleSnapUnit1 = grid_scale.mV[VZ];
01456 }
01457 else if (y_axis_proj > z_axis_proj)
01458 {
01459 mSnapGuideDir1 = LLVector3::x_axis;
01460 mScaleSnapUnit2 = grid_scale.mV[VX];
01461 mSnapGuideDir2 = LLVector3::z_axis;
01462 mScaleSnapUnit1 = grid_scale.mV[VZ];
01463 }
01464 else
01465 {
01466 mSnapGuideDir1 = LLVector3::x_axis;
01467 mScaleSnapUnit2 = grid_scale.mV[VX];
01468 mSnapGuideDir2 = LLVector3::y_axis;
01469 mScaleSnapUnit1 = grid_scale.mV[VY];
01470 }
01471
01472 LLVector3 snap_guide_flip(1.f, 1.f, 1.f);
01473 switch (mManipPart)
01474 {
01475 case LL_CORNER_NNN:
01476 break;
01477 case LL_CORNER_NNP:
01478 snap_guide_flip.setVec(1.f, 1.f, -1.f);
01479 break;
01480 case LL_CORNER_NPN:
01481 snap_guide_flip.setVec(1.f, -1.f, 1.f);
01482 break;
01483 case LL_CORNER_NPP:
01484 snap_guide_flip.setVec(1.f, -1.f, -1.f);
01485 break;
01486 case LL_CORNER_PNN:
01487 snap_guide_flip.setVec(-1.f, 1.f, 1.f);
01488 break;
01489 case LL_CORNER_PNP:
01490 snap_guide_flip.setVec(-1.f, 1.f, -1.f);
01491 break;
01492 case LL_CORNER_PPN:
01493 snap_guide_flip.setVec(-1.f, -1.f, 1.f);
01494 break;
01495 case LL_CORNER_PPP:
01496 snap_guide_flip.setVec(-1.f, -1.f, -1.f);
01497 break;
01498 default:
01499 break;
01500 }
01501 mSnapGuideDir1.scaleVec(snap_guide_flip);
01502 mSnapGuideDir2.scaleVec(snap_guide_flip);
01503 mSnapGuideDir1.rotVec(bbox.getRotation());
01504 mSnapGuideDir2.rotVec(bbox.getRotation());
01505 mSnapDir1 = -1.f * mSnapGuideDir2;
01506 mSnapDir2 = -1.f * mSnapGuideDir1;
01507 }
01508
01509 mScalePlaneNormal1 = mSnapGuideDir1 % mScaleDir;
01510 mScalePlaneNormal1.normVec();
01511
01512 mScalePlaneNormal2 = mSnapGuideDir2 % mScaleDir;
01513 mScalePlaneNormal2.normVec();
01514
01515 mScaleSnapUnit1 = mScaleSnapUnit1 / (mSnapDir1 * mScaleDir);
01516 mScaleSnapUnit2 = mScaleSnapUnit2 / (mSnapDir2 * mScaleDir);
01517 }
01518
01519 void LLManipScale::renderSnapGuides(const LLBBox& bbox)
01520 {
01521 if (!gSavedSettings.getBOOL("SnapEnabled"))
01522 {
01523 return;
01524 }
01525
01526 F32 max_subdivisions = sGridMaxSubdivisionLevel;
01527 F32 grid_alpha = gSavedSettings.getF32("GridOpacity");
01528
01529 F32 max_point_on_scale_line = partToMaxScale(mManipPart, bbox);
01530 LLVector3 drag_point = gAgent.getPosAgentFromGlobal(mDragPointGlobal);
01531
01532 updateGridSettings();
01533
01534 S32 pass;
01535 for (pass = 0; pass < 3; pass++)
01536 {
01537 LLColor4 tick_color = setupSnapGuideRenderPass(pass);
01538
01539 glBegin(GL_LINES);
01540 LLVector3 line_mid = mScaleCenter + (mScaleSnapValue * mScaleDir) + (mSnapGuideDir1 * mSnapRegimeOffset);
01541 LLVector3 line_start = line_mid - (mScaleDir * (llmin(mScaleSnapValue, mSnapGuideLength * 0.5f)));
01542 LLVector3 line_end = line_mid + (mScaleDir * llmin(max_point_on_scale_line - mScaleSnapValue, mSnapGuideLength * 0.5f));
01543
01544 glColor4f(tick_color.mV[VRED], tick_color.mV[VGREEN], tick_color.mV[VBLUE], tick_color.mV[VALPHA] * 0.1f);
01545 glVertex3fv(line_start.mV);
01546 glColor4fv(tick_color.mV);
01547 glVertex3fv(line_mid.mV);
01548 glVertex3fv(line_mid.mV);
01549 glColor4f(tick_color.mV[VRED], tick_color.mV[VGREEN], tick_color.mV[VBLUE], tick_color.mV[VALPHA] * 0.1f);
01550 glVertex3fv(line_end.mV);
01551
01552 line_mid = mScaleCenter + (mScaleSnapValue * mScaleDir) + (mSnapGuideDir2 * mSnapRegimeOffset);
01553 line_start = line_mid - (mScaleDir * (llmin(mScaleSnapValue, mSnapGuideLength * 0.5f)));
01554 line_end = line_mid + (mScaleDir * llmin(max_point_on_scale_line - mScaleSnapValue, mSnapGuideLength * 0.5f));
01555 glVertex3fv(line_start.mV);
01556 glColor4fv(tick_color.mV);
01557 glVertex3fv(line_mid.mV);
01558 glVertex3fv(line_mid.mV);
01559 glColor4f(tick_color.mV[VRED], tick_color.mV[VGREEN], tick_color.mV[VBLUE], tick_color.mV[VALPHA] * 0.1f);
01560 glVertex3fv(line_end.mV);
01561 glEnd();
01562 }
01563
01564 {
01565 LLGLDepthTest gls_depth(GL_FALSE);
01566
01567 F32 dist_grid_axis = (drag_point - mScaleCenter) * mScaleDir;
01568
01569 F32 grid_offset1 = fmodf(dist_grid_axis, mScaleSnapUnit1 / max_subdivisions);
01570 F32 grid_offset2 = fmodf(dist_grid_axis, mScaleSnapUnit2 / max_subdivisions);
01571
01572
01573 S32 sub_div_offset_1 = llround(fmod(dist_grid_axis - grid_offset1, mScaleSnapUnit1 / sGridMinSubdivisionLevel) / (mScaleSnapUnit1 / max_subdivisions));
01574 S32 sub_div_offset_2 = llround(fmod(dist_grid_axis - grid_offset2, mScaleSnapUnit2 / sGridMinSubdivisionLevel) / (mScaleSnapUnit2 / max_subdivisions));
01575
01576 S32 num_ticks_per_side1 = llmax(1, lltrunc(0.5f * mSnapGuideLength / (mScaleSnapUnit1 / max_subdivisions)));
01577 S32 num_ticks_per_side2 = llmax(1, lltrunc(0.5f * mSnapGuideLength / (mScaleSnapUnit2 / max_subdivisions)));
01578 F32 dist_scale_units_1 = dist_grid_axis / (mScaleSnapUnit1 / max_subdivisions);
01579 F32 dist_scale_units_2 = dist_grid_axis / (mScaleSnapUnit2 / max_subdivisions);
01580 S32 ticks_from_scale_center_1 = lltrunc(dist_scale_units_1);
01581 S32 ticks_from_scale_center_2 = lltrunc(dist_scale_units_2);
01582 S32 max_ticks1 = llceil(max_point_on_scale_line / (mScaleSnapUnit1 / max_subdivisions) - dist_scale_units_1);
01583 S32 max_ticks2 = llceil(max_point_on_scale_line / (mScaleSnapUnit2 / max_subdivisions) - dist_scale_units_2);
01584 S32 start_tick = 0;
01585 S32 stop_tick = 0;
01586
01587 if (mInSnapRegime)
01588 {
01589
01590 glBegin(GL_LINES);
01591 LLVector3 snap_line_center = mScaleCenter + (mScaleSnapValue * mScaleDir);
01592
01593 LLVector3 snap_line_start = snap_line_center + (mSnapGuideDir1 * mSnapRegimeOffset);
01594 LLVector3 snap_line_end = snap_line_center + (mSnapGuideDir2 * mSnapRegimeOffset);
01595
01596 glColor4f(1.f, 1.f, 1.f, grid_alpha);
01597 glVertex3fv(snap_line_start.mV);
01598 glVertex3fv(snap_line_center.mV);
01599 glVertex3fv(snap_line_center.mV);
01600 glVertex3fv(snap_line_end.mV);
01601 glEnd();
01602
01603
01604 glBegin(GL_TRIANGLES);
01605 {
01606
01607 glColor4f(1.f, 1.f, 1.f, grid_alpha);
01608
01609 LLVector3 arrow_dir;
01610 LLVector3 arrow_span = mScaleDir;
01611
01612 arrow_dir = snap_line_start - snap_line_center;
01613 arrow_dir.normVec();
01614 glVertex3fv((snap_line_start + arrow_dir * mBoxHandleSize).mV);
01615 glVertex3fv((snap_line_start + arrow_span * mBoxHandleSize).mV);
01616 glVertex3fv((snap_line_start - arrow_span * mBoxHandleSize).mV);
01617
01618 arrow_dir = snap_line_end - snap_line_center;
01619 arrow_dir.normVec();
01620 glVertex3fv((snap_line_end + arrow_dir * mBoxHandleSize).mV);
01621 glVertex3fv((snap_line_end + arrow_span * mBoxHandleSize).mV);
01622 glVertex3fv((snap_line_end - arrow_span * mBoxHandleSize).mV);
01623 }
01624 glEnd();
01625 }
01626
01627 LLVector2 screen_translate_axis(llabs(mScaleDir * gCamera->getLeftAxis()), llabs(mScaleDir * gCamera->getUpAxis()));
01628 screen_translate_axis.normVec();
01629
01630 S32 tick_label_spacing = llround(screen_translate_axis * sTickLabelSpacing);
01631
01632 for (pass = 0; pass < 3; pass++)
01633 {
01634 LLColor4 tick_color = setupSnapGuideRenderPass(pass);
01635
01636 start_tick = -(llmin(ticks_from_scale_center_1, num_ticks_per_side1));
01637 stop_tick = llmin(max_ticks1, num_ticks_per_side1);
01638
01639 glBegin(GL_LINES);
01640
01641 for (S32 i = start_tick; i <= stop_tick; i++)
01642 {
01643 F32 alpha = (1.f - (1.f * ((F32)llabs(i) / (F32)num_ticks_per_side1)));
01644 LLVector3 tick_pos = drag_point + (mScaleDir * (mScaleSnapUnit1 / max_subdivisions * (F32)i - grid_offset1));
01645
01646 F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
01647
01648 if (fmodf((F32)(i + sub_div_offset_1), (max_subdivisions / cur_subdivisions)) != 0.f)
01649 {
01650 continue;
01651 }
01652
01653 F32 tick_scale = 1.f;
01654 for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f)
01655 {
01656 if (fmodf((F32)(i + sub_div_offset_1), division_level) == 0.f)
01657 {
01658 break;
01659 }
01660 tick_scale *= 0.7f;
01661 }
01662
01663 glColor4f(tick_color.mV[VRED], tick_color.mV[VGREEN], tick_color.mV[VBLUE], tick_color.mV[VALPHA] * alpha);
01664 LLVector3 tick_start = tick_pos + (mSnapGuideDir1 * mSnapRegimeOffset);
01665 LLVector3 tick_end = tick_start + (mSnapGuideDir1 * mSnapRegimeOffset * tick_scale);
01666 glVertex3fv(tick_start.mV);
01667 glVertex3fv(tick_end.mV);
01668 }
01669
01670
01671 start_tick = -(llmin(ticks_from_scale_center_2, num_ticks_per_side2));
01672 stop_tick = llmin(max_ticks2, num_ticks_per_side2);
01673 for (S32 i = start_tick; i <= stop_tick; i++)
01674 {
01675 F32 alpha = (1.f - (1.f * ((F32)llabs(i) / (F32)num_ticks_per_side2)));
01676 LLVector3 tick_pos = drag_point + (mScaleDir * (mScaleSnapUnit2 / max_subdivisions * (F32)i - grid_offset2));
01677
01678 F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit2), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
01679
01680 if (fmodf((F32)(i + sub_div_offset_2), (max_subdivisions / cur_subdivisions)) != 0.f)
01681 {
01682 continue;
01683 }
01684
01685 F32 tick_scale = 1.f;
01686 for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f)
01687 {
01688 if (fmodf((F32)(i + sub_div_offset_2), division_level) == 0.f)
01689 {
01690 break;
01691 }
01692 tick_scale *= 0.7f;
01693 }
01694
01695 glColor4f(tick_color.mV[VRED], tick_color.mV[VGREEN], tick_color.mV[VBLUE], tick_color.mV[VALPHA] * alpha);
01696 LLVector3 tick_start = tick_pos + (mSnapGuideDir2 * mSnapRegimeOffset);
01697 LLVector3 tick_end = tick_start + (mSnapGuideDir2 * mSnapRegimeOffset * tick_scale);
01698 glVertex3fv(tick_start.mV);
01699 glVertex3fv(tick_end.mV);
01700 }
01701 glEnd();
01702 }
01703
01704
01705 start_tick = -(llmin(ticks_from_scale_center_1, num_ticks_per_side1));
01706 stop_tick = llmin(max_ticks1, num_ticks_per_side1);
01707
01708 F32 grid_resolution = mObjectSelection->getSelectType() == SELECT_TYPE_HUD ? 0.25f : llmax(gSavedSettings.getF32("GridResolution"), 0.001f);
01709 S32 label_sub_div_offset_1 = llround(fmod(dist_grid_axis - grid_offset1, mScaleSnapUnit1 * 32.f) / (mScaleSnapUnit1 / max_subdivisions));
01710 S32 label_sub_div_offset_2 = llround(fmod(dist_grid_axis - grid_offset2, mScaleSnapUnit2 * 32.f) / (mScaleSnapUnit2 / max_subdivisions));
01711
01712 for (S32 i = start_tick; i <= stop_tick; i++)
01713 {
01714 F32 tick_scale = 1.f;
01715 F32 alpha = grid_alpha * (1.f - (0.5f * ((F32)llabs(i) / (F32)num_ticks_per_side1)));
01716 LLVector3 tick_pos = drag_point + (mScaleDir * (mScaleSnapUnit1 / max_subdivisions * (F32)i - grid_offset1));
01717
01718 for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f)
01719 {
01720 if (fmodf((F32)(i + label_sub_div_offset_1), division_level) == 0.f)
01721 {
01722 break;
01723 }
01724 tick_scale *= 0.7f;
01725 }
01726
01727 if (fmodf((F32)(i + label_sub_div_offset_1), (max_subdivisions / llmin(sGridMaxSubdivisionLevel, getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit1, tick_label_spacing)))) == 0.f)
01728 {
01729 LLVector3 text_origin = tick_pos +
01730 (mSnapGuideDir1 * mSnapRegimeOffset * (1.f + tick_scale));
01731
01732 EGridMode grid_mode = gSelectMgr->getGridMode();
01733 F32 tick_val;
01734 if (grid_mode == GRID_MODE_WORLD)
01735 {
01736 tick_val = (tick_pos - mScaleCenter) * mScaleDir / (mScaleSnapUnit1 / grid_resolution);
01737 }
01738 else
01739 {
01740 tick_val = (tick_pos - mScaleCenter) * mScaleDir / (mScaleSnapUnit1 * 2.f);
01741 }
01742
01743 if (getUniform())
01744 {
01745 tick_val *= 2.f;
01746 }
01747
01748 F32 text_highlight = 0.8f;
01749
01750 if (is_approx_equal(tick_val, mScaleSnapValue) && mInSnapRegime)
01751 {
01752 text_highlight = 1.f;
01753 }
01754
01755 renderTickValue(text_origin, tick_val, grid_mode == GRID_MODE_WORLD ? "m" : "x", LLColor4(text_highlight, text_highlight, text_highlight, alpha));
01756 }
01757 }
01758
01759
01760 if (mScaleSnapUnit2 != mScaleSnapUnit1)
01761 {
01762 start_tick = -(llmin(ticks_from_scale_center_2, num_ticks_per_side2));
01763 stop_tick = llmin(max_ticks2, num_ticks_per_side2);
01764 for (S32 i = start_tick; i <= stop_tick; i++)
01765 {
01766 F32 tick_scale = 1.f;
01767 F32 alpha = grid_alpha * (1.f - (0.5f * ((F32)llabs(i) / (F32)num_ticks_per_side2)));
01768 LLVector3 tick_pos = drag_point + (mScaleDir * (mScaleSnapUnit2 / max_subdivisions * (F32)i - grid_offset2));
01769
01770 for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f)
01771 {
01772 if (fmodf((F32)(i + label_sub_div_offset_2), division_level) == 0.f)
01773 {
01774 break;
01775 }
01776 tick_scale *= 0.7f;
01777 }
01778
01779 if (fmodf((F32)(i + label_sub_div_offset_2), (max_subdivisions / llmin(max_subdivisions, getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit2, tick_label_spacing)))) == 0.f)
01780 {
01781 LLVector3 text_origin = tick_pos +
01782 (mSnapGuideDir2 * mSnapRegimeOffset * (1.f + tick_scale));
01783
01784 EGridMode grid_mode = gSelectMgr->getGridMode();
01785 F32 tick_val;
01786 if (grid_mode == GRID_MODE_WORLD)
01787 {
01788 tick_val = (tick_pos - mScaleCenter) * mScaleDir / (mScaleSnapUnit2 / grid_resolution);
01789 }
01790 else
01791 {
01792 tick_val = (tick_pos - mScaleCenter) * mScaleDir / (mScaleSnapUnit2 * 2.f);
01793 }
01794
01795 if (getUniform())
01796 {
01797 tick_val *= 2.f;
01798 }
01799
01800 F32 text_highlight = 0.8f;
01801
01802 if (is_approx_equal(tick_val, mScaleSnapValue) && mInSnapRegime)
01803 {
01804 text_highlight = 1.f;
01805 }
01806
01807 renderTickValue(text_origin, tick_val, grid_mode == GRID_MODE_WORLD ? "m" : "x", LLColor4(text_highlight, text_highlight, text_highlight, alpha));
01808 }
01809 }
01810 }
01811
01812
01813
01814 if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD)
01815 {
01816 if (mHelpTextTimer.getElapsedTimeF32() < sHelpTextVisibleTime + sHelpTextFadeTime && sNumTimesHelpTextShown < sMaxTimesShowHelpText)
01817 {
01818 LLVector3 selection_center_start = gSelectMgr->getSavedBBoxOfSelection().getCenterAgent();
01819
01820 LLVector3 offset_dir;
01821 if (mSnapGuideDir1 * gCamera->getAtAxis() > mSnapGuideDir2 * gCamera->getAtAxis())
01822 {
01823 offset_dir = mSnapGuideDir2;
01824 }
01825 else
01826 {
01827 offset_dir = mSnapGuideDir1;
01828 }
01829
01830 LLVector3 help_text_pos = selection_center_start + (mSnapRegimeOffset * 5.f * offset_dir);
01831 const LLFontGL* big_fontp = LLFontGL::sSansSerif;
01832
01833 std::string help_text = "Move mouse cursor over ruler";
01834 LLColor4 help_text_color = LLColor4::white;
01835 help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, grid_alpha, 0.f);
01836 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);
01837 help_text = "to snap to grid";
01838 help_text_pos -= gCamera->getUpAxis() * mSnapRegimeOffset * 0.4f;
01839 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);
01840 }
01841 }
01842 }
01843 }
01844
01845
01846 LLVector3 LLManipScale::partToUnitVector( S32 part ) const
01847 {
01848 if( (LL_FACE_MIN <= part) && (part <= LL_FACE_MAX) )
01849 {
01850 return faceToUnitVector( part );
01851 }
01852 else
01853 if( (LL_CORNER_MIN <= part) && (part <= LL_CORNER_MAX) )
01854 {
01855 return cornerToUnitVector( part );
01856 }
01857 else
01858 if( (LL_EDGE_MIN <= part) && (part <= LL_EDGE_MAX ) )
01859 {
01860 return edgeToUnitVector( part );
01861 }
01862 return LLVector3();
01863 }
01864
01865
01866
01867 LLVector3 LLManipScale::faceToUnitVector( S32 part ) const
01868 {
01869 llassert( (LL_FACE_MIN <= part) && (part <= LL_FACE_MAX) );
01870 switch( part )
01871 {
01872 case LL_FACE_POSX:
01873 return LLVector3( 1.f, 0.f, 0.f );
01874
01875 case LL_FACE_NEGX:
01876 return LLVector3( -1.f, 0.f, 0.f );
01877
01878 case LL_FACE_POSY:
01879 return LLVector3( 0.f, 1.f, 0.f );
01880
01881 case LL_FACE_NEGY:
01882 return LLVector3( 0.f, -1.f, 0.f );
01883
01884 case LL_FACE_POSZ:
01885 return LLVector3( 0.f, 0.f, 1.f );
01886
01887 case LL_FACE_NEGZ:
01888 return LLVector3( 0.f, 0.f, -1.f );
01889 }
01890 return LLVector3();
01891 }
01892
01893
01894
01895 LLVector3 LLManipScale::cornerToUnitVector( S32 part ) const
01896 {
01897 llassert( (LL_CORNER_MIN <= part) && (part <= LL_CORNER_MAX) );
01898 LLVector3 vec;
01899 switch(part)
01900 {
01901 case LL_CORNER_NNN:
01902 vec.setVec(-F_SQRT3, -F_SQRT3, -F_SQRT3);
01903 break;
01904 case LL_CORNER_NNP:
01905 vec.setVec(-F_SQRT3, -F_SQRT3, F_SQRT3);
01906 break;
01907 case LL_CORNER_NPN:
01908 vec.setVec(-F_SQRT3, F_SQRT3, -F_SQRT3);
01909 break;
01910 case LL_CORNER_NPP:
01911 vec.setVec(-F_SQRT3, F_SQRT3, F_SQRT3);
01912 break;
01913 case LL_CORNER_PNN:
01914 vec.setVec(F_SQRT3, -F_SQRT3, -F_SQRT3);
01915 break;
01916 case LL_CORNER_PNP:
01917 vec.setVec(F_SQRT3, -F_SQRT3, F_SQRT3);
01918 break;
01919 case LL_CORNER_PPN:
01920 vec.setVec(F_SQRT3, F_SQRT3, -F_SQRT3);
01921 break;
01922 case LL_CORNER_PPP:
01923 vec.setVec(F_SQRT3, F_SQRT3, F_SQRT3);
01924 break;
01925 default:
01926 vec.clearVec();
01927 }
01928
01929 return vec;
01930 }
01931
01932
01933 LLVector3 LLManipScale::edgeToUnitVector( S32 part ) const
01934 {
01935 llassert( (LL_EDGE_MIN <= part) && (part <= LL_EDGE_MAX) );
01936 part -= LL_EDGE_MIN;
01937 S32 rotation = part >> 2;
01938 LLVector3 v;
01939 v.mV[rotation] = (part & 1) ? F_SQRT2 : -F_SQRT2;
01940 v.mV[(rotation+1) % 3] = (part & 2) ? F_SQRT2 : -F_SQRT2;
01941
01942 return v;
01943 }
01944
01945
01946 LLVector3 LLManipScale::unitVectorToLocalBBoxExtent( const LLVector3& v, const LLBBox& bbox ) const
01947 {
01948 const LLVector3& min = bbox.getMinLocal();
01949 const LLVector3& max = bbox.getMaxLocal();
01950 LLVector3 ctr = bbox.getCenterLocal();
01951
01952 return LLVector3(
01953 v.mV[0] ? (v.mV[0]>0 ? max.mV[0] : min.mV[0] ) : ctr.mV[0],
01954 v.mV[1] ? (v.mV[1]>0 ? max.mV[1] : min.mV[1] ) : ctr.mV[1],
01955 v.mV[2] ? (v.mV[2]>0 ? max.mV[2] : min.mV[2] ) : ctr.mV[2] );
01956 }
01957
01958
01959 F32 LLManipScale::partToMaxScale( S32 part, const LLBBox &bbox ) const
01960 {
01961 F32 max_scale_factor = 0.f;
01962 LLVector3 bbox_extents = unitVectorToLocalBBoxExtent( partToUnitVector( part ), bbox );
01963 bbox_extents.abs();
01964 F32 max_extent = 0.f;
01965 for (U32 i = VX; i <= VZ; i++)
01966 {
01967 if (bbox_extents.mV[i] > max_extent)
01968 {
01969 max_extent = bbox_extents.mV[i];
01970 }
01971 }
01972 max_scale_factor = bbox_extents.magVec() * MAX_OBJECT_SCALE / max_extent;
01973
01974 if (getUniform())
01975 {
01976 max_scale_factor *= 0.5f;
01977 }
01978
01979 return max_scale_factor;
01980 }
01981
01982
01983 F32 LLManipScale::partToMinScale( S32 part, const LLBBox &bbox ) const
01984 {
01985 LLVector3 bbox_extents = unitVectorToLocalBBoxExtent( partToUnitVector( part ), bbox );
01986 bbox_extents.abs();
01987 F32 min_extent = MAX_OBJECT_SCALE;
01988 for (U32 i = VX; i <= VZ; i++)
01989 {
01990 if (bbox_extents.mV[i] > 0.f && bbox_extents.mV[i] < min_extent)
01991 {
01992 min_extent = bbox_extents.mV[i];
01993 }
01994 }
01995 F32 min_scale_factor = bbox_extents.magVec() * MIN_OBJECT_SCALE / min_extent;
01996
01997 if (getUniform())
01998 {
01999 min_scale_factor *= 0.5f;
02000 }
02001
02002 return min_scale_factor;
02003 }
02004
02005
02006 LLVector3 LLManipScale::nearestAxis( const LLVector3& v ) const
02007 {
02008
02009
02010
02011 F32 coords[][3] =
02012 {
02013 { 1.f, 0.f, 0.f },
02014 { 0.f, 1.f, 0.f },
02015 { 0.f, 0.f, 1.f },
02016 {-1.f, 0.f, 0.f },
02017 { 0.f,-1.f, 0.f },
02018 { 0.f, 0.f,-1.f }
02019 };
02020
02021 F32 cosine[6];
02022 cosine[0] = v * LLVector3( coords[0] );
02023 cosine[1] = v * LLVector3( coords[1] );
02024 cosine[2] = v * LLVector3( coords[2] );
02025 cosine[3] = -cosine[0];
02026 cosine[4] = -cosine[1];
02027 cosine[5] = -cosine[2];
02028
02029 F32 greatest_cos = cosine[0];
02030 S32 greatest_index = 0;
02031 for( S32 i=1; i<6; i++ )
02032 {
02033 if( greatest_cos < cosine[i] )
02034 {
02035 greatest_cos = cosine[i];
02036 greatest_index = i;
02037 }
02038 }
02039
02040 return LLVector3( coords[greatest_index] );
02041 }
02042
02043
02044 BOOL LLManipScale::canAffectSelection()
02045 {
02046
02047
02048 BOOL can_scale = mObjectSelection->getObjectCount() != 0;
02049 if (can_scale)
02050 {
02051 struct f : public LLSelectedObjectFunctor
02052 {
02053 virtual bool apply(LLViewerObject* objectp)
02054 {
02055 return objectp->permModify() && objectp->permMove() && !objectp->isSeat();
02056 }
02057 } func;
02058 can_scale = mObjectSelection->applyToObjects(&func);
02059 }
02060 return can_scale;
02061 }