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