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