diff options
Diffstat (limited to 'indra/newview/llmanipscale.cpp')
-rwxr-xr-x | indra/newview/llmanipscale.cpp | 698 |
1 files changed, 365 insertions, 333 deletions
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index ae0884ac5d..6c1b25f2b4 100755 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -59,7 +59,7 @@ #include "v2math.h" #include "llvoavatar.h" #include "llmeshrepository.h" - +#include "lltrans.h" const F32 MAX_MANIP_SELECT_DISTANCE_SQUARED = 11.f * 11.f; const F32 SNAP_GUIDE_SCREEN_OFFSET = 0.05f; @@ -68,7 +68,7 @@ const F32 SELECTED_MANIPULATOR_SCALE = 1.2f; const F32 MANIPULATOR_SCALE_HALF_LIFE = 0.07f; const S32 NUM_MANIPULATORS = 14; -const LLManip::EManipPart MANIPULATOR_IDS[NUM_MANIPULATORS] = +const LLManip::EManipPart MANIPULATOR_IDS[NUM_MANIPULATORS] = { LLManip::LL_CORNER_NNN, LLManip::LL_CORNER_NNP, @@ -87,7 +87,7 @@ const LLManip::EManipPart MANIPULATOR_IDS[NUM_MANIPULATORS] = }; -F32 get_default_max_prim_scale(bool is_flora) +F32 get_default_max_prim_scale(bool is_flora) { // a bit of a hack, but if it's foilage, we don't want to use the // new larger scale which would result in giant trees and grass @@ -97,7 +97,7 @@ F32 get_default_max_prim_scale(bool is_flora) return DEFAULT_MAX_PRIM_SCALE; } else - { + { return DEFAULT_MAX_PRIM_SCALE_NO_MESH; } } @@ -179,7 +179,7 @@ void LLManipScale::handleSelect() } LLManipScale::LLManipScale( LLToolComposite* composite ) - : + : LLManip( std::string("Scale"), composite ), mBoxHandleSize( 1.f ), mScaledBoxHandleSize( 1.f ), @@ -190,10 +190,12 @@ LLManipScale::LLManipScale( LLToolComposite* composite ) mScaleSnapUnit1(1.f), mScaleSnapUnit2(1.f), mSnapRegimeOffset(0.f), + mTickPixelSpacing1(0.f), + mTickPixelSpacing2(0.f), mSnapGuideLength(0.f), - mInSnapRegime(FALSE), - mScaleSnapValue(0.f) -{ + mSnapRegime(SNAP_REGIME_NONE), + mScaleSnappedValue(0.f) +{ mManipulatorScales = new F32[NUM_MANIPULATORS]; for (S32 i = 0; i < NUM_MANIPULATORS; i++) { @@ -214,7 +216,7 @@ void LLManipScale::render() LLGLDepthTest gls_depth(GL_TRUE); LLGLEnable gl_blend(GL_BLEND); LLGLEnable gls_alpha_test(GL_ALPHA_TEST); - + if( canAffectSelection() ) { gGL.matrixMode(LLRender::MM_MODELVIEW); @@ -226,11 +228,11 @@ void LLManipScale::render() } //////////////////////////////////////////////////////////////////////// - // Calculate size of drag handles + // Calculate size of drag handles const F32 BOX_HANDLE_BASE_SIZE = 50.0f; // box size in pixels = BOX_HANDLE_BASE_SIZE * BOX_HANDLE_BASE_FACTOR const F32 BOX_HANDLE_BASE_FACTOR = 0.2f; - + LLVector3 center_agent = gAgent.getPosAgentFromGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal()); if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) @@ -283,7 +285,7 @@ void LLManipScale::render() rot.getAngleAxis(&angle_radians, &x, &y, &z); gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); - + { LLGLEnable poly_offset(GL_POLYGON_OFFSET_FILL); glPolygonOffset( -2.f, -2.f); @@ -345,7 +347,7 @@ BOOL LLManipScale::handleMouseDownOnPart( S32 x, S32 y, MASK mask ) LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); LLVector3 box_center_agent = bbox.getCenterAgent(); LLVector3 box_corner_agent = bbox.localToAgent( unitVectorToLocalBBoxExtent( partToUnitVector( mManipPart ), bbox ) ); - + updateSnapGuides(bbox); mDragStartPointGlobal = gAgent.getPosGlobalFromAgent(box_corner_agent); @@ -372,27 +374,27 @@ BOOL LLManipScale::handleMouseUp(S32 x, S32 y, MASK mask) if( hasMouseCapture() ) { - if( (LL_FACE_MIN <= (S32)mManipPart) + if( (LL_FACE_MIN <= (S32)mManipPart) && ((S32)mManipPart <= LL_FACE_MAX) ) { sendUpdates(TRUE,TRUE,FALSE); } else - if( (LL_CORNER_MIN <= (S32)mManipPart) + if( (LL_CORNER_MIN <= (S32)mManipPart) && ((S32)mManipPart <= LL_CORNER_MAX) ) { sendUpdates(TRUE,TRUE,TRUE); } - + //send texture update LLSelectMgr::getInstance()->adjustTexturesByScale(TRUE, getStretchTextures()); - + LLSelectMgr::getInstance()->enableSilhouette(TRUE); mManipPart = LL_NO_PART; // Might have missed last update due to UPDATE_DELAY timing LLSelectMgr::getInstance()->sendMultipleUpdate( mLastUpdateFlags ); - + //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject")); LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); } @@ -413,15 +415,15 @@ BOOL LLManipScale::handleHover(S32 x, S32 y, MASK mask) { drag( x, y ); } - lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipScale (active)" << llendl; + lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipScale (active)" << llendl; } else { - mInSnapRegime = FALSE; + mSnapRegime = SNAP_REGIME_NONE; // not dragging... highlightManipulators(x, y); } - + // Patch up textures, if possible. LLSelectMgr::getInstance()->adjustTexturesByScale(FALSE, getStretchTextures()); @@ -458,7 +460,7 @@ void LLManipScale::highlightManipulators(S32 x, S32 y) LLMatrix4 projMatrix = LLViewerCamera::getInstance()->getProjection(); LLMatrix4 modelView = LLViewerCamera::getInstance()->getModelview(); transform.initAll(LLVector3(1.f, 1.f, 1.f), bbox.getRotation(), bbox.getPositionAgent()); - + transform *= modelView; transform *= projMatrix; } @@ -477,7 +479,7 @@ void LLManipScale::highlightManipulators(S32 x, S32 y) mManipulatorVertices[numManips++] = LLVector4(max.mV[VX], min.mV[VY], max.mV[VZ], 1.f); mManipulatorVertices[numManips++] = LLVector4(max.mV[VX], max.mV[VY], min.mV[VZ], 1.f); mManipulatorVertices[numManips++] = LLVector4(max.mV[VX], max.mV[VY], max.mV[VZ], 1.f); - + // 1-D highlights are applicable iff one object is selected if( mObjectSelection->getObjectCount() == 1 ) { @@ -492,13 +494,13 @@ void LLManipScale::highlightManipulators(S32 x, S32 y) for_each(mProjectedManipulators.begin(), mProjectedManipulators.end(), DeletePointer()); mProjectedManipulators.clear(); - + for (S32 i = 0; i < numManips; i++) { LLVector4 projectedVertex = mManipulatorVertices[i] * transform; projectedVertex = projectedVertex * (1.f / projectedVertex.mV[VW]); - ManipulatorHandle* projManipulator = new ManipulatorHandle(LLVector3(projectedVertex.mV[VX], projectedVertex.mV[VY], + ManipulatorHandle* projManipulator = new ManipulatorHandle(LLVector3(projectedVertex.mV[VX], projectedVertex.mV[VY], projectedVertex.mV[VZ]), MANIPULATOR_IDS[i], (i < 7) ? SCALE_MANIP_CORNER : SCALE_MANIP_FACE); mProjectedManipulators.insert(projManipulator); } @@ -512,13 +514,13 @@ void LLManipScale::highlightManipulators(S32 x, S32 y) mHighlightedPart = LL_NO_PART; - for (minpulator_list_t::iterator iter = mProjectedManipulators.begin(); + for (manipulator_list_t::iterator iter = mProjectedManipulators.begin(); iter != mProjectedManipulators.end(); ++iter) { ManipulatorHandle* manipulator = *iter; { - manip2d.setVec(manipulator->mPosition.mV[VX] * half_width, manipulator->mPosition.mV[VY] * half_height); - + manip2d.set(manipulator->mPosition.mV[VX] * half_width, manipulator->mPosition.mV[VY] * half_height); + delta = manip2d - mousePos; if (delta.magVecSquared() < MAX_MANIP_SELECT_DISTANCE_SQUARED) { @@ -549,36 +551,36 @@ void LLManipScale::highlightManipulators(S32 x, S32 y) void LLManipScale::renderFaces( const LLBBox& bbox ) { - // Don't bother to render the drag handles for 1-D scaling if + // Don't bother to render the drag handles for 1-D scaling if // more than one object is selected or if it is an attachment if ( mObjectSelection->getObjectCount() > 1 ) { return; } - // This is a flattened representation of the box as render here - // . - // (+++) (++-) /|\t - // +------------+ | (texture coordinates) - // | | | - // | 1 | (*) --->s - // | +X | + // This is a flattened representation of the box as render here + // . + // (+++) (++-) /|\t + // +------------+ | (texture coordinates) + // | | | + // | 1 | (*) --->s + // | +X | // | | - // (+++) (+-+)| |(+--) (++-) (+++) - // +------------+------------+------------+------------+ - // |0 3|3 7|7 4|4 0| - // | 0 | 4 | 5 | 2 | - // | +Z | -Y | -Z | +Y | - // | | | | | - // |1 2|2 6|6 5|5 1| - // +------------+------------+------------+------------+ - // (-++) (--+)| |(---) (-+-) (-++) - // | 3 | - // | -X | - // | | - // | | - // +------------+ - // (-++) (-+-) + // (+++) (+-+)| |(+--) (++-) (+++) + // +------------+------------+------------+------------+ + // |0 3|3 7|7 4|4 0| + // | 0 | 4 | 5 | 2 | + // | +Z | -Y | -Z | +Y | + // | | | | | + // |1 2|2 6|6 5|5 1| + // +------------+------------+------------+------------+ + // (-++) (--+)| |(---) (-+-) (-++) + // | 3 | + // | -X | + // | | + // | | + // +------------+ + // (-++) (-+-) LLColor4 highlight_color( 1.f, 1.f, 1.f, 0.5f); LLColor4 normal_color( 1.f, 1.f, 1.f, 0.3f); @@ -602,7 +604,7 @@ void LLManipScale::renderFaces( const LLBBox& bbox ) { gGL.color4fv( default_normal_color.mV ); LLGLDepthTest gls_depth(GL_FALSE); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::QUADS); { // Face 0 gGL.vertex3f(min.mV[VX], max.mV[VY], max.mV[VZ]); @@ -645,9 +647,9 @@ void LLManipScale::renderFaces( const LLBBox& bbox ) // Find nearest vertex LLVector3 orientWRTHead = bbox.agentToLocalBasis( bbox.getCenterAgent() - gAgentCamera.getCameraPositionAgent() ); - U32 nearest = - (orientWRTHead.mV[0] < 0.0f ? 1 : 0) + - (orientWRTHead.mV[1] < 0.0f ? 2 : 0) + + U32 nearest = + (orientWRTHead.mV[0] < 0.0f ? 1 : 0) + + (orientWRTHead.mV[1] < 0.0f ? 2 : 0) + (orientWRTHead.mV[2] < 0.0f ? 4 : 0); // opposite faces on Linden cubes: @@ -656,7 +658,7 @@ void LLManipScale::renderFaces( const LLBBox& bbox ) // 2 & 4 // Table of order to draw faces, based on nearest vertex - static U32 face_list[8][6] = { + static U32 face_list[8][6] = { { 2,0,1, 4,5,3 }, // v6 F201 F453 { 2,0,3, 4,5,1 }, // v7 F203 F451 { 4,0,1, 2,5,3 }, // v5 F401 F253 @@ -723,7 +725,7 @@ void LLManipScale::renderEdges( const LLBBox& bbox ) { gGL.translatef( center_to_edge.mV[0], center_to_edge.mV[1], center_to_edge.mV[2] ); conditionalHighlight( part ); - gGL.scalef( + gGL.scalef( direction.mV[0] ? edge_width : extent.mV[VX], direction.mV[1] ? edge_width : extent.mV[VY], direction.mV[2] ? edge_width : extent.mV[VZ] ); @@ -757,7 +759,7 @@ void LLManipScale::renderCorners( const LLBBox& bbox ) y_offset = bbox.getMaxLocal().mV[VY]; } x_offset = bbox.getMaxLocal().mV[VX]; - } + } } @@ -782,7 +784,7 @@ void LLManipScale::renderAxisHandle( const LLVector3& start, const LLVector3& en { // Draws a single "jacks" style handle: a long, retangular box from start to end. LLVector3 offset_start = end - start; - offset_start.normVec(); + offset_start.normalize(); offset_start = start + mBoxHandleSize * offset_start; LLVector3 delta = end - offset_start; @@ -791,7 +793,7 @@ void LLManipScale::renderAxisHandle( const LLVector3& start, const LLVector3& en gGL.pushMatrix(); { gGL.translatef( pos.mV[VX], pos.mV[VY], pos.mV[VZ] ); - gGL.scalef( + gGL.scalef( mBoxHandleSize + llabs(delta.mV[VX]), mBoxHandleSize + llabs(delta.mV[VY]), mBoxHandleSize + llabs(delta.mV[VZ])); @@ -805,21 +807,20 @@ void LLManipScale::renderAxisHandle( const LLVector3& start, const LLVector3& en } } - +// General scale call void LLManipScale::drag( S32 x, S32 y ) { - if( (LL_FACE_MIN <= (S32)mManipPart) + if( (LL_FACE_MIN <= (S32)mManipPart) && ((S32)mManipPart <= LL_FACE_MAX) ) { dragFace( x, y ); } - else - if( (LL_CORNER_MIN <= (S32)mManipPart) + else if( (LL_CORNER_MIN <= (S32)mManipPart) && ((S32)mManipPart <= LL_CORNER_MAX) ) { dragCorner( x, y ); } - + // store changes to override updates for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin(); iter != LLSelectMgr::getInstance()->getSelection()->end(); iter++) @@ -834,139 +835,110 @@ void LLManipScale::drag( S32 x, S32 y ) selectNode->mLastScale = cur->getScale(); selectNode->mLastPositionLocal = cur->getPosition(); } - } + } LLSelectMgr::getInstance()->updateSelectionCenter(); - gAgentCamera.clearFocusObject(); + gAgentCamera.clearFocusObject(); } -// Scale around the +// Scale on three axis simultaneously void LLManipScale::dragCorner( S32 x, S32 y ) { - LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); - // Suppress scale if mouse hasn't moved. if (x == mLastMouseX && y == mLastMouseY) { - // sendUpdates(TRUE,TRUE,TRUE); return; } mLastMouseX = x; mLastMouseY = y; - LLVector3d drag_start_point_global = mDragStartPointGlobal; - LLVector3d drag_start_center_global = mDragStartCenterGlobal; - LLVector3 drag_start_point_agent = gAgent.getPosAgentFromGlobal(drag_start_point_global); - LLVector3 drag_start_center_agent = gAgent.getPosAgentFromGlobal(drag_start_center_global); + LLVector3 drag_start_point_agent = gAgent.getPosAgentFromGlobal(mDragStartPointGlobal); + LLVector3 drag_start_center_agent = gAgent.getPosAgentFromGlobal(mDragStartCenterGlobal); LLVector3d drag_start_dir_d; - drag_start_dir_d.setVec(drag_start_point_global - drag_start_center_global); - LLVector3 drag_start_dir_f; - drag_start_dir_f.setVec(drag_start_dir_d); + drag_start_dir_d.set(mDragStartPointGlobal - mDragStartCenterGlobal); F32 s = 0; F32 t = 0; - nearestPointOnLineFromMouse(x, y, - drag_start_center_agent, - drag_start_point_agent, - s, t ); - - F32 drag_start_dist = dist_vec(drag_start_point_agent, drag_start_center_agent); + nearestPointOnLineFromMouse(x, y, + drag_start_center_agent, + drag_start_point_agent, + s, t ); if( s <= 0 ) // we only care about intersections in front of the camera { return; } + mDragPointGlobal = lerp(mDragStartCenterGlobal, mDragStartPointGlobal, t); - LLVector3d drag_point_global = drag_start_center_global + t * drag_start_dir_d; - - F32 scale_factor = t; - - BOOL uniform = LLManipScale::getUniform(); - - if( !uniform ) - { - scale_factor = 0.5f + (scale_factor * 0.5f); - } + LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); + F32 scale_factor = 1.f; + F32 max_scale = partToMaxScale(mManipPart, bbox); + F32 min_scale = partToMinScale(mManipPart, bbox); + BOOL uniform = LLManipScale::getUniform(); // check for snapping - LLVector3 drag_center_agent = gAgent.getPosAgentFromGlobal(drag_point_global); LLVector3 mouse_on_plane1; - getMousePointOnPlaneAgent(mouse_on_plane1, x, y, drag_center_agent, mScalePlaneNormal1); - LLVector3 mouse_on_plane2; - getMousePointOnPlaneAgent(mouse_on_plane2, x, y, drag_center_agent, mScalePlaneNormal2); - LLVector3 mouse_dir_1 = mouse_on_plane1 - mScaleCenter; - LLVector3 mouse_dir_2 = mouse_on_plane2 - mScaleCenter; - LLVector3 mouse_to_scale_line_1 = mouse_dir_1 - projected_vec(mouse_dir_1, mScaleDir); - LLVector3 mouse_to_scale_line_2 = mouse_dir_2 - projected_vec(mouse_dir_2, mScaleDir); - LLVector3 mouse_to_scale_line_dir_1 = mouse_to_scale_line_1; - mouse_to_scale_line_dir_1.normVec(); - if (mouse_to_scale_line_dir_1 * mSnapGuideDir1 < 0.f) - { - // need to keep sign of mouse offset wrt to snap guide direction - mouse_to_scale_line_dir_1 *= -1.f; - } - LLVector3 mouse_to_scale_line_dir_2 = mouse_to_scale_line_2; - mouse_to_scale_line_dir_2.normVec(); - if (mouse_to_scale_line_dir_2 * mSnapGuideDir2 < 0.f) - { - // need to keep sign of mouse offset wrt to snap guide direction - mouse_to_scale_line_dir_2 *= -1.f; - } - - F32 snap_dir_dot_mouse_offset1 = mSnapGuideDir1 * mouse_to_scale_line_dir_1; - F32 snap_dir_dot_mouse_offset2 = mSnapGuideDir2 * mouse_to_scale_line_dir_2; + getMousePointOnPlaneAgent(mouse_on_plane1, x, y, mScaleCenter, mScalePlaneNormal1); + mouse_on_plane1 -= mScaleCenter; - F32 dist_from_scale_line_1 = mouse_to_scale_line_1 * mouse_to_scale_line_dir_1; - F32 dist_from_scale_line_2 = mouse_to_scale_line_2 * mouse_to_scale_line_dir_2; + LLVector3 mouse_on_plane2; + getMousePointOnPlaneAgent(mouse_on_plane2, x, y, mScaleCenter, mScalePlaneNormal2); + mouse_on_plane2 -= mScaleCenter; - F32 max_scale = partToMaxScale(mManipPart, bbox); - F32 min_scale = partToMinScale(mManipPart, bbox); + LLVector3 projected_drag_pos1 = inverse_projected_vec(mScaleDir, orthogonal_component(mouse_on_plane1, mSnapGuideDir1)); + LLVector3 projected_drag_pos2 = inverse_projected_vec(mScaleDir, orthogonal_component(mouse_on_plane2, mSnapGuideDir2)); BOOL snap_enabled = gSavedSettings.getBOOL("SnapEnabled"); - if (snap_enabled && dist_from_scale_line_1 > mSnapRegimeOffset * snap_dir_dot_mouse_offset1) + if (snap_enabled && (mouse_on_plane1 - projected_drag_pos1) * mSnapGuideDir1 > mSnapRegimeOffset) { - mInSnapRegime = TRUE; - LLVector3 projected_drag_pos = mouse_on_plane1 - (dist_from_scale_line_1 / snap_dir_dot_mouse_offset1) * mSnapGuideDir1; - F32 drag_dist = (projected_drag_pos - mScaleCenter) * mScaleDir; + F32 drag_dist = mScaleDir * projected_drag_pos1; // Projecting the drag position allows for negative results, vs using the length which will result in a "reverse scaling" bug. - F32 cur_subdivisions = llclamp(getSubdivisionLevel(projected_drag_pos, mScaleDir, mScaleSnapUnit1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); + F32 cur_subdivisions = llclamp(getSubdivisionLevel(mScaleCenter + projected_drag_pos1, mScaleDir, mScaleSnapUnit1, mTickPixelSpacing1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); F32 snap_dist = mScaleSnapUnit1 / (2.f * cur_subdivisions); F32 relative_snap_dist = fmodf(drag_dist + snap_dist, mScaleSnapUnit1 / cur_subdivisions); - mScaleSnapValue = llclamp((drag_dist - (relative_snap_dist - snap_dist)), min_scale, max_scale); + mScaleSnappedValue = llclamp((drag_dist - (relative_snap_dist - snap_dist)), min_scale, max_scale); + scale_factor = mScaleSnappedValue / dist_vec(drag_start_point_agent, drag_start_center_agent); + mScaleSnappedValue /= mScaleSnapUnit1 * 2.f; + mSnapRegime = SNAP_REGIME_UPPER; - scale_factor = mScaleSnapValue / drag_start_dist; - if( !uniform ) + if (!uniform) { scale_factor *= 0.5f; } } - else if (snap_enabled && dist_from_scale_line_2 > mSnapRegimeOffset * snap_dir_dot_mouse_offset2) + else if (snap_enabled && (mouse_on_plane2 - projected_drag_pos2) * mSnapGuideDir2 > mSnapRegimeOffset ) { - mInSnapRegime = TRUE; - LLVector3 projected_drag_pos = mouse_on_plane2 - (dist_from_scale_line_2 / snap_dir_dot_mouse_offset2) * mSnapGuideDir2; - F32 drag_dist = (projected_drag_pos - mScaleCenter) * mScaleDir; + F32 drag_dist = mScaleDir * projected_drag_pos2; // Projecting the drag position allows for negative results, vs using the length which will result in a "reverse scaling" bug. - F32 cur_subdivisions = llclamp(getSubdivisionLevel(projected_drag_pos, mScaleDir, mScaleSnapUnit2), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); + F32 cur_subdivisions = llclamp(getSubdivisionLevel(mScaleCenter + projected_drag_pos2, mScaleDir, mScaleSnapUnit2, mTickPixelSpacing2), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); F32 snap_dist = mScaleSnapUnit2 / (2.f * cur_subdivisions); F32 relative_snap_dist = fmodf(drag_dist + snap_dist, mScaleSnapUnit2 / cur_subdivisions); - mScaleSnapValue = llclamp((drag_dist - (relative_snap_dist - snap_dist)), min_scale, max_scale); + mScaleSnappedValue = llclamp((drag_dist - (relative_snap_dist - snap_dist)), min_scale, max_scale); + scale_factor = mScaleSnappedValue / dist_vec(drag_start_point_agent, drag_start_center_agent); + mScaleSnappedValue /= mScaleSnapUnit2 * 2.f; + mSnapRegime = SNAP_REGIME_LOWER; - scale_factor = mScaleSnapValue / drag_start_dist; - if( !uniform ) + if (!uniform) { scale_factor *= 0.5f; } } - else + else { - mInSnapRegime = FALSE; + mSnapRegime = SNAP_REGIME_NONE; + scale_factor = t; + if (!uniform) + { + scale_factor = 0.5f + (scale_factor * 0.5f); + } } + F32 max_scale_factor = get_default_max_prim_scale() / MIN_PRIM_SCALE; F32 min_scale_factor = MIN_PRIM_SCALE / get_default_max_prim_scale(); @@ -1008,7 +980,7 @@ void LLManipScale::dragCorner( S32 x, S32 y ) { const LLVector3& scale = selectNode->mSavedScale; cur->setScale( scale_factor * scale ); - + LLVector3 delta_pos; LLVector3 original_pos = cur->getPositionEdit(); LLVector3d new_pos_global = drag_global + (selectNode->mSavedPositionGlobal - drag_global) * scale_factor; @@ -1018,7 +990,7 @@ void LLManipScale::dragCorner( S32 x, S32 y ) } cur->setPositionAbsoluteGlobal( new_pos_global ); rebuild(cur); - + delta_pos = cur->getPositionEdit() - original_pos; if (selectNode->mIndividualSelection) @@ -1059,7 +1031,7 @@ void LLManipScale::dragCorner( S32 x, S32 y ) { const LLVector3& scale = selectNode->mSavedScale; cur->setScale( scale_factor * scale, FALSE ); - + if (!selectNode->mIndividualSelection) { cur->setPosition(selectNode->mSavedPositionLocal * scale_factor); @@ -1068,19 +1040,14 @@ void LLManipScale::dragCorner( S32 x, S32 y ) rebuild(cur); } } - - - - mDragPointGlobal = drag_point_global; } - +// Scale on a single axis void LLManipScale::dragFace( S32 x, S32 y ) { // Suppress scale if mouse hasn't moved. if (x == mLastMouseX && y == mLastMouseY) { - // sendUpdates(TRUE,TRUE,FALSE); return; } @@ -1093,9 +1060,9 @@ void LLManipScale::dragFace( S32 x, S32 y ) LLVector3 drag_start_center_agent = gAgent.getPosAgentFromGlobal(drag_start_center_global); LLVector3d drag_start_dir_d; - drag_start_dir_d.setVec(drag_start_point_global - drag_start_center_global); + drag_start_dir_d.set(drag_start_point_global - drag_start_center_global); LLVector3 drag_start_dir_f; - drag_start_dir_f.setVec(drag_start_dir_d); + drag_start_dir_f.set(drag_start_dir_d); LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); @@ -1139,26 +1106,26 @@ void LLManipScale::dragFace( S32 x, S32 y ) if (snap_enabled && dist_from_scale_line > mSnapRegimeOffset) { - mInSnapRegime = TRUE; + mSnapRegime = static_cast<ESnapRegimes>(SNAP_REGIME_UPPER | SNAP_REGIME_LOWER); // A face drag doesn't have split regimes. - if (dist_along_scale_line > max_drag_dist) + if (dist_along_scale_line > max_drag_dist) { - mScaleSnapValue = max_drag_dist; + mScaleSnappedValue = max_drag_dist; LLVector3 clamp_point = mScaleCenter + max_drag_dist * mScaleDir; - drag_delta.setVec(clamp_point - drag_start_point_agent); + drag_delta.set(clamp_point - drag_start_point_agent); } else if (dist_along_scale_line < min_drag_dist) { - mScaleSnapValue = min_drag_dist; + mScaleSnappedValue = min_drag_dist; LLVector3 clamp_point = mScaleCenter + min_drag_dist * mScaleDir; - drag_delta.setVec(clamp_point - drag_start_point_agent); + drag_delta.set(clamp_point - drag_start_point_agent); } else { F32 drag_dist = scale_center_to_mouse * mScaleDir; - F32 cur_subdivisions = llclamp(getSubdivisionLevel(mScaleCenter + mScaleDir * drag_dist, mScaleDir, mScaleSnapUnit1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); + F32 cur_subdivisions = llclamp(getSubdivisionLevel(mScaleCenter + mScaleDir * drag_dist, mScaleDir, mScaleSnapUnit1, mTickPixelSpacing1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); F32 snap_dist = mScaleSnapUnit1 / (2.f * cur_subdivisions); F32 relative_snap_dist = fmodf(drag_dist + snap_dist, mScaleSnapUnit1 / cur_subdivisions); relative_snap_dist -= snap_dist; @@ -1172,7 +1139,7 @@ void LLManipScale::dragFace( S32 x, S32 y ) drag_dist - max_drag_dist, drag_dist - min_drag_dist); - mScaleSnapValue = drag_dist - relative_snap_dist; + mScaleSnappedValue = drag_dist - relative_snap_dist; if (llabs(relative_snap_dist) < snap_dist) { @@ -1186,9 +1153,9 @@ void LLManipScale::dragFace( S32 x, S32 y ) } } } - else + else { - mInSnapRegime = FALSE; + mSnapRegime = SNAP_REGIME_NONE; } LLVector3 dir_agent; @@ -1204,7 +1171,7 @@ void LLManipScale::dragFace( S32 x, S32 y ) { dir_agent = bbox.localToAgentBasis( LLVector3::z_axis ); } - stretchFace( + stretchFace( projected_vec(drag_start_dir_f, dir_agent) + drag_start_center_agent, projected_vec(drag_delta, dir_agent)); @@ -1223,7 +1190,7 @@ void LLManipScale::sendUpdates( BOOL send_position_update, BOOL send_scale_updat U32 update_flags = UPD_NONE; if (send_position_update) update_flags |= UPD_POSITION; if (send_scale_update) update_flags |= UPD_SCALE; - + // BOOL send_type = SEND_INDIVIDUALS; if (corner) { @@ -1271,7 +1238,7 @@ void LLManipScale::stretchFace( const LLVector3& drag_start_agent, const LLVecto S32 axis_index = axis.mV[0] ? 0 : (axis.mV[1] ? 1 : 2 ); LLVector3 delta_local = end_local - start_local; - F32 delta_local_mag = delta_local.magVec(); + F32 delta_local_mag = delta_local.length(); LLVector3 dir_local; if (delta_local_mag == 0.f) { @@ -1291,13 +1258,13 @@ void LLManipScale::stretchFace( const LLVector3& drag_start_agent, const LLVecto LLVector3 scale = cur->getScale(); scale.mV[axis_index] = desired_scale; cur->setScale(scale, FALSE); - rebuild(cur); + rebuild(cur); LLVector3 delta_pos; if( !getUniform() ) { LLVector3 delta_pos_local = axis * (0.5f * desired_delta_size); LLVector3d delta_pos_global; - delta_pos_global.setVec(cur_bbox.localToAgent( delta_pos_local ) - cur_bbox.getCenterAgent()); + delta_pos_global.set(cur_bbox.localToAgent( delta_pos_local ) - cur_bbox.getCenterAgent()); LLVector3 cur_pos = cur->getPositionEdit(); if (cur->isRootEdit() && !cur->isAttachment()) @@ -1346,7 +1313,7 @@ void LLManipScale::stretchFace( const LLVector3& drag_start_agent, const LLVecto void LLManipScale::renderGuidelinesPart( const LLBBox& bbox ) { LLVector3 guideline_start = bbox.getCenterLocal(); - + LLVector3 guideline_end = unitVectorToLocalBBoxExtent( partToUnitVector( mManipPart ), bbox ); if (!getUniform()) @@ -1355,7 +1322,7 @@ void LLManipScale::renderGuidelinesPart( const LLBBox& bbox ) } guideline_end -= guideline_start; - guideline_end.normVec(); + guideline_end.normalize(); guideline_end *= LLWorld::getInstance()->getRegionWidthInMeters(); guideline_end += guideline_start; @@ -1376,26 +1343,27 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox) LLQuaternion grid_rotation; LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); + bool uniform = LLManipScale::getUniform(); + LLVector3 box_corner_agent = bbox.localToAgent(unitVectorToLocalBBoxExtent( partToUnitVector( mManipPart ), bbox )); - mScaleCenter = getUniform() ? bbox.getCenterAgent() : bbox.localToAgent(unitVectorToLocalBBoxExtent( -1.f * partToUnitVector( mManipPart ), bbox )); + mScaleCenter = uniform ? bbox.getCenterAgent() : bbox.localToAgent(unitVectorToLocalBBoxExtent( -1.f * partToUnitVector( mManipPart ), bbox )); mScaleDir = box_corner_agent - mScaleCenter; - mScaleDir.normVec(); + mScaleDir.normalize(); if(mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { mSnapRegimeOffset = SNAP_GUIDE_SCREEN_OFFSET / gAgentCamera.mHUDCurZoom; - } else { - F32 object_distance = dist_vec(mScaleCenter, LLViewerCamera::getInstance()->getOrigin()); + F32 object_distance = dist_vec(box_corner_agent, LLViewerCamera::getInstance()->getOrigin()); mSnapRegimeOffset = (SNAP_GUIDE_SCREEN_OFFSET * gViewerWindow->getWorldViewWidthRaw() * object_distance) / LLViewerCamera::getInstance()->getPixelMeterRatio(); } LLVector3 cam_at_axis; F32 snap_guide_length; if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { - cam_at_axis.setVec(1.f, 0.f, 0.f); + cam_at_axis.set(1.f, 0.f, 0.f); snap_guide_length = SNAP_GUIDE_SCREEN_LENGTH / gAgentCamera.mHUDCurZoom; } else @@ -1404,22 +1372,21 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox) F32 manipulator_distance = dist_vec(box_corner_agent, LLViewerCamera::getInstance()->getOrigin()); snap_guide_length = (SNAP_GUIDE_SCREEN_LENGTH * gViewerWindow->getWorldViewWidthRaw() * manipulator_distance) / LLViewerCamera::getInstance()->getPixelMeterRatio(); } - + mSnapGuideLength = snap_guide_length / llmax(0.1f, (llmin(mSnapGuideDir1 * cam_at_axis, mSnapGuideDir2 * cam_at_axis))); LLVector3 off_axis_dir = mScaleDir % cam_at_axis; - off_axis_dir.normVec(); + off_axis_dir.normalize(); if( (LL_FACE_MIN <= (S32)mManipPart) && ((S32)mManipPart <= LL_FACE_MAX) ) { - LLVector3 object_scale = bbox.getMaxLocal(); - object_scale.scaleVec(off_axis_dir * ~bbox.getRotation()); - object_scale.abs(); - if (object_scale.mV[VX] > object_scale.mV[VY] && object_scale.mV[VX] > object_scale.mV[VZ]) + LLVector3 bbox_relative_cam_dir = off_axis_dir * ~bbox.getRotation(); + bbox_relative_cam_dir.abs(); + if (bbox_relative_cam_dir.mV[VX] > bbox_relative_cam_dir.mV[VY] && bbox_relative_cam_dir.mV[VX] > bbox_relative_cam_dir.mV[VZ]) { mSnapGuideDir1 = LLVector3::x_axis * bbox.getRotation(); } - else if (object_scale.mV[VY] > object_scale.mV[VZ]) + else if (bbox_relative_cam_dir.mV[VY] > bbox_relative_cam_dir.mV[VZ]) { mSnapGuideDir1 = LLVector3::y_axis * bbox.getRotation(); } @@ -1429,7 +1396,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox) } LLVector3 scale_snap = grid_scale; - mScaleSnapUnit1 = scale_snap.scaleVec(partToUnitVector( mManipPart )).magVec(); + mScaleSnapUnit1 = scale_snap.scaleVec(partToUnitVector( mManipPart )).length(); mScaleSnapUnit2 = mScaleSnapUnit1; mSnapGuideDir1 *= mSnapGuideDir1 * LLViewerCamera::getInstance()->getUpAxis() > 0.f ? 1.f : -1.f; mSnapGuideDir2 = mSnapGuideDir1 * -1.f; @@ -1438,7 +1405,6 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox) } else if( (LL_CORNER_MIN <= (S32)mManipPart) && ((S32)mManipPart <= LL_CORNER_MAX) ) { - LLVector3 local_scale_dir = partToUnitVector( mManipPart ); LLVector3 local_camera_dir; if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { @@ -1446,74 +1412,133 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox) } else { - local_camera_dir = (LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent()) * ~bbox.getRotation(); - local_camera_dir.normVec(); - } - local_scale_dir -= projected_vec(local_scale_dir, local_camera_dir); - local_scale_dir.normVec(); - LLVector3 x_axis_proj_camera = LLVector3::x_axis - projected_vec(LLVector3::x_axis, local_camera_dir); - x_axis_proj_camera.normVec(); - LLVector3 y_axis_proj_camera = LLVector3::y_axis - projected_vec(LLVector3::y_axis, local_camera_dir); - y_axis_proj_camera.normVec(); - LLVector3 z_axis_proj_camera = LLVector3::z_axis - projected_vec(LLVector3::z_axis, local_camera_dir); - z_axis_proj_camera.normVec(); - F32 x_axis_proj = llabs(local_scale_dir * x_axis_proj_camera); - F32 y_axis_proj = llabs(local_scale_dir * y_axis_proj_camera); - F32 z_axis_proj = llabs(local_scale_dir * z_axis_proj_camera); - - if (x_axis_proj > y_axis_proj && x_axis_proj > z_axis_proj) - { - mSnapGuideDir1 = LLVector3::y_axis; - mScaleSnapUnit2 = grid_scale.mV[VY]; - mSnapGuideDir2 = LLVector3::z_axis; - mScaleSnapUnit1 = grid_scale.mV[VZ]; - } - else if (y_axis_proj > z_axis_proj) - { - mSnapGuideDir1 = LLVector3::x_axis; - mScaleSnapUnit2 = grid_scale.mV[VX]; - mSnapGuideDir2 = LLVector3::z_axis; - mScaleSnapUnit1 = grid_scale.mV[VZ]; - } - else - { - mSnapGuideDir1 = LLVector3::x_axis; - mScaleSnapUnit2 = grid_scale.mV[VX]; - mSnapGuideDir2 = LLVector3::y_axis; - mScaleSnapUnit1 = grid_scale.mV[VY]; + local_camera_dir = (LLViewerCamera::getInstance()->getOrigin() - box_corner_agent) * ~bbox.getRotation(); + local_camera_dir.normalize(); } - LLVector3 snap_guide_flip(1.f, 1.f, 1.f); + LLVector3 axis_flip; switch (mManipPart) { case LL_CORNER_NNN: + axis_flip.set(1.f, 1.f, 1.f); break; case LL_CORNER_NNP: - snap_guide_flip.setVec(1.f, 1.f, -1.f); + axis_flip.set(1.f, 1.f, -1.f); break; case LL_CORNER_NPN: - snap_guide_flip.setVec(1.f, -1.f, 1.f); + axis_flip.set(1.f, -1.f, 1.f); break; case LL_CORNER_NPP: - snap_guide_flip.setVec(1.f, -1.f, -1.f); + axis_flip.set(1.f, -1.f, -1.f); break; case LL_CORNER_PNN: - snap_guide_flip.setVec(-1.f, 1.f, 1.f); + axis_flip.set(-1.f, 1.f, 1.f); break; case LL_CORNER_PNP: - snap_guide_flip.setVec(-1.f, 1.f, -1.f); + axis_flip.set(-1.f, 1.f, -1.f); break; case LL_CORNER_PPN: - snap_guide_flip.setVec(-1.f, -1.f, 1.f); + axis_flip.set(-1.f, -1.f, 1.f); break; case LL_CORNER_PPP: - snap_guide_flip.setVec(-1.f, -1.f, -1.f); + axis_flip.set(-1.f, -1.f, -1.f); + break; + default: + break; + } + + // account for which side of the object the camera is located and negate appropriate axes + local_camera_dir.scaleVec(axis_flip); + + // normalize to object scale + LLVector3 bbox_extent = bbox.getExtentLocal(); + local_camera_dir.scaleVec(LLVector3(1.f / bbox_extent.mV[VX], 1.f / bbox_extent.mV[VY], 1.f / bbox_extent.mV[VZ])); + + S32 scale_face = -1; + + if ((local_camera_dir.mV[VX] > 0.f) == (local_camera_dir.mV[VY] > 0.f)) + { + if ((local_camera_dir.mV[VZ] > 0.f) == (local_camera_dir.mV[VY] > 0.f)) + { + LLVector3 local_camera_dir_abs = local_camera_dir; + local_camera_dir_abs.abs(); + // all neighboring faces of bbox are pointing towards camera or away from camera + // use largest magnitude face for snap guides + if (local_camera_dir_abs.mV[VX] > local_camera_dir_abs.mV[VY]) + { + if (local_camera_dir_abs.mV[VX] > local_camera_dir_abs.mV[VZ]) + { + scale_face = VX; + } + else + { + scale_face = VZ; + } + } + else // y > x + { + if (local_camera_dir_abs.mV[VY] > local_camera_dir_abs.mV[VZ]) + { + scale_face = VY; + } + else + { + scale_face = VZ; + } + } + } + else + { + // z axis facing opposite direction from x and y relative to camera, use x and y for snap guides + scale_face = VZ; + } + } + else // x and y axes are facing in opposite directions relative to camera + { + if ((local_camera_dir.mV[VZ] > 0.f) == (local_camera_dir.mV[VY] > 0.f)) + { + // x axis facing opposite direction from y and z relative to camera, use y and z for snap guides + scale_face = VX; + } + else + { + // y axis facing opposite direction from x and z relative to camera, use x and z for snap guides + scale_face = VY; + } + } + + switch(scale_face) + { + case VX: + // x axis face being scaled, use y and z for snap guides + mSnapGuideDir1 = LLVector3::y_axis.scaledVec(axis_flip); + mScaleSnapUnit1 = grid_scale.mV[VZ]; + mSnapGuideDir2 = LLVector3::z_axis.scaledVec(axis_flip); + mScaleSnapUnit2 = grid_scale.mV[VY]; + break; + case VY: + // y axis facing being scaled, use x and z for snap guides + mSnapGuideDir1 = LLVector3::x_axis.scaledVec(axis_flip); + mScaleSnapUnit1 = grid_scale.mV[VZ]; + mSnapGuideDir2 = LLVector3::z_axis.scaledVec(axis_flip); + mScaleSnapUnit2 = grid_scale.mV[VX]; + break; + case VZ: + // z axis facing being scaled, use x and y for snap guides + mSnapGuideDir1 = LLVector3::x_axis.scaledVec(axis_flip); + mScaleSnapUnit1 = grid_scale.mV[VY]; + mSnapGuideDir2 = LLVector3::y_axis.scaledVec(axis_flip); + mScaleSnapUnit2 = grid_scale.mV[VX]; break; default: + mSnapGuideDir1.setZero(); + mScaleSnapUnit1 = 0.f; + + mSnapGuideDir2.setZero(); + mScaleSnapUnit2 = 0.f; break; } - mSnapGuideDir1.scaleVec(snap_guide_flip); - mSnapGuideDir2.scaleVec(snap_guide_flip); + mSnapGuideDir1.rotVec(bbox.getRotation()); mSnapGuideDir2.rotVec(bbox.getRotation()); mSnapDir1 = -1.f * mSnapGuideDir2; @@ -1521,13 +1546,22 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox) } mScalePlaneNormal1 = mSnapGuideDir1 % mScaleDir; - mScalePlaneNormal1.normVec(); + mScalePlaneNormal1.normalize(); mScalePlaneNormal2 = mSnapGuideDir2 % mScaleDir; - mScalePlaneNormal2.normVec(); + mScalePlaneNormal2.normalize(); mScaleSnapUnit1 = mScaleSnapUnit1 / (mSnapDir1 * mScaleDir); mScaleSnapUnit2 = mScaleSnapUnit2 / (mSnapDir2 * mScaleDir); + + mTickPixelSpacing1 = llround((F32)MIN_DIVISION_PIXEL_WIDTH / (mScaleDir % mSnapGuideDir1).length()); + mTickPixelSpacing2 = llround((F32)MIN_DIVISION_PIXEL_WIDTH / (mScaleDir % mSnapGuideDir2).length()); + + if (uniform) + { + mScaleSnapUnit1 *= 0.5f; + mScaleSnapUnit2 *= 0.5f; + } } void LLManipScale::renderSnapGuides(const LLBBox& bbox) @@ -1537,7 +1571,6 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) return; } - F32 max_subdivisions = sGridMaxSubdivisionLevel; F32 grid_alpha = gSavedSettings.getF32("GridOpacity"); F32 max_point_on_scale_line = partToMaxScale(mManipPart, bbox); @@ -1551,10 +1584,10 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) LLColor4 tick_color = setupSnapGuideRenderPass(pass); gGL.begin(LLRender::LINES); - LLVector3 line_mid = mScaleCenter + (mScaleSnapValue * mScaleDir) + (mSnapGuideDir1 * mSnapRegimeOffset); - LLVector3 line_start = line_mid - (mScaleDir * (llmin(mScaleSnapValue, mSnapGuideLength * 0.5f))); - LLVector3 line_end = line_mid + (mScaleDir * llmin(max_point_on_scale_line - mScaleSnapValue, mSnapGuideLength * 0.5f)); - + LLVector3 line_mid = mScaleCenter + (mScaleSnappedValue * mScaleDir) + (mSnapGuideDir1 * mSnapRegimeOffset); + LLVector3 line_start = line_mid - (mScaleDir * (llmin(mScaleSnappedValue, mSnapGuideLength * 0.5f))); + LLVector3 line_end = line_mid + (mScaleDir * llmin(max_point_on_scale_line - mScaleSnappedValue, mSnapGuideLength * 0.5f)); + gGL.color4f(tick_color.mV[VRED], tick_color.mV[VGREEN], tick_color.mV[VBLUE], tick_color.mV[VALPHA] * 0.1f); gGL.vertex3fv(line_start.mV); gGL.color4fv(tick_color.mV); @@ -1563,9 +1596,9 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) gGL.color4f(tick_color.mV[VRED], tick_color.mV[VGREEN], tick_color.mV[VBLUE], tick_color.mV[VALPHA] * 0.1f); gGL.vertex3fv(line_end.mV); - line_mid = mScaleCenter + (mScaleSnapValue * mScaleDir) + (mSnapGuideDir2 * mSnapRegimeOffset); - line_start = line_mid - (mScaleDir * (llmin(mScaleSnapValue, mSnapGuideLength * 0.5f))); - line_end = line_mid + (mScaleDir * llmin(max_point_on_scale_line - mScaleSnapValue, mSnapGuideLength * 0.5f)); + line_mid = mScaleCenter + (mScaleSnappedValue * mScaleDir) + (mSnapGuideDir2 * mSnapRegimeOffset); + line_start = line_mid - (mScaleDir * (llmin(mScaleSnappedValue, mSnapGuideLength * 0.5f))); + line_end = line_mid + (mScaleDir * llmin(max_point_on_scale_line - mScaleSnappedValue, mSnapGuideLength * 0.5f)); gGL.vertex3fv(line_start.mV); gGL.color4fv(tick_color.mV); gGL.vertex3fv(line_mid.mV); @@ -1578,31 +1611,38 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) { LLGLDepthTest gls_depth(GL_FALSE); - F32 dist_grid_axis = (drag_point - mScaleCenter) * mScaleDir; + F32 dist_grid_axis = llmax(0.f, (drag_point - mScaleCenter) * mScaleDir); + + F32 smallest_subdivision1 = mScaleSnapUnit1 / sGridMaxSubdivisionLevel; + F32 smallest_subdivision2 = mScaleSnapUnit2 / sGridMaxSubdivisionLevel; + + F32 dist_scale_units_1 = dist_grid_axis / smallest_subdivision1; + F32 dist_scale_units_2 = dist_grid_axis / smallest_subdivision2; + // find distance to nearest smallest grid unit - F32 grid_offset1 = fmodf(dist_grid_axis, mScaleSnapUnit1 / max_subdivisions); - F32 grid_offset2 = fmodf(dist_grid_axis, mScaleSnapUnit2 / max_subdivisions); + F32 grid_multiple1 = llfloor(dist_scale_units_1); + F32 grid_multiple2 = llfloor(dist_scale_units_2); + F32 grid_offset1 = fmodf(dist_grid_axis, smallest_subdivision1); + F32 grid_offset2 = fmodf(dist_grid_axis, smallest_subdivision2); // how many smallest grid units are we away from largest grid scale? - S32 sub_div_offset_1 = llround(fmod(dist_grid_axis - grid_offset1, mScaleSnapUnit1 / sGridMinSubdivisionLevel) / (mScaleSnapUnit1 / max_subdivisions)); - S32 sub_div_offset_2 = llround(fmod(dist_grid_axis - grid_offset2, mScaleSnapUnit2 / sGridMinSubdivisionLevel) / (mScaleSnapUnit2 / max_subdivisions)); + S32 sub_div_offset_1 = llround(fmod(dist_grid_axis - grid_offset1, mScaleSnapUnit1 / sGridMinSubdivisionLevel) / smallest_subdivision1); + S32 sub_div_offset_2 = llround(fmod(dist_grid_axis - grid_offset2, mScaleSnapUnit2 / sGridMinSubdivisionLevel) / smallest_subdivision2); - S32 num_ticks_per_side1 = llmax(1, lltrunc(0.5f * mSnapGuideLength / (mScaleSnapUnit1 / max_subdivisions))); - S32 num_ticks_per_side2 = llmax(1, lltrunc(0.5f * mSnapGuideLength / (mScaleSnapUnit2 / max_subdivisions))); - F32 dist_scale_units_1 = dist_grid_axis / (mScaleSnapUnit1 / max_subdivisions); - F32 dist_scale_units_2 = dist_grid_axis / (mScaleSnapUnit2 / max_subdivisions); + S32 num_ticks_per_side1 = llmax(1, lltrunc(0.5f * mSnapGuideLength / smallest_subdivision1)); + S32 num_ticks_per_side2 = llmax(1, lltrunc(0.5f * mSnapGuideLength / smallest_subdivision2)); S32 ticks_from_scale_center_1 = lltrunc(dist_scale_units_1); S32 ticks_from_scale_center_2 = lltrunc(dist_scale_units_2); - S32 max_ticks1 = llceil(max_point_on_scale_line / (mScaleSnapUnit1 / max_subdivisions) - dist_scale_units_1); - S32 max_ticks2 = llceil(max_point_on_scale_line / (mScaleSnapUnit2 / max_subdivisions) - dist_scale_units_2); + S32 max_ticks1 = llceil(max_point_on_scale_line / smallest_subdivision1 - dist_scale_units_1); + S32 max_ticks2 = llceil(max_point_on_scale_line / smallest_subdivision2 - dist_scale_units_2); S32 start_tick = 0; S32 stop_tick = 0; - if (mInSnapRegime) + if (mSnapRegime != SNAP_REGIME_NONE) { // draw snap guide line gGL.begin(LLRender::LINES); - LLVector3 snap_line_center = mScaleCenter + (mScaleSnapValue * mScaleDir); + LLVector3 snap_line_center = bbox.localToAgent(unitVectorToLocalBBoxExtent( partToUnitVector( mManipPart ), bbox )); LLVector3 snap_line_start = snap_line_center + (mSnapGuideDir1 * mSnapRegimeOffset); LLVector3 snap_line_end = snap_line_center + (mSnapGuideDir2 * mSnapRegimeOffset); @@ -1624,22 +1664,22 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) LLVector3 arrow_span = mScaleDir; arrow_dir = snap_line_start - snap_line_center; - arrow_dir.normVec(); + arrow_dir.normalize(); gGL.vertex3fv((snap_line_start + arrow_dir * mBoxHandleSize).mV); gGL.vertex3fv((snap_line_start + arrow_span * mBoxHandleSize).mV); gGL.vertex3fv((snap_line_start - arrow_span * mBoxHandleSize).mV); arrow_dir = snap_line_end - snap_line_center; - arrow_dir.normVec(); + arrow_dir.normalize(); gGL.vertex3fv((snap_line_end + arrow_dir * mBoxHandleSize).mV); gGL.vertex3fv((snap_line_end + arrow_span * mBoxHandleSize).mV); gGL.vertex3fv((snap_line_end - arrow_span * mBoxHandleSize).mV); } gGL.end(); } - + LLVector2 screen_translate_axis(llabs(mScaleDir * LLViewerCamera::getInstance()->getLeftAxis()), llabs(mScaleDir * LLViewerCamera::getInstance()->getUpAxis())); - screen_translate_axis.normVec(); + screen_translate_axis.normalize(); S32 tick_label_spacing = llround(screen_translate_axis * sTickLabelSpacing); @@ -1655,17 +1695,17 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) for (S32 i = start_tick; i <= stop_tick; i++) { F32 alpha = (1.f - (1.f * ((F32)llabs(i) / (F32)num_ticks_per_side1))); - LLVector3 tick_pos = drag_point + (mScaleDir * (mScaleSnapUnit1 / max_subdivisions * (F32)i - grid_offset1)); + LLVector3 tick_pos = mScaleCenter + (mScaleDir * (grid_multiple1 + i) * smallest_subdivision1); - F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); + F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit1, mTickPixelSpacing1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); - if (fmodf((F32)(i + sub_div_offset_1), (max_subdivisions / cur_subdivisions)) != 0.f) + if (fmodf((F32)(i + sub_div_offset_1), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f) { continue; } F32 tick_scale = 1.f; - for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) + for (F32 division_level = sGridMaxSubdivisionLevel; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) { if (fmodf((F32)(i + sub_div_offset_1), division_level) == 0.f) { @@ -1688,17 +1728,17 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) for (S32 i = start_tick; i <= stop_tick; i++) { F32 alpha = (1.f - (1.f * ((F32)llabs(i) / (F32)num_ticks_per_side2))); - LLVector3 tick_pos = drag_point + (mScaleDir * (mScaleSnapUnit2 / max_subdivisions * (F32)i - grid_offset2)); + LLVector3 tick_pos = mScaleCenter + (mScaleDir * (grid_multiple2 + i) * smallest_subdivision2); - F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit2), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); + F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit2, mTickPixelSpacing2), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); - if (fmodf((F32)(i + sub_div_offset_2), (max_subdivisions / cur_subdivisions)) != 0.f) + if (fmodf((F32)(i + sub_div_offset_2), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f) { continue; } F32 tick_scale = 1.f; - for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) + for (F32 division_level = sGridMaxSubdivisionLevel; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) { if (fmodf((F32)(i + sub_div_offset_2), division_level) == 0.f) { @@ -1716,21 +1756,21 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) gGL.end(); } - // render tick labels + // render upper tick labels start_tick = -(llmin(ticks_from_scale_center_1, num_ticks_per_side1)); stop_tick = llmin(max_ticks1, num_ticks_per_side1); F32 grid_resolution = mObjectSelection->getSelectType() == SELECT_TYPE_HUD ? 0.25f : llmax(gSavedSettings.getF32("GridResolution"), 0.001f); - S32 label_sub_div_offset_1 = llround(fmod(dist_grid_axis - grid_offset1, mScaleSnapUnit1 * 32.f) / (mScaleSnapUnit1 / max_subdivisions)); - S32 label_sub_div_offset_2 = llround(fmod(dist_grid_axis - grid_offset2, mScaleSnapUnit2 * 32.f) / (mScaleSnapUnit2 / max_subdivisions)); + S32 label_sub_div_offset_1 = llround(fmod(dist_grid_axis - grid_offset1, mScaleSnapUnit1 * 32.f) / smallest_subdivision1); + S32 label_sub_div_offset_2 = llround(fmod(dist_grid_axis - grid_offset2, mScaleSnapUnit2 * 32.f) / smallest_subdivision2); for (S32 i = start_tick; i <= stop_tick; i++) { F32 tick_scale = 1.f; F32 alpha = grid_alpha * (1.f - (0.5f * ((F32)llabs(i) / (F32)num_ticks_per_side1))); - LLVector3 tick_pos = drag_point + (mScaleDir * (mScaleSnapUnit1 / max_subdivisions * (F32)i - grid_offset1)); + LLVector3 tick_pos = mScaleCenter + (mScaleDir * (grid_multiple1 + i) * smallest_subdivision1); - for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) + for (F32 division_level = sGridMaxSubdivisionLevel; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) { if (fmodf((F32)(i + label_sub_div_offset_1), division_level) == 0.f) { @@ -1739,39 +1779,34 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) tick_scale *= 0.7f; } - if (fmodf((F32)(i + label_sub_div_offset_1), (max_subdivisions / llmin(sGridMaxSubdivisionLevel, getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit1, tick_label_spacing)))) == 0.f) + if (fmodf((F32)(i + label_sub_div_offset_1), (sGridMaxSubdivisionLevel / llmin(sGridMaxSubdivisionLevel, getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit1, tick_label_spacing)))) == 0.f) { - LLVector3 text_origin = tick_pos + - (mSnapGuideDir1 * mSnapRegimeOffset * (1.f + tick_scale)); + LLVector3 text_origin = tick_pos + (mSnapGuideDir1 * mSnapRegimeOffset * (1.f + tick_scale)); EGridMode grid_mode = LLSelectMgr::getInstance()->getGridMode(); - F32 tick_val; + F32 tick_value; if (grid_mode == GRID_MODE_WORLD) { - tick_val = (tick_pos - mScaleCenter) * mScaleDir / (mScaleSnapUnit1 / grid_resolution); + tick_value = (grid_multiple1 + i) / (sGridMaxSubdivisionLevel / grid_resolution); } else { - tick_val = (tick_pos - mScaleCenter) * mScaleDir / (mScaleSnapUnit1 * 2.f); - } - - if (getUniform()) - { - tick_val *= 2.f; + tick_value = (grid_multiple1 + i) / (2.f * sGridMaxSubdivisionLevel); } F32 text_highlight = 0.8f; - if (is_approx_equal(tick_val, mScaleSnapValue) && mInSnapRegime) + // Highlight this text if the tick value matches the snapped to value, and if either the second set of ticks isn't going to be shown or cursor is in the first snap regime. + if (is_approx_equal(tick_value, mScaleSnappedValue) && (mScaleSnapUnit2 == mScaleSnapUnit1 || (mSnapRegime & SNAP_REGIME_UPPER))) { text_highlight = 1.f; } - renderTickValue(text_origin, tick_val, grid_mode == GRID_MODE_WORLD ? std::string("m") : std::string("x"), LLColor4(text_highlight, text_highlight, text_highlight, alpha)); + renderTickValue(text_origin, tick_value, grid_mode == GRID_MODE_WORLD ? std::string("m") : std::string("x"), LLColor4(text_highlight, text_highlight, text_highlight, alpha)); } } - // label ticks on opposite side + // label ticks on opposite side, only can happen in scaling modes that effect more than one axis and when the object's axis don't have the same scale. A differing scale indicates both conditions. if (mScaleSnapUnit2 != mScaleSnapUnit1) { start_tick = -(llmin(ticks_from_scale_center_2, num_ticks_per_side2)); @@ -1780,9 +1815,9 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) { F32 tick_scale = 1.f; F32 alpha = grid_alpha * (1.f - (0.5f * ((F32)llabs(i) / (F32)num_ticks_per_side2))); - LLVector3 tick_pos = drag_point + (mScaleDir * (mScaleSnapUnit2 / max_subdivisions * (F32)i - grid_offset2)); + LLVector3 tick_pos = mScaleCenter + (mScaleDir * (grid_multiple2 + i) * smallest_subdivision2); - for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) + for (F32 division_level = sGridMaxSubdivisionLevel; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) { if (fmodf((F32)(i + label_sub_div_offset_2), division_level) == 0.f) { @@ -1791,35 +1826,29 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) tick_scale *= 0.7f; } - if (fmodf((F32)(i + label_sub_div_offset_2), (max_subdivisions / llmin(max_subdivisions, getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit2, tick_label_spacing)))) == 0.f) + if (fmodf((F32)(i + label_sub_div_offset_2), (sGridMaxSubdivisionLevel / llmin(sGridMaxSubdivisionLevel, getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit2, tick_label_spacing)))) == 0.f) { - LLVector3 text_origin = tick_pos + - (mSnapGuideDir2 * mSnapRegimeOffset * (1.f + tick_scale)); + LLVector3 text_origin = tick_pos + (mSnapGuideDir2 * mSnapRegimeOffset * (1.f + tick_scale)); EGridMode grid_mode = LLSelectMgr::getInstance()->getGridMode(); - F32 tick_val; + F32 tick_value; if (grid_mode == GRID_MODE_WORLD) { - tick_val = (tick_pos - mScaleCenter) * mScaleDir / (mScaleSnapUnit2 / grid_resolution); + tick_value = (grid_multiple2 + i) / (sGridMaxSubdivisionLevel / grid_resolution); } else { - tick_val = (tick_pos - mScaleCenter) * mScaleDir / (mScaleSnapUnit2 * 2.f); - } - - if (getUniform()) - { - tick_val *= 2.f; + tick_value = (grid_multiple2 + i) / (2.f * sGridMaxSubdivisionLevel); } F32 text_highlight = 0.8f; - if (is_approx_equal(tick_val, mScaleSnapValue) && mInSnapRegime) + if (is_approx_equal(tick_value, mScaleSnappedValue) && (mSnapRegime & SNAP_REGIME_LOWER)) { text_highlight = 1.f; } - renderTickValue(text_origin, tick_val, grid_mode == GRID_MODE_WORLD ? std::string("m") : std::string("x"), LLColor4(text_highlight, text_highlight, text_highlight, alpha)); + renderTickValue(text_origin, tick_value, grid_mode == GRID_MODE_WORLD ? std::string("m") : std::string("x"), LLColor4(text_highlight, text_highlight, text_highlight, alpha)); } } } @@ -1845,13 +1874,13 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) LLVector3 help_text_pos = selection_center_start + (mSnapRegimeOffset * 5.f * offset_dir); const LLFontGL* big_fontp = LLFontGL::getFontSansSerif(); - std::string help_text = "Move mouse cursor over ruler"; + std::string help_text = LLTrans::getString("manip_hint1"); LLColor4 help_text_color = LLColor4::white; help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, grid_alpha, 0.f); - hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD); - help_text = "to snap to grid"; + hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false); + help_text = LLTrans::getString("manip_hint2"); help_text_pos -= LLViewerCamera::getInstance()->getUpAxis() * mSnapRegimeOffset * 0.4f; - hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD); + hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false); } } } @@ -1860,17 +1889,15 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) // Returns unit vector in direction of part of an origin-centered cube LLVector3 LLManipScale::partToUnitVector( S32 part ) const { - if( (LL_FACE_MIN <= part) && (part <= LL_FACE_MAX) ) + if ( (LL_FACE_MIN <= part) && (part <= LL_FACE_MAX) ) { return faceToUnitVector( part ); } - else - if( (LL_CORNER_MIN <= part) && (part <= LL_CORNER_MAX) ) + else if ( (LL_CORNER_MIN <= part) && (part <= LL_CORNER_MAX) ) { return cornerToUnitVector( part ); } - else - if( (LL_EDGE_MIN <= part) && (part <= LL_EDGE_MAX ) ) + else if ( (LL_EDGE_MIN <= part) && (part <= LL_EDGE_MAX ) ) { return edgeToUnitVector( part ); } @@ -1882,27 +1909,32 @@ LLVector3 LLManipScale::partToUnitVector( S32 part ) const LLVector3 LLManipScale::faceToUnitVector( S32 part ) const { llassert( (LL_FACE_MIN <= part) && (part <= LL_FACE_MAX) ); + LLVector3 vec; switch( part ) { case LL_FACE_POSX: - return LLVector3( 1.f, 0.f, 0.f ); - + vec.set( 1.f, 0.f, 0.f ); + break; case LL_FACE_NEGX: - return LLVector3( -1.f, 0.f, 0.f ); - + vec.set( -1.f, 0.f, 0.f ); + break; case LL_FACE_POSY: - return LLVector3( 0.f, 1.f, 0.f ); - + vec.set( 0.f, 1.f, 0.f ); + break; case LL_FACE_NEGY: - return LLVector3( 0.f, -1.f, 0.f ); - + vec.set( 0.f, -1.f, 0.f ); + break; case LL_FACE_POSZ: - return LLVector3( 0.f, 0.f, 1.f ); - + vec.set( 0.f, 0.f, 1.f ); + break; case LL_FACE_NEGZ: - return LLVector3( 0.f, 0.f, -1.f ); + vec.set( 0.f, 0.f, -1.f ); + break; + default: + vec.clear(); } - return LLVector3(); + + return vec; } @@ -1914,31 +1946,31 @@ LLVector3 LLManipScale::cornerToUnitVector( S32 part ) const switch(part) { case LL_CORNER_NNN: - vec.setVec(-F_SQRT3, -F_SQRT3, -F_SQRT3); + vec.set(-OO_SQRT3, -OO_SQRT3, -OO_SQRT3); break; - case LL_CORNER_NNP: - vec.setVec(-F_SQRT3, -F_SQRT3, F_SQRT3); + case LL_CORNER_NNP: + vec.set(-OO_SQRT3, -OO_SQRT3, OO_SQRT3); break; case LL_CORNER_NPN: - vec.setVec(-F_SQRT3, F_SQRT3, -F_SQRT3); + vec.set(-OO_SQRT3, OO_SQRT3, -OO_SQRT3); break; case LL_CORNER_NPP: - vec.setVec(-F_SQRT3, F_SQRT3, F_SQRT3); + vec.set(-OO_SQRT3, OO_SQRT3, OO_SQRT3); break; case LL_CORNER_PNN: - vec.setVec(F_SQRT3, -F_SQRT3, -F_SQRT3); + vec.set(OO_SQRT3, -OO_SQRT3, -OO_SQRT3); break; case LL_CORNER_PNP: - vec.setVec(F_SQRT3, -F_SQRT3, F_SQRT3); + vec.set(OO_SQRT3, -OO_SQRT3, OO_SQRT3); break; case LL_CORNER_PPN: - vec.setVec(F_SQRT3, F_SQRT3, -F_SQRT3); + vec.set(OO_SQRT3, OO_SQRT3, -OO_SQRT3); break; case LL_CORNER_PPP: - vec.setVec(F_SQRT3, F_SQRT3, F_SQRT3); + vec.set(OO_SQRT3, OO_SQRT3, OO_SQRT3); break; default: - vec.clearVec(); + vec.clear(); } return vec; @@ -1965,8 +1997,8 @@ LLVector3 LLManipScale::unitVectorToLocalBBoxExtent( const LLVector3& v, const L LLVector3 ctr = bbox.getCenterLocal(); return LLVector3( - v.mV[0] ? (v.mV[0]>0 ? max.mV[0] : min.mV[0] ) : ctr.mV[0], - v.mV[1] ? (v.mV[1]>0 ? max.mV[1] : min.mV[1] ) : ctr.mV[1], + v.mV[0] ? (v.mV[0]>0 ? max.mV[0] : min.mV[0] ) : ctr.mV[0], + v.mV[1] ? (v.mV[1]>0 ? max.mV[1] : min.mV[1] ) : ctr.mV[1], v.mV[2] ? (v.mV[2]>0 ? max.mV[2] : min.mV[2] ) : ctr.mV[2] ); } @@ -1984,7 +2016,7 @@ F32 LLManipScale::partToMaxScale( S32 part, const LLBBox &bbox ) const max_extent = bbox_extents.mV[i]; } } - max_scale_factor = bbox_extents.magVec() * get_default_max_prim_scale() / max_extent; + max_scale_factor = bbox_extents.length() * get_default_max_prim_scale() / max_extent; if (getUniform()) { @@ -2007,7 +2039,7 @@ F32 LLManipScale::partToMinScale( S32 part, const LLBBox &bbox ) const min_extent = bbox_extents.mV[i]; } } - F32 min_scale_factor = bbox_extents.magVec() * MIN_PRIM_SCALE / min_extent; + F32 min_scale_factor = bbox_extents.length() * MIN_PRIM_SCALE / min_extent; if (getUniform()) { @@ -2058,7 +2090,7 @@ LLVector3 LLManipScale::nearestAxis( const LLVector3& v ) const // virtual BOOL LLManipScale::canAffectSelection() { - // An selection is scalable if you are allowed to both edit and move + // An selection is scalable if you are allowed to both edit and move // everything in it, and it does not have any sitting agents BOOL can_scale = mObjectSelection->getObjectCount() != 0; if (can_scale) |