00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llmaniprotate.h"
00035
00036
00037 #include "llmath.h"
00038 #include "llgl.h"
00039 #include "llglimmediate.h"
00040 #include "v4color.h"
00041 #include "llprimitive.h"
00042 #include "llview.h"
00043 #include "llfontgl.h"
00044
00045
00046 #include "llagent.h"
00047 #include "llbox.h"
00048 #include "llbutton.h"
00049 #include "llviewercontrol.h"
00050 #include "llcriticaldamp.h"
00051 #include "llhoverview.h"
00052 #include "llfloatertools.h"
00053 #include "llselectmgr.h"
00054 #include "llstatusbar.h"
00055 #include "llui.h"
00056 #include "llvoavatar.h"
00057 #include "llviewercamera.h"
00058 #include "llviewerobject.h"
00059 #include "llviewerobject.h"
00060 #include "llviewerwindow.h"
00061 #include "llworld.h"
00062 #include "pipeline.h"
00063 #include "lldrawable.h"
00064 #include "llglheaders.h"
00065
00066 const F32 RADIUS_PIXELS = 100.f;
00067 const F32 SQ_RADIUS = RADIUS_PIXELS * RADIUS_PIXELS;
00068 const F32 WIDTH_PIXELS = 8;
00069 const S32 CIRCLE_STEPS = 100;
00070 const F32 DELTA = F_TWO_PI / CIRCLE_STEPS;
00071 const F32 SIN_DELTA = sin( DELTA );
00072 const F32 COS_DELTA = cos( DELTA );
00073 const F32 MAX_MANIP_SELECT_DISTANCE = 100.f;
00074 const F32 SNAP_ANGLE_INCREMENT = 5.625f;
00075 const F32 SNAP_ANGLE_DETENTE = SNAP_ANGLE_INCREMENT;
00076 const F32 SNAP_GUIDE_RADIUS_1 = 2.8f;
00077 const F32 SNAP_GUIDE_RADIUS_2 = 2.4f;
00078 const F32 SNAP_GUIDE_RADIUS_3 = 2.2f;
00079 const F32 SNAP_GUIDE_RADIUS_4 = 2.1f;
00080 const F32 SNAP_GUIDE_RADIUS_5 = 2.05f;
00081 const F32 SNAP_GUIDE_INNER_RADIUS = 2.f;
00082 const F32 AXIS_ONTO_CAM_TOLERANCE = cos( 80.f * DEG_TO_RAD );
00083 const F32 SELECTED_MANIPULATOR_SCALE = 1.05f;
00084 const F32 MANIPULATOR_SCALE_HALF_LIFE = 0.07f;
00085
00086 extern void handle_reset_rotation(void*);
00087
00088 LLManipRotate::LLManipRotate( LLToolComposite* composite )
00089 : LLManip( "Rotate", composite ),
00090 mRotationCenter(),
00091 mCenterScreen(),
00092 mRotation(),
00093 mMouseDown(),
00094 mMouseCur(),
00095 mRadiusMeters(0.f),
00096 mCenterToCam(),
00097 mCenterToCamNorm(),
00098 mCenterToCamMag(0.f),
00099 mCenterToProfilePlane(),
00100 mCenterToProfilePlaneMag(0.f),
00101 mManipPart( LL_NO_PART ),
00102 mSendUpdateOnMouseUp( FALSE ),
00103 mSmoothRotate( FALSE ),
00104 mCamEdgeOn(FALSE),
00105 mManipulatorScales(1.f, 1.f, 1.f, 1.f)
00106 { }
00107
00108 void LLManipRotate::handleSelect()
00109 {
00110
00111 LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
00112 gFloaterTools->setStatusText("rotate");
00113 LLManip::handleSelect();
00114 }
00115
00116 void LLManipRotate::handleDeselect()
00117 {
00118 mHighlightedPart = LL_NO_PART;
00119 mManipPart = LL_NO_PART;
00120 LLManip::handleDeselect();
00121 }
00122
00123 void LLManipRotate::render()
00124 {
00125 LLGLSUIDefault gls_ui;
00126 LLGLSNoTexture gls_no_texture;
00127 LLGLDepthTest gls_depth(GL_TRUE);
00128 LLGLEnable gl_blend(GL_BLEND);
00129 LLGLEnable gls_alpha_test(GL_ALPHA_TEST);
00130
00131
00132 LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(TRUE);
00133 if( !first_object )
00134 {
00135 return;
00136 }
00137
00138 if( !updateVisiblity() )
00139 {
00140 return;
00141 }
00142
00143 glMatrixMode(GL_MODELVIEW);
00144 glPushMatrix();
00145 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
00146 {
00147 F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
00148 glScalef(zoom, zoom, zoom);
00149 }
00150
00151
00152 LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter );
00153
00154 LLColor4 highlight_outside( 1.f, 1.f, 0.f, 1.f );
00155 LLColor4 highlight_inside( 0.7f, 0.7f, 0.f, 0.5f );
00156 F32 width_meters = WIDTH_PIXELS * mRadiusMeters / RADIUS_PIXELS;
00157
00158 glPushMatrix();
00159 {
00160
00161 if (mManipPart >= LL_ROT_X && mManipPart <= LL_ROT_Z)
00162 {
00163 renderSnapGuides();
00164 }
00165 else
00166 {
00167 LLGLEnable cull_face(GL_CULL_FACE);
00168 LLGLDepthTest gls_depth(GL_FALSE);
00169 glPushMatrix();
00170 {
00171
00172 glTranslatef( mCenterToProfilePlane.mV[VX], mCenterToProfilePlane.mV[VY], mCenterToProfilePlane.mV[VZ] );
00173 glTranslatef( center.mV[VX], center.mV[VY], center.mV[VZ] );
00174
00175
00176 LLVector3 forward = mCenterToCamNorm;
00177 LLVector3 left = gAgent.getUpAxis() % forward;
00178 left.normVec();
00179 LLVector3 up = forward % left;
00180
00181 LLVector4 a(-forward);
00182 a.mV[3] = 0;
00183 LLVector4 b(up);
00184 b.mV[3] = 0;
00185 LLVector4 c(left);
00186 c.mV[3] = 0;
00187 LLMatrix4 mat;
00188 mat.initRows(a, b, c, LLVector4(0.f, 0.f, 0.f, 1.f));
00189
00190 glMultMatrixf( &mat.mMatrix[0][0] );
00191
00192 glRotatef( -90, 0.f, 1.f, 0.f);
00193 LLColor4 color;
00194 if (mManipPart == LL_ROT_ROLL || mHighlightedPart == LL_ROT_ROLL)
00195 {
00196 color.setVec(0.8f, 0.8f, 0.8f, 0.8f);
00197 glScalef(mManipulatorScales.mV[VW], mManipulatorScales.mV[VW], mManipulatorScales.mV[VW]);
00198 }
00199 else
00200 {
00201 color.setVec( 0.7f, 0.7f, 0.7f, 0.6f );
00202 }
00203 gl_washer_2d(mRadiusMeters + width_meters, mRadiusMeters, CIRCLE_STEPS, color, color);
00204
00205
00206 if (mManipPart == LL_NO_PART)
00207 {
00208 gGL.color4f( 0.7f, 0.7f, 0.7f, 0.3f );
00209 gl_circle_2d( 0, 0, mRadiusMeters, CIRCLE_STEPS, TRUE );
00210 }
00211
00212 GLdouble plane_eqn[] = { 0, 0, 1, 0 };
00213 glClipPlane( GL_CLIP_PLANE0, plane_eqn );
00214 }
00215 glPopMatrix();
00216 }
00217
00218 glTranslatef( center.mV[VX], center.mV[VY], center.mV[VZ] );
00219
00220 LLQuaternion rot;
00221 F32 angle_radians, x, y, z;
00222
00223 LLVector3 grid_origin;
00224 LLVector3 grid_scale;
00225 LLQuaternion grid_rotation;
00226
00227 LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale);
00228
00229 grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z);
00230 glRotatef(angle_radians * RAD_TO_DEG, x, y, z);
00231
00232
00233 if (mManipPart == LL_ROT_Z)
00234 {
00235 mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE));
00236 glPushMatrix();
00237 {
00238
00239 glScalef(mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ]);
00240 renderActiveRing( mRadiusMeters, width_meters, LLColor4( 0.f, 0.f, 1.f, 1.f) , LLColor4( 0.f, 0.f, 1.f, 0.3f ));
00241 }
00242 glPopMatrix();
00243 }
00244 else if (mManipPart == LL_ROT_Y)
00245 {
00246 mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE));
00247 glPushMatrix();
00248 {
00249 glRotatef( 90.f, 1.f, 0.f, 0.f );
00250 glScalef(mManipulatorScales.mV[VY], mManipulatorScales.mV[VY], mManipulatorScales.mV[VY]);
00251 renderActiveRing( mRadiusMeters, width_meters, LLColor4( 0.f, 1.f, 0.f, 1.f), LLColor4( 0.f, 1.f, 0.f, 0.3f));
00252 }
00253 glPopMatrix();
00254 }
00255 else if (mManipPart == LL_ROT_X)
00256 {
00257 mManipulatorScales = lerp(mManipulatorScales, LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE));
00258 glPushMatrix();
00259 {
00260 glRotatef( 90.f, 0.f, 1.f, 0.f );
00261 glScalef(mManipulatorScales.mV[VX], mManipulatorScales.mV[VX], mManipulatorScales.mV[VX]);
00262 renderActiveRing( mRadiusMeters, width_meters, LLColor4( 1.f, 0.f, 0.f, 1.f), LLColor4( 1.f, 0.f, 0.f, 0.3f));
00263 }
00264 glPopMatrix();
00265 }
00266 else if (mManipPart == LL_ROT_ROLL)
00267 {
00268 mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE));
00269 }
00270 else if (mManipPart == LL_NO_PART)
00271 {
00272 if (mHighlightedPart == LL_NO_PART)
00273 {
00274 mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE));
00275 }
00276
00277 LLGLEnable cull_face(GL_CULL_FACE);
00278 LLGLEnable clip_plane0(GL_CLIP_PLANE0);
00279 LLGLDepthTest gls_depth(GL_FALSE);
00280
00281
00282 for( S32 i=0; i<2; i++ )
00283 {
00284 glPushMatrix();
00285 {
00286 if (mHighlightedPart == LL_ROT_Z)
00287 {
00288 mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE));
00289 glScalef(mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ]);
00290
00291 gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 0.f, 1.f, 1.f ), LLColor4( 0.f, 0.f, 1.f, 0.5f ), CIRCLE_STEPS, i);
00292 }
00293 else
00294 {
00295
00296 gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 0.f, 0.8f, 0.8f ), LLColor4( 0.f, 0.f, 0.8f, 0.4f ), CIRCLE_STEPS, i);
00297 }
00298 }
00299 glPopMatrix();
00300
00301 glPushMatrix();
00302 {
00303 glRotatef( 90.f, 1.f, 0.f, 0.f );
00304 if (mHighlightedPart == LL_ROT_Y)
00305 {
00306 mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE));
00307 glScalef(mManipulatorScales.mV[VY], mManipulatorScales.mV[VY], mManipulatorScales.mV[VY]);
00308
00309 gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 1.f, 0.f, 1.f ), LLColor4( 0.f, 1.f, 0.f, 0.5f ), CIRCLE_STEPS, i);
00310 }
00311 else
00312 {
00313
00314 gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 0.8f, 0.f, 0.8f ), LLColor4( 0.f, 0.8f, 0.f, 0.4f ), CIRCLE_STEPS, i);
00315 }
00316 }
00317 glPopMatrix();
00318
00319 glPushMatrix();
00320 {
00321 glRotatef( 90.f, 0.f, 1.f, 0.f );
00322 if (mHighlightedPart == LL_ROT_X)
00323 {
00324 mManipulatorScales = lerp(mManipulatorScales, LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE));
00325 glScalef(mManipulatorScales.mV[VX], mManipulatorScales.mV[VX], mManipulatorScales.mV[VX]);
00326
00327
00328 gl_ring( mRadiusMeters, width_meters, LLColor4( 1.f, 0.f, 0.f, 1.f ), LLColor4( 1.f, 0.f, 0.f, 0.5f ), CIRCLE_STEPS, i);
00329 }
00330 else
00331 {
00332
00333 gl_ring( mRadiusMeters, width_meters, LLColor4( 0.8f, 0.f, 0.f, 0.8f ), LLColor4( 0.8f, 0.f, 0.f, 0.4f ), CIRCLE_STEPS, i);
00334 }
00335 }
00336 glPopMatrix();
00337
00338 if (mHighlightedPart == LL_ROT_ROLL)
00339 {
00340 mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE));
00341 }
00342 }
00343 }
00344 }
00345 glPopMatrix();
00346 glPopMatrix();
00347
00348 LLVector3 euler_angles;
00349 LLQuaternion object_rot = first_object->getRotationEdit();
00350 object_rot.getEulerAngles(&(euler_angles.mV[VX]), &(euler_angles.mV[VY]), &(euler_angles.mV[VZ]));
00351 euler_angles *= RAD_TO_DEG;
00352 euler_angles.mV[VX] = llround(fmodf(euler_angles.mV[VX] + 360.f, 360.f), 0.05f);
00353 euler_angles.mV[VY] = llround(fmodf(euler_angles.mV[VY] + 360.f, 360.f), 0.05f);
00354 euler_angles.mV[VZ] = llround(fmodf(euler_angles.mV[VZ] + 360.f, 360.f), 0.05f);
00355
00356 renderXYZ(euler_angles);
00357 }
00358
00359 BOOL LLManipRotate::handleMouseDown(S32 x, S32 y, MASK mask)
00360 {
00361 BOOL handled = FALSE;
00362
00363 LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(TRUE);
00364 if( first_object )
00365 {
00366 LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
00367 if( hit_obj && mHighlightedPart != LL_NO_PART )
00368 {
00369 handled = handleMouseDownOnPart( x, y, mask );
00370 }
00371 }
00372
00373 return handled;
00374 }
00375
00376
00377 BOOL LLManipRotate::handleMouseDownOnPart( S32 x, S32 y, MASK mask )
00378 {
00379 BOOL can_rotate = canAffectSelection();
00380 if (!can_rotate)
00381 {
00382 return FALSE;
00383 }
00384
00385 highlightManipulators(x, y);
00386 S32 hit_part = mHighlightedPart;
00387
00388 LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_ROTATE);
00389
00390
00391 mRotationCenter = gAgent.getPosGlobalFromAgent( getPivotPoint() );
00392
00393 mManipPart = (EManipPart)hit_part;
00394 LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter );
00395
00396 if( mManipPart == LL_ROT_GENERAL)
00397 {
00398 mMouseDown = intersectMouseWithSphere( x, y, center, mRadiusMeters);
00399 }
00400 else
00401 {
00402
00403 LLVector3 axis = getConstraintAxis();
00404
00405 F32 axis_onto_cam = llabs( axis * mCenterToCamNorm );
00406 const F32 AXIS_ONTO_CAM_TOL = cos( 85.f * DEG_TO_RAD );
00407 if( axis_onto_cam < AXIS_ONTO_CAM_TOL )
00408 {
00409 LLVector3 up_from_axis = mCenterToCamNorm % axis;
00410 up_from_axis.normVec();
00411 LLVector3 cur_intersection;
00412 getMousePointOnPlaneAgent(cur_intersection, x, y, center, mCenterToCam);
00413 cur_intersection -= center;
00414 mMouseDown = projected_vec(cur_intersection, up_from_axis);
00415 F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters;
00416 F32 mouse_dist_sqrd = mMouseDown.magVecSquared();
00417 if (mouse_dist_sqrd > 0.0001f)
00418 {
00419 mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) -
00420 mouse_dist_sqrd);
00421 }
00422 LLVector3 projected_center_to_cam = mCenterToCamNorm - projected_vec(mCenterToCamNorm, axis);
00423 mMouseDown += mouse_depth * projected_center_to_cam;
00424
00425 }
00426 else
00427 {
00428 mMouseDown = findNearestPointOnRing( x, y, center, axis ) - center;
00429 mMouseDown.normVec();
00430 }
00431 }
00432
00433 mMouseCur = mMouseDown;
00434
00435
00436 setMouseCapture( TRUE );
00437 LLSelectMgr::getInstance()->enableSilhouette(FALSE);
00438 return TRUE;
00439 }
00440
00441
00442 LLVector3 LLManipRotate::findNearestPointOnRing( S32 x, S32 y, const LLVector3& center, const LLVector3& axis )
00443 {
00444
00445 LLVector3 proj_onto_ring;
00446 getMousePointOnPlaneAgent(proj_onto_ring, x, y, center, axis);
00447 proj_onto_ring -= center;
00448 proj_onto_ring.normVec();
00449
00450 return center + proj_onto_ring * mRadiusMeters;
00451 }
00452
00453 BOOL LLManipRotate::handleMouseUp(S32 x, S32 y, MASK mask)
00454 {
00455
00456 handleHover(x, y, mask);
00457
00458 if( hasMouseCapture() )
00459 {
00460 mManipPart = LL_NO_PART;
00461
00462
00463 LLSelectMgr::getInstance()->sendMultipleUpdate( UPD_ROTATION | UPD_POSITION );
00464 LLSelectMgr::getInstance()->enableSilhouette(TRUE);
00465
00466
00467 LLSelectMgr::getInstance()->updateSelectionCenter();
00468 LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
00469 }
00470
00471 return LLManip::handleMouseUp(x, y, mask);
00472 }
00473
00474
00475 BOOL LLManipRotate::handleHover(S32 x, S32 y, MASK mask)
00476 {
00477 if( hasMouseCapture() )
00478 {
00479 if( mObjectSelection->isEmpty() )
00480 {
00481
00482 setMouseCapture( FALSE );
00483 }
00484 else
00485 {
00486 drag(x, y);
00487 }
00488
00489 lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipRotate (active)" << llendl;
00490 }
00491 else
00492 {
00493 highlightManipulators(x, y);
00494 lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipRotate (inactive)" << llendl;
00495 }
00496
00497 gViewerWindow->setCursor(UI_CURSOR_TOOLROTATE);
00498 return TRUE;
00499 }
00500
00501
00502 LLVector3 LLManipRotate::projectToSphere( F32 x, F32 y, BOOL* on_sphere )
00503 {
00504 F32 z = 0.f;
00505 F32 dist_squared = x*x + y*y;
00506
00507 *on_sphere = dist_squared <= SQ_RADIUS;
00508 if( *on_sphere )
00509 {
00510 z = sqrt(SQ_RADIUS - dist_squared);
00511 }
00512 return LLVector3( x, y, z );
00513 }
00514
00515
00516 void LLManipRotate::drag( S32 x, S32 y )
00517 {
00518 if( !updateVisiblity() )
00519 {
00520 return;
00521 }
00522
00523 if( mManipPart == LL_ROT_GENERAL )
00524 {
00525 mRotation = dragUnconstrained(x, y);
00526 }
00527 else
00528 {
00529 mRotation = dragConstrained(x, y);
00530 }
00531
00532 BOOL damped = mSmoothRotate;
00533 mSmoothRotate = FALSE;
00534
00535 for (LLObjectSelection::iterator iter = mObjectSelection->begin();
00536 iter != mObjectSelection->end(); iter++)
00537 {
00538 LLSelectNode* selectNode = *iter;
00539 LLViewerObject* object = selectNode->getObject();
00540
00541
00542 if (object->permMove() && (object->isRootEdit() || selectNode->mIndividualSelection))
00543 {
00544 if (!object->isRootEdit())
00545 {
00546
00547 LLViewerObject* editable_root = (LLViewerObject*)object->getParent();
00548 if (editable_root->isSelected())
00549 {
00550
00551 continue;
00552 }
00553 }
00554
00555 LLQuaternion new_rot = selectNode->mSavedRotation * mRotation;
00556 std::vector<LLVector3> child_positions;
00557 std::vector<LLQuaternion> child_rotations;
00558 if (object->isRootEdit() && selectNode->mIndividualSelection)
00559 {
00560 for (U32 i = 0; i < object->mChildList.size(); i++)
00561 {
00562 LLViewerObject* childp = object->mChildList[i];
00563 child_positions.push_back(childp->getPositionEdit());
00564 child_rotations.push_back(childp->getRotationEdit());
00565 }
00566 }
00567
00568 if (object->getParent() && object->mDrawable.notNull())
00569 {
00570 LLQuaternion invParentRotation = object->mDrawable->mXform.getParent()->getWorldRotation();
00571 invParentRotation.transQuat();
00572
00573 object->setRotation(new_rot * invParentRotation, damped);
00574 rebuild(object);
00575 }
00576 else
00577 {
00578 object->setRotation(new_rot, damped);
00579 rebuild(object);
00580 }
00581
00582
00583 if (object->isRootEdit() && selectNode->mIndividualSelection)
00584 {
00585
00586
00587 for (U32 i = 0; i < object->mChildList.size(); i++)
00588 {
00589 LLViewerObject* childp = object->mChildList[i];
00590 LLVector3 child_offset = ((child_positions[i] - object->getPositionEdit()) * ~object->getRotationEdit()) - childp->getPosition();
00591 if (!childp->isSelected() && childp->mDrawable.notNull())
00592 {
00593 childp->setRotation(child_rotations[i] * ~object->getRotationEdit());
00594 childp->setPosition((child_positions[i] - object->getPositionEdit()) * ~object->getRotationEdit());
00595 rebuild(childp);
00596 }
00597 }
00598 }
00599 }
00600 }
00601
00602
00603 for (LLObjectSelection::iterator iter = mObjectSelection->begin();
00604 iter != mObjectSelection->end(); iter++)
00605 {
00606 LLSelectNode* selectNode = *iter;
00607 LLViewerObject* object = selectNode->getObject();
00608
00609
00610 if (object && object->permMove())
00611 {
00612 LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter );
00613
00614 LLVector3 old_position;
00615 LLVector3 new_position;
00616
00617 if (object->isAttachment() && object->mDrawable.notNull())
00618 {
00619
00620
00621 LLXform* parent_xform = object->mDrawable->getXform()->getParent();
00622 new_position = (selectNode->mSavedPositionLocal * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition();
00623 old_position = (object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition();
00624 }
00625 else
00626 {
00627 new_position = gAgent.getPosAgentFromGlobal( selectNode->mSavedPositionGlobal );
00628 old_position = object->getPositionAgent();
00629 }
00630
00631 new_position = (new_position - center) * mRotation;
00632 new_position += center;
00633
00634 if (object->isRootEdit() && !object->isAttachment())
00635 {
00636 LLVector3d new_pos_global = gAgent.getPosGlobalFromAgent(new_position);
00637 new_pos_global = LLWorld::getInstance()->clipToVisibleRegions(selectNode->mSavedPositionGlobal, new_pos_global);
00638 new_position = gAgent.getPosAgentFromGlobal(new_pos_global);
00639 }
00640
00641
00642 if (!object->isRootEdit() && selectNode->mIndividualSelection)
00643 {
00644 LLViewerObject* parentp = (LLViewerObject*)object->getParent();
00645 if (!parentp->isSelected())
00646 {
00647 if (object->isAttachment() && object->mDrawable.notNull())
00648 {
00649
00650 object->setPosition((new_position - parentp->getRenderPosition()) * ~parentp->getRenderRotation());
00651 rebuild(object);
00652 }
00653 else
00654 {
00655 object->setPositionParent((new_position - parentp->getPositionAgent()) * ~parentp->getRotationRegion());
00656 rebuild(object);
00657 }
00658 }
00659 }
00660 else if (object->isRootEdit())
00661 {
00662 if (object->isAttachment() && object->mDrawable.notNull())
00663 {
00664 LLXform* parent_xform = object->mDrawable->getXform()->getParent();
00665 object->setPosition((new_position - parent_xform->getWorldPosition()) * ~parent_xform->getWorldRotation());
00666 rebuild(object);
00667 }
00668 else
00669 {
00670 object->setPositionAgent(new_position);
00671 rebuild(object);
00672 }
00673 }
00674
00675
00676 if (object->isRootEdit() && selectNode->mIndividualSelection)
00677 {
00678
00679 LLVector3 child_offset;
00680 if (object->isAttachment() && object->mDrawable.notNull())
00681 {
00682 LLXform* attachment_point_xform = object->mDrawable->getXform()->getParent();
00683 LLQuaternion parent_rotation = object->getRotation() * attachment_point_xform->getWorldRotation();
00684 child_offset = LLVector3(old_position - new_position) * ~parent_rotation;
00685 }
00686 else
00687 {
00688 child_offset = LLVector3(old_position - new_position) * ~object->getRenderRotation();
00689 }
00690
00691 rebuild(object);
00692 for (U32 i = 0; i < object->mChildList.size(); i++)
00693 {
00694 LLViewerObject* childp = object->mChildList[i];
00695 if (!childp->isSelected() && childp->mDrawable.notNull())
00696 {
00697 childp->setPosition(childp->getPosition() + child_offset);
00698 rebuild(childp);
00699 }
00700 }
00701 }
00702 }
00703 }
00704
00705
00706 for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin();
00707 iter != LLSelectMgr::getInstance()->getSelection()->end(); iter++)
00708 {
00709 LLSelectNode* selectNode = *iter;
00710 LLViewerObject*cur = selectNode->getObject();
00711 if( cur->permModify() && cur->permMove() && !cur->isAvatar())
00712 {
00713 selectNode->mLastRotation = cur->getRotation();
00714 selectNode->mLastPositionLocal = cur->getPosition();
00715 }
00716 }
00717
00718 LLSelectMgr::getInstance()->updateSelectionCenter();
00719
00720
00721 gAgent.clearFocusObject();
00722 dialog_refresh_all();
00723 }
00724
00725 void LLManipRotate::renderActiveRing( F32 radius, F32 width, const LLColor4& front_color, const LLColor4& back_color)
00726 {
00727 LLGLEnable cull_face(GL_CULL_FACE);
00728 {
00729 gl_ring(radius, width, back_color, back_color * 0.5f, CIRCLE_STEPS, FALSE);
00730 gl_ring(radius, width, back_color, back_color * 0.5f, CIRCLE_STEPS, TRUE);
00731 }
00732 {
00733 LLGLDepthTest gls_depth(GL_FALSE);
00734 gl_ring(radius, width, front_color, front_color * 0.5f, CIRCLE_STEPS, FALSE);
00735 gl_ring(radius, width, front_color, front_color * 0.5f, CIRCLE_STEPS, TRUE);
00736 }
00737 }
00738
00739 void LLManipRotate::renderSnapGuides()
00740 {
00741 LLVector3 grid_origin;
00742 LLVector3 grid_scale;
00743 LLQuaternion grid_rotation;
00744 LLVector3 constraint_axis = getConstraintAxis();
00745
00746 LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale);
00747
00748 if (!gSavedSettings.getBOOL("SnapEnabled"))
00749 {
00750 return;
00751 }
00752
00753 LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter );
00754 LLVector3 cam_at_axis;
00755 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
00756 {
00757 cam_at_axis.setVec(1.f, 0.f, 0.f);
00758 }
00759 else
00760 {
00761 cam_at_axis = center - gAgent.getCameraPositionAgent();
00762 cam_at_axis.normVec();
00763 }
00764
00765 LLVector3 world_snap_axis;
00766 LLVector3 test_axis = constraint_axis;
00767
00768 BOOL constrain_to_ref_object = FALSE;
00769 if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
00770 {
00771 test_axis = test_axis * ~grid_rotation;
00772 }
00773 else if (LLSelectMgr::getInstance()->getGridMode() == GRID_MODE_REF_OBJECT)
00774 {
00775 test_axis = test_axis * ~grid_rotation;
00776 constrain_to_ref_object = TRUE;
00777 }
00778
00779 test_axis.abs();
00780
00781
00782 if (test_axis.mV[VX] > test_axis.mV[VY] && test_axis.mV[VX] > test_axis.mV[VZ])
00783 {
00784 world_snap_axis = LLVector3::y_axis;
00785 }
00786 else if (test_axis.mV[VY] > test_axis.mV[VZ])
00787 {
00788 world_snap_axis = LLVector3::z_axis;
00789 }
00790 else
00791 {
00792 world_snap_axis = LLVector3::x_axis;
00793 }
00794
00795 LLVector3 projected_snap_axis = world_snap_axis;
00796 if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
00797 {
00798 projected_snap_axis = projected_snap_axis * grid_rotation;
00799 }
00800 else if (constrain_to_ref_object)
00801 {
00802 projected_snap_axis = projected_snap_axis * grid_rotation;
00803 }
00804
00805
00806 projected_snap_axis -= projected_vec(projected_snap_axis, constraint_axis);
00807 projected_snap_axis.normVec();
00808
00809 S32 num_rings = mCamEdgeOn ? 2 : 1;
00810 for (S32 ring_num = 0; ring_num < num_rings; ring_num++)
00811 {
00812 LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter );
00813
00814 if (mCamEdgeOn)
00815 {
00816
00817 if (ring_num == 0)
00818 {
00819 center += constraint_axis * mRadiusMeters * 0.5f;
00820 }
00821 else
00822 {
00823 center -= constraint_axis * mRadiusMeters * 0.5f;
00824 }
00825 }
00826
00827 LLGLDepthTest gls_depth(GL_FALSE);
00828 for (S32 pass = 0; pass < 3; pass++)
00829 {
00830
00831 glPushMatrix();
00832
00833 LLQuaternion snap_guide_rot;
00834 F32 angle_radians, x, y, z;
00835 snap_guide_rot.shortestArc(LLVector3::z_axis, getConstraintAxis());
00836 snap_guide_rot.getAngleAxis(&angle_radians, &x, &y, &z);
00837 glTranslatef(center.mV[VX], center.mV[VY], center.mV[VZ]);
00838 glRotatef(angle_radians * RAD_TO_DEG, x, y, z);
00839
00840 LLColor4 line_color = setupSnapGuideRenderPass(pass);
00841
00842 gGL.color4fv(line_color.mV);
00843
00844 if (mCamEdgeOn)
00845 {
00846
00847 LLVector3 edge_normal = cam_at_axis % constraint_axis;
00848 edge_normal.normVec();
00849 LLVector3 x_axis_snap = LLVector3::x_axis * snap_guide_rot;
00850 LLVector3 y_axis_snap = LLVector3::y_axis * snap_guide_rot;
00851
00852 F32 end_angle = atan2(y_axis_snap * edge_normal, x_axis_snap * edge_normal);
00853
00854 F32 start_angle = end_angle - F_PI;
00855 gl_arc_2d(0.f, 0.f, mRadiusMeters * SNAP_GUIDE_INNER_RADIUS, CIRCLE_STEPS, FALSE, start_angle, end_angle);
00856 }
00857 else
00858 {
00859 gl_circle_2d(0.f, 0.f, mRadiusMeters * SNAP_GUIDE_INNER_RADIUS, CIRCLE_STEPS, FALSE);
00860 }
00861 glPopMatrix();
00862
00863 for (S32 i = 0; i < 64; i++)
00864 {
00865 BOOL render_text = TRUE;
00866 F32 deg = 5.625f * (F32)i;
00867 LLVector3 inner_point;
00868 LLVector3 outer_point;
00869 LLVector3 text_point;
00870 LLQuaternion rot(deg * DEG_TO_RAD, constraint_axis);
00871 gGL.begin(LLVertexBuffer::LINES);
00872 {
00873 inner_point = (projected_snap_axis * mRadiusMeters * SNAP_GUIDE_INNER_RADIUS * rot) + center;
00874 F32 tick_length = 0.f;
00875 if (i % 16 == 0)
00876 {
00877 tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_1 - SNAP_GUIDE_INNER_RADIUS);
00878 }
00879 else if (i % 8 == 0)
00880 {
00881 tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_2 - SNAP_GUIDE_INNER_RADIUS);
00882 }
00883 else if (i % 4 == 0)
00884 {
00885 tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_3 - SNAP_GUIDE_INNER_RADIUS);
00886 }
00887 else if (i % 2 == 0)
00888 {
00889 tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_4 - SNAP_GUIDE_INNER_RADIUS);
00890 }
00891 else
00892 {
00893 tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_5 - SNAP_GUIDE_INNER_RADIUS);
00894 }
00895
00896 if (mCamEdgeOn)
00897 {
00898
00899 F32 dot = cam_at_axis * (projected_snap_axis * rot);
00900 if (dot > 0.f)
00901 {
00902 outer_point = inner_point;
00903 render_text = FALSE;
00904 }
00905 else
00906 {
00907 if (ring_num == 0)
00908 {
00909 outer_point = inner_point + (constraint_axis * tick_length) * rot;
00910 }
00911 else
00912 {
00913 outer_point = inner_point - (constraint_axis * tick_length) * rot;
00914 }
00915 }
00916 }
00917 else
00918 {
00919 outer_point = inner_point + (projected_snap_axis * tick_length) * rot;
00920 }
00921
00922 text_point = outer_point + (projected_snap_axis * mRadiusMeters * 0.1f) * rot;
00923
00924 gGL.vertex3fv(inner_point.mV);
00925 gGL.vertex3fv(outer_point.mV);
00926 }
00927 gGL.end();
00928
00929
00930 if (pass == 1 && render_text && i % 16 == 0)
00931 {
00932 if (world_snap_axis.mV[VX])
00933 {
00934 if (i == 0)
00935 {
00936 renderTickText(text_point, mObjectSelection->isAttachment() ? "Forward" : "East", LLColor4::white);
00937 }
00938 else if (i == 16)
00939 {
00940 if (constraint_axis.mV[VZ] > 0.f)
00941 {
00942 renderTickText(text_point, mObjectSelection->isAttachment() ? "Left" : "North", LLColor4::white);
00943 }
00944 else
00945 {
00946 renderTickText(text_point, mObjectSelection->isAttachment() ? "Right" : "South", LLColor4::white);
00947 }
00948 }
00949 else if (i == 32)
00950 {
00951 renderTickText(text_point, mObjectSelection->isAttachment() ? "Back" : "West", LLColor4::white);
00952 }
00953 else
00954 {
00955 if (constraint_axis.mV[VZ] > 0.f)
00956 {
00957 renderTickText(text_point, mObjectSelection->isAttachment() ? "Right" : "South", LLColor4::white);
00958 }
00959 else
00960 {
00961 renderTickText(text_point, mObjectSelection->isAttachment() ? "Left" : "North", LLColor4::white);
00962 }
00963 }
00964 }
00965 else if (world_snap_axis.mV[VY])
00966 {
00967 if (i == 0)
00968 {
00969 renderTickText(text_point, mObjectSelection->isAttachment() ? "Left" : "North", LLColor4::white);
00970 }
00971 else if (i == 16)
00972 {
00973 if (constraint_axis.mV[VX] > 0.f)
00974 {
00975 renderTickText(text_point, "Up", LLColor4::white);
00976 }
00977 else
00978 {
00979 renderTickText(text_point, "Down", LLColor4::white);
00980 }
00981 }
00982 else if (i == 32)
00983 {
00984 renderTickText(text_point, mObjectSelection->isAttachment() ? "Right" : "South", LLColor4::white);
00985 }
00986 else
00987 {
00988 if (constraint_axis.mV[VX] > 0.f)
00989 {
00990 renderTickText(text_point, "Down", LLColor4::white);
00991 }
00992 else
00993 {
00994 renderTickText(text_point, "Up", LLColor4::white);
00995 }
00996 }
00997 }
00998 else if (world_snap_axis.mV[VZ])
00999 {
01000 if (i == 0)
01001 {
01002 renderTickText(text_point, "Up", LLColor4::white);
01003 }
01004 else if (i == 16)
01005 {
01006 if (constraint_axis.mV[VY] > 0.f)
01007 {
01008 renderTickText(text_point, mObjectSelection->isAttachment() ? "Forward" : "East", LLColor4::white);
01009 }
01010 else
01011 {
01012 renderTickText(text_point, mObjectSelection->isAttachment() ? "Back" : "West", LLColor4::white);
01013 }
01014 }
01015 else if (i == 32)
01016 {
01017 renderTickText(text_point, "Down", LLColor4::white);
01018 }
01019 else
01020 {
01021 if (constraint_axis.mV[VY] > 0.f)
01022 {
01023 renderTickText(text_point, mObjectSelection->isAttachment() ? "Back" : "West", LLColor4::white);
01024 }
01025 else
01026 {
01027 renderTickText(text_point, mObjectSelection->isAttachment() ? "Forward" : "East", LLColor4::white);
01028 }
01029 }
01030 }
01031 }
01032 gGL.color4fv(line_color.mV);
01033 }
01034
01035
01036 if (mInSnapRegime)
01037 {
01038 LLVector3 object_axis;
01039 getObjectAxisClosestToMouse(object_axis);
01040
01041
01042 LLSelectNode* first_node = mObjectSelection->getFirstMoveableNode(TRUE);
01043 object_axis = object_axis * first_node->getObject()->getRenderRotation();
01044 object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis();
01045 object_axis.normVec();
01046 object_axis = object_axis * SNAP_GUIDE_INNER_RADIUS * mRadiusMeters + center;
01047 LLVector3 line_start = center;
01048
01049 gGL.begin(LLVertexBuffer::LINES);
01050 {
01051 gGL.vertex3fv(line_start.mV);
01052 gGL.vertex3fv(object_axis.mV);
01053 }
01054 gGL.end();
01055
01056
01057 gGL.begin(LLVertexBuffer::TRIANGLES);
01058 {
01059 LLVector3 arrow_dir;
01060 LLVector3 arrow_span = (object_axis - line_start) % getConstraintAxis();
01061 arrow_span.normVec();
01062
01063 arrow_dir = mCamEdgeOn ? getConstraintAxis() : object_axis - line_start;
01064 arrow_dir.normVec();
01065 if (ring_num == 1)
01066 {
01067 arrow_dir *= -1.f;
01068 }
01069 gGL.vertex3fv((object_axis + arrow_dir * mRadiusMeters * 0.1f).mV);
01070 gGL.vertex3fv((object_axis + arrow_span * mRadiusMeters * 0.1f).mV);
01071 gGL.vertex3fv((object_axis - arrow_span * mRadiusMeters * 0.1f).mV);
01072 }
01073 gGL.end();
01074
01075 {
01076 LLGLDepthTest gls_depth(GL_TRUE);
01077 gGL.begin(LLVertexBuffer::LINES);
01078 {
01079 gGL.vertex3fv(line_start.mV);
01080 gGL.vertex3fv(object_axis.mV);
01081 }
01082 gGL.end();
01083
01084
01085 gGL.begin(LLVertexBuffer::TRIANGLES);
01086 {
01087 LLVector3 arrow_dir;
01088 LLVector3 arrow_span = (object_axis - line_start) % getConstraintAxis();
01089 arrow_span.normVec();
01090
01091 arrow_dir = mCamEdgeOn ? getConstraintAxis() : object_axis - line_start;
01092 arrow_dir.normVec();
01093 if (ring_num == 1)
01094 {
01095 arrow_dir *= -1.f;
01096 }
01097
01098 gGL.vertex3fv((object_axis + arrow_dir * mRadiusMeters * 0.1f).mV);
01099 gGL.vertex3fv((object_axis + arrow_span * mRadiusMeters * 0.1f).mV);
01100 gGL.vertex3fv((object_axis - arrow_span * mRadiusMeters * 0.1f).mV);
01101 }
01102 gGL.end();
01103 }
01104 }
01105 }
01106 }
01107 }
01108
01109
01110 BOOL LLManipRotate::updateVisiblity()
01111 {
01112
01113
01114
01115
01116
01117
01118 if (!hasMouseCapture())
01119 {
01120 mRotationCenter = gAgent.getPosGlobalFromAgent( getPivotPoint() );
01121 }
01122
01123 BOOL visible = FALSE;
01124
01125 LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter );
01126 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
01127 {
01128 mCenterToCam = LLVector3(-1.f / gAgent.getAvatarObject()->mHUDCurZoom, 0.f, 0.f);
01129 mCenterToCamNorm = mCenterToCam;
01130 mCenterToCamMag = mCenterToCamNorm.normVec();
01131
01132 mRadiusMeters = RADIUS_PIXELS / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels();
01133 mRadiusMeters /= gAgent.getAvatarObject()->mHUDCurZoom;
01134
01135 mCenterToProfilePlaneMag = mRadiusMeters * mRadiusMeters / mCenterToCamMag;
01136 mCenterToProfilePlane = -mCenterToProfilePlaneMag * mCenterToCamNorm;
01137
01138 mCenterScreen.set((S32)((0.5f - mRotationCenter.mdV[VY]) / gAgent.getAvatarObject()->mHUDCurZoom * gViewerWindow->getWindowWidth()),
01139 (S32)((mRotationCenter.mdV[VZ] + 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom * gViewerWindow->getWindowHeight()));
01140 visible = TRUE;
01141 }
01142 else
01143 {
01144 visible = LLViewerCamera::getInstance()->projectPosAgentToScreen(center, mCenterScreen );
01145 if( visible )
01146 {
01147 mCenterToCam = gAgent.getCameraPositionAgent() - center;
01148 mCenterToCamNorm = mCenterToCam;
01149 mCenterToCamMag = mCenterToCamNorm.normVec();
01150 LLVector3 cameraAtAxis = LLViewerCamera::getInstance()->getAtAxis();
01151 cameraAtAxis.normVec();
01152
01153 F32 z_dist = -1.f * (mCenterToCam * cameraAtAxis);
01154
01155
01156 if (gSavedSettings.getBOOL("LimitSelectDistance"))
01157 {
01158 F32 max_select_distance = gSavedSettings.getF32("MaxSelectDistance");
01159 if (dist_vec(gAgent.getPositionAgent(), center) > max_select_distance)
01160 {
01161 visible = FALSE;
01162 }
01163 }
01164
01165 if (mCenterToCamMag > 0.001f)
01166 {
01167 F32 fraction_of_fov = RADIUS_PIXELS / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels();
01168 F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView();
01169 mRadiusMeters = z_dist * tan(apparent_angle);
01170
01171 mCenterToProfilePlaneMag = mRadiusMeters * mRadiusMeters / mCenterToCamMag;
01172 mCenterToProfilePlane = -mCenterToProfilePlaneMag * mCenterToCamNorm;
01173 }
01174 else
01175 {
01176 visible = FALSE;
01177 }
01178 }
01179 }
01180
01181 mCamEdgeOn = FALSE;
01182 F32 axis_onto_cam = mManipPart >= LL_ROT_X ? llabs( getConstraintAxis() * mCenterToCamNorm ) : 0.f;
01183 if( axis_onto_cam < AXIS_ONTO_CAM_TOLERANCE )
01184 {
01185 mCamEdgeOn = TRUE;
01186 }
01187
01188 return visible;
01189 }
01190
01191 LLQuaternion LLManipRotate::dragUnconstrained( S32 x, S32 y )
01192 {
01193 LLVector3 cam = gAgent.getCameraPositionAgent();
01194 LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter );
01195
01196 mMouseCur = intersectMouseWithSphere( x, y, center, mRadiusMeters);
01197
01198 F32 delta_x = (F32)(mCenterScreen.mX - x);
01199 F32 delta_y = (F32)(mCenterScreen.mY - y);
01200
01201 F32 dist_from_sphere_center = sqrt(delta_x * delta_x + delta_y * delta_y);
01202
01203 LLVector3 axis = mMouseDown % mMouseCur;
01204 axis.normVec();
01205 F32 angle = acos(mMouseDown * mMouseCur);
01206 LLQuaternion sphere_rot( angle, axis );
01207
01208 if (is_approx_zero(1.f - mMouseDown * mMouseCur))
01209 {
01210 return LLQuaternion::DEFAULT;
01211 }
01212 else if (dist_from_sphere_center < RADIUS_PIXELS)
01213 {
01214 return sphere_rot;
01215 }
01216 else
01217 {
01218 LLVector3 intersection;
01219 getMousePointOnPlaneAgent( intersection, x, y, center + mCenterToProfilePlane, mCenterToCamNorm );
01220
01221
01222 F32 in_sphere_angle = F_PI_BY_TWO;
01223 F32 dist_to_tangent_point = mRadiusMeters;
01224 if( !is_approx_zero( mCenterToProfilePlaneMag ) )
01225 {
01226 dist_to_tangent_point = sqrt( mRadiusMeters * mRadiusMeters - mCenterToProfilePlaneMag * mCenterToProfilePlaneMag );
01227 in_sphere_angle = atan2( dist_to_tangent_point, mCenterToProfilePlaneMag );
01228 }
01229
01230 LLVector3 profile_center_to_intersection = intersection - (center + mCenterToProfilePlane);
01231 F32 dist_to_intersection = profile_center_to_intersection.normVec();
01232 F32 angle = (-1.f + dist_to_intersection / dist_to_tangent_point) * in_sphere_angle;
01233
01234 LLVector3 axis;
01235 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
01236 {
01237 axis = LLVector3(-1.f, 0.f, 0.f) % profile_center_to_intersection;
01238 }
01239 else
01240 {
01241 axis = (cam - center) % profile_center_to_intersection;
01242 axis.normVec();
01243 }
01244 return sphere_rot * LLQuaternion( angle, axis );
01245 }
01246 }
01247
01248 LLVector3 LLManipRotate::getConstraintAxis()
01249 {
01250 LLVector3 axis;
01251 if( LL_ROT_ROLL == mManipPart )
01252 {
01253 axis = mCenterToCamNorm;
01254 }
01255 else
01256 {
01257 S32 axis_dir = mManipPart - LL_ROT_X;
01258 if ((axis_dir >= 0) && (axis_dir < 3))
01259 {
01260 axis.mV[axis_dir] = 1.f;
01261 }
01262 else
01263 {
01264 #ifndef LL_RELEASE_FOR_DOWNLOAD
01265 llerrs << "Got bogus hit part in LLManipRotate::getConstraintAxis():" << mManipPart << llendl
01266 #else
01267 llwarns << "Got bogus hit part in LLManipRotate::getConstraintAxis():" << mManipPart << llendl
01268 #endif
01269 axis.mV[0] = 1.f;
01270 }
01271
01272 LLVector3 grid_origin;
01273 LLVector3 grid_scale;
01274 LLQuaternion grid_rotation;
01275
01276 LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale);
01277
01278 LLSelectNode* first_node = mObjectSelection->getFirstMoveableNode(TRUE);
01279 if (first_node)
01280 {
01281
01282
01283 axis = axis * grid_rotation;
01284 }
01285 }
01286
01287 return axis;
01288 }
01289
01290 LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y )
01291 {
01292 LLSelectNode* first_object_node = mObjectSelection->getFirstMoveableNode(TRUE);
01293 LLVector3 constraint_axis = getConstraintAxis();
01294 LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter );
01295
01296 F32 angle = 0.f;
01297
01298
01299 LLVector3 grid_origin;
01300 LLVector3 grid_scale;
01301 LLQuaternion grid_rotation;
01302
01303 LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale);
01304
01305 LLVector3 axis1;
01306 LLVector3 axis2;
01307
01308 LLVector3 test_axis = constraint_axis;
01309 if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
01310 {
01311 test_axis = test_axis * ~grid_rotation;
01312 }
01313 else if (LLSelectMgr::getInstance()->getGridMode() == GRID_MODE_REF_OBJECT)
01314 {
01315 test_axis = test_axis * ~grid_rotation;
01316 }
01317 test_axis.abs();
01318
01319
01320 if (test_axis.mV[VX] > test_axis.mV[VY] && test_axis.mV[VX] > test_axis.mV[VZ])
01321 {
01322 axis1 = LLVector3::y_axis;
01323 }
01324 else if (test_axis.mV[VY] > test_axis.mV[VZ])
01325 {
01326 axis1 = LLVector3::z_axis;
01327 }
01328 else
01329 {
01330 axis1 = LLVector3::x_axis;
01331 }
01332
01333 if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
01334 {
01335 axis1 = axis1 * grid_rotation;
01336 }
01337 else if (LLSelectMgr::getInstance()->getGridMode() == GRID_MODE_REF_OBJECT)
01338 {
01339 axis1 = axis1 * grid_rotation;
01340 }
01341
01342
01343 axis1 -= (axis1 * constraint_axis) * constraint_axis;
01344 axis1.normVec();
01345
01346
01347 axis2 = constraint_axis % axis1;
01348
01349
01350 if( mCamEdgeOn )
01351 {
01352
01353 LLVector3 snap_plane_center = (center + (constraint_axis * mRadiusMeters * 0.5f));
01354 LLVector3 cam_to_snap_plane;
01355 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
01356 {
01357 cam_to_snap_plane.setVec(1.f, 0.f, 0.f);
01358 }
01359 else
01360 {
01361 cam_to_snap_plane = snap_plane_center - gAgent.getCameraPositionAgent();
01362 cam_to_snap_plane.normVec();
01363 }
01364
01365 LLVector3 projected_mouse;
01366 BOOL hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis);
01367 projected_mouse -= snap_plane_center;
01368
01369 S32 snap_plane = 0;
01370
01371 F32 dot = cam_to_snap_plane * constraint_axis;
01372 if (llabs(dot) < 0.01f)
01373 {
01374
01375 getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane);
01376 projected_mouse -= snap_plane_center;
01377 dot = projected_mouse * constraint_axis;
01378 if (projected_mouse * constraint_axis > 0)
01379 {
01380 snap_plane = 1;
01381 }
01382 projected_mouse -= dot * constraint_axis;
01383 }
01384 else if (dot > 0.f)
01385 {
01386
01387 if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f)
01388 {
01389 snap_plane = 1;
01390 }
01391 }
01392 else
01393 {
01394
01395 if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit)
01396 {
01397 snap_plane = 1;
01398 }
01399 }
01400
01401 if (snap_plane == 0)
01402 {
01403
01404 snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f));
01405 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
01406 {
01407 cam_to_snap_plane.setVec(1.f, 0.f, 0.f);
01408 }
01409 else
01410 {
01411 cam_to_snap_plane = snap_plane_center - gAgent.getCameraPositionAgent();
01412 cam_to_snap_plane.normVec();
01413 }
01414
01415 hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis);
01416 projected_mouse -= snap_plane_center;
01417
01418 dot = cam_to_snap_plane * constraint_axis;
01419 if (llabs(dot) < 0.01f)
01420 {
01421
01422 getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane);
01423 projected_mouse -= snap_plane_center;
01424 dot = projected_mouse * constraint_axis;
01425 if (projected_mouse * constraint_axis < 0)
01426 {
01427 snap_plane = 2;
01428 }
01429 projected_mouse -= dot * constraint_axis;
01430 }
01431 else if (dot < 0.f)
01432 {
01433
01434 if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f)
01435 {
01436 snap_plane = 2;
01437 }
01438 }
01439 else
01440 {
01441
01442 if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit)
01443 {
01444 snap_plane = 2;
01445 }
01446 }
01447 }
01448
01449 if (snap_plane > 0)
01450 {
01451 LLVector3 cam_at_axis;
01452 if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
01453 {
01454 cam_at_axis.setVec(1.f, 0.f, 0.f);
01455 }
01456 else
01457 {
01458 cam_at_axis = snap_plane_center - gAgent.getCameraPositionAgent();
01459 cam_at_axis.normVec();
01460 }
01461
01462
01463 getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_at_axis);
01464
01465 projected_mouse -= snap_plane_center;
01466 projected_mouse -= projected_vec(projected_mouse, constraint_axis);
01467
01468 F32 mouse_lateral_dist = llmin(SNAP_GUIDE_INNER_RADIUS * mRadiusMeters, projected_mouse.magVec());
01469 F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters;
01470 if (llabs(mouse_lateral_dist) > 0.01f)
01471 {
01472 mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) -
01473 (mouse_lateral_dist * mouse_lateral_dist));
01474 }
01475 LLVector3 projected_camera_at = cam_at_axis - projected_vec(cam_at_axis, constraint_axis);
01476 projected_mouse -= mouse_depth * projected_camera_at;
01477
01478 if (!mInSnapRegime)
01479 {
01480 mSmoothRotate = TRUE;
01481 }
01482 mInSnapRegime = TRUE;
01483
01484 F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f);
01485
01486 F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT);
01487
01488
01489 LLVector3 object_axis;
01490 getObjectAxisClosestToMouse(object_axis);
01491 object_axis = object_axis * first_object_node->mSavedRotation;
01492
01493
01494 object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis();
01495 object_axis.normVec();
01496
01497 if (relative_mouse_angle < SNAP_ANGLE_DETENTE)
01498 {
01499 F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f));
01500 angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2);
01501 }
01502 else
01503 {
01504 angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2);
01505 }
01506 return LLQuaternion( -angle, constraint_axis );
01507 }
01508 else
01509 {
01510 if (mInSnapRegime)
01511 {
01512 mSmoothRotate = TRUE;
01513 }
01514 mInSnapRegime = FALSE;
01515
01516 LLVector3 up_from_axis = mCenterToCamNorm % constraint_axis;
01517 up_from_axis.normVec();
01518 LLVector3 cur_intersection;
01519 getMousePointOnPlaneAgent(cur_intersection, x, y, center, mCenterToCam);
01520 cur_intersection -= center;
01521 mMouseCur = projected_vec(cur_intersection, up_from_axis);
01522 F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters;
01523 F32 mouse_dist_sqrd = mMouseCur.magVecSquared();
01524 if (mouse_dist_sqrd > 0.0001f)
01525 {
01526 mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) -
01527 mouse_dist_sqrd);
01528 }
01529 LLVector3 projected_center_to_cam = mCenterToCamNorm - projected_vec(mCenterToCamNorm, constraint_axis);
01530 mMouseCur += mouse_depth * projected_center_to_cam;
01531
01532 F32 dist = (cur_intersection * up_from_axis) - (mMouseDown * up_from_axis);
01533 angle = dist / (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * -F_PI_BY_TWO;
01534 }
01535 }
01536 else
01537 {
01538 LLVector3 projected_mouse;
01539 getMousePointOnPlaneAgent(projected_mouse, x, y, center, constraint_axis);
01540 projected_mouse -= center;
01541 mMouseCur = projected_mouse;
01542 mMouseCur.normVec();
01543
01544 if (!first_object_node)
01545 {
01546 return LLQuaternion::DEFAULT;
01547 }
01548
01549 if (gSavedSettings.getBOOL("SnapEnabled") && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters)
01550 {
01551 if (!mInSnapRegime)
01552 {
01553 mSmoothRotate = TRUE;
01554 }
01555 mInSnapRegime = TRUE;
01556
01557 F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f);
01558
01559 F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT);
01560
01561
01562 LLVector3 object_axis;
01563 getObjectAxisClosestToMouse(object_axis);
01564 object_axis = object_axis * first_object_node->mSavedRotation;
01565
01566
01567 object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis();
01568 object_axis.normVec();
01569
01570 if (relative_mouse_angle < SNAP_ANGLE_DETENTE)
01571 {
01572 F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f));
01573 angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2);
01574 }
01575 else
01576 {
01577 angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2);
01578 }
01579 return LLQuaternion( -angle, constraint_axis );
01580 }
01581 else
01582 {
01583 if (mInSnapRegime)
01584 {
01585 mSmoothRotate = TRUE;
01586 }
01587 mInSnapRegime = FALSE;
01588 }
01589
01590 angle = acos(mMouseCur * mMouseDown);
01591
01592 F32 dir = (mMouseDown % mMouseCur) * constraint_axis;
01593 if( dir < 0.f )
01594 {
01595 angle *= -1.f;
01596 }
01597 }
01598
01599 F32 rot_step = gSavedSettings.getF32("RotationStep");
01600 F32 step_size = DEG_TO_RAD * rot_step;
01601 angle -= fmod(angle, step_size);
01602
01603 return LLQuaternion( angle, constraint_axis );
01604 }
01605
01606
01607
01608 LLVector3 LLManipRotate::intersectMouseWithSphere( S32 x, S32 y, const LLVector3& sphere_center, F32 sphere_radius)
01609 {
01610 LLVector3 ray_pt;
01611 LLVector3 ray_dir;
01612 mouseToRay( x, y, &ray_pt, &ray_dir);
01613 return intersectRayWithSphere( ray_pt, ray_dir, sphere_center, sphere_radius );
01614 }
01615
01616 LLVector3 LLManipRotate::intersectRayWithSphere( const LLVector3& ray_pt, const LLVector3& ray_dir, const LLVector3& sphere_center, F32 sphere_radius)
01617 {
01618 LLVector3 ray_pt_to_center = sphere_center - ray_pt;
01619 F32 center_distance = ray_pt_to_center.normVec();
01620
01621 F32 dot = ray_dir * ray_pt_to_center;
01622
01623 if (dot == 0.f)
01624 {
01625 return LLVector3::zero;
01626 }
01627
01628
01629 LLVector3 intersection_sphere_plane = ray_pt + (ray_dir * center_distance / dot);
01630
01631 LLVector3 sphere_center_to_intersection = (intersection_sphere_plane - sphere_center) / sphere_radius;
01632
01633 F32 dist_squared = sphere_center_to_intersection.magVecSquared();
01634 LLVector3 result;
01635
01636 if (dist_squared > 1.f)
01637 {
01638 result = sphere_center_to_intersection;
01639 result.normVec();
01640 }
01641 else
01642 {
01643 result = sphere_center_to_intersection - ray_dir * sqrt(1.f - dist_squared);
01644 }
01645
01646 return result;
01647 }
01648
01649
01650
01651 void LLManipRotate::mouseToRay( S32 x, S32 y, LLVector3* ray_pt, LLVector3* ray_dir )
01652 {
01653 if (LLSelectMgr::getInstance()->getSelection()->getSelectType() == SELECT_TYPE_HUD)
01654 {
01655 F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom;
01656 F32 mouse_y = ((((F32)y) / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom;
01657
01658 *ray_pt = LLVector3(-1.f, -mouse_x, mouse_y);
01659 *ray_dir = LLVector3(1.f, 0.f, 0.f);
01660 }
01661 else
01662 {
01663 *ray_pt = gAgent.getCameraPositionAgent();
01664 LLViewerCamera::getInstance()->projectScreenToPosAgent(x, y, ray_dir);
01665 *ray_dir -= *ray_pt;
01666 ray_dir->normVec();
01667 }
01668 }
01669
01670 void LLManipRotate::highlightManipulators( S32 x, S32 y )
01671 {
01672 mHighlightedPart = LL_NO_PART;
01673
01674
01675 LLViewerObject *first_object = mObjectSelection->getFirstMoveableObject(TRUE);
01676
01677 if (!first_object)
01678 {
01679 return;
01680 }
01681
01682 LLQuaternion object_rot = first_object->getRenderRotation();
01683 LLVector3 rotation_center = gAgent.getPosAgentFromGlobal(mRotationCenter);
01684 LLVector3 mouse_dir_x;
01685 LLVector3 mouse_dir_y;
01686 LLVector3 mouse_dir_z;
01687 LLVector3 intersection_roll;
01688
01689 LLVector3 grid_origin;
01690 LLVector3 grid_scale;
01691 LLQuaternion grid_rotation;
01692
01693 LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale);
01694
01695 LLVector3 rot_x_axis = LLVector3::x_axis * grid_rotation;
01696 LLVector3 rot_y_axis = LLVector3::y_axis * grid_rotation;
01697 LLVector3 rot_z_axis = LLVector3::z_axis * grid_rotation;
01698
01699 F32 proj_rot_x_axis = llabs(rot_x_axis * mCenterToCamNorm);
01700 F32 proj_rot_y_axis = llabs(rot_y_axis * mCenterToCamNorm);
01701 F32 proj_rot_z_axis = llabs(rot_z_axis * mCenterToCamNorm);
01702
01703 F32 min_select_distance = 0.f;
01704 F32 cur_select_distance = 0.f;
01705
01706
01707 getMousePointOnPlaneAgent(mouse_dir_x, x, y, rotation_center, rot_x_axis);
01708 mouse_dir_x -= rotation_center;
01709
01710 mouse_dir_x *= 1.f + (1.f - llabs(rot_x_axis * mCenterToCamNorm)) * 0.1f;
01711
01712
01713 getMousePointOnPlaneAgent(mouse_dir_y, x, y, rotation_center, rot_y_axis);
01714 mouse_dir_y -= rotation_center;
01715 mouse_dir_y *= 1.f + (1.f - llabs(rot_y_axis * mCenterToCamNorm)) * 0.1f;
01716
01717
01718 getMousePointOnPlaneAgent(mouse_dir_z, x, y, rotation_center, rot_z_axis);
01719 mouse_dir_z -= rotation_center;
01720 mouse_dir_z *= 1.f + (1.f - llabs(rot_z_axis * mCenterToCamNorm)) * 0.1f;
01721
01722
01723 getMousePointOnPlaneAgent(intersection_roll, x, y, rotation_center, mCenterToCamNorm);
01724 intersection_roll -= rotation_center;
01725
01726 F32 dist_x = mouse_dir_x.normVec();
01727 F32 dist_y = mouse_dir_y.normVec();
01728 F32 dist_z = mouse_dir_z.normVec();
01729
01730 F32 distance_threshold = (MAX_MANIP_SELECT_DISTANCE * mRadiusMeters) / gViewerWindow->getWindowHeight();
01731
01732 if (llabs(dist_x - mRadiusMeters) * llmax(0.05f, proj_rot_x_axis) < distance_threshold)
01733 {
01734
01735 cur_select_distance = dist_x * mouse_dir_x * mCenterToCamNorm;
01736 if (cur_select_distance >= -0.05f && (min_select_distance == 0.f || cur_select_distance > min_select_distance))
01737 {
01738 min_select_distance = cur_select_distance;
01739 mHighlightedPart = LL_ROT_X;
01740 }
01741 }
01742 if (llabs(dist_y - mRadiusMeters) * llmax(0.05f, proj_rot_y_axis) < distance_threshold)
01743 {
01744
01745 cur_select_distance = dist_y * mouse_dir_y * mCenterToCamNorm;
01746 if (cur_select_distance >= -0.05f && (min_select_distance == 0.f || cur_select_distance > min_select_distance))
01747 {
01748 min_select_distance = cur_select_distance;
01749 mHighlightedPart = LL_ROT_Y;
01750 }
01751 }
01752 if (llabs(dist_z - mRadiusMeters) * llmax(0.05f, proj_rot_z_axis) < distance_threshold)
01753 {
01754
01755 cur_select_distance = dist_z * mouse_dir_z * mCenterToCamNorm;
01756 if (cur_select_distance >= -0.05f && (min_select_distance == 0.f || cur_select_distance > min_select_distance))
01757 {
01758 min_select_distance = cur_select_distance;
01759 mHighlightedPart = LL_ROT_Z;
01760 }
01761 }
01762
01763
01764 if (proj_rot_x_axis < 0.05f)
01765 {
01766 if ((proj_rot_y_axis > 0.05f && (dist_y * llabs(mouse_dir_y * rot_x_axis) < distance_threshold) && dist_y < mRadiusMeters) ||
01767 (proj_rot_z_axis > 0.05f && (dist_z * llabs(mouse_dir_z * rot_x_axis) < distance_threshold) && dist_z < mRadiusMeters))
01768 {
01769 mHighlightedPart = LL_ROT_X;
01770 }
01771 }
01772
01773 if (proj_rot_y_axis < 0.05f)
01774 {
01775 if ((proj_rot_x_axis > 0.05f && (dist_x * llabs(mouse_dir_x * rot_y_axis) < distance_threshold) && dist_x < mRadiusMeters) ||
01776 (proj_rot_z_axis > 0.05f && (dist_z * llabs(mouse_dir_z * rot_y_axis) < distance_threshold) && dist_z < mRadiusMeters))
01777 {
01778 mHighlightedPart = LL_ROT_Y;
01779 }
01780 }
01781
01782 if (proj_rot_z_axis < 0.05f)
01783 {
01784 if ((proj_rot_x_axis > 0.05f && (dist_x * llabs(mouse_dir_x * rot_z_axis) < distance_threshold) && dist_x < mRadiusMeters) ||
01785 (proj_rot_y_axis > 0.05f && (dist_y * llabs(mouse_dir_y * rot_z_axis) < distance_threshold) && dist_y < mRadiusMeters))
01786 {
01787 mHighlightedPart = LL_ROT_Z;
01788 }
01789 }
01790
01791
01792 if (mHighlightedPart == LL_NO_PART)
01793 {
01794 F32 roll_distance = intersection_roll.magVec();
01795 F32 width_meters = WIDTH_PIXELS * mRadiusMeters / RADIUS_PIXELS;
01796
01797
01798 if (llabs(roll_distance - (mRadiusMeters + (width_meters * 2.f))) < distance_threshold * 2.f)
01799 {
01800 mHighlightedPart = LL_ROT_ROLL;
01801 }
01802 else if (roll_distance < mRadiusMeters)
01803 {
01804 mHighlightedPart = LL_ROT_GENERAL;
01805 }
01806 }
01807 }
01808
01809 S32 LLManipRotate::getObjectAxisClosestToMouse(LLVector3& object_axis)
01810 {
01811 LLSelectNode* first_object_node = mObjectSelection->getFirstMoveableNode(TRUE);
01812
01813 if (!first_object_node)
01814 {
01815 object_axis.clearVec();
01816 return -1;
01817 }
01818
01819 LLQuaternion obj_rotation = first_object_node->mSavedRotation;
01820 LLVector3 mouse_down_object = mMouseDown * ~obj_rotation;
01821 LLVector3 mouse_down_abs = mouse_down_object;
01822 mouse_down_abs.abs();
01823
01824 S32 axis_index = 0;
01825 if (mouse_down_abs.mV[VX] > mouse_down_abs.mV[VY] && mouse_down_abs.mV[VX] > mouse_down_abs.mV[VZ])
01826 {
01827 if (mouse_down_object.mV[VX] > 0.f)
01828 {
01829 object_axis = LLVector3::x_axis;
01830 }
01831 else
01832 {
01833 object_axis = LLVector3::x_axis_neg;
01834 }
01835 axis_index = VX;
01836 }
01837 else if (mouse_down_abs.mV[VY] > mouse_down_abs.mV[VZ])
01838 {
01839 if (mouse_down_object.mV[VY] > 0.f)
01840 {
01841 object_axis = LLVector3::y_axis;
01842 }
01843 else
01844 {
01845 object_axis = LLVector3::y_axis_neg;
01846 }
01847 axis_index = VY;
01848 }
01849 else
01850 {
01851 if (mouse_down_object.mV[VZ] > 0.f)
01852 {
01853 object_axis = LLVector3::z_axis;
01854 }
01855 else
01856 {
01857 object_axis = LLVector3::z_axis_neg;
01858 }
01859 axis_index = VZ;
01860 }
01861
01862 return axis_index;
01863 }
01864
01865
01866 BOOL LLManipRotate::canAffectSelection()
01867 {
01868 BOOL can_rotate = mObjectSelection->getObjectCount() != 0;
01869 if (can_rotate)
01870 {
01871 struct f : public LLSelectedObjectFunctor
01872 {
01873 virtual bool apply(LLViewerObject* objectp)
01874 {
01875 return objectp->permMove() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts"));
01876 }
01877 } func;
01878 can_rotate = mObjectSelection->applyToObjects(&func);
01879 }
01880 return can_rotate;
01881 }
01882