diff options
Diffstat (limited to 'indra/newview/llmaniptranslate.cpp')
-rw-r--r-- | indra/newview/llmaniptranslate.cpp | 4171 |
1 files changed, 2091 insertions, 2080 deletions
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 8cd7f44f70..9fc5ad502c 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llmaniptranslate.cpp * @brief LLManipTranslate class implementation * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -76,202 +76,202 @@ const F32 SNAP_ARROW_SCALE = 0.7f; static LLPointer<LLViewerTexture> sGridTex = NULL ; -const LLManip::EManipPart MANIPULATOR_IDS[9] = +const LLManip::EManipPart MANIPULATOR_IDS[9] = { - LLManip::LL_X_ARROW, - LLManip::LL_Y_ARROW, - LLManip::LL_Z_ARROW, - LLManip::LL_X_ARROW, - LLManip::LL_Y_ARROW, - LLManip::LL_Z_ARROW, - LLManip::LL_YZ_PLANE, - LLManip::LL_XZ_PLANE, - LLManip::LL_XY_PLANE + LLManip::LL_X_ARROW, + LLManip::LL_Y_ARROW, + LLManip::LL_Z_ARROW, + LLManip::LL_X_ARROW, + LLManip::LL_Y_ARROW, + LLManip::LL_Z_ARROW, + LLManip::LL_YZ_PLANE, + LLManip::LL_XZ_PLANE, + LLManip::LL_XY_PLANE }; -const U32 ARROW_TO_AXIS[4] = +const U32 ARROW_TO_AXIS[4] = { - VX, - VX, - VY, - VZ + VX, + VX, + VY, + VZ }; // Sort manipulator handles by their screen-space projection struct ClosestToCamera { - bool operator()(const LLManipTranslate::ManipulatorHandle& a, - const LLManipTranslate::ManipulatorHandle& b) const - { - return a.mEndPosition.mV[VZ] < b.mEndPosition.mV[VZ]; - } + bool operator()(const LLManipTranslate::ManipulatorHandle& a, + const LLManipTranslate::ManipulatorHandle& b) const + { + return a.mEndPosition.mV[VZ] < b.mEndPosition.mV[VZ]; + } }; LLManipTranslate::LLManipTranslate( LLToolComposite* composite ) -: LLManip( std::string("Move"), composite ), - mLastHoverMouseX(-1), - mLastHoverMouseY(-1), - mMouseOutsideSlop(FALSE), - mCopyMadeThisDrag(FALSE), - mMouseDownX(-1), - mMouseDownY(-1), - mAxisArrowLength(50), - mConeSize(0), - mArrowLengthMeters(0.f), - mGridSizeMeters(1.f), - mPlaneManipOffsetMeters(0.f), - mUpdateTimer(), - mSnapOffsetMeters(0.f), - mSubdivisions(10.f), - mInSnapRegime(FALSE), - mArrowScales(1.f, 1.f, 1.f), - mPlaneScales(1.f, 1.f, 1.f), - mPlaneManipPositions(1.f, 1.f, 1.f, 1.f) -{ - if (sGridTex.isNull()) - { - restoreGL(); - } +: LLManip( std::string("Move"), composite ), + mLastHoverMouseX(-1), + mLastHoverMouseY(-1), + mMouseOutsideSlop(FALSE), + mCopyMadeThisDrag(FALSE), + mMouseDownX(-1), + mMouseDownY(-1), + mAxisArrowLength(50), + mConeSize(0), + mArrowLengthMeters(0.f), + mGridSizeMeters(1.f), + mPlaneManipOffsetMeters(0.f), + mUpdateTimer(), + mSnapOffsetMeters(0.f), + mSubdivisions(10.f), + mInSnapRegime(FALSE), + mArrowScales(1.f, 1.f, 1.f), + mPlaneScales(1.f, 1.f, 1.f), + mPlaneManipPositions(1.f, 1.f, 1.f, 1.f) +{ + if (sGridTex.isNull()) + { + restoreGL(); + } } //static U32 LLManipTranslate::getGridTexName() { - if(sGridTex.isNull()) - { - restoreGL() ; - } + if(sGridTex.isNull()) + { + restoreGL() ; + } - return sGridTex.isNull() ? 0 : sGridTex->getTexName() ; + return sGridTex.isNull() ? 0 : sGridTex->getTexName() ; } //static void LLManipTranslate::destroyGL() { - if (sGridTex) - { - sGridTex = NULL ; - } + if (sGridTex) + { + sGridTex = NULL ; + } } //static void LLManipTranslate::restoreGL() { - //generate grid texture - U32 rez = 512; - U32 mip = 0; - - destroyGL() ; - sGridTex = LLViewerTextureManager::getLocalTexture() ; - if(!sGridTex->createGLTexture()) - { - sGridTex = NULL ; - return ; - } - - GLuint* d = new GLuint[rez*rez]; - - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex->getTexName(), true); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); - - while (rez >= 1) - { - for (U32 i = 0; i < rez*rez; i++) - { - d[i] = 0x00FFFFFF; - } - - U32 subcol = 0xFFFFFFFF; - if (rez >= 4) - { //large grain grid - for (U32 i = 0; i < rez; i++) - { - if (rez <= 16) - { - if (rez == 16) - { - subcol = 0xA0FFFFFF; - } - else if (rez == 8) - { - subcol = 0x80FFFFFF; - } - else - { - subcol = 0x40FFFFFF; - } - } - else - { - subcol = 0xFFFFFFFF; - } - d[i *rez+ 0 ] = subcol; - d[0 *rez+ i ] = subcol; - if (rez >= 32) - { - d[i *rez+ (rez-1)] = subcol; - d[(rez-1) *rez+ i ] = subcol; - } - - if (rez >= 64) - { - subcol = 0xFFFFFFFF; - - if (i > 0 && i < (rez-1)) - { - d[i *rez+ 1 ] = subcol; - d[i *rez+ (rez-2)] = subcol; - d[1 *rez+ i ] = subcol; - d[(rez-2) *rez+ i ] = subcol; - } - } - } - } - - subcol = 0x50A0A0A0; - if (rez >= 128) - { //small grain grid - for (U32 i = 8; i < rez; i+=8) - { - for (U32 j = 2; j < rez-2; j++) - { - d[i *rez+ j] = subcol; - d[j *rez+ i] = subcol; - } - } - } - if (rez >= 64) - { //medium grain grid - if (rez == 64) - { - subcol = 0x50A0A0A0; - } - else - { - subcol = 0xA0D0D0D0; - } - - for (U32 i = 32; i < rez; i+=32) - { - U32 pi = i-1; - for (U32 j = 2; j < rez-2; j++) - { - d[i *rez+ j] = subcol; - d[j *rez+ i] = subcol; - - if (rez > 128) - { - d[pi *rez+ j] = subcol; - d[j *rez+ pi] = subcol; - } - } - } - } - LLImageGL::setManualImage(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, GL_RGBA, GL_UNSIGNED_BYTE, d); - rez = rez >> 1; - mip++; - } - delete [] d; + //generate grid texture + U32 rez = 512; + U32 mip = 0; + + destroyGL() ; + sGridTex = LLViewerTextureManager::getLocalTexture() ; + if(!sGridTex->createGLTexture()) + { + sGridTex = NULL ; + return ; + } + + GLuint* d = new GLuint[rez*rez]; + + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex->getTexName(), true); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); + + while (rez >= 1) + { + for (U32 i = 0; i < rez*rez; i++) + { + d[i] = 0x00FFFFFF; + } + + U32 subcol = 0xFFFFFFFF; + if (rez >= 4) + { //large grain grid + for (U32 i = 0; i < rez; i++) + { + if (rez <= 16) + { + if (rez == 16) + { + subcol = 0xA0FFFFFF; + } + else if (rez == 8) + { + subcol = 0x80FFFFFF; + } + else + { + subcol = 0x40FFFFFF; + } + } + else + { + subcol = 0xFFFFFFFF; + } + d[i *rez+ 0 ] = subcol; + d[0 *rez+ i ] = subcol; + if (rez >= 32) + { + d[i *rez+ (rez-1)] = subcol; + d[(rez-1) *rez+ i ] = subcol; + } + + if (rez >= 64) + { + subcol = 0xFFFFFFFF; + + if (i > 0 && i < (rez-1)) + { + d[i *rez+ 1 ] = subcol; + d[i *rez+ (rez-2)] = subcol; + d[1 *rez+ i ] = subcol; + d[(rez-2) *rez+ i ] = subcol; + } + } + } + } + + subcol = 0x50A0A0A0; + if (rez >= 128) + { //small grain grid + for (U32 i = 8; i < rez; i+=8) + { + for (U32 j = 2; j < rez-2; j++) + { + d[i *rez+ j] = subcol; + d[j *rez+ i] = subcol; + } + } + } + if (rez >= 64) + { //medium grain grid + if (rez == 64) + { + subcol = 0x50A0A0A0; + } + else + { + subcol = 0xA0D0D0D0; + } + + for (U32 i = 32; i < rez; i+=32) + { + U32 pi = i-1; + for (U32 j = 2; j < rez-2; j++) + { + d[i *rez+ j] = subcol; + d[j *rez+ i] = subcol; + + if (rez > 128) + { + d[pi *rez+ j] = subcol; + d[j *rez+ pi] = subcol; + } + } + } + } + LLImageGL::setManualImage(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, GL_RGBA, GL_UNSIGNED_BYTE, d); + rez = rez >> 1; + mip++; + } + delete [] d; } @@ -282,2018 +282,2029 @@ LLManipTranslate::~LLManipTranslate() void LLManipTranslate::handleSelect() { - LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); if (gFloaterTools) { gFloaterTools->setStatusText("move"); } - LLManip::handleSelect(); + LLManip::handleSelect(); } BOOL LLManipTranslate::handleMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - - // didn't click in any UI object, so must have clicked in the world - if( (mHighlightedPart == LL_X_ARROW || - mHighlightedPart == LL_Y_ARROW || - mHighlightedPart == LL_Z_ARROW || - mHighlightedPart == LL_YZ_PLANE || - mHighlightedPart == LL_XZ_PLANE || - mHighlightedPart == LL_XY_PLANE ) ) - { - handled = handleMouseDownOnPart( x, y, mask ); - } - - return handled; + BOOL handled = FALSE; + + // didn't click in any UI object, so must have clicked in the world + if( (mHighlightedPart == LL_X_ARROW || + mHighlightedPart == LL_Y_ARROW || + mHighlightedPart == LL_Z_ARROW || + mHighlightedPart == LL_YZ_PLANE || + mHighlightedPart == LL_XZ_PLANE || + mHighlightedPart == LL_XY_PLANE ) ) + { + handled = handleMouseDownOnPart( x, y, mask ); + } + + return handled; } // Assumes that one of the arrows on an object was hit. BOOL LLManipTranslate::handleMouseDownOnPart( S32 x, S32 y, MASK mask ) { - BOOL can_move = canAffectSelection(); - if (!can_move) - { - return FALSE; - } - - highlightManipulators(x, y); - S32 hit_part = mHighlightedPart; - - if( (hit_part != LL_X_ARROW) && - (hit_part != LL_Y_ARROW) && - (hit_part != LL_Z_ARROW) && - (hit_part != LL_YZ_PLANE) && - (hit_part != LL_XZ_PLANE) && - (hit_part != LL_XY_PLANE) ) - { - return TRUE; - } - - mHelpTextTimer.reset(); - sNumTimesHelpTextShown++; - - LLSelectMgr::getInstance()->getGrid(mGridOrigin, mGridRotation, mGridScale); - - LLSelectMgr::getInstance()->enableSilhouette(FALSE); - - // we just started a drag, so save initial object positions - LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_MOVE); - - mManipPart = (EManipPart)hit_part; - mMouseDownX = x; - mMouseDownY = y; - mMouseOutsideSlop = FALSE; - - LLVector3 axis; - - LLSelectNode *selectNode = mObjectSelection->getFirstMoveableNode(TRUE); - - if (!selectNode) - { - // didn't find the object in our selection...oh well - LL_WARNS() << "Trying to translate an unselected object" << LL_ENDL; - return TRUE; - } - - LLViewerObject *selected_object = selectNode->getObject(); - if (!selected_object) - { - // somehow we lost the object! - LL_WARNS() << "Translate manip lost the object, no selected object" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - return TRUE; - } - - // Compute unit vectors for arrow hit and a plane through that vector - BOOL axis_exists = getManipAxis(selected_object, mManipPart, axis); - getManipNormal(selected_object, mManipPart, mManipNormal); - - //LLVector3 select_center_agent = gAgent.getPosAgentFromGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal()); - // TomY: The above should (?) be identical to the below - LLVector3 select_center_agent = getPivotPoint(); - mSubdivisions = getSubdivisionLevel(select_center_agent, axis_exists ? axis : LLVector3::z_axis, getMinGridScale()); - - // if we clicked on a planar manipulator, recenter mouse cursor - if (mManipPart >= LL_YZ_PLANE && mManipPart <= LL_XY_PLANE) - { - LLCoordGL mouse_pos; - if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(select_center_agent, mouse_pos)) - { - // mouse_pos may be nonsense - LL_WARNS() << "Failed to project object center to screen" << LL_ENDL; - } - else if (gSavedSettings.getBOOL("SnapToMouseCursor")) - { - LLUI::getInstance()->setMousePositionScreen(mouse_pos.mX, mouse_pos.mY); - x = mouse_pos.mX; - y = mouse_pos.mY; - } - } - - LLSelectMgr::getInstance()->updateSelectionCenter(); - LLVector3d object_start_global = gAgent.getPosGlobalFromAgent(getPivotPoint()); - getMousePointOnPlaneGlobal(mDragCursorStartGlobal, x, y, object_start_global, mManipNormal); - mDragSelectionStartGlobal = object_start_global; - mCopyMadeThisDrag = FALSE; - - // Route future Mouse messages here preemptively. (Release on mouse up.) - setMouseCapture( TRUE ); - - return TRUE; + BOOL can_move = canAffectSelection(); + if (!can_move) + { + return FALSE; + } + + highlightManipulators(x, y); + S32 hit_part = mHighlightedPart; + + if( (hit_part != LL_X_ARROW) && + (hit_part != LL_Y_ARROW) && + (hit_part != LL_Z_ARROW) && + (hit_part != LL_YZ_PLANE) && + (hit_part != LL_XZ_PLANE) && + (hit_part != LL_XY_PLANE) ) + { + return TRUE; + } + + mHelpTextTimer.reset(); + sNumTimesHelpTextShown++; + + LLSelectMgr::getInstance()->getGrid(mGridOrigin, mGridRotation, mGridScale); + + LLSelectMgr::getInstance()->enableSilhouette(FALSE); + + // we just started a drag, so save initial object positions + LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_MOVE); + + mManipPart = (EManipPart)hit_part; + mMouseDownX = x; + mMouseDownY = y; + mMouseOutsideSlop = FALSE; + + LLVector3 axis; + + LLSelectNode *selectNode = mObjectSelection->getFirstMoveableNode(TRUE); + + if (!selectNode) + { + // didn't find the object in our selection...oh well + LL_WARNS() << "Trying to translate an unselected object" << LL_ENDL; + return TRUE; + } + + LLViewerObject *selected_object = selectNode->getObject(); + if (!selected_object) + { + // somehow we lost the object! + LL_WARNS() << "Translate manip lost the object, no selected object" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + return TRUE; + } + + // Compute unit vectors for arrow hit and a plane through that vector + BOOL axis_exists = getManipAxis(selected_object, mManipPart, axis); + getManipNormal(selected_object, mManipPart, mManipNormal); + + //LLVector3 select_center_agent = gAgent.getPosAgentFromGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal()); + // TomY: The above should (?) be identical to the below + LLVector3 select_center_agent = getPivotPoint(); + mSubdivisions = getSubdivisionLevel(select_center_agent, axis_exists ? axis : LLVector3::z_axis, getMinGridScale()); + + // if we clicked on a planar manipulator, recenter mouse cursor + if (mManipPart >= LL_YZ_PLANE && mManipPart <= LL_XY_PLANE) + { + LLCoordGL mouse_pos; + if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(select_center_agent, mouse_pos)) + { + // mouse_pos may be nonsense + LL_WARNS() << "Failed to project object center to screen" << LL_ENDL; + } + else if (gSavedSettings.getBOOL("SnapToMouseCursor")) + { + LLUI::getInstance()->setMousePositionScreen(mouse_pos.mX, mouse_pos.mY); + x = mouse_pos.mX; + y = mouse_pos.mY; + } + } + + LLSelectMgr::getInstance()->updateSelectionCenter(); + LLVector3d object_start_global = gAgent.getPosGlobalFromAgent(getPivotPoint()); + getMousePointOnPlaneGlobal(mDragCursorStartGlobal, x, y, object_start_global, mManipNormal); + mDragSelectionStartGlobal = object_start_global; + mCopyMadeThisDrag = FALSE; + + // Route future Mouse messages here preemptively. (Release on mouse up.) + setMouseCapture( TRUE ); + + return TRUE; } BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) { - // Translation tool only works if mouse button is down. - // Bail out if mouse not down. - if( !hasMouseCapture() ) - { - LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (inactive)" << LL_ENDL; - // Always show cursor - // gViewerWindow->setCursor(UI_CURSOR_ARROW); - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - - highlightManipulators(x, y); - return TRUE; - } - - // Handle auto-rotation if necessary. - LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); - const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD; - const S32 ROTATE_H_MARGIN = world_rect.getWidth() / 20; - const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped; - BOOL rotated = FALSE; - - // ...build mode moves camera about focus point - if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD) - { - if (x < ROTATE_H_MARGIN) - { - gAgentCamera.cameraOrbitAround(rotate_angle); - rotated = TRUE; - } - else if (x > world_rect.getWidth() - ROTATE_H_MARGIN) - { - gAgentCamera.cameraOrbitAround(-rotate_angle); - rotated = TRUE; - } - } - - // Suppress processing if mouse hasn't actually moved. - // This may cause problems if the camera moves outside of the - // rotation above. - if( x == mLastHoverMouseX && y == mLastHoverMouseY && !rotated) - { - LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (mouse unmoved)" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - return TRUE; - } - mLastHoverMouseX = x; - mLastHoverMouseY = y; - - // Suppress if mouse hasn't moved past the initial slop region - // Reset once we start moving - if( !mMouseOutsideSlop ) - { - if (abs(mMouseDownX - x) < MOUSE_DRAG_SLOP && abs(mMouseDownY - y) < MOUSE_DRAG_SLOP ) - { - LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (mouse inside slop)" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - return TRUE; - } - else - { - // ...just went outside the slop region - mMouseOutsideSlop = TRUE; - // If holding down shift, leave behind a copy. - if (mask == MASK_COPY) - { - // ...we're trying to make a copy - LLSelectMgr::getInstance()->selectDuplicate(LLVector3::zero, FALSE); - mCopyMadeThisDrag = TRUE; - - // When we make the copy, we don't want to do any other processing. - // If so, the object will also be moved, and the copy will be offset. - LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (made copy)" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - } - } - } - - // Throttle updates to 10 per second. - - LLVector3 axis_f; - LLVector3d axis_d; - - // pick the first object to constrain to grid w/ common origin - // this is so we don't screw up groups - LLSelectNode* selectNode = mObjectSelection->getFirstMoveableNode(TRUE); - if (!selectNode) - { - // somehow we lost the object! - LL_WARNS() << "Translate manip lost the object, no selectNode" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - return TRUE; - } - - LLViewerObject* object = selectNode->getObject(); - if (!object) - { - // somehow we lost the object! - LL_WARNS() << "Translate manip lost the object, no object in selectNode" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - return TRUE; - } - - // Compute unit vectors for arrow hit and a plane through that vector - BOOL axis_exists = getManipAxis(object, mManipPart, axis_f); // TODO: move this - - axis_d.setVec(axis_f); - - LLSelectMgr::getInstance()->updateSelectionCenter(); - LLVector3d current_pos_global = gAgent.getPosGlobalFromAgent(getPivotPoint()); - - mSubdivisions = getSubdivisionLevel(getPivotPoint(), axis_f, getMinGridScale()); - - // Project the cursor onto that plane - LLVector3d relative_move; - getMousePointOnPlaneGlobal(relative_move, x, y, current_pos_global, mManipNormal);\ - relative_move -= mDragCursorStartGlobal; - - // You can't move more than some distance from your original mousedown point. - if (gSavedSettings.getBOOL("LimitDragDistance")) - { - F32 max_drag_distance = gSavedSettings.getF32("MaxDragDistance"); - - if (relative_move.magVecSquared() > max_drag_distance * max_drag_distance) - { - LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (too far)" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_NOLOCKED); - return TRUE; - } - } - - F64 axis_magnitude = relative_move * axis_d; // dot product - LLVector3d cursor_point_snap_line; - - F64 off_axis_magnitude; - - getMousePointOnPlaneGlobal(cursor_point_snap_line, x, y, current_pos_global, mSnapOffsetAxis % axis_f); - off_axis_magnitude = axis_exists ? llabs((cursor_point_snap_line - current_pos_global) * LLVector3d(mSnapOffsetAxis)) : 0.f; - - if (gSavedSettings.getBOOL("SnapEnabled")) - { - if (off_axis_magnitude > mSnapOffsetMeters) - { - mInSnapRegime = TRUE; - LLVector3 cursor_snap_agent = gAgent.getPosAgentFromGlobal(cursor_point_snap_line); - - F32 cursor_grid_dist = (cursor_snap_agent - mGridOrigin) * axis_f; - - F32 snap_dist = getMinGridScale() / (2.f * mSubdivisions); - F32 relative_snap_dist = fmodf(llabs(cursor_grid_dist) + snap_dist, getMinGridScale() / mSubdivisions); - if (relative_snap_dist < snap_dist * 2.f) - { - if (cursor_grid_dist > 0.f) - { - cursor_grid_dist -= relative_snap_dist - snap_dist; - } - else - { - cursor_grid_dist += relative_snap_dist - snap_dist; - } - } - - F32 object_start_on_axis = (gAgent.getPosAgentFromGlobal(mDragSelectionStartGlobal) - mGridOrigin) * axis_f; - axis_magnitude = cursor_grid_dist - object_start_on_axis; - } - else if (mManipPart >= LL_YZ_PLANE && mManipPart <= LL_XY_PLANE) - { - // subtract offset from object center - LLVector3d cursor_point_global; - getMousePointOnPlaneGlobal( cursor_point_global, x, y, current_pos_global, mManipNormal ); - cursor_point_global -= (mDragCursorStartGlobal - mDragSelectionStartGlobal); - - // snap to planar grid - LLVector3 cursor_point_agent = gAgent.getPosAgentFromGlobal(cursor_point_global); - LLVector3 camera_plane_projection = LLViewerCamera::getInstance()->getAtAxis(); - camera_plane_projection -= projected_vec(camera_plane_projection, mManipNormal); - camera_plane_projection.normVec(); - LLVector3 camera_projected_dir = camera_plane_projection; - camera_plane_projection.rotVec(~mGridRotation); - camera_plane_projection.scaleVec(mGridScale); - camera_plane_projection.abs(); - F32 max_grid_scale; - if (camera_plane_projection.mV[VX] > camera_plane_projection.mV[VY] && - camera_plane_projection.mV[VX] > camera_plane_projection.mV[VZ]) - { - max_grid_scale = mGridScale.mV[VX]; - } - else if (camera_plane_projection.mV[VY] > camera_plane_projection.mV[VZ]) - { - max_grid_scale = mGridScale.mV[VY]; - } - else - { - max_grid_scale = mGridScale.mV[VZ]; - } - - F32 num_subdivisions = getSubdivisionLevel(getPivotPoint(), camera_projected_dir, max_grid_scale); - - F32 grid_scale_a; - F32 grid_scale_b; - LLVector3 cursor_point_grid = (cursor_point_agent - mGridOrigin) * ~mGridRotation; - - switch (mManipPart) - { - case LL_YZ_PLANE: - grid_scale_a = mGridScale.mV[VY] / num_subdivisions; - grid_scale_b = mGridScale.mV[VZ] / num_subdivisions; - cursor_point_grid.mV[VY] -= fmod(cursor_point_grid.mV[VY] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f; - cursor_point_grid.mV[VZ] -= fmod(cursor_point_grid.mV[VZ] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f; - break; - case LL_XZ_PLANE: - grid_scale_a = mGridScale.mV[VX] / num_subdivisions; - grid_scale_b = mGridScale.mV[VZ] / num_subdivisions; - cursor_point_grid.mV[VX] -= fmod(cursor_point_grid.mV[VX] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f; - cursor_point_grid.mV[VZ] -= fmod(cursor_point_grid.mV[VZ] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f; - break; - case LL_XY_PLANE: - grid_scale_a = mGridScale.mV[VX] / num_subdivisions; - grid_scale_b = mGridScale.mV[VY] / num_subdivisions; - cursor_point_grid.mV[VX] -= fmod(cursor_point_grid.mV[VX] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f; - cursor_point_grid.mV[VY] -= fmod(cursor_point_grid.mV[VY] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f; - break; - default: - break; - } - cursor_point_agent = (cursor_point_grid * mGridRotation) + mGridOrigin; - relative_move.setVec(cursor_point_agent - gAgent.getPosAgentFromGlobal(mDragSelectionStartGlobal)); - mInSnapRegime = TRUE; - } - else - { - mInSnapRegime = FALSE; - } - } - else - { - mInSnapRegime = FALSE; - } - - // Clamp to arrow direction - // *FIX: does this apply anymore? - if (!axis_exists) - { - axis_magnitude = relative_move.normVec(); - axis_d.setVec(relative_move); - axis_d.normVec(); - axis_f.setVec(axis_d); - } - - LLVector3d clamped_relative_move = axis_magnitude * axis_d; // scalar multiply - LLVector3 clamped_relative_move_f = (F32)axis_magnitude * axis_f; // scalar multiply - + // Translation tool only works if mouse button is down. + // Bail out if mouse not down. + if( !hasMouseCapture() ) + { + LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (inactive)" << LL_ENDL; + // Always show cursor + // gViewerWindow->setCursor(UI_CURSOR_ARROW); + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + + highlightManipulators(x, y); + return TRUE; + } + + // Handle auto-rotation if necessary. + LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); + const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD; + const S32 ROTATE_H_MARGIN = world_rect.getWidth() / 20; + const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped; + BOOL rotated = FALSE; + + // ...build mode moves camera about focus point + if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD) + { + if (x < ROTATE_H_MARGIN) + { + gAgentCamera.cameraOrbitAround(rotate_angle); + rotated = TRUE; + } + else if (x > world_rect.getWidth() - ROTATE_H_MARGIN) + { + gAgentCamera.cameraOrbitAround(-rotate_angle); + rotated = TRUE; + } + } + + // Suppress processing if mouse hasn't actually moved. + // This may cause problems if the camera moves outside of the + // rotation above. + if( x == mLastHoverMouseX && y == mLastHoverMouseY && !rotated) + { + LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (mouse unmoved)" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + return TRUE; + } + mLastHoverMouseX = x; + mLastHoverMouseY = y; + + // Suppress if mouse hasn't moved past the initial slop region + // Reset once we start moving + if( !mMouseOutsideSlop ) + { + if (abs(mMouseDownX - x) < MOUSE_DRAG_SLOP && abs(mMouseDownY - y) < MOUSE_DRAG_SLOP ) + { + LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (mouse inside slop)" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + return TRUE; + } + else + { + // ...just went outside the slop region + mMouseOutsideSlop = TRUE; + // If holding down shift, leave behind a copy. + if (mask == MASK_COPY) + { + // ...we're trying to make a copy + LLSelectMgr::getInstance()->selectDuplicate(LLVector3::zero, FALSE); + mCopyMadeThisDrag = TRUE; + + // When we make the copy, we don't want to do any other processing. + // If so, the object will also be moved, and the copy will be offset. + LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (made copy)" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + } + } + } + + // Throttle updates to 10 per second. + + LLVector3 axis_f; + LLVector3d axis_d; + + // pick the first object to constrain to grid w/ common origin + // this is so we don't screw up groups + LLSelectNode* selectNode = mObjectSelection->getFirstMoveableNode(TRUE); + if (!selectNode) + { + // somehow we lost the object! + LL_WARNS() << "Translate manip lost the object, no selectNode" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + return TRUE; + } + + LLViewerObject* object = selectNode->getObject(); + if (!object) + { + // somehow we lost the object! + LL_WARNS() << "Translate manip lost the object, no object in selectNode" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + return TRUE; + } + + // Compute unit vectors for arrow hit and a plane through that vector + BOOL axis_exists = getManipAxis(object, mManipPart, axis_f); // TODO: move this + + axis_d.setVec(axis_f); + + LLSelectMgr::getInstance()->updateSelectionCenter(); + LLVector3d current_pos_global = gAgent.getPosGlobalFromAgent(getPivotPoint()); + + mSubdivisions = getSubdivisionLevel(getPivotPoint(), axis_f, getMinGridScale()); + + // Project the cursor onto that plane + LLVector3d relative_move; + getMousePointOnPlaneGlobal(relative_move, x, y, current_pos_global, mManipNormal);\ + relative_move -= mDragCursorStartGlobal; + + // You can't move more than some distance from your original mousedown point. + if (gSavedSettings.getBOOL("LimitDragDistance")) + { + F32 max_drag_distance = gSavedSettings.getF32("MaxDragDistance"); + + if (relative_move.magVecSquared() > max_drag_distance * max_drag_distance) + { + LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (too far)" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_NOLOCKED); + return TRUE; + } + } + + F64 axis_magnitude = relative_move * axis_d; // dot product + LLVector3d cursor_point_snap_line; + + F64 off_axis_magnitude; + + getMousePointOnPlaneGlobal(cursor_point_snap_line, x, y, current_pos_global, mSnapOffsetAxis % axis_f); + off_axis_magnitude = axis_exists ? llabs((cursor_point_snap_line - current_pos_global) * LLVector3d(mSnapOffsetAxis)) : 0.f; + + if (gSavedSettings.getBOOL("SnapEnabled")) + { + if (off_axis_magnitude > mSnapOffsetMeters) + { + mInSnapRegime = TRUE; + LLVector3 cursor_snap_agent = gAgent.getPosAgentFromGlobal(cursor_point_snap_line); + + F32 cursor_grid_dist = (cursor_snap_agent - mGridOrigin) * axis_f; + + F32 snap_dist = getMinGridScale() / (2.f * mSubdivisions); + F32 relative_snap_dist = fmodf(llabs(cursor_grid_dist) + snap_dist, getMinGridScale() / mSubdivisions); + if (relative_snap_dist < snap_dist * 2.f) + { + if (cursor_grid_dist > 0.f) + { + cursor_grid_dist -= relative_snap_dist - snap_dist; + } + else + { + cursor_grid_dist += relative_snap_dist - snap_dist; + } + } + + F32 object_start_on_axis = (gAgent.getPosAgentFromGlobal(mDragSelectionStartGlobal) - mGridOrigin) * axis_f; + axis_magnitude = cursor_grid_dist - object_start_on_axis; + } + else if (mManipPart >= LL_YZ_PLANE && mManipPart <= LL_XY_PLANE) + { + // subtract offset from object center + LLVector3d cursor_point_global; + getMousePointOnPlaneGlobal( cursor_point_global, x, y, current_pos_global, mManipNormal ); + cursor_point_global -= (mDragCursorStartGlobal - mDragSelectionStartGlobal); + + // snap to planar grid + LLVector3 cursor_point_agent = gAgent.getPosAgentFromGlobal(cursor_point_global); + LLVector3 camera_plane_projection = LLViewerCamera::getInstance()->getAtAxis(); + camera_plane_projection -= projected_vec(camera_plane_projection, mManipNormal); + camera_plane_projection.normVec(); + LLVector3 camera_projected_dir = camera_plane_projection; + camera_plane_projection.rotVec(~mGridRotation); + camera_plane_projection.scaleVec(mGridScale); + camera_plane_projection.abs(); + F32 max_grid_scale; + if (camera_plane_projection.mV[VX] > camera_plane_projection.mV[VY] && + camera_plane_projection.mV[VX] > camera_plane_projection.mV[VZ]) + { + max_grid_scale = mGridScale.mV[VX]; + } + else if (camera_plane_projection.mV[VY] > camera_plane_projection.mV[VZ]) + { + max_grid_scale = mGridScale.mV[VY]; + } + else + { + max_grid_scale = mGridScale.mV[VZ]; + } + + F32 num_subdivisions = getSubdivisionLevel(getPivotPoint(), camera_projected_dir, max_grid_scale); + + F32 grid_scale_a; + F32 grid_scale_b; + LLVector3 cursor_point_grid = (cursor_point_agent - mGridOrigin) * ~mGridRotation; + + switch (mManipPart) + { + case LL_YZ_PLANE: + grid_scale_a = mGridScale.mV[VY] / num_subdivisions; + grid_scale_b = mGridScale.mV[VZ] / num_subdivisions; + cursor_point_grid.mV[VY] -= fmod(cursor_point_grid.mV[VY] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f; + cursor_point_grid.mV[VZ] -= fmod(cursor_point_grid.mV[VZ] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f; + break; + case LL_XZ_PLANE: + grid_scale_a = mGridScale.mV[VX] / num_subdivisions; + grid_scale_b = mGridScale.mV[VZ] / num_subdivisions; + cursor_point_grid.mV[VX] -= fmod(cursor_point_grid.mV[VX] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f; + cursor_point_grid.mV[VZ] -= fmod(cursor_point_grid.mV[VZ] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f; + break; + case LL_XY_PLANE: + grid_scale_a = mGridScale.mV[VX] / num_subdivisions; + grid_scale_b = mGridScale.mV[VY] / num_subdivisions; + cursor_point_grid.mV[VX] -= fmod(cursor_point_grid.mV[VX] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f; + cursor_point_grid.mV[VY] -= fmod(cursor_point_grid.mV[VY] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f; + break; + default: + break; + } + cursor_point_agent = (cursor_point_grid * mGridRotation) + mGridOrigin; + relative_move.setVec(cursor_point_agent - gAgent.getPosAgentFromGlobal(mDragSelectionStartGlobal)); + mInSnapRegime = TRUE; + } + else + { + mInSnapRegime = FALSE; + } + } + else + { + mInSnapRegime = FALSE; + } + + // Clamp to arrow direction + // *FIX: does this apply anymore? + if (!axis_exists) + { + axis_magnitude = relative_move.normVec(); + axis_d.setVec(relative_move); + axis_d.normVec(); + axis_f.setVec(axis_d); + } + + LLVector3d clamped_relative_move = axis_magnitude * axis_d; // scalar multiply + LLVector3 clamped_relative_move_f = (F32)axis_magnitude * axis_f; // scalar multiply + for (LLObjectSelection::iterator iter = mObjectSelection->begin(); - iter != mObjectSelection->end(); iter++) + iter != mObjectSelection->end(); iter++) { LLSelectNode* selectNode = *iter; LLViewerObject* object = selectNode->getObject(); - // Only apply motion to root objects and objects selected - // as "individual". - if (!object->isRootEdit() && !selectNode->mIndividualSelection) + if (selectNode->mSelectedGLTFNode != -1) { - continue; + // manipulating a GLTF node + clamped_relative_move_f -= selectNode->mLastMoveLocal; + object->moveGLTFNode(selectNode->mSelectedGLTFNode, clamped_relative_move_f); + selectNode->mLastMoveLocal += clamped_relative_move_f; } - - if (!object->isRootEdit()) + else { - // child objects should not update if parent is selected - LLViewerObject* editable_root = (LLViewerObject*)object->getParent(); - if (editable_root->isSelected()) + // Only apply motion to root objects and objects selected + // as "individual". + if (!object->isRootEdit() && !selectNode->mIndividualSelection) { - // we will be moved properly by our parent, so skip continue; } - } - LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); - if (object->permMove() && !object->isPermanentEnforced() && - ((root_object == NULL) || !root_object->isPermanentEnforced())) - { - // handle attachments in local space - if (object->isAttachment() && object->mDrawable.notNull()) + if (!object->isRootEdit()) { - // calculate local version of relative move - LLQuaternion objWorldRotation = object->mDrawable->mXform.getParent()->getWorldRotation(); - objWorldRotation.transQuat(); - - LLVector3 old_position_local = object->getPosition(); - LLVector3 new_position_local = selectNode->mSavedPositionLocal + (clamped_relative_move_f * objWorldRotation); - - //RN: I forget, but we need to do this because of snapping which doesn't often result - // in position changes even when the mouse moves - object->setPosition(new_position_local); - rebuild(object); - gAgentAvatarp->clampAttachmentPositions(); - new_position_local = object->getPosition(); - - if (selectNode->mIndividualSelection) + // child objects should not update if parent is selected + LLViewerObject* editable_root = (LLViewerObject*)object->getParent(); + if (editable_root->isSelected()) { - // counter-translate child objects if we are moving the root as an individual - object->resetChildrenPosition(old_position_local - new_position_local, TRUE) ; + // we will be moved properly by our parent, so skip + continue; } } - else - { - // compute new position to send to simulators, but don't set it yet. - // We need the old position to know which simulator to send the move message to. - LLVector3d new_position_global = selectNode->mSavedPositionGlobal + clamped_relative_move; - - // Don't let object centers go too far underground - F64 min_height = LLWorld::getInstance()->getMinAllowedZ(object, object->getPositionGlobal()); - if (new_position_global.mdV[VZ] < min_height) - { - new_position_global.mdV[VZ] = min_height; - } - - // For safety, cap heights where objects can be dragged - if (new_position_global.mdV[VZ] > MAX_OBJECT_Z) - { - new_position_global.mdV[VZ] = MAX_OBJECT_Z; - } - // Grass is always drawn on the ground, so clamp its position to the ground - if (object->getPCode() == LL_PCODE_LEGACY_GRASS) + LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); + if (object->permMove() && !object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced())) + { + // handle attachments in local space + if (object->isAttachment() && object->mDrawable.notNull()) { - new_position_global.mdV[VZ] = LLWorld::getInstance()->resolveLandHeightGlobal(new_position_global) + 1.f; - } + // calculate local version of relative move + LLQuaternion objWorldRotation = object->mDrawable->mXform.getParent()->getWorldRotation(); + objWorldRotation.transQuat(); - if (object->isRootEdit()) - { - new_position_global = LLWorld::getInstance()->clipToVisibleRegions(object->getPositionGlobal(), new_position_global); - } + LLVector3 old_position_local = object->getPosition(); + LLVector3 new_position_local = selectNode->mSavedPositionLocal + (clamped_relative_move_f * objWorldRotation); - // PR: Only update if changed - LLVector3 old_position_agent = object->getPositionAgent(); - LLVector3 new_position_agent = gAgent.getPosAgentFromGlobal(new_position_global); - if (object->isRootEdit()) - { - // finally, move parent object after children have calculated new offsets - object->setPositionAgent(new_position_agent); + //RN: I forget, but we need to do this because of snapping which doesn't often result + // in position changes even when the mouse moves + object->setPosition(new_position_local); rebuild(object); + gAgentAvatarp->clampAttachmentPositions(); + new_position_local = object->getPosition(); + + if (selectNode->mIndividualSelection) + { + // counter-translate child objects if we are moving the root as an individual + object->resetChildrenPosition(old_position_local - new_position_local, TRUE); + } } else { - LLViewerObject* root_object = object->getRootEdit(); - new_position_agent -= root_object->getPositionAgent(); - new_position_agent = new_position_agent * ~root_object->getRotation(); - object->setPositionParent(new_position_agent, FALSE); - rebuild(object); - } - - if (selectNode->mIndividualSelection) - { - // counter-translate child objects if we are moving the root as an individual - object->resetChildrenPosition(old_position_agent - new_position_agent, TRUE) ; - } - } - selectNode->mLastPositionLocal = object->getPosition(); - } - } - - LLSelectMgr::getInstance()->updateSelectionCenter(); - gAgentCamera.clearFocusObject(); - dialog_refresh_all(); // ??? is this necessary? - - LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (active)" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - return TRUE; -} - -void LLManipTranslate::highlightManipulators(S32 x, S32 y) -{ - mHighlightedPart = LL_NO_PART; + // compute new position to send to simulators, but don't set it yet. + // We need the old position to know which simulator to send the move message to. + LLVector3d new_position_global = selectNode->mSavedPositionGlobal + clamped_relative_move; - if (!mObjectSelection->getObjectCount()) - { - return; - } - - //LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); - LLMatrix4 projMatrix = LLViewerCamera::getInstance()->getProjection(); - LLMatrix4 modelView = LLViewerCamera::getInstance()->getModelview(); - - LLVector3 object_position = getPivotPoint(); - - LLVector3 grid_origin; - LLVector3 grid_scale; - LLQuaternion grid_rotation; - - LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); - - LLVector3 relative_camera_dir; - - LLMatrix4 transform; - - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - relative_camera_dir = LLVector3(1.f, 0.f, 0.f) * ~grid_rotation; - LLVector4 translation(object_position); - transform.initRotTrans(grid_rotation, translation); - LLMatrix4 cfr(OGL_TO_CFR_ROTATION); - transform *= cfr; - LLMatrix4 window_scale; - F32 zoom_level = 2.f * gAgentCamera.mHUDCurZoom; - window_scale.initAll(LLVector3(zoom_level / LLViewerCamera::getInstance()->getAspect(), zoom_level, 0.f), - LLQuaternion::DEFAULT, - LLVector3::zero); - transform *= window_scale; - } - else - { - relative_camera_dir = (object_position - LLViewerCamera::getInstance()->getOrigin()) * ~grid_rotation; - relative_camera_dir.normVec(); - - transform.initRotTrans(grid_rotation, LLVector4(object_position)); - transform *= modelView; - transform *= projMatrix; - } - - S32 numManips = 0; - - // edges - mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 0.f, 0.f, 1.f); - mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 0.f, 0.f, 1.f); - - mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 0.f, 1.f); - mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 0.f, 1.f); - - mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 1.f); - mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 1.f); - - mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 0.f, 0.f, 1.f); - mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 0.f, 0.f, 1.f); - - mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 0.f, 1.f); - mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 0.f, 1.f); - - mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 1.f); - mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 1.f); - - S32 num_arrow_manips = numManips; - - // planar manipulators - BOOL planar_manip_yz_visible = FALSE; - BOOL planar_manip_xz_visible = FALSE; - BOOL planar_manip_xy_visible = FALSE; - - mManipulatorVertices[numManips] = LLVector4(0.f, mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 1.f); - mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); - mManipulatorVertices[numManips] = LLVector4(0.f, mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 1.f); - mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); - if (llabs(relative_camera_dir.mV[VX]) > MIN_PLANE_MANIP_DOT_PRODUCT) - { - planar_manip_yz_visible = TRUE; - } - - mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 0.f, mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 1.f); - mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); - mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 0.f, mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 1.f); - mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); - if (llabs(relative_camera_dir.mV[VY]) > MIN_PLANE_MANIP_DOT_PRODUCT) - { - planar_manip_xz_visible = TRUE; - } - - mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 0.f, 1.f); - mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); - mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 0.f, 1.f); - mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); - if (llabs(relative_camera_dir.mV[VZ]) > MIN_PLANE_MANIP_DOT_PRODUCT) - { - planar_manip_xy_visible = TRUE; - } + // Don't let object centers go too far underground + F64 min_height = LLWorld::getInstance()->getMinAllowedZ(object, object->getPositionGlobal()); + if (new_position_global.mdV[VZ] < min_height) + { + new_position_global.mdV[VZ] = min_height; + } - // Project up to 9 manipulators to screen space 2*X, 2*Y, 2*Z, 3*planes - std::vector<ManipulatorHandle> projected_manipulators; - projected_manipulators.reserve(9); + // For safety, cap heights where objects can be dragged + if (new_position_global.mdV[VZ] > MAX_OBJECT_Z) + { + new_position_global.mdV[VZ] = MAX_OBJECT_Z; + } - for (S32 i = 0; i < num_arrow_manips; i+= 2) - { - LLVector4 projected_start = mManipulatorVertices[i] * transform; - projected_start = projected_start * (1.f / projected_start.mV[VW]); - - LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; - projected_end = projected_end * (1.f / projected_end.mV[VW]); - - ManipulatorHandle projected_manip( - LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), - LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), - MANIPULATOR_IDS[i / 2], - 10.f); // 10 pixel hotspot for arrows - projected_manipulators.push_back(projected_manip); - } + // Grass is always drawn on the ground, so clamp its position to the ground + if (object->getPCode() == LL_PCODE_LEGACY_GRASS) + { + new_position_global.mdV[VZ] = LLWorld::getInstance()->resolveLandHeightGlobal(new_position_global) + 1.f; + } - if (planar_manip_yz_visible) - { - S32 i = num_arrow_manips; - LLVector4 projected_start = mManipulatorVertices[i] * transform; - projected_start = projected_start * (1.f / projected_start.mV[VW]); - - LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; - projected_end = projected_end * (1.f / projected_end.mV[VW]); - - ManipulatorHandle projected_manip( - LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), - LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), - MANIPULATOR_IDS[i / 2], - 20.f); // 20 pixels for planar manipulators - projected_manipulators.push_back(projected_manip); - } + if (object->isRootEdit()) + { + new_position_global = LLWorld::getInstance()->clipToVisibleRegions(object->getPositionGlobal(), new_position_global); + } - if (planar_manip_xz_visible) - { - S32 i = num_arrow_manips + 2; - LLVector4 projected_start = mManipulatorVertices[i] * transform; - projected_start = projected_start * (1.f / projected_start.mV[VW]); - - LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; - projected_end = projected_end * (1.f / projected_end.mV[VW]); - - ManipulatorHandle projected_manip( - LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), - LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), - MANIPULATOR_IDS[i / 2], - 20.f); // 20 pixels for planar manipulators - projected_manipulators.push_back(projected_manip); - } + // PR: Only update if changed + LLVector3 old_position_agent = object->getPositionAgent(); + LLVector3 new_position_agent = gAgent.getPosAgentFromGlobal(new_position_global); + if (object->isRootEdit()) + { + // finally, move parent object after children have calculated new offsets + object->setPositionAgent(new_position_agent); + rebuild(object); + } + else + { + LLViewerObject* root_object = object->getRootEdit(); + new_position_agent -= root_object->getPositionAgent(); + new_position_agent = new_position_agent * ~root_object->getRotation(); + object->setPositionParent(new_position_agent, FALSE); + rebuild(object); + } - if (planar_manip_xy_visible) - { - S32 i = num_arrow_manips + 4; - LLVector4 projected_start = mManipulatorVertices[i] * transform; - projected_start = projected_start * (1.f / projected_start.mV[VW]); - - LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; - projected_end = projected_end * (1.f / projected_end.mV[VW]); - - ManipulatorHandle projected_manip( - LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), - LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), - MANIPULATOR_IDS[i / 2], - 20.f); // 20 pixels for planar manipulators - projected_manipulators.push_back(projected_manip); + if (selectNode->mIndividualSelection) + { + // counter-translate child objects if we are moving the root as an individual + object->resetChildrenPosition(old_position_agent - new_position_agent, TRUE); + } + } + selectNode->mLastPositionLocal = object->getPosition(); + } + } } - LLVector2 manip_start_2d; - LLVector2 manip_end_2d; - LLVector2 manip_dir; - LLRect world_view_rect = gViewerWindow->getWorldViewRectScaled(); - F32 half_width = (F32)world_view_rect.getWidth() / 2.f; - F32 half_height = (F32)world_view_rect.getHeight() / 2.f; - LLVector2 mousePos((F32)x - half_width, (F32)y - half_height); - LLVector2 mouse_delta; - - // Keep order consistent with insertion via stable_sort - std::stable_sort( projected_manipulators.begin(), - projected_manipulators.end(), - ClosestToCamera() ); - - std::vector<ManipulatorHandle>::iterator it = projected_manipulators.begin(); - for ( ; it != projected_manipulators.end(); ++it) - { - ManipulatorHandle& manipulator = *it; - { - manip_start_2d.setVec(manipulator.mStartPosition.mV[VX] * half_width, manipulator.mStartPosition.mV[VY] * half_height); - manip_end_2d.setVec(manipulator.mEndPosition.mV[VX] * half_width, manipulator.mEndPosition.mV[VY] * half_height); - manip_dir = manip_end_2d - manip_start_2d; - - mouse_delta = mousePos - manip_start_2d; - F32 manip_length = manip_dir.normVec(); + LLSelectMgr::getInstance()->updateSelectionCenter(); + gAgentCamera.clearFocusObject(); + dialog_refresh_all(); // ??? is this necessary? - F32 mouse_pos_manip = mouse_delta * manip_dir; - F32 mouse_dist_manip_squared = mouse_delta.magVecSquared() - (mouse_pos_manip * mouse_pos_manip); + LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (active)" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + return TRUE; +} - if (mouse_pos_manip > 0.f && - mouse_pos_manip < manip_length && - mouse_dist_manip_squared < manipulator.mHotSpotRadius * manipulator.mHotSpotRadius) - { - mHighlightedPart = manipulator.mManipID; - break; - } - } - } +void LLManipTranslate::highlightManipulators(S32 x, S32 y) +{ + mHighlightedPart = LL_NO_PART; + + if (!mObjectSelection->getObjectCount()) + { + return; + } + + //LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); + LLMatrix4 projMatrix = LLViewerCamera::getInstance()->getProjection(); + LLMatrix4 modelView = LLViewerCamera::getInstance()->getModelview(); + + LLVector3 object_position = getPivotPoint(); + + LLVector3 grid_origin; + LLVector3 grid_scale; + LLQuaternion grid_rotation; + + LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); + + LLVector3 relative_camera_dir; + + LLMatrix4 transform; + + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + relative_camera_dir = LLVector3(1.f, 0.f, 0.f) * ~grid_rotation; + LLVector4 translation(object_position); + transform.initRotTrans(grid_rotation, translation); + LLMatrix4 cfr(OGL_TO_CFR_ROTATION); + transform *= cfr; + LLMatrix4 window_scale; + F32 zoom_level = 2.f * gAgentCamera.mHUDCurZoom; + window_scale.initAll(LLVector3(zoom_level / LLViewerCamera::getInstance()->getAspect(), zoom_level, 0.f), + LLQuaternion::DEFAULT, + LLVector3::zero); + transform *= window_scale; + } + else + { + relative_camera_dir = (object_position - LLViewerCamera::getInstance()->getOrigin()) * ~grid_rotation; + relative_camera_dir.normVec(); + + transform.initRotTrans(grid_rotation, LLVector4(object_position)); + transform *= modelView; + transform *= projMatrix; + } + + S32 numManips = 0; + + // edges + mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 0.f, 0.f, 1.f); + mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 0.f, 0.f, 1.f); + + mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 0.f, 1.f); + mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 0.f, 1.f); + + mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 1.f); + mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 1.f); + + mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 0.f, 0.f, 1.f); + mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 0.f, 0.f, 1.f); + + mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 0.f, 1.f); + mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 0.f, 1.f); + + mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 1.f); + mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 1.f); + + S32 num_arrow_manips = numManips; + + // planar manipulators + BOOL planar_manip_yz_visible = FALSE; + BOOL planar_manip_xz_visible = FALSE; + BOOL planar_manip_xy_visible = FALSE; + + mManipulatorVertices[numManips] = LLVector4(0.f, mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 1.f); + mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); + mManipulatorVertices[numManips] = LLVector4(0.f, mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 1.f); + mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); + if (llabs(relative_camera_dir.mV[VX]) > MIN_PLANE_MANIP_DOT_PRODUCT) + { + planar_manip_yz_visible = TRUE; + } + + mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 0.f, mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 1.f); + mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); + mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 0.f, mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 1.f); + mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); + if (llabs(relative_camera_dir.mV[VY]) > MIN_PLANE_MANIP_DOT_PRODUCT) + { + planar_manip_xz_visible = TRUE; + } + + mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 0.f, 1.f); + mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); + mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 0.f, 1.f); + mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); + if (llabs(relative_camera_dir.mV[VZ]) > MIN_PLANE_MANIP_DOT_PRODUCT) + { + planar_manip_xy_visible = TRUE; + } + + // Project up to 9 manipulators to screen space 2*X, 2*Y, 2*Z, 3*planes + std::vector<ManipulatorHandle> projected_manipulators; + projected_manipulators.reserve(9); + + for (S32 i = 0; i < num_arrow_manips; i+= 2) + { + LLVector4 projected_start = mManipulatorVertices[i] * transform; + projected_start = projected_start * (1.f / projected_start.mV[VW]); + + LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; + projected_end = projected_end * (1.f / projected_end.mV[VW]); + + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), + MANIPULATOR_IDS[i / 2], + 10.f); // 10 pixel hotspot for arrows + projected_manipulators.push_back(projected_manip); + } + + if (planar_manip_yz_visible) + { + S32 i = num_arrow_manips; + LLVector4 projected_start = mManipulatorVertices[i] * transform; + projected_start = projected_start * (1.f / projected_start.mV[VW]); + + LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; + projected_end = projected_end * (1.f / projected_end.mV[VW]); + + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), + MANIPULATOR_IDS[i / 2], + 20.f); // 20 pixels for planar manipulators + projected_manipulators.push_back(projected_manip); + } + + if (planar_manip_xz_visible) + { + S32 i = num_arrow_manips + 2; + LLVector4 projected_start = mManipulatorVertices[i] * transform; + projected_start = projected_start * (1.f / projected_start.mV[VW]); + + LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; + projected_end = projected_end * (1.f / projected_end.mV[VW]); + + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), + MANIPULATOR_IDS[i / 2], + 20.f); // 20 pixels for planar manipulators + projected_manipulators.push_back(projected_manip); + } + + if (planar_manip_xy_visible) + { + S32 i = num_arrow_manips + 4; + LLVector4 projected_start = mManipulatorVertices[i] * transform; + projected_start = projected_start * (1.f / projected_start.mV[VW]); + + LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; + projected_end = projected_end * (1.f / projected_end.mV[VW]); + + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), + MANIPULATOR_IDS[i / 2], + 20.f); // 20 pixels for planar manipulators + projected_manipulators.push_back(projected_manip); + } + + LLVector2 manip_start_2d; + LLVector2 manip_end_2d; + LLVector2 manip_dir; + LLRect world_view_rect = gViewerWindow->getWorldViewRectScaled(); + F32 half_width = (F32)world_view_rect.getWidth() / 2.f; + F32 half_height = (F32)world_view_rect.getHeight() / 2.f; + LLVector2 mousePos((F32)x - half_width, (F32)y - half_height); + LLVector2 mouse_delta; + + // Keep order consistent with insertion via stable_sort + std::stable_sort( projected_manipulators.begin(), + projected_manipulators.end(), + ClosestToCamera() ); + + std::vector<ManipulatorHandle>::iterator it = projected_manipulators.begin(); + for ( ; it != projected_manipulators.end(); ++it) + { + ManipulatorHandle& manipulator = *it; + { + manip_start_2d.setVec(manipulator.mStartPosition.mV[VX] * half_width, manipulator.mStartPosition.mV[VY] * half_height); + manip_end_2d.setVec(manipulator.mEndPosition.mV[VX] * half_width, manipulator.mEndPosition.mV[VY] * half_height); + manip_dir = manip_end_2d - manip_start_2d; + + mouse_delta = mousePos - manip_start_2d; + + F32 manip_length = manip_dir.normVec(); + + F32 mouse_pos_manip = mouse_delta * manip_dir; + F32 mouse_dist_manip_squared = mouse_delta.magVecSquared() - (mouse_pos_manip * mouse_pos_manip); + + if (mouse_pos_manip > 0.f && + mouse_pos_manip < manip_length && + mouse_dist_manip_squared < manipulator.mHotSpotRadius * manipulator.mHotSpotRadius) + { + mHighlightedPart = manipulator.mManipID; + break; + } + } + } } F32 LLManipTranslate::getMinGridScale() { - F32 scale; - switch (mManipPart) - { - case LL_NO_PART: - default: - scale = 1.f; - break; - case LL_X_ARROW: - scale = mGridScale.mV[VX]; - break; - case LL_Y_ARROW: - scale = mGridScale.mV[VY]; - break; - case LL_Z_ARROW: - scale = mGridScale.mV[VZ]; - break; - case LL_YZ_PLANE: - scale = llmin(mGridScale.mV[VY], mGridScale.mV[VZ]); - break; - case LL_XZ_PLANE: - scale = llmin(mGridScale.mV[VX], mGridScale.mV[VZ]); - break; - case LL_XY_PLANE: - scale = llmin(mGridScale.mV[VX], mGridScale.mV[VY]); - break; - } - - return scale; + F32 scale; + switch (mManipPart) + { + case LL_NO_PART: + default: + scale = 1.f; + break; + case LL_X_ARROW: + scale = mGridScale.mV[VX]; + break; + case LL_Y_ARROW: + scale = mGridScale.mV[VY]; + break; + case LL_Z_ARROW: + scale = mGridScale.mV[VZ]; + break; + case LL_YZ_PLANE: + scale = llmin(mGridScale.mV[VY], mGridScale.mV[VZ]); + break; + case LL_XZ_PLANE: + scale = llmin(mGridScale.mV[VX], mGridScale.mV[VZ]); + break; + case LL_XY_PLANE: + scale = llmin(mGridScale.mV[VX], mGridScale.mV[VY]); + break; + } + + return scale; } BOOL LLManipTranslate::handleMouseUp(S32 x, S32 y, MASK mask) { - // first, perform normal processing in case this was a quick-click - handleHover(x, y, mask); - - if(hasMouseCapture()) - { - // make sure arrow colors go back to normal - mManipPart = LL_NO_PART; - LLSelectMgr::getInstance()->enableSilhouette(TRUE); - - // Might have missed last update due to UPDATE_DELAY timing. - LLSelectMgr::getInstance()->sendMultipleUpdate( UPD_POSITION ); - - mInSnapRegime = FALSE; - LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject")); - } - - return LLManip::handleMouseUp(x, y, mask); + // first, perform normal processing in case this was a quick-click + handleHover(x, y, mask); + + if(hasMouseCapture()) + { + // make sure arrow colors go back to normal + mManipPart = LL_NO_PART; + LLSelectMgr::getInstance()->enableSilhouette(TRUE); + + // Might have missed last update due to UPDATE_DELAY timing. + LLSelectMgr::getInstance()->sendMultipleUpdate( UPD_POSITION ); + + mInSnapRegime = FALSE; + LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject")); + } + + return LLManip::handleMouseUp(x, y, mask); } void LLManipTranslate::render() { - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - F32 zoom = gAgentCamera.mHUDCurZoom; - gGL.scalef(zoom, zoom, zoom); - } - { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - renderGuidelines(); - } - { - //LLGLDisable gls_stencil(GL_STENCIL_TEST); - renderTranslationHandles(); - renderSnapGuides(); - } - gGL.popMatrix(); - - renderText(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + F32 zoom = gAgentCamera.mHUDCurZoom; + gGL.scalef(zoom, zoom, zoom); + } + { + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + renderGuidelines(); + } + { + //LLGLDisable gls_stencil(GL_STENCIL_TEST); + renderTranslationHandles(); + renderSnapGuides(); + } + gGL.popMatrix(); + + renderText(); } void LLManipTranslate::renderSnapGuides() { - if (!gSavedSettings.getBOOL("SnapEnabled")) - { - return; - } - - F32 max_subdivisions = sGridMaxSubdivisionLevel;//(F32)gSavedSettings.getS32("GridSubdivision"); - F32 line_alpha = gSavedSettings.getF32("GridOpacity"); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest gls_depth(GL_TRUE); - LLGLDisable gls_cull(GL_CULL_FACE); - LLVector3 translate_axis; - - if (mManipPart == LL_NO_PART) - { - return; - } - - LLSelectNode *first_node = mObjectSelection->getFirstMoveableNode(TRUE); - if (!first_node) - { - return; - } - - updateGridSettings(); - - F32 smallest_grid_unit_scale = getMinGridScale() / max_subdivisions; - LLVector3 grid_origin; - LLVector3 grid_scale; - LLQuaternion grid_rotation; - - LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); - LLVector3 saved_selection_center = getSavedPivotPoint(); //LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent(); - LLVector3 selection_center = getPivotPoint(); - - LLViewerObject *first_object = first_node->getObject(); - - //pick appropriate projection plane for snap rulers according to relative camera position - if (mManipPart >= LL_X_ARROW && mManipPart <= LL_Z_ARROW) - { - LLVector3 normal; + if (!gSavedSettings.getBOOL("SnapEnabled")) + { + return; + } + + F32 max_subdivisions = sGridMaxSubdivisionLevel;//(F32)gSavedSettings.getS32("GridSubdivision"); + F32 line_alpha = gSavedSettings.getF32("GridOpacity"); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLDepthTest gls_depth(GL_TRUE); + LLGLDisable gls_cull(GL_CULL_FACE); + LLVector3 translate_axis; + + if (mManipPart == LL_NO_PART) + { + return; + } + + LLSelectNode *first_node = mObjectSelection->getFirstMoveableNode(TRUE); + if (!first_node) + { + return; + } + + updateGridSettings(); + + F32 smallest_grid_unit_scale = getMinGridScale() / max_subdivisions; + LLVector3 grid_origin; + LLVector3 grid_scale; + LLQuaternion grid_rotation; + + LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); + LLVector3 saved_selection_center = getSavedPivotPoint(); //LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent(); + LLVector3 selection_center = getPivotPoint(); + + LLViewerObject *first_object = first_node->getObject(); + + //pick appropriate projection plane for snap rulers according to relative camera position + if (mManipPart >= LL_X_ARROW && mManipPart <= LL_Z_ARROW) + { + LLVector3 normal; + LLColor4 inner_color; + LLManip::EManipPart temp_manip = mManipPart; + switch (mManipPart) + { + case LL_X_ARROW: + normal.setVec(1,0,0); + inner_color.setVec(0,1,1,line_alpha); + mManipPart = LL_YZ_PLANE; + break; + case LL_Y_ARROW: + normal.setVec(0,1,0); + inner_color.setVec(1,0,1,line_alpha); + mManipPart = LL_XZ_PLANE; + break; + case LL_Z_ARROW: + normal.setVec(0,0,1); + inner_color.setVec(1,1,0,line_alpha); + mManipPart = LL_XY_PLANE; + break; + default: + break; + } + + highlightIntersection(normal, selection_center, grid_rotation, inner_color); + mManipPart = temp_manip; + getManipAxis(first_object, mManipPart, translate_axis); + + LLVector3 at_axis_abs; + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + at_axis_abs = LLVector3::x_axis * ~grid_rotation; + } + else + { + at_axis_abs = saved_selection_center - LLViewerCamera::getInstance()->getOrigin(); + at_axis_abs.normVec(); + + at_axis_abs = at_axis_abs * ~grid_rotation; + } + at_axis_abs.abs(); + + if (at_axis_abs.mV[VX] > at_axis_abs.mV[VY] && at_axis_abs.mV[VX] > at_axis_abs.mV[VZ]) + { + if (mManipPart == LL_Y_ARROW) + { + mSnapOffsetAxis = LLVector3::z_axis; + } + else if (mManipPart == LL_Z_ARROW) + { + mSnapOffsetAxis = LLVector3::y_axis; + } + else if (at_axis_abs.mV[VY] > at_axis_abs.mV[VZ]) + { + mSnapOffsetAxis = LLVector3::z_axis; + } + else + { + mSnapOffsetAxis = LLVector3::y_axis; + } + } + else if (at_axis_abs.mV[VY] > at_axis_abs.mV[VZ]) + { + if (mManipPart == LL_X_ARROW) + { + mSnapOffsetAxis = LLVector3::z_axis; + } + else if (mManipPart == LL_Z_ARROW) + { + mSnapOffsetAxis = LLVector3::x_axis; + } + else if (at_axis_abs.mV[VX] > at_axis_abs.mV[VZ]) + { + mSnapOffsetAxis = LLVector3::z_axis; + } + else + { + mSnapOffsetAxis = LLVector3::x_axis; + } + } + else + { + if (mManipPart == LL_X_ARROW) + { + mSnapOffsetAxis = LLVector3::y_axis; + } + else if (mManipPart == LL_Y_ARROW) + { + mSnapOffsetAxis = LLVector3::x_axis; + } + else if (at_axis_abs.mV[VX] > at_axis_abs.mV[VY]) + { + mSnapOffsetAxis = LLVector3::y_axis; + } + else + { + mSnapOffsetAxis = LLVector3::x_axis; + } + } + + mSnapOffsetAxis = mSnapOffsetAxis * grid_rotation; + + F32 guide_size_meters; + + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + guide_size_meters = 1.f / gAgentCamera.mHUDCurZoom; + mSnapOffsetMeters = mArrowLengthMeters * 1.5f; + } + else + { + LLVector3 cam_to_selection = getPivotPoint() - LLViewerCamera::getInstance()->getOrigin(); + F32 current_range = cam_to_selection.normVec(); + guide_size_meters = SNAP_GUIDE_SCREEN_SIZE * gViewerWindow->getWorldViewHeightRaw() * current_range / LLViewerCamera::getInstance()->getPixelMeterRatio(); + + F32 fraction_of_fov = mAxisArrowLength / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); + F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians + F32 offset_at_camera = tan(apparent_angle) * 1.5f; + F32 range = dist_vec(gAgent.getPosAgentFromGlobal(first_node->mSavedPositionGlobal), LLViewerCamera::getInstance()->getOrigin()); + mSnapOffsetMeters = range * offset_at_camera; + } + + LLVector3 tick_start; + LLVector3 tick_end; + + // how far away from grid origin is the selection along the axis of translation? + F32 dist_grid_axis = (selection_center - mGridOrigin) * translate_axis; + // find distance to nearest smallest grid unit + F32 offset_nearest_grid_unit = fmodf(dist_grid_axis, smallest_grid_unit_scale); + // how many smallest grid units are we away from largest grid scale? + S32 sub_div_offset = ll_round(fmodf(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() / sGridMinSubdivisionLevel) / smallest_grid_unit_scale); + S32 num_ticks_per_side = llmax(1, llfloor(0.5f * guide_size_meters / smallest_grid_unit_scale)); + + LLGLDepthTest gls_depth(GL_FALSE); + + for (S32 pass = 0; pass < 3; pass++) + { + LLColor4 line_color = setupSnapGuideRenderPass(pass); + LLGLDepthTest gls_depth(pass != 1); + + gGL.begin(LLRender::LINES); + { + LLVector3 line_start = selection_center + (mSnapOffsetMeters * mSnapOffsetAxis) + (translate_axis * (guide_size_meters * 0.5f + offset_nearest_grid_unit)); + LLVector3 line_end = selection_center + (mSnapOffsetMeters * mSnapOffsetAxis) - (translate_axis * (guide_size_meters * 0.5f + offset_nearest_grid_unit)); + LLVector3 line_mid = (line_start + line_end) * 0.5f; + + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); + gGL.vertex3fv(line_start.mV); + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); + gGL.vertex3fv(line_mid.mV); + gGL.vertex3fv(line_mid.mV); + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); + gGL.vertex3fv(line_end.mV); + + line_start.setVec(selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) + (translate_axis * guide_size_meters * 0.5f)); + line_end.setVec(selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) - (translate_axis * guide_size_meters * 0.5f)); + line_mid = (line_start + line_end) * 0.5f; + + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); + gGL.vertex3fv(line_start.mV); + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); + gGL.vertex3fv(line_mid.mV); + gGL.vertex3fv(line_mid.mV); + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); + gGL.vertex3fv(line_end.mV); + + for (S32 i = -num_ticks_per_side; i <= num_ticks_per_side; i++) + { + tick_start = selection_center + (translate_axis * (smallest_grid_unit_scale * (F32)i - offset_nearest_grid_unit)); + + //No need check this condition to prevent tick position scaling (FIX MAINT-5207/5208) + //F32 cur_subdivisions = getSubdivisionLevel(tick_start, translate_axis, getMinGridScale()); + /*if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / cur_subdivisions)) != 0.f) + { + continue; + }*/ + + // add in off-axis offset + tick_start += (mSnapOffsetAxis * mSnapOffsetMeters); + + F32 tick_scale = 1.f; + for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) + { + if (fmodf((F32)(i + sub_div_offset), division_level) == 0.f) + { + break; + } + tick_scale *= 0.7f; + } + +// S32 num_ticks_to_fade = is_sub_tick ? num_ticks_per_side / 2 : num_ticks_per_side; +// F32 alpha = line_alpha * (1.f - (0.8f * ((F32)llabs(i) / (F32)num_ticks_to_fade))); + + tick_end = tick_start + (mSnapOffsetAxis * mSnapOffsetMeters * tick_scale); + + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); + gGL.vertex3fv(tick_start.mV); + gGL.vertex3fv(tick_end.mV); + + tick_start = selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) + + (translate_axis * (getMinGridScale() / (F32)(max_subdivisions) * (F32)i - offset_nearest_grid_unit)); + tick_end = tick_start - (mSnapOffsetAxis * mSnapOffsetMeters * tick_scale); + + gGL.vertex3fv(tick_start.mV); + gGL.vertex3fv(tick_end.mV); + } + } + gGL.end(); + + if (mInSnapRegime) + { + LLVector3 line_start = selection_center - mSnapOffsetAxis * mSnapOffsetMeters; + LLVector3 line_end = selection_center + mSnapOffsetAxis * mSnapOffsetMeters; + + gGL.begin(LLRender::LINES); + { + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); + + gGL.vertex3fv(line_start.mV); + gGL.vertex3fv(line_end.mV); + } + gGL.end(); + + // draw snap guide arrow + gGL.begin(LLRender::TRIANGLES); + { + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); + + LLVector3 arrow_dir; + LLVector3 arrow_span = translate_axis; + + arrow_dir = -mSnapOffsetAxis; + gGL.vertex3fv((line_start + arrow_dir * mConeSize * SNAP_ARROW_SCALE).mV); + gGL.vertex3fv((line_start + arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); + gGL.vertex3fv((line_start - arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); + + arrow_dir = mSnapOffsetAxis; + gGL.vertex3fv((line_end + arrow_dir * mConeSize * SNAP_ARROW_SCALE).mV); + gGL.vertex3fv((line_end + arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); + gGL.vertex3fv((line_end - arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); + } + gGL.end(); + } + } + + sub_div_offset = ll_round(fmod(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() * 32.f) / smallest_grid_unit_scale); + + LLVector2 screen_translate_axis(llabs(translate_axis * LLViewerCamera::getInstance()->getLeftAxis()), llabs(translate_axis * LLViewerCamera::getInstance()->getUpAxis())); + screen_translate_axis.normVec(); + + S32 tick_label_spacing = ll_round(screen_translate_axis * sTickLabelSpacing); + + // render tickmark values + for (S32 i = -num_ticks_per_side; i <= num_ticks_per_side; i++) + { + LLVector3 tick_pos = selection_center + (translate_axis * ((smallest_grid_unit_scale * (F32)i) - offset_nearest_grid_unit)); + F32 alpha = line_alpha * (1.f - (0.5f * ((F32)llabs(i) / (F32)num_ticks_per_side))); + + F32 tick_scale = 1.f; + for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) + { + if (fmodf((F32)(i + sub_div_offset), division_level) == 0.f) + { + break; + } + tick_scale *= 0.7f; + } + + if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / getSubdivisionLevel(tick_pos, translate_axis, getMinGridScale(), tick_label_spacing))) == 0.f) + { + F32 snap_offset_meters; + + if (mSnapOffsetAxis * LLViewerCamera::getInstance()->getUpAxis() > 0.f) + { + snap_offset_meters = mSnapOffsetMeters; + } + else + { + snap_offset_meters = -mSnapOffsetMeters; + } + LLVector3 text_origin = selection_center + + (translate_axis * ((smallest_grid_unit_scale * (F32)i) - offset_nearest_grid_unit)) + + (mSnapOffsetAxis * snap_offset_meters * (1.f + tick_scale)); + + LLVector3 tick_offset = (tick_pos - mGridOrigin) * ~mGridRotation; + F32 offset_val = 0.5f * tick_offset.mV[ARROW_TO_AXIS[mManipPart]] / getMinGridScale(); + EGridMode grid_mode = LLSelectMgr::getInstance()->getGridMode(); + F32 text_highlight = 0.8f; + if(i - ll_round(offset_nearest_grid_unit / smallest_grid_unit_scale) == 0 && mInSnapRegime) + { + text_highlight = 1.f; + } + + if (grid_mode == GRID_MODE_WORLD) + { + // rescale units to meters from multiple of grid scale + offset_val *= 2.f * grid_scale[ARROW_TO_AXIS[mManipPart]]; + renderTickValue(text_origin, offset_val, std::string("m"), LLColor4(text_highlight, text_highlight, text_highlight, alpha)); + } + else + { + renderTickValue(text_origin, offset_val, std::string("x"), LLColor4(text_highlight, text_highlight, text_highlight, alpha)); + } + } + } + if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD) + { + // render helpful text + if (mHelpTextTimer.getElapsedTimeF32() < sHelpTextVisibleTime + sHelpTextFadeTime && sNumTimesHelpTextShown < sMaxTimesShowHelpText) + { + F32 snap_offset_meters_up; + if (mSnapOffsetAxis * LLViewerCamera::getInstance()->getUpAxis() > 0.f) + { + snap_offset_meters_up = mSnapOffsetMeters; + } + else + { + snap_offset_meters_up = -mSnapOffsetMeters; + } + + LLVector3 selection_center_start = getSavedPivotPoint();//LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent(); + + LLVector3 help_text_pos = selection_center_start + (snap_offset_meters_up * 3.f * mSnapOffsetAxis); + const LLFontGL* big_fontp = LLFontGL::getFontSansSerif(); + + 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, line_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, false); + help_text = LLTrans::getString("manip_hint2"); + help_text_pos -= LLViewerCamera::getInstance()->getUpAxis() * mSnapOffsetMeters * 0.2f; + 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); + } + } + } + else + { + // render gridlines for planar snapping + + F32 u = 0, v = 0; LLColor4 inner_color; - LLManip::EManipPart temp_manip = mManipPart; - switch (mManipPart) - { - case LL_X_ARROW: - normal.setVec(1,0,0); - inner_color.setVec(0,1,1,line_alpha); - mManipPart = LL_YZ_PLANE; - break; - case LL_Y_ARROW: - normal.setVec(0,1,0); - inner_color.setVec(1,0,1,line_alpha); - mManipPart = LL_XZ_PLANE; - break; - case LL_Z_ARROW: - normal.setVec(0,0,1); - inner_color.setVec(1,1,0,line_alpha); - mManipPart = LL_XY_PLANE; - break; - default: - break; - } - - highlightIntersection(normal, selection_center, grid_rotation, inner_color); - mManipPart = temp_manip; - getManipAxis(first_object, mManipPart, translate_axis); - - LLVector3 at_axis_abs; - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - at_axis_abs = LLVector3::x_axis * ~grid_rotation; - } - else - { - at_axis_abs = saved_selection_center - LLViewerCamera::getInstance()->getOrigin(); - at_axis_abs.normVec(); - - at_axis_abs = at_axis_abs * ~grid_rotation; - } - at_axis_abs.abs(); - - if (at_axis_abs.mV[VX] > at_axis_abs.mV[VY] && at_axis_abs.mV[VX] > at_axis_abs.mV[VZ]) - { - if (mManipPart == LL_Y_ARROW) - { - mSnapOffsetAxis = LLVector3::z_axis; - } - else if (mManipPart == LL_Z_ARROW) - { - mSnapOffsetAxis = LLVector3::y_axis; - } - else if (at_axis_abs.mV[VY] > at_axis_abs.mV[VZ]) - { - mSnapOffsetAxis = LLVector3::z_axis; - } - else - { - mSnapOffsetAxis = LLVector3::y_axis; - } - } - else if (at_axis_abs.mV[VY] > at_axis_abs.mV[VZ]) - { - if (mManipPart == LL_X_ARROW) - { - mSnapOffsetAxis = LLVector3::z_axis; - } - else if (mManipPart == LL_Z_ARROW) - { - mSnapOffsetAxis = LLVector3::x_axis; - } - else if (at_axis_abs.mV[VX] > at_axis_abs.mV[VZ]) - { - mSnapOffsetAxis = LLVector3::z_axis; - } - else - { - mSnapOffsetAxis = LLVector3::x_axis; - } - } - else - { - if (mManipPart == LL_X_ARROW) - { - mSnapOffsetAxis = LLVector3::y_axis; - } - else if (mManipPart == LL_Y_ARROW) - { - mSnapOffsetAxis = LLVector3::x_axis; - } - else if (at_axis_abs.mV[VX] > at_axis_abs.mV[VY]) - { - mSnapOffsetAxis = LLVector3::y_axis; - } - else - { - mSnapOffsetAxis = LLVector3::x_axis; - } - } - - mSnapOffsetAxis = mSnapOffsetAxis * grid_rotation; - - F32 guide_size_meters; - - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - guide_size_meters = 1.f / gAgentCamera.mHUDCurZoom; - mSnapOffsetMeters = mArrowLengthMeters * 1.5f; - } - else - { - LLVector3 cam_to_selection = getPivotPoint() - LLViewerCamera::getInstance()->getOrigin(); - F32 current_range = cam_to_selection.normVec(); - guide_size_meters = SNAP_GUIDE_SCREEN_SIZE * gViewerWindow->getWorldViewHeightRaw() * current_range / LLViewerCamera::getInstance()->getPixelMeterRatio(); - - F32 fraction_of_fov = mAxisArrowLength / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); - F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians - F32 offset_at_camera = tan(apparent_angle) * 1.5f; - F32 range = dist_vec(gAgent.getPosAgentFromGlobal(first_node->mSavedPositionGlobal), LLViewerCamera::getInstance()->getOrigin()); - mSnapOffsetMeters = range * offset_at_camera; - } - - LLVector3 tick_start; - LLVector3 tick_end; - - // how far away from grid origin is the selection along the axis of translation? - F32 dist_grid_axis = (selection_center - mGridOrigin) * translate_axis; - // find distance to nearest smallest grid unit - F32 offset_nearest_grid_unit = fmodf(dist_grid_axis, smallest_grid_unit_scale); - // how many smallest grid units are we away from largest grid scale? - S32 sub_div_offset = ll_round(fmodf(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() / sGridMinSubdivisionLevel) / smallest_grid_unit_scale); - S32 num_ticks_per_side = llmax(1, llfloor(0.5f * guide_size_meters / smallest_grid_unit_scale)); - - LLGLDepthTest gls_depth(GL_FALSE); - - for (S32 pass = 0; pass < 3; pass++) - { - LLColor4 line_color = setupSnapGuideRenderPass(pass); - LLGLDepthTest gls_depth(pass != 1); - - gGL.begin(LLRender::LINES); - { - LLVector3 line_start = selection_center + (mSnapOffsetMeters * mSnapOffsetAxis) + (translate_axis * (guide_size_meters * 0.5f + offset_nearest_grid_unit)); - LLVector3 line_end = selection_center + (mSnapOffsetMeters * mSnapOffsetAxis) - (translate_axis * (guide_size_meters * 0.5f + offset_nearest_grid_unit)); - LLVector3 line_mid = (line_start + line_end) * 0.5f; - - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); - gGL.vertex3fv(line_start.mV); - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); - gGL.vertex3fv(line_mid.mV); - gGL.vertex3fv(line_mid.mV); - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); - gGL.vertex3fv(line_end.mV); - - line_start.setVec(selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) + (translate_axis * guide_size_meters * 0.5f)); - line_end.setVec(selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) - (translate_axis * guide_size_meters * 0.5f)); - line_mid = (line_start + line_end) * 0.5f; - - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); - gGL.vertex3fv(line_start.mV); - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); - gGL.vertex3fv(line_mid.mV); - gGL.vertex3fv(line_mid.mV); - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); - gGL.vertex3fv(line_end.mV); - - for (S32 i = -num_ticks_per_side; i <= num_ticks_per_side; i++) - { - tick_start = selection_center + (translate_axis * (smallest_grid_unit_scale * (F32)i - offset_nearest_grid_unit)); - - //No need check this condition to prevent tick position scaling (FIX MAINT-5207/5208) - //F32 cur_subdivisions = getSubdivisionLevel(tick_start, translate_axis, getMinGridScale()); - /*if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / cur_subdivisions)) != 0.f) - { - continue; - }*/ - - // add in off-axis offset - tick_start += (mSnapOffsetAxis * mSnapOffsetMeters); - - F32 tick_scale = 1.f; - for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) - { - if (fmodf((F32)(i + sub_div_offset), division_level) == 0.f) - { - break; - } - tick_scale *= 0.7f; - } - -// S32 num_ticks_to_fade = is_sub_tick ? num_ticks_per_side / 2 : num_ticks_per_side; -// F32 alpha = line_alpha * (1.f - (0.8f * ((F32)llabs(i) / (F32)num_ticks_to_fade))); - - tick_end = tick_start + (mSnapOffsetAxis * mSnapOffsetMeters * tick_scale); - - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); - gGL.vertex3fv(tick_start.mV); - gGL.vertex3fv(tick_end.mV); - - tick_start = selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) + - (translate_axis * (getMinGridScale() / (F32)(max_subdivisions) * (F32)i - offset_nearest_grid_unit)); - tick_end = tick_start - (mSnapOffsetAxis * mSnapOffsetMeters * tick_scale); - - gGL.vertex3fv(tick_start.mV); - gGL.vertex3fv(tick_end.mV); - } - } - gGL.end(); - - if (mInSnapRegime) - { - LLVector3 line_start = selection_center - mSnapOffsetAxis * mSnapOffsetMeters; - LLVector3 line_end = selection_center + mSnapOffsetAxis * mSnapOffsetMeters; - - gGL.begin(LLRender::LINES); - { - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); - - gGL.vertex3fv(line_start.mV); - gGL.vertex3fv(line_end.mV); - } - gGL.end(); - - // draw snap guide arrow - gGL.begin(LLRender::TRIANGLES); - { - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); - - LLVector3 arrow_dir; - LLVector3 arrow_span = translate_axis; - - arrow_dir = -mSnapOffsetAxis; - gGL.vertex3fv((line_start + arrow_dir * mConeSize * SNAP_ARROW_SCALE).mV); - gGL.vertex3fv((line_start + arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); - gGL.vertex3fv((line_start - arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); - - arrow_dir = mSnapOffsetAxis; - gGL.vertex3fv((line_end + arrow_dir * mConeSize * SNAP_ARROW_SCALE).mV); - gGL.vertex3fv((line_end + arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); - gGL.vertex3fv((line_end - arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); - } - gGL.end(); - } - } - - sub_div_offset = ll_round(fmod(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() * 32.f) / smallest_grid_unit_scale); - - LLVector2 screen_translate_axis(llabs(translate_axis * LLViewerCamera::getInstance()->getLeftAxis()), llabs(translate_axis * LLViewerCamera::getInstance()->getUpAxis())); - screen_translate_axis.normVec(); - - S32 tick_label_spacing = ll_round(screen_translate_axis * sTickLabelSpacing); - - // render tickmark values - for (S32 i = -num_ticks_per_side; i <= num_ticks_per_side; i++) - { - LLVector3 tick_pos = selection_center + (translate_axis * ((smallest_grid_unit_scale * (F32)i) - offset_nearest_grid_unit)); - F32 alpha = line_alpha * (1.f - (0.5f * ((F32)llabs(i) / (F32)num_ticks_per_side))); - - F32 tick_scale = 1.f; - for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) - { - if (fmodf((F32)(i + sub_div_offset), division_level) == 0.f) - { - break; - } - tick_scale *= 0.7f; - } - - if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / getSubdivisionLevel(tick_pos, translate_axis, getMinGridScale(), tick_label_spacing))) == 0.f) - { - F32 snap_offset_meters; - - if (mSnapOffsetAxis * LLViewerCamera::getInstance()->getUpAxis() > 0.f) - { - snap_offset_meters = mSnapOffsetMeters; - } - else - { - snap_offset_meters = -mSnapOffsetMeters; - } - LLVector3 text_origin = selection_center + - (translate_axis * ((smallest_grid_unit_scale * (F32)i) - offset_nearest_grid_unit)) + - (mSnapOffsetAxis * snap_offset_meters * (1.f + tick_scale)); - - LLVector3 tick_offset = (tick_pos - mGridOrigin) * ~mGridRotation; - F32 offset_val = 0.5f * tick_offset.mV[ARROW_TO_AXIS[mManipPart]] / getMinGridScale(); - EGridMode grid_mode = LLSelectMgr::getInstance()->getGridMode(); - F32 text_highlight = 0.8f; - if(i - ll_round(offset_nearest_grid_unit / smallest_grid_unit_scale) == 0 && mInSnapRegime) - { - text_highlight = 1.f; - } - - if (grid_mode == GRID_MODE_WORLD) - { - // rescale units to meters from multiple of grid scale - offset_val *= 2.f * grid_scale[ARROW_TO_AXIS[mManipPart]]; - renderTickValue(text_origin, offset_val, std::string("m"), LLColor4(text_highlight, text_highlight, text_highlight, alpha)); - } - else - { - renderTickValue(text_origin, offset_val, std::string("x"), LLColor4(text_highlight, text_highlight, text_highlight, alpha)); - } - } - } - if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD) - { - // render helpful text - if (mHelpTextTimer.getElapsedTimeF32() < sHelpTextVisibleTime + sHelpTextFadeTime && sNumTimesHelpTextShown < sMaxTimesShowHelpText) - { - F32 snap_offset_meters_up; - if (mSnapOffsetAxis * LLViewerCamera::getInstance()->getUpAxis() > 0.f) - { - snap_offset_meters_up = mSnapOffsetMeters; - } - else - { - snap_offset_meters_up = -mSnapOffsetMeters; - } - - LLVector3 selection_center_start = getSavedPivotPoint();//LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent(); - - LLVector3 help_text_pos = selection_center_start + (snap_offset_meters_up * 3.f * mSnapOffsetAxis); - const LLFontGL* big_fontp = LLFontGL::getFontSansSerif(); - - 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, line_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, false); - help_text = LLTrans::getString("manip_hint2"); - help_text_pos -= LLViewerCamera::getInstance()->getUpAxis() * mSnapOffsetMeters * 0.2f; - 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); - } - } - } - else - { - // render gridlines for planar snapping - - F32 u = 0, v = 0; - LLColor4 inner_color; - LLVector3 normal; - LLVector3 grid_center = selection_center - grid_origin; - F32 usc = 1; - F32 vsc = 1; - - grid_center *= ~grid_rotation; - - switch (mManipPart) - { - case LL_YZ_PLANE: - u = grid_center.mV[VY]; - v = grid_center.mV[VZ]; - usc = grid_scale.mV[VY]; - vsc = grid_scale.mV[VZ]; - inner_color.setVec(0,1,1,line_alpha); - normal.setVec(1,0,0); - break; - case LL_XZ_PLANE: - u = grid_center.mV[VX]; - v = grid_center.mV[VZ]; - usc = grid_scale.mV[VX]; - vsc = grid_scale.mV[VZ]; - inner_color.setVec(1,0,1,line_alpha); - normal.setVec(0,1,0); - break; - case LL_XY_PLANE: - u = grid_center.mV[VX]; - v = grid_center.mV[VY]; - usc = grid_scale.mV[VX]; - vsc = grid_scale.mV[VY]; - inner_color.setVec(1,1,0,line_alpha); - normal.setVec(0,0,1); - break; - default: - break; - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - highlightIntersection(normal, selection_center, grid_rotation, inner_color); - - gGL.pushMatrix(); - - F32 x,y,z,angle_radians; - grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); - gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); - gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); - - F32 sz = mGridSizeMeters; - F32 tiles = sz; - - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.pushMatrix(); - usc = 1.0f/usc; - vsc = 1.0f/vsc; - - while (usc > vsc*4.0f) - { - usc *= 0.5f; - } - while (vsc > usc * 4.0f) - { - vsc *= 0.5f; - } - - gGL.scalef(usc, vsc, 1.0f); - gGL.translatef(u, v, 0); - - float a = line_alpha; - - { - //draw grid behind objects - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - - { - //LLGLDisable stencil(GL_STENCIL_TEST); - { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getGridTexName()); - gGL.flush(); - gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - renderGrid(u,v,tiles,0.9f, 0.9f, 0.9f,a*0.15f); - gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - } - - { - //draw black overlay - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - renderGrid(u,v,tiles,0.0f, 0.0f, 0.0f,a*0.16f); - - //draw grid top - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getGridTexName()); - renderGrid(u,v,tiles,1,1,1,a); - - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); - } - - { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - renderGuidelines(); - } - - { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER); - gGL.flush(); - - switch (mManipPart) - { - case LL_YZ_PLANE: - renderGuidelines(FALSE, TRUE, TRUE); - break; - case LL_XZ_PLANE: - renderGuidelines(TRUE, FALSE, TRUE); - break; - case LL_XY_PLANE: - renderGuidelines(TRUE, TRUE, FALSE); - break; - default: - break; - } - gGL.flush(); - } - } - } - } + LLVector3 normal; + LLVector3 grid_center = selection_center - grid_origin; + F32 usc = 1; + F32 vsc = 1; + + grid_center *= ~grid_rotation; + + switch (mManipPart) + { + case LL_YZ_PLANE: + u = grid_center.mV[VY]; + v = grid_center.mV[VZ]; + usc = grid_scale.mV[VY]; + vsc = grid_scale.mV[VZ]; + inner_color.setVec(0,1,1,line_alpha); + normal.setVec(1,0,0); + break; + case LL_XZ_PLANE: + u = grid_center.mV[VX]; + v = grid_center.mV[VZ]; + usc = grid_scale.mV[VX]; + vsc = grid_scale.mV[VZ]; + inner_color.setVec(1,0,1,line_alpha); + normal.setVec(0,1,0); + break; + case LL_XY_PLANE: + u = grid_center.mV[VX]; + v = grid_center.mV[VY]; + usc = grid_scale.mV[VX]; + vsc = grid_scale.mV[VY]; + inner_color.setVec(1,1,0,line_alpha); + normal.setVec(0,0,1); + break; + default: + break; + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + highlightIntersection(normal, selection_center, grid_rotation, inner_color); + + gGL.pushMatrix(); + + F32 x,y,z,angle_radians; + grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); + gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); + gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); + + F32 sz = mGridSizeMeters; + F32 tiles = sz; + + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.pushMatrix(); + usc = 1.0f/usc; + vsc = 1.0f/vsc; + + while (usc > vsc*4.0f) + { + usc *= 0.5f; + } + while (vsc > usc * 4.0f) + { + vsc *= 0.5f; + } + + gGL.scalef(usc, vsc, 1.0f); + gGL.translatef(u, v, 0); + + float a = line_alpha; + + { + //draw grid behind objects + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + + { + //LLGLDisable stencil(GL_STENCIL_TEST); + { + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getGridTexName()); + gGL.flush(); + gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + renderGrid(u,v,tiles,0.9f, 0.9f, 0.9f,a*0.15f); + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } + + { + //draw black overlay + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + renderGrid(u,v,tiles,0.0f, 0.0f, 0.0f,a*0.16f); + + //draw grid top + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getGridTexName()); + renderGrid(u,v,tiles,1,1,1,a); + + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + } + + { + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + renderGuidelines(); + } + + { + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER); + gGL.flush(); + + switch (mManipPart) + { + case LL_YZ_PLANE: + renderGuidelines(FALSE, TRUE, TRUE); + break; + case LL_XZ_PLANE: + renderGuidelines(TRUE, FALSE, TRUE); + break; + case LL_XY_PLANE: + renderGuidelines(TRUE, TRUE, FALSE); + break; + default: + break; + } + gGL.flush(); + } + } + } + } } void LLManipTranslate::renderGrid(F32 x, F32 y, F32 size, F32 r, F32 g, F32 b, F32 a) { - F32 d = size*0.5f; - - for (F32 xx = -size-d; xx < size+d; xx += d) - { - gGL.begin(LLRender::TRIANGLE_STRIP); - for (F32 yy = -size-d; yy < size+d; yy += d) - { - float dx, dy, da; - - dx = xx; dy = yy; - da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; - gGL.texCoord2f(dx, dy); - renderGridVert(dx,dy,r,g,b,da); - - dx = xx+d; dy = yy; - da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; - gGL.texCoord2f(dx, dy); - renderGridVert(dx,dy,r,g,b,da); - - dx = xx; dy = yy+d; - da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; - gGL.texCoord2f(dx, dy); - renderGridVert(dx,dy,r,g,b,da); - - dx = xx+d; dy = yy+d; - da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; - gGL.texCoord2f(dx, dy); - renderGridVert(dx,dy,r,g,b,da); - } - gGL.end(); - } - - + F32 d = size*0.5f; + + for (F32 xx = -size-d; xx < size+d; xx += d) + { + gGL.begin(LLRender::TRIANGLE_STRIP); + for (F32 yy = -size-d; yy < size+d; yy += d) + { + float dx, dy, da; + + dx = xx; dy = yy; + da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; + gGL.texCoord2f(dx, dy); + renderGridVert(dx,dy,r,g,b,da); + + dx = xx+d; dy = yy; + da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; + gGL.texCoord2f(dx, dy); + renderGridVert(dx,dy,r,g,b,da); + + dx = xx; dy = yy+d; + da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; + gGL.texCoord2f(dx, dy); + renderGridVert(dx,dy,r,g,b,da); + + dx = xx+d; dy = yy+d; + da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; + gGL.texCoord2f(dx, dy); + renderGridVert(dx,dy,r,g,b,da); + } + gGL.end(); + } + + } -void LLManipTranslate::highlightIntersection(LLVector3 normal, - LLVector3 selection_center, - LLQuaternion grid_rotation, - LLColor4 inner_color) +void LLManipTranslate::highlightIntersection(LLVector3 normal, + LLVector3 selection_center, + LLQuaternion grid_rotation, + LLColor4 inner_color) { #if 0 // DEPRECATED - if (!gSavedSettings.getBOOL("GridCrossSections")) - { - return; - } - - - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - - - static const U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY }; - static const U32 num_types = LL_ARRAY_SIZE(types); - - GLuint stencil_mask = 0xFFFFFFFF; - //stencil in volumes - - gGL.flush(); - - if (shader) - { - gClipProgram.bind(); - } - - { - //glStencilMask(stencil_mask); //deprecated - //glClearStencil(1); - //glClear(GL_STENCIL_BUFFER_BIT); - LLGLEnable cull_face(GL_CULL_FACE); - //LLGLEnable stencil(GL_STENCIL_TEST); - LLGLDepthTest depth (GL_TRUE, GL_FALSE, GL_ALWAYS); - //glStencilFunc(GL_ALWAYS, 0, stencil_mask); - gGL.setColorMask(false, false); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.diffuseColor4f(1,1,1,1); - - //setup clip plane - normal = normal * grid_rotation; - if (normal * (LLViewerCamera::getInstance()->getOrigin()-selection_center) < 0) - { - normal = -normal; - } - F32 d = -(selection_center * normal); - glh::vec4f plane(normal.mV[0], normal.mV[1], normal.mV[2], d ); - - gGL.getModelviewMatrix().inverse().mult_vec_matrix(plane); - - static LLStaticHashedString sClipPlane("clip_plane"); - gClipProgram.uniform4fv(sClipPlane, 1, plane.v); - - BOOL particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES); - BOOL clouds = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS); - - if (particles) - { - LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); - } - if (clouds) - { - LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS); - } - - //stencil in volumes - //glStencilOp(GL_INCR, GL_INCR, GL_INCR); - glCullFace(GL_FRONT); - for (U32 i = 0; i < num_types; i++) - { - gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); - } - - //glStencilOp(GL_DECR, GL_DECR, GL_DECR); - glCullFace(GL_BACK); - for (U32 i = 0; i < num_types; i++) - { - gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); - } - - if (particles) - { - LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); - } - if (clouds) - { - LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS); - } - - gGL.setColorMask(true, false); - } - gGL.color4f(1,1,1,1); - - gGL.pushMatrix(); - - F32 x,y,z,angle_radians; - grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); - gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); - gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); - - F32 sz = mGridSizeMeters; - F32 tiles = sz; - - if (shader) - { - shader->bind(); - } - - if (shader) - { - shader->bind(); - } - - //draw volume/plane intersections - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest depth(GL_FALSE); - //LLGLEnable stencil(GL_STENCIL_TEST); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - glStencilFunc(GL_EQUAL, 0, stencil_mask); - renderGrid(0,0,tiles,inner_color.mV[0], inner_color.mV[1], inner_color.mV[2], 0.25f); - } - - glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF); - glStencilMask(0xFFFFFFFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - - gGL.popMatrix(); + if (!gSavedSettings.getBOOL("GridCrossSections")) + { + return; + } + + + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + + + static const U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY }; + static const U32 num_types = LL_ARRAY_SIZE(types); + + GLuint stencil_mask = 0xFFFFFFFF; + //stencil in volumes + + gGL.flush(); + + if (shader) + { + gClipProgram.bind(); + } + + { + //glStencilMask(stencil_mask); //deprecated + //glClearStencil(1); + //glClear(GL_STENCIL_BUFFER_BIT); + LLGLEnable cull_face(GL_CULL_FACE); + //LLGLEnable stencil(GL_STENCIL_TEST); + LLGLDepthTest depth (GL_TRUE, GL_FALSE, GL_ALWAYS); + //glStencilFunc(GL_ALWAYS, 0, stencil_mask); + gGL.setColorMask(false, false); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.diffuseColor4f(1,1,1,1); + + //setup clip plane + normal = normal * grid_rotation; + if (normal * (LLViewerCamera::getInstance()->getOrigin()-selection_center) < 0) + { + normal = -normal; + } + F32 d = -(selection_center * normal); + glh::vec4f plane(normal.mV[0], normal.mV[1], normal.mV[2], d ); + + gGL.getModelviewMatrix().inverse().mult_vec_matrix(plane); + + static LLStaticHashedString sClipPlane("clip_plane"); + gClipProgram.uniform4fv(sClipPlane, 1, plane.v); + + BOOL particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES); + BOOL clouds = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS); + + if (particles) + { + LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); + } + if (clouds) + { + LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS); + } + + //stencil in volumes + //glStencilOp(GL_INCR, GL_INCR, GL_INCR); + glCullFace(GL_FRONT); + for (U32 i = 0; i < num_types; i++) + { + gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); + } + + //glStencilOp(GL_DECR, GL_DECR, GL_DECR); + glCullFace(GL_BACK); + for (U32 i = 0; i < num_types; i++) + { + gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); + } + + if (particles) + { + LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); + } + if (clouds) + { + LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS); + } + + gGL.setColorMask(true, false); + } + gGL.color4f(1,1,1,1); + + gGL.pushMatrix(); + + F32 x,y,z,angle_radians; + grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); + gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); + gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); + + F32 sz = mGridSizeMeters; + F32 tiles = sz; + + if (shader) + { + shader->bind(); + } + + if (shader) + { + shader->bind(); + } + + //draw volume/plane intersections + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLDepthTest depth(GL_FALSE); + //LLGLEnable stencil(GL_STENCIL_TEST); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glStencilFunc(GL_EQUAL, 0, stencil_mask); + renderGrid(0,0,tiles,inner_color.mV[0], inner_color.mV[1], inner_color.mV[2], 0.25f); + } + + glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF); + glStencilMask(0xFFFFFFFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + gGL.popMatrix(); #endif } void LLManipTranslate::renderText() { - if (mObjectSelection->getRootObjectCount() && !mObjectSelection->isAttachment()) - { - LLVector3 pos = getPivotPoint(); - renderXYZ(pos); - } - else - { - const BOOL children_ok = TRUE; - LLViewerObject* objectp = mObjectSelection->getFirstRootObject(children_ok); - if (objectp) - { - renderXYZ(objectp->getPositionEdit()); - } - } + if (mObjectSelection->getRootObjectCount() && !mObjectSelection->isAttachment()) + { + LLVector3 pos = getPivotPoint(); + renderXYZ(pos); + } + else + { + const BOOL children_ok = TRUE; + LLViewerObject* objectp = mObjectSelection->getFirstRootObject(children_ok); + if (objectp) + { + renderXYZ(objectp->getPositionEdit()); + } + } } void LLManipTranslate::renderTranslationHandles() { - LLVector3 grid_origin; - LLVector3 grid_scale; - LLQuaternion grid_rotation; - LLGLDepthTest gls_depth(GL_FALSE); - - LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); - LLVector3 at_axis; - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - at_axis = LLVector3::x_axis * ~grid_rotation; - } - else - { - at_axis = LLViewerCamera::getInstance()->getAtAxis() * ~grid_rotation; - } - - if (at_axis.mV[VX] > 0.f) - { - mPlaneManipPositions.mV[VX] = 1.f; - } - else - { - mPlaneManipPositions.mV[VX] = -1.f; - } - - if (at_axis.mV[VY] > 0.f) - { - mPlaneManipPositions.mV[VY] = 1.f; - } - else - { - mPlaneManipPositions.mV[VY] = -1.f; - } - - if (at_axis.mV[VZ] > 0.f) - { - mPlaneManipPositions.mV[VZ] = 1.f; - } - else - { - mPlaneManipPositions.mV[VZ] = -1.f; - } - - LLViewerObject *first_object = mObjectSelection->getFirstMoveableObject(TRUE); - if (!first_object) return; - - LLVector3 selection_center = getPivotPoint(); - - // Drag handles - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWorldViewHeightRaw(); - mArrowLengthMeters /= gAgentCamera.mHUDCurZoom; - } - else - { - LLVector3 camera_pos_agent = gAgentCamera.getCameraPositionAgent(); - F32 range = dist_vec(camera_pos_agent, selection_center); - F32 range_from_agent = dist_vec(gAgent.getPositionAgent(), selection_center); - - // Don't draw handles if you're too far away - if (gSavedSettings.getBOOL("LimitSelectDistance")) - { - if (range_from_agent > gSavedSettings.getF32("MaxSelectDistance")) - { - return; - } - } - - if (range > 0.001f) - { - // range != zero - F32 fraction_of_fov = mAxisArrowLength / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); - F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians - mArrowLengthMeters = range * tan(apparent_angle); - } - else - { - // range == zero - mArrowLengthMeters = 1.0f; - } - } - //Assume that UI scale factor is equivalent for X and Y axis - F32 ui_scale_factor = LLUI::getScaleFactor().mV[VX]; - mArrowLengthMeters *= ui_scale_factor; - - mPlaneManipOffsetMeters = mArrowLengthMeters * 1.8f; - mGridSizeMeters = gSavedSettings.getF32("GridDrawSize"); - mConeSize = mArrowLengthMeters / 4.f; - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - { - gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); - - F32 angle_radians, x, y, z; - grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); - - gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); - - LLQuaternion invRotation = grid_rotation; - invRotation.conjQuat(); - - LLVector3 relative_camera_dir; - - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - relative_camera_dir = LLVector3::x_axis * invRotation; - } - else - { - relative_camera_dir = (selection_center - LLViewerCamera::getInstance()->getOrigin()) * invRotation; - } - relative_camera_dir.normVec(); - - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDisable cull_face(GL_CULL_FACE); - - LLColor4 color1; - LLColor4 color2; - - // update manipulator sizes - for (S32 index = 0; index < 3; index++) - { - if (index == mManipPart - LL_X_ARROW || index == mHighlightedPart - LL_X_ARROW) - { - mArrowScales.mV[index] = lerp(mArrowScales.mV[index], SELECTED_ARROW_SCALE, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - } - else if (index == mManipPart - LL_YZ_PLANE || index == mHighlightedPart - LL_YZ_PLANE) - { - mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], SELECTED_ARROW_SCALE, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - } - else - { - mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - } - } - - if ((mManipPart == LL_NO_PART || mManipPart == LL_YZ_PLANE) && llabs(relative_camera_dir.mV[VX]) > MIN_PLANE_MANIP_DOT_PRODUCT) - { - // render YZ plane manipulator - gGL.pushMatrix(); - gGL.scalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]); - gGL.translatef(0.f, mPlaneManipOffsetMeters, mPlaneManipOffsetMeters); - gGL.scalef(mPlaneScales.mV[VX], mPlaneScales.mV[VX], mPlaneScales.mV[VX]); - if (mHighlightedPart == LL_YZ_PLANE) - { - color1.setVec(0.f, 1.f, 0.f, 1.f); - color2.setVec(0.f, 0.f, 1.f, 1.f); - } - else - { - color1.setVec(0.f, 1.f, 0.f, 0.6f); - color2.setVec(0.f, 0.f, 1.f, 0.6f); - } - gGL.begin(LLRender::TRIANGLES); - { - gGL.color4fv(color1.mV); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f)); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); - - gGL.color4fv(color2.mV); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); - } - gGL.end(); - - LLUI::setLineWidth(3.0f); - gGL.begin(LLRender::LINES); - { - gGL.color4f(0.f, 0.f, 0.f, 0.3f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f); - - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); - } - gGL.end(); - LLUI::setLineWidth(1.0f); - gGL.popMatrix(); - } - - if ((mManipPart == LL_NO_PART || mManipPart == LL_XZ_PLANE) && llabs(relative_camera_dir.mV[VY]) > MIN_PLANE_MANIP_DOT_PRODUCT) - { - // render XZ plane manipulator - gGL.pushMatrix(); - gGL.scalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]); - gGL.translatef(mPlaneManipOffsetMeters, 0.f, mPlaneManipOffsetMeters); - gGL.scalef(mPlaneScales.mV[VY], mPlaneScales.mV[VY], mPlaneScales.mV[VY]); - if (mHighlightedPart == LL_XZ_PLANE) - { - color1.setVec(0.f, 0.f, 1.f, 1.f); - color2.setVec(1.f, 0.f, 0.f, 1.f); - } - else - { - color1.setVec(0.f, 0.f, 1.f, 0.6f); - color2.setVec(1.f, 0.f, 0.f, 0.6f); - } - - gGL.begin(LLRender::TRIANGLES); - { - gGL.color4fv(color1.mV); - gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); - gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); - gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); - - gGL.color4fv(color2.mV); - gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); - gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f)); - gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); - } - gGL.end(); - - LLUI::setLineWidth(3.0f); - gGL.begin(LLRender::LINES); - { - gGL.color4f(0.f, 0.f, 0.f, 0.3f); - gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f); - gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f); - - gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); - gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); - } - gGL.end(); - LLUI::setLineWidth(1.0f); - - gGL.popMatrix(); - } - - if ((mManipPart == LL_NO_PART || mManipPart == LL_XY_PLANE) && llabs(relative_camera_dir.mV[VZ]) > MIN_PLANE_MANIP_DOT_PRODUCT) - { - // render XY plane manipulator - gGL.pushMatrix(); - gGL.scalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]); - -/* Y - ^ - v1 - | \ - |<- v0 - | /| \ - v2__v__v3 > X + LLVector3 grid_origin; + LLVector3 grid_scale; + LLQuaternion grid_rotation; + LLGLDepthTest gls_depth(GL_FALSE); + + LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); + LLVector3 at_axis; + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + at_axis = LLVector3::x_axis * ~grid_rotation; + } + else + { + at_axis = LLViewerCamera::getInstance()->getAtAxis() * ~grid_rotation; + } + + if (at_axis.mV[VX] > 0.f) + { + mPlaneManipPositions.mV[VX] = 1.f; + } + else + { + mPlaneManipPositions.mV[VX] = -1.f; + } + + if (at_axis.mV[VY] > 0.f) + { + mPlaneManipPositions.mV[VY] = 1.f; + } + else + { + mPlaneManipPositions.mV[VY] = -1.f; + } + + if (at_axis.mV[VZ] > 0.f) + { + mPlaneManipPositions.mV[VZ] = 1.f; + } + else + { + mPlaneManipPositions.mV[VZ] = -1.f; + } + + LLViewerObject *first_object = mObjectSelection->getFirstMoveableObject(TRUE); + if (!first_object) return; + + LLVector3 selection_center = getPivotPoint(); + + // Drag handles + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWorldViewHeightRaw(); + mArrowLengthMeters /= gAgentCamera.mHUDCurZoom; + } + else + { + LLVector3 camera_pos_agent = gAgentCamera.getCameraPositionAgent(); + F32 range = dist_vec(camera_pos_agent, selection_center); + F32 range_from_agent = dist_vec(gAgent.getPositionAgent(), selection_center); + + // Don't draw handles if you're too far away + if (gSavedSettings.getBOOL("LimitSelectDistance")) + { + if (range_from_agent > gSavedSettings.getF32("MaxSelectDistance")) + { + return; + } + } + + if (range > 0.001f) + { + // range != zero + F32 fraction_of_fov = mAxisArrowLength / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); + F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians + mArrowLengthMeters = range * tan(apparent_angle); + } + else + { + // range == zero + mArrowLengthMeters = 1.0f; + } + } + //Assume that UI scale factor is equivalent for X and Y axis + F32 ui_scale_factor = LLUI::getScaleFactor().mV[VX]; + mArrowLengthMeters *= ui_scale_factor; + + mPlaneManipOffsetMeters = mArrowLengthMeters * 1.8f; + mGridSizeMeters = gSavedSettings.getF32("GridDrawSize"); + mConeSize = mArrowLengthMeters / 4.f; + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + { + gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); + + F32 angle_radians, x, y, z; + grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); + + gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); + + LLQuaternion invRotation = grid_rotation; + invRotation.conjQuat(); + + LLVector3 relative_camera_dir; + + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + relative_camera_dir = LLVector3::x_axis * invRotation; + } + else + { + relative_camera_dir = (selection_center - LLViewerCamera::getInstance()->getOrigin()) * invRotation; + } + relative_camera_dir.normVec(); + + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLDisable cull_face(GL_CULL_FACE); + + LLColor4 color1; + LLColor4 color2; + + // update manipulator sizes + for (S32 index = 0; index < 3; index++) + { + if (index == mManipPart - LL_X_ARROW || index == mHighlightedPart - LL_X_ARROW) + { + mArrowScales.mV[index] = lerp(mArrowScales.mV[index], SELECTED_ARROW_SCALE, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + } + else if (index == mManipPart - LL_YZ_PLANE || index == mHighlightedPart - LL_YZ_PLANE) + { + mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], SELECTED_ARROW_SCALE, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + } + else + { + mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + } + } + + if ((mManipPart == LL_NO_PART || mManipPart == LL_YZ_PLANE) && llabs(relative_camera_dir.mV[VX]) > MIN_PLANE_MANIP_DOT_PRODUCT) + { + // render YZ plane manipulator + gGL.pushMatrix(); + gGL.scalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]); + gGL.translatef(0.f, mPlaneManipOffsetMeters, mPlaneManipOffsetMeters); + gGL.scalef(mPlaneScales.mV[VX], mPlaneScales.mV[VX], mPlaneScales.mV[VX]); + if (mHighlightedPart == LL_YZ_PLANE) + { + color1.setVec(0.f, 1.f, 0.f, 1.f); + color2.setVec(0.f, 0.f, 1.f, 1.f); + } + else + { + color1.setVec(0.f, 1.f, 0.f, 0.6f); + color2.setVec(0.f, 0.f, 1.f, 0.6f); + } + gGL.begin(LLRender::TRIANGLES); + { + gGL.color4fv(color1.mV); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f)); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); + + gGL.color4fv(color2.mV); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); + } + gGL.end(); + + LLUI::setLineWidth(3.0f); + gGL.begin(LLRender::LINES); + { + gGL.color4f(0.f, 0.f, 0.f, 0.3f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f); + + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); + } + gGL.end(); + LLUI::setLineWidth(1.0f); + gGL.popMatrix(); + } + + if ((mManipPart == LL_NO_PART || mManipPart == LL_XZ_PLANE) && llabs(relative_camera_dir.mV[VY]) > MIN_PLANE_MANIP_DOT_PRODUCT) + { + // render XZ plane manipulator + gGL.pushMatrix(); + gGL.scalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]); + gGL.translatef(mPlaneManipOffsetMeters, 0.f, mPlaneManipOffsetMeters); + gGL.scalef(mPlaneScales.mV[VY], mPlaneScales.mV[VY], mPlaneScales.mV[VY]); + if (mHighlightedPart == LL_XZ_PLANE) + { + color1.setVec(0.f, 0.f, 1.f, 1.f); + color2.setVec(1.f, 0.f, 0.f, 1.f); + } + else + { + color1.setVec(0.f, 0.f, 1.f, 0.6f); + color2.setVec(1.f, 0.f, 0.f, 0.6f); + } + + gGL.begin(LLRender::TRIANGLES); + { + gGL.color4fv(color1.mV); + gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); + gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); + gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); + + gGL.color4fv(color2.mV); + gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); + gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f)); + gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); + } + gGL.end(); + + LLUI::setLineWidth(3.0f); + gGL.begin(LLRender::LINES); + { + gGL.color4f(0.f, 0.f, 0.f, 0.3f); + gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f); + gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f); + + gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); + gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); + } + gGL.end(); + LLUI::setLineWidth(1.0f); + + gGL.popMatrix(); + } + + if ((mManipPart == LL_NO_PART || mManipPart == LL_XY_PLANE) && llabs(relative_camera_dir.mV[VZ]) > MIN_PLANE_MANIP_DOT_PRODUCT) + { + // render XY plane manipulator + gGL.pushMatrix(); + gGL.scalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]); + +/* Y + ^ + v1 + | \ + |<- v0 + | /| \ + v2__v__v3 > X */ - LLVector3 v0,v1,v2,v3; + LLVector3 v0,v1,v2,v3; #if 0 - // This should theoretically work but looks off; could be tuned later -SJB - gGL.translatef(-mPlaneManipOffsetMeters, -mPlaneManipOffsetMeters, 0.f); - v0 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f); - v1 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.75f), 0.f); - v2 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f); - v3 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f); + // This should theoretically work but looks off; could be tuned later -SJB + gGL.translatef(-mPlaneManipOffsetMeters, -mPlaneManipOffsetMeters, 0.f); + v0 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f); + v1 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.75f), 0.f); + v2 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f); + v3 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f); #else - gGL.translatef(mPlaneManipOffsetMeters, mPlaneManipOffsetMeters, 0.f); - v0 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f); - v1 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), 0.f); - v2 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f); - v3 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f); + gGL.translatef(mPlaneManipOffsetMeters, mPlaneManipOffsetMeters, 0.f); + v0 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f); + v1 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), 0.f); + v2 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f); + v3 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f); #endif - gGL.scalef(mPlaneScales.mV[VZ], mPlaneScales.mV[VZ], mPlaneScales.mV[VZ]); - if (mHighlightedPart == LL_XY_PLANE) - { - color1.setVec(1.f, 0.f, 0.f, 1.f); - color2.setVec(0.f, 1.f, 0.f, 1.f); - } - else - { - color1.setVec(0.8f, 0.f, 0.f, 0.6f); - color2.setVec(0.f, 0.8f, 0.f, 0.6f); - } - - gGL.begin(LLRender::TRIANGLES); - { - gGL.color4fv(color1.mV); - gGL.vertex3fv(v0.mV); - gGL.vertex3fv(v1.mV); - gGL.vertex3fv(v2.mV); - - gGL.color4fv(color2.mV); - gGL.vertex3fv(v2.mV); - gGL.vertex3fv(v3.mV); - gGL.vertex3fv(v0.mV); - } - gGL.end(); - - LLUI::setLineWidth(3.0f); - gGL.begin(LLRender::LINES); - { - gGL.color4f(0.f, 0.f, 0.f, 0.3f); - LLVector3 v12 = (v1 + v2) * .5f; - gGL.vertex3fv(v0.mV); - gGL.vertex3fv(v12.mV); - gGL.vertex3fv(v12.mV); - gGL.vertex3fv((v12 + (v0-v12)*.3f + (v2-v12)*.3f).mV); - gGL.vertex3fv(v12.mV); - gGL.vertex3fv((v12 + (v0-v12)*.3f + (v1-v12)*.3f).mV); - - LLVector3 v23 = (v2 + v3) * .5f; - gGL.vertex3fv(v0.mV); - gGL.vertex3fv(v23.mV); - gGL.vertex3fv(v23.mV); - gGL.vertex3fv((v23 + (v0-v23)*.3f + (v3-v23)*.3f).mV); - gGL.vertex3fv(v23.mV); - gGL.vertex3fv((v23 + (v0-v23)*.3f + (v2-v23)*.3f).mV); - } - gGL.end(); - LLUI::setLineWidth(1.0f); - - gGL.popMatrix(); - } - } - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // Since we draw handles with depth testing off, we need to draw them in the - // proper depth order. - - // Copied from LLDrawable::updateGeometry - LLVector3 pos_agent = first_object->getPositionAgent(); - LLVector3 camera_agent = gAgentCamera.getCameraPositionAgent(); - LLVector3 headPos = pos_agent - camera_agent; - - LLVector3 orientWRTHead = headPos * invRotation; - - // Find nearest vertex - 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: - // 0 & 5 - // 1 & 3 - // 2 & 4 - - // Table of order to draw faces, based on nearest vertex - static U32 face_list[8][NUM_AXES*2] = { - { 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 - { 4,0,3, 2,5,1 }, // v4 F403 F251 - { 2,5,1, 4,0,3 }, // v2 F251 F403 - { 2,5,3, 4,0,1 }, // v3 F253 F401 - { 4,5,1, 2,0,3 }, // v1 F451 F203 - { 4,5,3, 2,0,1 }, // v0 F453 F201 - }; - static const EManipPart which_arrow[6] = { - LL_Z_ARROW, - LL_X_ARROW, - LL_Y_ARROW, - LL_X_ARROW, - LL_Y_ARROW, - LL_Z_ARROW}; - - // draw arrows for deeper faces first, closer faces last - LLVector3 camera_axis; - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - camera_axis = LLVector3::x_axis; - } - else - { - camera_axis.setVec(gAgentCamera.getCameraPositionAgent() - first_object->getPositionAgent()); - } - - for (U32 i = 0; i < NUM_AXES*2; i++) - { - U32 face = face_list[nearest][i]; - - LLVector3 arrow_axis; - getManipAxis(first_object, which_arrow[face], arrow_axis); - - renderArrow(which_arrow[face], - mManipPart, - (face >= 3) ? -mConeSize : mConeSize, - (face >= 3) ? -mArrowLengthMeters : mArrowLengthMeters, - mConeSize, - FALSE); - } - } - } - gGL.popMatrix(); + gGL.scalef(mPlaneScales.mV[VZ], mPlaneScales.mV[VZ], mPlaneScales.mV[VZ]); + if (mHighlightedPart == LL_XY_PLANE) + { + color1.setVec(1.f, 0.f, 0.f, 1.f); + color2.setVec(0.f, 1.f, 0.f, 1.f); + } + else + { + color1.setVec(0.8f, 0.f, 0.f, 0.6f); + color2.setVec(0.f, 0.8f, 0.f, 0.6f); + } + + gGL.begin(LLRender::TRIANGLES); + { + gGL.color4fv(color1.mV); + gGL.vertex3fv(v0.mV); + gGL.vertex3fv(v1.mV); + gGL.vertex3fv(v2.mV); + + gGL.color4fv(color2.mV); + gGL.vertex3fv(v2.mV); + gGL.vertex3fv(v3.mV); + gGL.vertex3fv(v0.mV); + } + gGL.end(); + + LLUI::setLineWidth(3.0f); + gGL.begin(LLRender::LINES); + { + gGL.color4f(0.f, 0.f, 0.f, 0.3f); + LLVector3 v12 = (v1 + v2) * .5f; + gGL.vertex3fv(v0.mV); + gGL.vertex3fv(v12.mV); + gGL.vertex3fv(v12.mV); + gGL.vertex3fv((v12 + (v0-v12)*.3f + (v2-v12)*.3f).mV); + gGL.vertex3fv(v12.mV); + gGL.vertex3fv((v12 + (v0-v12)*.3f + (v1-v12)*.3f).mV); + + LLVector3 v23 = (v2 + v3) * .5f; + gGL.vertex3fv(v0.mV); + gGL.vertex3fv(v23.mV); + gGL.vertex3fv(v23.mV); + gGL.vertex3fv((v23 + (v0-v23)*.3f + (v3-v23)*.3f).mV); + gGL.vertex3fv(v23.mV); + gGL.vertex3fv((v23 + (v0-v23)*.3f + (v2-v23)*.3f).mV); + } + gGL.end(); + LLUI::setLineWidth(1.0f); + + gGL.popMatrix(); + } + } + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // Since we draw handles with depth testing off, we need to draw them in the + // proper depth order. + + // Copied from LLDrawable::updateGeometry + LLVector3 pos_agent = first_object->getPositionAgent(); + LLVector3 camera_agent = gAgentCamera.getCameraPositionAgent(); + LLVector3 headPos = pos_agent - camera_agent; + + LLVector3 orientWRTHead = headPos * invRotation; + + // Find nearest vertex + 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: + // 0 & 5 + // 1 & 3 + // 2 & 4 + + // Table of order to draw faces, based on nearest vertex + static U32 face_list[8][NUM_AXES*2] = { + { 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 + { 4,0,3, 2,5,1 }, // v4 F403 F251 + { 2,5,1, 4,0,3 }, // v2 F251 F403 + { 2,5,3, 4,0,1 }, // v3 F253 F401 + { 4,5,1, 2,0,3 }, // v1 F451 F203 + { 4,5,3, 2,0,1 }, // v0 F453 F201 + }; + static const EManipPart which_arrow[6] = { + LL_Z_ARROW, + LL_X_ARROW, + LL_Y_ARROW, + LL_X_ARROW, + LL_Y_ARROW, + LL_Z_ARROW}; + + // draw arrows for deeper faces first, closer faces last + LLVector3 camera_axis; + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + camera_axis = LLVector3::x_axis; + } + else + { + camera_axis.setVec(gAgentCamera.getCameraPositionAgent() - first_object->getPositionAgent()); + } + + for (U32 i = 0; i < NUM_AXES*2; i++) + { + U32 face = face_list[nearest][i]; + + LLVector3 arrow_axis; + getManipAxis(first_object, which_arrow[face], arrow_axis); + + renderArrow(which_arrow[face], + mManipPart, + (face >= 3) ? -mConeSize : mConeSize, + (face >= 3) ? -mArrowLengthMeters : mArrowLengthMeters, + mConeSize, + FALSE); + } + } + } + gGL.popMatrix(); } void LLManipTranslate::renderArrow(S32 which_arrow, S32 selected_arrow, F32 box_size, F32 arrow_size, F32 handle_size, BOOL reverse_direction) { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLEnable gls_blend(GL_BLEND); - - for (S32 pass = 1; pass <= 2; pass++) - { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, pass == 1 ? GL_LEQUAL : GL_GREATER); - gGL.pushMatrix(); - - S32 index = 0; - - index = ARROW_TO_AXIS[which_arrow]; - - // assign a color for this arrow - LLColor4 color; // black - if (which_arrow == selected_arrow || which_arrow == mHighlightedPart) - { - color.mV[index] = (pass == 1) ? 1.f : 0.5f; - } - else if (selected_arrow != LL_NO_PART) - { - color.mV[VALPHA] = 0.f; - } - else - { - color.mV[index] = pass == 1 ? .8f : .35f ; // red, green, or blue - color.mV[VALPHA] = 0.6f; - } - gGL.color4fv( color.mV ); - - LLVector3 vec; - - { - LLUI::setLineWidth(2.0f); - gGL.begin(LLRender::LINES); - vec.mV[index] = box_size; - gGL.vertex3f(vec.mV[0], vec.mV[1], vec.mV[2]); - - vec.mV[index] = arrow_size; - gGL.vertex3f(vec.mV[0], vec.mV[1], vec.mV[2]); - gGL.end(); - LLUI::setLineWidth(1.0f); - } - - gGL.translatef(vec.mV[0], vec.mV[1], vec.mV[2]); - gGL.scalef(handle_size, handle_size, handle_size); - - F32 rot = 0.0f; - LLVector3 axis; - - switch(which_arrow) - { - case LL_X_ARROW: - rot = reverse_direction ? -90.0f : 90.0f; - axis.mV[1] = 1.0f; - break; - case LL_Y_ARROW: - rot = reverse_direction ? 90.0f : -90.0f; - axis.mV[0] = 1.0f; - break; - case LL_Z_ARROW: - rot = reverse_direction ? 180.0f : 0.0f; - axis.mV[0] = 1.0f; - break; - default: - LL_ERRS() << "renderArrow called with bad arrow " << which_arrow << LL_ENDL; - break; - } - - gGL.diffuseColor4fv(color.mV); - gGL.rotatef(rot, axis.mV[0], axis.mV[1], axis.mV[2]); - gGL.scalef(mArrowScales.mV[index], mArrowScales.mV[index], mArrowScales.mV[index] * 1.5f); - - gCone.render(); - - gGL.popMatrix(); - } + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLEnable gls_blend(GL_BLEND); + + for (S32 pass = 1; pass <= 2; pass++) + { + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, pass == 1 ? GL_LEQUAL : GL_GREATER); + gGL.pushMatrix(); + + S32 index = 0; + + index = ARROW_TO_AXIS[which_arrow]; + + // assign a color for this arrow + LLColor4 color; // black + if (which_arrow == selected_arrow || which_arrow == mHighlightedPart) + { + color.mV[index] = (pass == 1) ? 1.f : 0.5f; + } + else if (selected_arrow != LL_NO_PART) + { + color.mV[VALPHA] = 0.f; + } + else + { + color.mV[index] = pass == 1 ? .8f : .35f ; // red, green, or blue + color.mV[VALPHA] = 0.6f; + } + gGL.color4fv( color.mV ); + + LLVector3 vec; + + { + LLUI::setLineWidth(2.0f); + gGL.begin(LLRender::LINES); + vec.mV[index] = box_size; + gGL.vertex3f(vec.mV[0], vec.mV[1], vec.mV[2]); + + vec.mV[index] = arrow_size; + gGL.vertex3f(vec.mV[0], vec.mV[1], vec.mV[2]); + gGL.end(); + LLUI::setLineWidth(1.0f); + } + + gGL.translatef(vec.mV[0], vec.mV[1], vec.mV[2]); + gGL.scalef(handle_size, handle_size, handle_size); + + F32 rot = 0.0f; + LLVector3 axis; + + switch(which_arrow) + { + case LL_X_ARROW: + rot = reverse_direction ? -90.0f : 90.0f; + axis.mV[1] = 1.0f; + break; + case LL_Y_ARROW: + rot = reverse_direction ? 90.0f : -90.0f; + axis.mV[0] = 1.0f; + break; + case LL_Z_ARROW: + rot = reverse_direction ? 180.0f : 0.0f; + axis.mV[0] = 1.0f; + break; + default: + LL_ERRS() << "renderArrow called with bad arrow " << which_arrow << LL_ENDL; + break; + } + + gGL.diffuseColor4fv(color.mV); + gGL.rotatef(rot, axis.mV[0], axis.mV[1], axis.mV[2]); + gGL.scalef(mArrowScales.mV[index], mArrowScales.mV[index], mArrowScales.mV[index] * 1.5f); + + gCone.render(); + + gGL.popMatrix(); + } } void LLManipTranslate::renderGridVert(F32 x_trans, F32 y_trans, F32 r, F32 g, F32 b, F32 alpha) { - gGL.color4f(r, g, b, alpha); - switch (mManipPart) - { - case LL_YZ_PLANE: - gGL.vertex3f(0, x_trans, y_trans); - break; - case LL_XZ_PLANE: - gGL.vertex3f(x_trans, 0, y_trans); - break; - case LL_XY_PLANE: - gGL.vertex3f(x_trans, y_trans, 0); - break; - default: - gGL.vertex3f(0,0,0); - break; - } + gGL.color4f(r, g, b, alpha); + switch (mManipPart) + { + case LL_YZ_PLANE: + gGL.vertex3f(0, x_trans, y_trans); + break; + case LL_XZ_PLANE: + gGL.vertex3f(x_trans, 0, y_trans); + break; + case LL_XY_PLANE: + gGL.vertex3f(x_trans, y_trans, 0); + break; + default: + gGL.vertex3f(0,0,0); + break; + } } // virtual BOOL LLManipTranslate::canAffectSelection() { - BOOL can_move = mObjectSelection->getObjectCount() != 0; - if (can_move) - { - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* objectp) - { - LLViewerObject *root_object = (objectp == NULL) ? NULL : objectp->getRootEdit(); - return objectp->permMove() && !objectp->isPermanentEnforced() && - ((root_object == NULL) || !root_object->isPermanentEnforced()) && - (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); - } - } func; - can_move = mObjectSelection->applyToObjects(&func); - } - return can_move; + BOOL can_move = mObjectSelection->getObjectCount() != 0; + if (can_move) + { + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* objectp) + { + LLViewerObject *root_object = (objectp == NULL) ? NULL : objectp->getRootEdit(); + return objectp->permMove() && !objectp->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); + } + } func; + can_move = mObjectSelection->applyToObjects(&func); + } + return can_move; } |