diff options
author | Karl Steifvater <qarl@lindenlab.com> | 2008-07-22 20:12:37 +0000 |
---|---|---|
committer | Karl Steifvater <qarl@lindenlab.com> | 2008-07-22 20:12:37 +0000 |
commit | df4f20d4f51e41355e876f734527b4245543415c (patch) | |
tree | 36aaf66ddb96b27fb9701764153cd7d17add275a /indra | |
parent | 0c0391cc7114bd2e9e4462c40e88814326f61bc2 (diff) |
merge uv-picking branch.
svn merge -r92602:92632 svn+ssh://svn.lindenlab.com/svn/linden/branches/uv-picking-4
Diffstat (limited to 'indra')
71 files changed, 1973 insertions, 1334 deletions
diff --git a/indra/llmath/llrect.h b/indra/llmath/llrect.h index 17fa981c7c..21ca4189ff 100644 --- a/indra/llmath/llrect.h +++ b/indra/llmath/llrect.h @@ -183,10 +183,11 @@ public: LLRectBase& setCenterAndSize(Type x, Type y, Type width, Type height) { + // width and height could be odd, so favor top, right with extra pixel mLeft = x - width/2; - mTop = y + height/2; - mRight = x + width/2; mBottom = y - height/2; + mTop = mBottom + height; + mRight = mLeft + width; return *this; } diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 3b01140e3a..242b0809eb 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -104,46 +104,128 @@ BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLV } } -// intersect test between triangle pt1,pt2,pt3 and line from linept to linept+vect -//returns TRUE if intersecting and moves linept to the point of intersection -BOOL LLTriangleLineSegmentIntersect( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, LLVector3& linept, const LLVector3& vect) +BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size) { - LLVector3 V1 = pt2-pt1; - LLVector3 V2 = pt3-pt2; + float fAWdU[3]; + LLVector3 dir; + LLVector3 diff; + + for (U32 i = 0; i < 3; i++) + { + dir.mV[i] = 0.5f * (end.mV[i] - start.mV[i]); + diff.mV[i] = (0.5f * (end.mV[i] + start.mV[i])) - center.mV[i]; + fAWdU[i] = fabsf(dir.mV[i]); + if(fabsf(diff.mV[i])>size.mV[i] + fAWdU[i]) return false; + } + + float f; + f = dir.mV[1] * diff.mV[2] - dir.mV[2] * diff.mV[1]; if(fabsf(f)>size.mV[1]*fAWdU[2] + size.mV[2]*fAWdU[1]) return false; + f = dir.mV[2] * diff.mV[0] - dir.mV[0] * diff.mV[2]; if(fabsf(f)>size.mV[0]*fAWdU[2] + size.mV[2]*fAWdU[0]) return false; + f = dir.mV[0] * diff.mV[1] - dir.mV[1] * diff.mV[0]; if(fabsf(f)>size.mV[0]*fAWdU[1] + size.mV[1]*fAWdU[0]) return false; - LLVector3 norm = V1 % V2; + return true; +} + + +// intersect test between triangle vert0, vert1, vert2 and a ray from orig in direction dir. +// returns TRUE if intersecting and returns barycentric coordinates in intersection_a, intersection_b, +// and returns the intersection point along dir in intersection_t. + +// Moller-Trumbore algorithm +BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, + F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided) +{ + F32 u, v, t; + + /* find vectors for two edges sharing vert0 */ + LLVector3 edge1 = vert1 - vert0; + + LLVector3 edge2 = vert2 - vert0;; + + /* begin calculating determinant - also used to calculate U parameter */ + LLVector3 pvec = dir % edge2; - F32 dotprod = norm * vect; + /* if determinant is near zero, ray lies in plane of triangle */ + F32 det = edge1 * pvec; - if(dotprod < 0) + if (!two_sided) { - //Find point of intersect to triangle plane. - //find t to intersect point - F32 t = -(norm * (linept-pt1))/dotprod; + if (det < F_APPROXIMATELY_ZERO) + { + return FALSE; + } + + /* calculate distance from vert0 to ray origin */ + LLVector3 tvec = orig - vert0; - // if ds is neg line started past triangle so can't hit triangle. - if (t > 0) + /* calculate U parameter and test bounds */ + u = tvec * pvec; + + if (u < 0.f || u > det) { return FALSE; } - LLVector3 pt_int = linept + (vect*t); + /* prepare to test V parameter */ + LLVector3 qvec = tvec % edge1; - if(check_same_clock_dir(pt1, pt2, pt_int, norm)) + /* calculate V parameter and test bounds */ + v = dir * qvec; + if (v < 0.f || u + v > det) { - if(check_same_clock_dir(pt2, pt3, pt_int, norm)) + return FALSE; + } + + /* calculate t, scale parameters, ray intersects triangle */ + t = edge2 * qvec; + F32 inv_det = 1.0 / det; + t *= inv_det; + u *= inv_det; + v *= inv_det; + } + + else // two sided { - if(check_same_clock_dir(pt3, pt1, pt_int, norm)) + if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO) { - // answer in pt_int is insde triangle - linept.setVec(pt_int); - return TRUE; + return FALSE; } + F32 inv_det = 1.0 / det; + + /* calculate distance from vert0 to ray origin */ + LLVector3 tvec = orig - vert0; + + /* calculate U parameter and test bounds */ + u = (tvec * pvec) * inv_det; + if (u < 0.f || u > 1.f) + { + return FALSE; } + + /* prepare to test V parameter */ + LLVector3 qvec = tvec - edge1; + + /* calculate V parameter and test bounds */ + v = (dir * qvec) * inv_det; + + if (v < 0.f || u + v > 1.f) + { + return FALSE; } + + /* calculate t, ray intersects triangle */ + t = (edge2 * qvec) * inv_det; } - return FALSE; + if (intersection_a != NULL) + *intersection_a = u; + if (intersection_b != NULL) + *intersection_b = v; + if (intersection_t != NULL) + *intersection_t = t; + + + return TRUE; } @@ -3405,47 +3487,99 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, } } -S32 LLVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const +S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, + S32 face, + LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) { - S32 ret = -1; + S32 hit_face = -1; + + S32 start_face; + S32 end_face; - LLVector3 vec = end - start; + if (face == -1) // ALL_SIDES + { + start_face = 0; + end_face = getNumFaces() - 1; + } + else + { + start_face = face; + end_face = face; + } + + LLVector3 dir = end - start; + + F32 closest_t = 2.f; // must be larger than 1 - for (S32 i = 0; i < getNumFaces(); i++) + for (S32 i = start_face; i <= end_face; i++) { - const LLVolumeFace& face = getVolumeFace(i); + LLVolumeFace face = getVolumeFace((U32)i); + + LLVector3 box_center = (face.mExtents[0] + face.mExtents[1]) / 2.f; + LLVector3 box_size = face.mExtents[1] - face.mExtents[0]; + + if (LLLineSegmentBoxIntersect(start, end, box_center, box_size)) + { + if (bi_normal != NULL) // if the caller wants binormals, we may need to generate them + { + genBinormals(i); + } + + for (U32 tri = 0; tri < face.mIndices.size()/3; tri++) + { + S32 index1 = face.mIndices[tri*3+0]; + S32 index2 = face.mIndices[tri*3+1]; + S32 index3 = face.mIndices[tri*3+2]; - for (U32 j = 0; j < face.mIndices.size()/3; j++) + F32 a, b, t; + + if (LLTriangleRayIntersect(face.mVertices[index1].mPosition, + face.mVertices[index2].mPosition, + face.mVertices[index3].mPosition, + start, dir, &a, &b, &t, FALSE)) + { + if ((t >= 0.f) && // if hit is after start + (t <= 1.f) && // and before end + (t < closest_t)) // and this hit is closer { - //approximate normal - S32 v1 = face.mIndices[j*3+0]; - S32 v2 = face.mIndices[j*3+1]; - S32 v3 = face.mIndices[j*3+2]; + closest_t = t; + hit_face = i; - LLVector3 norm = (face.mVertices[v2].mPosition - face.mVertices[v1].mPosition) % - (face.mVertices[v3].mPosition - face.mVertices[v2].mPosition); + if (intersection != NULL) + { + *intersection = start + dir * closest_t; + } - if (norm.magVecSquared() >= 0.00000001f) + if (tex_coord != NULL) { - //get view vector - //LLVector3 view = (start-face.mVertices[v1].mPosition); - //if (view * norm < 0.0f) + *tex_coord = ((1.f - a - b) * face.mVertices[index1].mTexCoord + + a * face.mVertices[index2].mTexCoord + + b * face.mVertices[index3].mTexCoord); + + } + + if (normal != NULL) { - if (LLTriangleLineSegmentIntersect( face.mVertices[v1].mPosition, - face.mVertices[v2].mPosition, - face.mVertices[v3].mPosition, - end, - vec)) + *normal = ((1.f - a - b) * face.mVertices[index1].mNormal + + a * face.mVertices[index2].mNormal + + b * face.mVertices[index3].mNormal); + } + + if (bi_normal != NULL) { - vec = end-start; - ret = (S32) i; + *bi_normal = ((1.f - a - b) * face.mVertices[index1].mBinormal + + a * face.mVertices[index2].mBinormal + + b * face.mVertices[index3].mBinormal); + } + } } } } } - return ret; + + return hit_face; } class LLVertexIndexPair diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index c395ed7378..0444a02825 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -906,7 +906,13 @@ public: //get the face index of the face that intersects with the given line segment at the point //closest to start. Moves end to the point of intersection. Returns -1 if no intersection. //Line segment must be in volume space. - S32 lineSegmentIntersect(const LLVector3& start, LLVector3& end) const; + S32 lineSegmentIntersect(const LLVector3& start, const LLVector3& end, + S32 face = -1, // which face to check, -1 = ALL_SIDES + LLVector3* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector3* normal = NULL, // return the surface normal at the intersection point + LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point + ); // The following cleans up vertices and triangles, // getting rid of degenerate triangles and duplicate vertices, @@ -967,4 +973,10 @@ LLVector3 calc_binormal_from_triangle( const LLVector3& pos2, const LLVector2& tex2); +BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size); +BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, + F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided); + + + #endif diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp index 7033048575..f9e62cbd53 100644 --- a/indra/llmath/v2math.cpp +++ b/indra/llmath/v2math.cpp @@ -33,6 +33,7 @@ //#include "vmath.h" #include "v2math.h" +#include "v3math.h" #include "v4math.h" #include "m4math.h" #include "m3math.h" diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h index 5f46655a07..c896b80977 100644 --- a/indra/llmath/v2math.h +++ b/indra/llmath/v2math.h @@ -33,6 +33,7 @@ #define LL_V2MATH_H #include "llmath.h" +#include "v3math.h" class LLVector4; class LLMatrix3; @@ -49,9 +50,10 @@ class LLVector2 static LLVector2 zero; - LLVector2(); // Initializes LLVector2 to (0, 0) - LLVector2(F32 x, F32 y); // Initializes LLVector2 to (x. y) - LLVector2(const F32 *vec); // Initializes LLVector2 to (vec[0]. vec[1]) + LLVector2(); // Initializes LLVector2 to (0, 0) + LLVector2(F32 x, F32 y); // Initializes LLVector2 to (x. y) + LLVector2(const F32 *vec); // Initializes LLVector2 to (vec[0]. vec[1]) + explicit LLVector2(const LLVector3 &vec); // Initializes LLVector2 to (vec[0]. vec[1]) // Clears LLVector2 to (0, 0). DEPRECATED - prefer zeroVec. void clear(); @@ -137,6 +139,12 @@ inline LLVector2::LLVector2(const F32 *vec) mV[VY] = vec[VY]; } +inline LLVector2::LLVector2(const LLVector3 &vec) +{ + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; +} + // Clear and Assignment Functions diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp index 166761e550..12916b6253 100644 --- a/indra/llmath/v3math.cpp +++ b/indra/llmath/v3math.cpp @@ -34,6 +34,7 @@ #include "v3math.h" //#include "vmath.h" +#include "v2math.h" #include "v4math.h" #include "m4math.h" #include "m3math.h" @@ -270,6 +271,13 @@ const LLVector3& LLVector3::setVec(const LLVector4 &vec) return (*this); } +LLVector3::LLVector3(const LLVector2 &vec) +{ + mV[VX] = (F32)vec.mV[VX]; + mV[VY] = (F32)vec.mV[VY]; + mV[VZ] = 0; +} + LLVector3::LLVector3(const LLVector3d &vec) { mV[VX] = (F32)vec.mdV[VX]; diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index 051d5376b7..42ca1f88b2 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -36,6 +36,7 @@ #include "llmath.h" #include "llsd.h" +class LLVector2; class LLVector4; class LLMatrix3; class LLVector3d; @@ -62,6 +63,7 @@ class LLVector3 inline LLVector3(); // Initializes LLVector3 to (0, 0, 0) inline LLVector3(const F32 x, const F32 y, const F32 z); // Initializes LLVector3 to (x. y, z) inline explicit LLVector3(const F32 *vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2]) + explicit LLVector3(const LLVector2 &vec); // Initializes LLVector3 to (vec[0]. vec[1], 0) explicit LLVector3(const LLVector3d &vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2]) explicit LLVector3(const LLVector4 &vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2]) LLVector3(const LLSD& sd); diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp index b1395b0b70..b5186ad539 100644 --- a/indra/llmessage/lltemplatemessagereader.cpp +++ b/indra/llmessage/lltemplatemessagereader.cpp @@ -574,7 +574,9 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender // repeat number is a single byte if (decode_pos >= mReceiveSize) { - logRanOffEndOfPacket(sender, decode_pos, 1); + // commented out - hetgrid says that missing variable blocks + // at end of message are legal + // logRanOffEndOfPacket(sender, decode_pos, 1); // default to 0 repeats repeat_number = 0; diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index 0d537e0575..dd034904d3 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -1371,4 +1371,7 @@ char* _PREHASH_OwnerMask = LLMessageStringTable::getInstance()->getString("Owner char* _PREHASH_TransferInventoryAck = LLMessageStringTable::getInstance()->getString("TransferInventoryAck"); char* _PREHASH_RegionDenyAgeUnverified = LLMessageStringTable::getInstance()->getString("RegionDenyAgeUnverified"); char* _PREHASH_AgeVerificationBlock = LLMessageStringTable::getInstance()->getString("AgeVerificationBlock"); +char* _PREHASH_UCoord = LLMessageStringTable::getInstance()->getString("UCoord"); +char* _PREHASH_VCoord = LLMessageStringTable::getInstance()->getString("VCoord"); +char* _PREHASH_FaceIndex = LLMessageStringTable::getInstance()->getString("FaceIndex"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index 287296d1eb..9dfb3992ca 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -1371,6 +1371,8 @@ extern char * _PREHASH_OwnerMask; extern char * _PREHASH_TransferInventoryAck; extern char * _PREHASH_RegionDenyAgeUnverified; extern char * _PREHASH_AgeVerificationBlock; - +extern char * _PREHASH_UCoord; +extern char * _PREHASH_VCoord; +extern char * _PREHASH_FaceIndex; #endif diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index c20bfe6ac0..c1da6c93fe 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -63,7 +63,6 @@ BOOL LLView::sDebugKeys = FALSE; S32 LLView::sDepth = 0; BOOL LLView::sDebugMouseHandling = FALSE; std::string LLView::sMouseHandlerMessage; -S32 LLView::sSelectID = GL_NAME_UI_RESERVED; BOOL LLView::sEditingUI = FALSE; BOOL LLView::sForceReshape = FALSE; LLView* LLView::sEditingUIView = NULL; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 65f0a2b7e2..df3fb2e240 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1411,6 +1411,11 @@ BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position) // Under certain circumstances, this will trigger us to decouple the cursor. adjustCursorDecouple(true); + // trigger mouse move callback + LLCoordGL gl_pos; + convertCoords(position, &gl_pos); + mCallbacks->handleMouseMove(this, gl_pos, (MASK)0); + return result; } diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 4a81ddd1fd..526a6769a0 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1387,6 +1387,10 @@ BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position) return FALSE; } + LLCoordGL gl_pos; + convertCoords(position, &gl_pos); + mCallbacks->handleMouseMove(this, gl_pos, (MASK)0); + return SetCursorPos(screen_pos.mX, screen_pos.mY); } diff --git a/indra/lscript/lscript_library/lscript_library.cpp b/indra/lscript/lscript_library/lscript_library.cpp index 0b357c9182..b99bd64f2a 100644 --- a/indra/lscript/lscript_library/lscript_library.cpp +++ b/indra/lscript/lscript_library/lscript_library.cpp @@ -442,6 +442,14 @@ void LLScriptLibrary::init() addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetRegionAgentCount", "i", NULL, "int llGetRegionAgentCount()\nreturns the number of agents in a region")); addFunction(new LLScriptLibraryFunction(10.f, 1.f, dummy_func, "llTextBox", NULL, "ksi", "llTextBox(key avatar, string message, integer chat_channel\nShows a dialog box on the avatar's screen with the message.\nA text box asks for input, and if entered the text is chatted on chat_channel.")); addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetAgentLanguage", "s", "k", "string llGetAgentLanguage(key id)\nGets the agents preferred language..")); + addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchUV", "v", "i", "vector llDetectedTouchUV(integer number)\nreturns the u and v coordinates in the first two components of a vector, for a triggered touch event")); + addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchFace", "i", "i", "integer llDetectedTouchFace(integer number)\nreturns the index of the face on the object for a triggered touch event")); + addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchPos", "v", "i", "vector llDetectedTouchPos(integer number)\nreturns the position touched for a triggered touch event")); + addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchNormal", "v", "i", "vector llDetectedTouchNormal(integer number)\nreturns the surface normal for a triggered touch event")); + addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchBinormal", "v", "i", "vector llDetectedTouchBinormal(integer number)\nreturns the surface binormal for a triggered touch event")); + addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchST", "v", "i", "vector llDetectedTouchST(integer number)\nreturns the s and t coordinates in the first two components of a vector, for a triggered touch event")); + + // energy, sleep, dummy_func, name, return type, parameters, help text, gods-only diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 8ca74f6d0f..4c47cb45b2 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5201,6 +5201,28 @@ <key>Value</key> <string /> </map> + <key>PerFrameHoverPick</key> + <map> + <key>Comment</key> + <string>Detect the object under the mouse continually</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <real>1</real> + </map> + <key>PerFrameHoverPickCount</key> + <map> + <key>Comment</key> + <string>Detect the object under the mouse every n frames</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>1</integer> + </map> <key>PermissionsCautionEnabled</key> <map> <key>Comment</key> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 7fb9e57507..cffd4410c3 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -133,7 +133,6 @@ // end Ventrella extern LLMenuBarGL* gMenuBarView; -extern U8 gLastPickAlpha; //drone wandering constants const F32 MAX_WANDER_TIME = 20.f; // seconds @@ -330,6 +329,8 @@ LLAgent::LLAgent() mCameraZoomFraction(1.f), // deprecated mThirdPersonHeadOffset(0.f, 0.f, 1.f), mSitCameraEnabled(FALSE), + mHUDTargetZoom(1.f), + mHUDCurZoom(1.f), mFocusOnAvatar(TRUE), mFocusGlobal(), mFocusTargetGlobal(), @@ -530,10 +531,7 @@ void LLAgent::resetView(BOOL reset_camera) setFocusOnAvatar(TRUE, ANIMATE); } - if (mAvatarObject.notNull()) - { - mAvatarObject->mHUDTargetZoom = 1.f; - } + mHUDTargetZoom = 1.f; } // Handle any actions that need to be performed when the main app gains focus @@ -1298,7 +1296,7 @@ LLQuaternion LLAgent::getQuat() const //----------------------------------------------------------------------------- // calcFocusOffset() //----------------------------------------------------------------------------- -LLVector3d LLAgent::calcFocusOffset(LLViewerObject *object, S32 x, S32 y) +LLVector3 LLAgent::calcFocusOffset(LLViewerObject *object, S32 x, S32 y) { // calculate offset based on view direction BOOL is_avatar = object->isAvatar(); @@ -1457,10 +1455,10 @@ LLVector3d LLAgent::calcFocusOffset(LLViewerObject *object, S32 x, S32 y) obj_rel = lerp(focus_delta, obj_rel, bias); - return LLVector3d(obj_rel); + return LLVector3(obj_rel); } - return LLVector3d(focus_delta.mV[VX], focus_delta.mV[VY], focus_delta.mV[VZ]); + return LLVector3(focus_delta.mV[VX], focus_delta.mV[VY], focus_delta.mV[VZ]); } //----------------------------------------------------------------------------- @@ -1650,7 +1648,7 @@ F32 LLAgent::getCameraZoomFraction() if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) { // already [0,1] - return mAvatarObject->mHUDTargetZoom; + return mHUDTargetZoom; } else if (mFocusOnAvatar && cameraThirdPerson()) { @@ -1698,7 +1696,7 @@ void LLAgent::setCameraZoomFraction(F32 fraction) if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) { - mAvatarObject->mHUDTargetZoom = fraction; + mHUDTargetZoom = fraction; } else if (mFocusOnAvatar && cameraThirdPerson()) { @@ -1808,7 +1806,7 @@ void LLAgent::cameraZoomIn(const F32 fraction) if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) { // just update hud zoom level - mAvatarObject->mHUDTargetZoom /= fraction; + mHUDTargetZoom /= fraction; return; } @@ -3757,7 +3755,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit) lag_interp *= u; - if (gViewerWindow->getLeftMouseDown() && gLastHitObjectID == mAvatarObject->getID()) + if (gViewerWindow->getLeftMouseDown() && gViewerWindow->getLastPick().mObjectID == mAvatarObject->getID()) { // disable camera lag when using mouse-directed steering target_lag.clearVec(); @@ -4285,6 +4283,12 @@ void LLAgent::setFocusObject(LLViewerObject* object) //----------------------------------------------------------------------------- // setFocusGlobal() //----------------------------------------------------------------------------- +void LLAgent::setFocusGlobal(const LLPickInfo& pick) +{ + setFocusGlobal(pick.mPosGlobal, pick.mObjectID); +} + + void LLAgent::setFocusGlobal(const LLVector3d& focus, const LLUUID &object_id) { setFocusObject(gObjectList.findObject(object_id)); diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 45006fef8d..ea9138fdd1 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -95,6 +95,7 @@ class LLMessageSystem; class LLPermissions; class LLHost; class LLFriendObserver; +class LLPickInfo; struct LLGroupData { @@ -191,6 +192,7 @@ public: void changeCameraToFollow(BOOL animate = TRUE); //end Ventrella + void setFocusGlobal(const LLPickInfo& pick); void setFocusGlobal(const LLVector3d &focus, const LLUUID &object_id = LLUUID::null); void setFocusOnAvatar(BOOL focus, BOOL animate); void setCameraPosAndFocusGlobal(const LLVector3d& pos, const LLVector3d& focus, const LLUUID &object_id); @@ -374,7 +376,7 @@ public: void sendAnimationRequests(LLDynamicArray<LLUUID> &anim_ids, EAnimRequest request); void sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request); - LLVector3d calcFocusOffset(LLViewerObject *object, S32 x, S32 y); + LLVector3 calcFocusOffset(LLViewerObject *object, S32 x, S32 y); BOOL calcCameraMinDistance(F32 &obj_min_distance); void startCameraAnimation(); @@ -711,6 +713,9 @@ public: LLDynamicArray<LLGroupData> mGroups; + F32 mHUDTargetZoom; // target zoom level for HUD objects (used when editing) + F32 mHUDCurZoom; // current animated zoom level for HUD objects + BOOL mInitialized; static BOOL sDebugDisplayTarget; @@ -786,6 +791,7 @@ private: LLVector3 mSitCameraFocus; // root relative camera target when sitting LLVector3d mCameraSmoothingLastPositionGlobal; LLVector3d mCameraSmoothingLastPositionAgent; + //Ventrella LLVector3 mCameraUpVector; // camera's up direction in world coordinates (determines the 'roll' of the view) diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 422c0dc9a8..6d81edd7ca 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -53,8 +53,6 @@ static U32 sBufferUsage = GL_STREAM_DRAW_ARB; static U32 sShaderLevel = 0; static LLGLSLShader* sVertexProgram = NULL; -extern BOOL gUseGLPick; - F32 CLOTHING_GRAVITY_EFFECT = 0.7f; F32 CLOTHING_ACCEL_FORCE_FACTOR = 0.2f; const S32 NUM_TEST_AVATARS = 30; @@ -566,11 +564,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) //----------------------------------------------------------------------------- void LLDrawPoolAvatar::renderForSelect() { - if (gUseGLPick) - { - return; - } - if (!gRenderAvatar) { return; @@ -618,7 +611,7 @@ void LLDrawPoolAvatar::renderForSelect() glColor4ubv(color.mV); - if ((sShaderLevel > 0) && !gUseGLPick) // for hardware blending + if (sShaderLevel > 0) // for hardware blending { sRenderingSkinned = TRUE; sVertexProgram->bind(); @@ -628,7 +621,7 @@ void LLDrawPoolAvatar::renderForSelect() avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done - if ((sShaderLevel > 0) && !gUseGLPick) + if (sShaderLevel > 0) { sRenderingSkinned = FALSE; sVertexProgram->unbind(); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index b2f5caa57d..16668f81e2 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -54,8 +54,6 @@ #define LL_MAX_INDICES_COUNT 1000000 -extern BOOL gPickFaces; - BOOL LLFace::sSafeRenderSelect = TRUE; // FALSE #define DOTVEC(a,b) (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2]) @@ -73,14 +71,15 @@ The resulting texture coordinate <u,v> is: u = 2(B dot P) v = 2(T dot P) */ -void planarProjection(LLVector2 &tc, const LLVolumeFace::VertexData &vd, const LLVector3 &mCenter, const LLVector3& vec) +void planarProjection(LLVector2 &tc, const LLVector3& normal, + const LLVector3 &mCenter, const LLVector3& vec) { //DONE! LLVector3 binormal; - float d = vd.mNormal * LLVector3(1,0,0); + float d = normal * LLVector3(1,0,0); if (d >= 0.5f || d <= -0.5f) { binormal = LLVector3(0,1,0); - if (vd.mNormal.mV[0] < 0) + if (normal.mV[0] < 0) { binormal = -binormal; } @@ -88,18 +87,19 @@ void planarProjection(LLVector2 &tc, const LLVolumeFace::VertexData &vd, const L else { binormal = LLVector3(1,0,0); - if (vd.mNormal.mV[1] > 0) + if (normal.mV[1] > 0) { binormal = -binormal; } } - LLVector3 tangent = binormal % vd.mNormal; + LLVector3 tangent = binormal % normal; tc.mV[1] = -((tangent*vec)*2 - 0.5f); tc.mV[0] = 1.0f+((binormal*vec)*2 - 0.5f); } -void sphericalProjection(LLVector2 &tc, const LLVolumeFace::VertexData &vd, const LLVector3 &mCenter, const LLVector3& vec) +void sphericalProjection(LLVector2 &tc, const LLVector3& normal, + const LLVector3 &mCenter, const LLVector3& vec) { //BROKEN /*tc.mV[0] = acosf(vd.mNormal * LLVector3(1,0,0))/3.14159f; @@ -110,7 +110,7 @@ void sphericalProjection(LLVector2 &tc, const LLVolumeFace::VertexData &vd, cons }*/ } -void cylindricalProjection(LLVector2 &tc, const LLVolumeFace::VertexData &vd, const LLVector3 &mCenter, const LLVector3& vec) +void cylindricalProjection(LLVector2 &tc, const LLVector3& normal, const LLVector3 &mCenter, const LLVector3& vec) { //BROKEN /*LLVector3 binormal; float d = vd.mNormal * LLVector3(1,0,0); @@ -374,7 +374,7 @@ void LLFace::renderForSelect(U32 data_mask) #if !LL_RELEASE_FOR_DOWNLOAD LLGLState::checkClientArrays(data_mask); #endif - if (gPickFaces && mTEOffset != -1) + if (mTEOffset != -1) { // mask off high 4 bits (16 total possible faces) color.mV[0] &= 0x0f; @@ -419,12 +419,11 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color) if (mGeomCount > 0 && mIndicesCount > 0) { - LLGLSPipelineAlpha gls_pipeline_alpha; - glColor4fv(color.mV); + gGL.color4fv(color.mV); LLViewerImage::bindTexture(imagep); - glPushMatrix(); + gGL.pushMatrix(); if (mDrawablep->isActive()) { glMultMatrixf((GLfloat*)mDrawablep->getRenderMatrix().mMatrix); @@ -434,137 +433,49 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color) glMultMatrixf((GLfloat*)mDrawablep->getRegion()->mRenderMatrix.mMatrix); } - mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD); + mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD); #if !LL_RELEASE_FOR_DOWNLOAD - LLGLState::checkClientArrays(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD); + LLGLState::checkClientArrays(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD); #endif mVertexBuffer->draw(LLVertexBuffer::TRIANGLES, mIndicesCount, mIndicesIndex); - glPopMatrix(); + gGL.popMatrix(); } } -void LLFace::renderSelectedUV(const S32 offset, const S32 count) + +/* removed in lieu of raycast uv detection +void LLFace::renderSelectedUV() { -#if 0 LLViewerImage* red_blue_imagep = gImageList.getImageFromFile("uv_test1.j2c", TRUE, TRUE); LLViewerImage* green_imagep = gImageList.getImageFromFile("uv_test2.tga", TRUE, TRUE); - LLGLSObjectSelect object_select; - LLGLEnable blend(GL_BLEND); - - if (!mDrawPoolp || !getIndicesCount() || getIndicesStart() < 0) - { - return; - } - for (S32 pass = 0; pass < 2; pass++) - { - static F32 bias = 0.f; - static F32 factor = -10.f; - if (mGeomCount > 0) - { - gGL.color4fv(LLColor4::white.mV); - - if (pass == 0) - { - LLViewerImage::bindTexture(red_blue_imagep); - red_blue_imagep->setMipFilterNearest (TRUE, TRUE); - } - else // pass == 1 - { - gGL.blendFunc(GL_ONE, GL_ONE); - LLViewerImage::bindTexture(green_imagep); - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - glScalef(256.f, 256.f, 1.f); - green_imagep->setMipFilterNearest (TRUE, TRUE); - } - - - if (!isState(GLOBAL)) - { - // Apply the proper transform for non-global objects. - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glMultMatrixf((float*)getRenderMatrix().mMatrix); - } - - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(factor, bias); - if (sSafeRenderSelect) - { - gGL.begin(LLVertexBuffer::TRIANGLES); - if (count) - { - for (S32 i = offset; i < offset + count; i++) - { - LLVector2 tc = mDrawPoolp->getTexCoord(mDrawPoolp->getIndex(getIndicesStart() + i), 0); - gGL.texCoord2fv(tc.mV); - LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i)); - gGL.vertex3fv(vertex.mV); - } - } - else - { - for (U32 i = 0; i < getIndicesCount(); i++) - { - LLVector2 tc = mDrawPoolp->getTexCoord(mDrawPoolp->getIndex(getIndicesStart() + i), 0); - gGL.texCoord2fv(tc.mV); - LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i)); - gGL.vertex3fv(vertex.mV); - } - } - gGL.end(); - } - else - { - llassert(mGeomIndex >= 0); - if (count) - { - if (mIndicesCount > 0) - { - glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, getRawIndices() + offset); - } - else - { - llerrs << "Rendering non-indexed volume face!" << llendl; - glDrawArrays(mPrimType, mGeomIndex, mGeomCount); - } - } - else - { - if (mIndicesCount > 0) - { - glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_SHORT, getRawIndices()); - } - else - { - glDrawArrays(GL_TRIANGLES, mGeomIndex, mGeomCount); - } - } - } + LLGLSUVSelect object_select; - glDisable(GL_POLYGON_OFFSET_FILL); - if (!isState(GLOBAL)) - { - // Restore the tranform for non-global objects - glPopMatrix(); - } - if (pass == 1) - { - glMatrixMode(GL_TEXTURE); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - gGL.blendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA); - } - } - } + // use red/blue gradient to get coarse UV coordinates + renderSelected(red_blue_imagep, LLColor4::white); - //restore blend func - gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -#endif + static F32 bias = 0.f; + static F32 factor = -10.f; + glPolygonOffset(factor, bias); + + // add green dither pattern on top of red/blue gradient + gGL.blendFunc(LLRender::BF_ONE, LLRender::BF_ONE); + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + // make green pattern repeat once per texel in red/blue texture + glScalef(256.f, 256.f, 1.f); + glMatrixMode(GL_MODELVIEW); + + renderSelected(green_imagep, LLColor4::white); + + glMatrixMode(GL_TEXTURE); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); } +*/ void LLFace::printDebugInfo() const { @@ -760,6 +671,69 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, return TRUE; } + + +// convert surface coordinates to texture coordinates, based on +// the values in the texture entry. probably should be +// integrated with getGeometryVolume() for its texture coordinate +// generation - but i'll leave that to someone more familiar +// with the implications. +LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, LLVector3 position, LLVector3 normal) +{ + LLVector2 tc = surface_coord; + + const LLTextureEntry *tep = getTextureEntry(); + + if (tep == NULL) + { + // can't do much without the texture entry + return surface_coord; + } + + // see if we have a non-default mapping + U8 texgen = getTextureEntry()->getTexGen(); + if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) + { + LLVector3 center = mDrawablep->getVOVolume()->getVolume()->getVolumeFace(mTEOffset).mCenter; + + LLVector3 scale = (mDrawablep->getVOVolume()->isVolumeGlobal()) ? LLVector3(1,1,1) : mVObjp->getScale(); + LLVector3 vec = position; + vec.scaleVec(scale); + + switch (texgen) + { + case LLTextureEntry::TEX_GEN_PLANAR: + planarProjection(tc, normal, center, vec); + break; + case LLTextureEntry::TEX_GEN_SPHERICAL: + sphericalProjection(tc, normal, center, vec); + break; + case LLTextureEntry::TEX_GEN_CYLINDRICAL: + cylindricalProjection(tc, normal, center, vec); + break; + default: + break; + } + } + + if (mTextureMatrix) // if we have a texture matrix, use it + { + LLVector3 tc3(tc); + tc3 = tc3 * *mTextureMatrix; + tc = LLVector2(tc3); + } + + else // otherwise use the texture entry parameters + { + xform(tc, cos(tep->getRotation()), sin(tep->getRotation()), + tep->mOffsetS, tep->mOffsetT, tep->mScaleS, tep->mScaleT); + } + + + return tc; +} + + BOOL LLFace::getGeometryVolume(const LLVolume& volume, const S32 &f, const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, @@ -1039,13 +1013,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, switch (texgen) { case LLTextureEntry::TEX_GEN_PLANAR: - planarProjection(tc, vf.mVertices[i], vf.mCenter, vec); + planarProjection(tc, vf.mVertices[i].mNormal, vf.mCenter, vec); break; case LLTextureEntry::TEX_GEN_SPHERICAL: - sphericalProjection(tc, vf.mVertices[i], vf.mCenter, vec); + sphericalProjection(tc, vf.mVertices[i].mNormal, vf.mCenter, vec); break; case LLTextureEntry::TEX_GEN_CYLINDRICAL: - cylindricalProjection(tc, vf.mVertices[i], vf.mCenter, vec); + cylindricalProjection(tc, vf.mVertices[i].mNormal, vf.mCenter, vec); break; default: break; diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 0391cda66f..9e7a33eb7b 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -91,6 +91,7 @@ public: LLXformMatrix* getXform() const { return mXform; } BOOL hasGeometry() const { return mGeomCount > 0; } LLVector3 getPositionAgent() const; + LLVector2 surfaceToTexture(LLVector2 surface_coord, LLVector3 position, LLVector3 normal); U32 getState() const { return mState; } void setState(U32 state) { mState |= state; } @@ -165,7 +166,7 @@ public: void update(); void updateCenterAgent(); // Update center when xform has changed. - void renderSelectedUV(const S32 offset = 0, const S32 count = 0); + void renderSelectedUV(); void renderForSelect(U32 data_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD); void renderSelected(LLImageGL *image, const LLColor4 &color); diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h index 11d9f43fcc..12b2eced9b 100644 --- a/indra/newview/llhudobject.h +++ b/indra/newview/llhudobject.h @@ -67,6 +67,8 @@ public: U8 getType() const { return mType; } + LLVector3d getPositionGlobal() const { return mPositionGlobal; } + static LLHUDObject *addHUDObject(const U8 type); static LLHUDEffect *addHUDEffect(const U8 type); static void updateAll(); diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp index 5e09e69e2b..891dd69f84 100644 --- a/indra/newview/llmanip.cpp +++ b/indra/newview/llmanip.cpp @@ -96,7 +96,8 @@ LLManip::LLManip( const std::string& name, LLToolComposite* composite ) : LLTool( name, composite ), mInSnapRegime(FALSE), - mHighlightedPart(LL_NO_PART) + mHighlightedPart(LL_NO_PART), + mManipPart(LL_NO_PART) { } @@ -177,7 +178,7 @@ F32 LLManip::getSubdivisionLevel(const LLVector3 &reference_point, const LLVecto LLVector3 cam_to_reference; if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { - cam_to_reference = LLVector3(1.f / gAgent.getAvatarObject()->mHUDCurZoom, 0.f, 0.f); + cam_to_reference = LLVector3(1.f / gAgent.mHUDCurZoom, 0.f, 0.f); } else { @@ -199,6 +200,8 @@ void LLManip::handleSelect() void LLManip::handleDeselect() { + mHighlightedPart = LL_NO_PART; + mManipPart = LL_NO_PART; mObjectSelection = NULL; } @@ -260,8 +263,8 @@ BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVect if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { BOOL result = FALSE; - F32 mouse_x = ((F32)x / gViewerWindow->getWindowWidth() - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgent.getAvatarObject()->mHUDCurZoom; - F32 mouse_y = ((F32)y / gViewerWindow->getWindowHeight() - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom; + F32 mouse_x = ((F32)x / gViewerWindow->getWindowWidth() - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgent.mHUDCurZoom; + F32 mouse_y = ((F32)y / gViewerWindow->getWindowHeight() - 0.5f) / gAgent.mHUDCurZoom; LLVector3 origin_agent = gAgent.getPosAgentFromGlobal(origin); LLVector3 mouse_pos = LLVector3(0.f, -mouse_x, mouse_y); @@ -299,8 +302,8 @@ BOOL LLManip::nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, co if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { - F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgent.getAvatarObject()->mHUDCurZoom; - F32 mouse_y = (((F32)y / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom; + F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgent.mHUDCurZoom; + F32 mouse_y = (((F32)y / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.mHUDCurZoom; a1 = LLVector3(llmin(b1.mV[VX] - 0.1f, b2.mV[VX] - 0.1f, 0.f), -mouse_x, mouse_y); a2 = a1 + LLVector3(1.f, 0.f, 0.f); } @@ -484,7 +487,7 @@ void LLManip::renderTickText(const LLVector3& pos, const std::string& text, cons LLVector3 render_pos = pos; if (hud_selection) { - F32 zoom_amt = gAgent.getAvatarObject()->mHUDCurZoom; + F32 zoom_amt = gAgent.mHUDCurZoom; F32 inv_zoom_amt = 1.f / zoom_amt; // scale text back up to counter-act zoom level render_pos = pos * zoom_amt; @@ -542,7 +545,7 @@ void LLManip::renderTickValue(const LLVector3& pos, F32 value, const std::string LLVector3 render_pos = pos; if (hud_selection) { - F32 zoom_amt = gAgent.getAvatarObject()->mHUDCurZoom; + F32 zoom_amt = gAgent.mHUDCurZoom; F32 inv_zoom_amt = 1.f / zoom_amt; // scale text back up to counter-act zoom level render_pos = pos * zoom_amt; diff --git a/indra/newview/llmanip.h b/indra/newview/llmanip.h index 1313f77c5b..43d6eaadc8 100644 --- a/indra/newview/llmanip.h +++ b/indra/newview/llmanip.h @@ -155,6 +155,7 @@ protected: BOOL mInSnapRegime; LLSafeHandle<LLObjectSelection> mObjectSelection; EManipPart mHighlightedPart; + EManipPart mManipPart; static F32 sHelpTextVisibleTime; static F32 sHelpTextFadeTime; diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index e98ded2a87..ca0812c8a0 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -98,7 +98,6 @@ LLManipRotate::LLManipRotate( LLToolComposite* composite ) mCenterToCamMag(0.f), mCenterToProfilePlane(), mCenterToProfilePlaneMag(0.f), - mManipPart( LL_NO_PART ), mSendUpdateOnMouseUp( FALSE ), mSmoothRotate( FALSE ), mCamEdgeOn(FALSE), @@ -113,13 +112,6 @@ void LLManipRotate::handleSelect() LLManip::handleSelect(); } -void LLManipRotate::handleDeselect() -{ - mHighlightedPart = LL_NO_PART; - mManipPart = LL_NO_PART; - LLManip::handleDeselect(); -} - void LLManipRotate::render() { LLGLSUIDefault gls_ui; @@ -144,7 +136,7 @@ void LLManipRotate::render() glPushMatrix(); if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { - F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom; + F32 zoom = gAgent.mHUDCurZoom; glScalef(zoom, zoom, zoom); } @@ -363,8 +355,7 @@ BOOL LLManipRotate::handleMouseDown(S32 x, S32 y, MASK mask) LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(TRUE); if( first_object ) { - LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); - if( hit_obj && mHighlightedPart != LL_NO_PART ) + if( mHighlightedPart != LL_NO_PART ) { handled = handleMouseDownOnPart( x, y, mask ); } @@ -1126,18 +1117,18 @@ BOOL LLManipRotate::updateVisiblity() LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { - mCenterToCam = LLVector3(-1.f / gAgent.getAvatarObject()->mHUDCurZoom, 0.f, 0.f); + mCenterToCam = LLVector3(-1.f / gAgent.mHUDCurZoom, 0.f, 0.f); mCenterToCamNorm = mCenterToCam; mCenterToCamMag = mCenterToCamNorm.normVec(); mRadiusMeters = RADIUS_PIXELS / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); - mRadiusMeters /= gAgent.getAvatarObject()->mHUDCurZoom; + mRadiusMeters /= gAgent.mHUDCurZoom; mCenterToProfilePlaneMag = mRadiusMeters * mRadiusMeters / mCenterToCamMag; mCenterToProfilePlane = -mCenterToProfilePlaneMag * mCenterToCamNorm; - mCenterScreen.set((S32)((0.5f - mRotationCenter.mdV[VY]) / gAgent.getAvatarObject()->mHUDCurZoom * gViewerWindow->getWindowWidth()), - (S32)((mRotationCenter.mdV[VZ] + 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom * gViewerWindow->getWindowHeight())); + mCenterScreen.set((S32)((0.5f - mRotationCenter.mdV[VY]) / gAgent.mHUDCurZoom * gViewerWindow->getWindowWidth()), + (S32)((mRotationCenter.mdV[VZ] + 0.5f) / gAgent.mHUDCurZoom * gViewerWindow->getWindowHeight())); visible = TRUE; } else @@ -1653,8 +1644,8 @@ void LLManipRotate::mouseToRay( S32 x, S32 y, LLVector3* ray_pt, LLVector3* ray_ { if (LLSelectMgr::getInstance()->getSelection()->getSelectType() == SELECT_TYPE_HUD) { - F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom; - F32 mouse_y = ((((F32)y) / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom; + F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) / gAgent.mHUDCurZoom; + F32 mouse_y = ((((F32)y) / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.mHUDCurZoom; *ray_pt = LLVector3(-1.f, -mouse_x, mouse_y); *ray_dir = LLVector3(1.f, 0.f, 0.f); diff --git a/indra/newview/llmaniprotate.h b/indra/newview/llmaniprotate.h index 460bd3fcba..f5c815d537 100644 --- a/indra/newview/llmaniprotate.h +++ b/indra/newview/llmaniprotate.h @@ -64,7 +64,6 @@ public: virtual void render(); virtual void handleSelect(); - virtual void handleDeselect(); virtual BOOL handleMouseDownOnPart(S32 x, S32 y, MASK mask); virtual void highlightManipulators(S32 x, S32 y); @@ -109,8 +108,6 @@ private: LLVector3 mCenterToProfilePlane; F32 mCenterToProfilePlaneMag; - EManipPart mManipPart; - BOOL mSendUpdateOnMouseUp; BOOL mSmoothRotate; diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index 57c901e9bc..5859d4c75f 100644 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -166,19 +166,11 @@ void LLManipScale::handleSelect() LLManip::handleSelect(); } -void LLManipScale::handleDeselect() -{ - mHighlightedPart = LL_NO_PART; - mManipPart = LL_NO_PART; - LLManip::handleDeselect(); -} - LLManipScale::LLManipScale( LLToolComposite* composite ) : LLManip( std::string("Scale"), composite ), mBoxHandleSize( 1.f ), mScaledBoxHandleSize( 1.f ), - mManipPart( LL_NO_PART ), mLastMouseX( -1 ), mLastMouseY( -1 ), mSendUpdateOnMouseUp( FALSE ), @@ -216,7 +208,7 @@ void LLManipScale::render() glPushMatrix(); if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { - F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom; + F32 zoom = gAgent.mHUDCurZoom; glScalef(zoom, zoom, zoom); } @@ -233,7 +225,7 @@ void LLManipScale::render() if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { mBoxHandleSize = BOX_HANDLE_BASE_SIZE * BOX_HANDLE_BASE_FACTOR / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); - mBoxHandleSize /= gAgent.getAvatarObject()->mHUDCurZoom; + mBoxHandleSize /= gAgent.mHUDCurZoom; } else { @@ -316,9 +308,7 @@ BOOL LLManipScale::handleMouseDown(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; - LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); - if( hit_obj || - (mHighlightedPart != LL_NO_PART) ) + if(mHighlightedPart != LL_NO_PART) { handled = handleMouseDownOnPart( x, y, mask ); } @@ -446,7 +436,7 @@ void LLManipScale::highlightManipulators(S32 x, S32 y) LLMatrix4 cfr(OGL_TO_CFR_ROTATION); transform *= cfr; LLMatrix4 window_scale; - F32 zoom_level = 2.f * gAgent.getAvatarObject()->mHUDCurZoom; + F32 zoom_level = 2.f * gAgent.mHUDCurZoom; window_scale.initAll(LLVector3(zoom_level / LLViewerCamera::getInstance()->getAspect(), zoom_level, 0.f), LLQuaternion::DEFAULT, LLVector3::zero); @@ -1367,7 +1357,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox) if(mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { - mSnapRegimeOffset = SNAP_GUIDE_SCREEN_OFFSET / gAgent.getAvatarObject()->mHUDCurZoom; + mSnapRegimeOffset = SNAP_GUIDE_SCREEN_OFFSET / gAgent.mHUDCurZoom; } else @@ -1380,7 +1370,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox) if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { cam_at_axis.setVec(1.f, 0.f, 0.f); - snap_guide_length = SNAP_GUIDE_SCREEN_LENGTH / gAgent.getAvatarObject()->mHUDCurZoom; + snap_guide_length = SNAP_GUIDE_SCREEN_LENGTH / gAgent.mHUDCurZoom; } else { diff --git a/indra/newview/llmanipscale.h b/indra/newview/llmanipscale.h index c02845e358..432be2cd3e 100644 --- a/indra/newview/llmanipscale.h +++ b/indra/newview/llmanipscale.h @@ -76,7 +76,6 @@ public: virtual BOOL handleHover( S32 x, S32 y, MASK mask ); virtual void render(); virtual void handleSelect(); - virtual void handleDeselect(); virtual BOOL handleMouseDownOnPart(S32 x, S32 y, MASK mask); virtual void highlightManipulators(S32 x, S32 y); // decided which manipulator, if any, should be highlighted by mouse hover @@ -140,7 +139,6 @@ private: F32 mBoxHandleSize; // The size of the handles at the corners of the bounding box F32 mScaledBoxHandleSize; // handle size after scaling for selection feedback - EManipPart mManipPart; LLVector3d mDragStartPointGlobal; LLVector3d mDragStartCenterGlobal; // The center of the bounding box of all selected objects at time of drag start LLVector3d mDragPointGlobal; diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index f4f3a535de..7785b5a078 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -113,7 +113,6 @@ LLManipTranslate::LLManipTranslate( LLToolComposite* composite ) mConeSize(0), mArrowLengthMeters(0.f), mPlaneManipOffsetMeters(0.f), - mManipPart(LL_NO_PART), mUpdateTimer(), mSnapOffsetMeters(0.f), mArrowScales(1.f, 1.f, 1.f), @@ -257,21 +256,12 @@ void LLManipTranslate::handleSelect() LLManip::handleSelect(); } -void LLManipTranslate::handleDeselect() -{ - mHighlightedPart = LL_NO_PART; - mManipPart = LL_NO_PART; - LLManip::handleDeselect(); -} - 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 - LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); - if( hit_obj && - (mHighlightedPart == LL_X_ARROW || + if( (mHighlightedPart == LL_X_ARROW || mHighlightedPart == LL_Y_ARROW || mHighlightedPart == LL_Z_ARROW || mHighlightedPart == LL_YZ_PLANE || @@ -818,7 +808,7 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) LLMatrix4 cfr(OGL_TO_CFR_ROTATION); transform *= cfr; LLMatrix4 window_scale; - F32 zoom_level = 2.f * gAgent.getAvatarObject()->mHUDCurZoom; + F32 zoom_level = 2.f * gAgent.mHUDCurZoom; window_scale.initAll(LLVector3(zoom_level / LLViewerCamera::getInstance()->getAspect(), zoom_level, 0.f), LLQuaternion::DEFAULT, LLVector3::zero); @@ -1056,7 +1046,7 @@ void LLManipTranslate::render() gGL.pushMatrix(); if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { - F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom; + F32 zoom = gAgent.mHUDCurZoom; glScalef(zoom, zoom, zoom); } { @@ -1220,7 +1210,7 @@ void LLManipTranslate::renderSnapGuides() if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { - guide_size_meters = 1.f / gAgent.getAvatarObject()->mHUDCurZoom; + guide_size_meters = 1.f / gAgent.mHUDCurZoom; mSnapOffsetMeters = mArrowLengthMeters * 1.5f; } else @@ -1803,7 +1793,7 @@ void LLManipTranslate::renderTranslationHandles() if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWindowHeight(); - mArrowLengthMeters /= gAgent.getAvatarObject()->mHUDCurZoom; + mArrowLengthMeters /= gAgent.mHUDCurZoom; } else { diff --git a/indra/newview/llmaniptranslate.h b/indra/newview/llmaniptranslate.h index c9f98e9c7d..8c17dd3d51 100644 --- a/indra/newview/llmaniptranslate.h +++ b/indra/newview/llmaniptranslate.h @@ -61,7 +61,6 @@ public: virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual void render(); virtual void handleSelect(); - virtual void handleDeselect(); virtual void highlightManipulators(S32 x, S32 y); virtual BOOL handleMouseDownOnPart(S32 x, S32 y, MASK mask); @@ -110,7 +109,6 @@ private: F32 mArrowLengthMeters; // meters F32 mGridSizeMeters; F32 mPlaneManipOffsetMeters; - EManipPart mManipPart; LLVector3 mManipNormal; LLVector3d mDragCursorStartGlobal; LLVector3d mDragSelectionStartGlobal; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 8ebaeb6758..2f11dad010 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -96,9 +96,6 @@ const S32 MAX_ACTION_QUEUE_SIZE = 20; const S32 MAX_SILS_PER_FRAME = 50; const S32 MAX_OBJECTS_PER_PACKET = 254; -extern LLUUID gLastHitObjectID; -extern LLVector3d gLastHitObjectOffset; - // // Globals // @@ -4833,7 +4830,7 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) { LLBBox hud_bbox = avatar->getHUDBBox(); - F32 cur_zoom = avatar->mHUDCurZoom; + F32 cur_zoom = gAgent.mHUDCurZoom; // set up transform to encompass bounding box of HUD glMatrixMode(GL_PROJECTION); @@ -5280,7 +5277,7 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) F32 silhouette_thickness; if (is_hud_object && gAgent.getAvatarObject()) { - silhouette_thickness = LLSelectMgr::sHighlightThickness / gAgent.getAvatarObject()->mHUDCurZoom; + silhouette_thickness = LLSelectMgr::sHighlightThickness / gAgent.mHUDCurZoom; } else { @@ -5479,8 +5476,8 @@ void LLSelectMgr::updateSelectionCenter() if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && gAgent.getAvatarObject()) { // reset hud ZOOM - gAgent.getAvatarObject()->mHUDTargetZoom = 1.f; - gAgent.getAvatarObject()->mHUDCurZoom = 1.f; + gAgent.mHUDTargetZoom = 1.f; + gAgent.mHUDCurZoom = 1.f; } mShowSelection = FALSE; @@ -5564,11 +5561,12 @@ void LLSelectMgr::updatePointAt() if (mSelectedObjects->getObjectCount()) { LLVector3 select_offset; - LLViewerObject *click_object = gObjectList.findObject(gLastHitObjectID); + const LLPickInfo& pick = gViewerWindow->getLastPick(); + LLViewerObject *click_object = pick.getObject(); if (click_object && click_object->isSelected()) { // clicked on another object in our selection group, use that as target - select_offset.setVec(gLastHitObjectOffset); + select_offset.setVec(pick.mObjectOffset); select_offset.rotVec(~click_object->getRenderRotation()); gAgent.setPointAt(POINTAT_TARGET_SELECT, click_object, select_offset); @@ -5766,29 +5764,20 @@ BOOL LLSelectMgr::setForceSelection(BOOL force) void LLSelectMgr::resetAgentHUDZoom() { - if (gAgent.getAvatarObject()) - { - gAgent.getAvatarObject()->mHUDTargetZoom = 1.f; - gAgent.getAvatarObject()->mHUDCurZoom = 1.f; - } + gAgent.mHUDTargetZoom = 1.f; + gAgent.mHUDCurZoom = 1.f; } void LLSelectMgr::getAgentHUDZoom(F32 &target_zoom, F32 ¤t_zoom) const { - if (gAgent.getAvatarObject()) - { - target_zoom = gAgent.getAvatarObject()->mHUDTargetZoom; - current_zoom = gAgent.getAvatarObject()->mHUDCurZoom; - } + target_zoom = gAgent.mHUDTargetZoom; + current_zoom = gAgent.mHUDCurZoom; } void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom) { - if (gAgent.getAvatarObject()) - { - gAgent.getAvatarObject()->mHUDTargetZoom = target_zoom; - gAgent.getAvatarObject()->mHUDCurZoom = current_zoom; - } + gAgent.mHUDTargetZoom = target_zoom; + gAgent.mHUDCurZoom = current_zoom; } LLObjectSelection::LLObjectSelection() : diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index a62b1ac56a..e9b09599e2 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -36,6 +36,7 @@ #include "llviewerwindow.h" #include "llviewerobjectlist.h" #include "llvovolume.h" +#include "llvolume.h" #include "llviewercamera.h" #include "llface.h" #include "llviewercontrol.h" @@ -243,28 +244,6 @@ void LLSpatialGroup::buildOcclusion() BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group); -BOOL LLLineSegmentAABB(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size) -{ - float fAWdU[3]; - LLVector3 dir; - LLVector3 diff; - - for (U32 i = 0; i < 3; i++) - { - dir.mV[i] = 0.5f * (end.mV[i] - start.mV[i]); - diff.mV[i] = (0.5f * (end.mV[i] + start.mV[i])) - center.mV[i]; - fAWdU[i] = fabsf(dir.mV[i]); - if(fabsf(diff.mV[i])>size.mV[i] + fAWdU[i]) return false; - } - - float f; - f = dir.mV[1] * diff.mV[2] - dir.mV[2] * diff.mV[1]; if(fabsf(f)>size.mV[1]*fAWdU[2] + size.mV[2]*fAWdU[1]) return false; - f = dir.mV[2] * diff.mV[0] - dir.mV[0] * diff.mV[2]; if(fabsf(f)>size.mV[0]*fAWdU[2] + size.mV[2]*fAWdU[0]) return false; - f = dir.mV[0] * diff.mV[1] - dir.mV[1] * diff.mV[0]; if(fabsf(f)>size.mV[0]*fAWdU[1] + size.mV[1]*fAWdU[0]) return false; - - return true; -} - //returns: // 0 if sphere and AABB are not intersecting // 1 if they are @@ -2305,6 +2284,56 @@ void renderLights(LLDrawable* drawablep) } } + +void renderRaycast(LLDrawable* drawablep) +{ + if (drawablep->getVObj() != gDebugRaycastObject) + { + return; + } + + if (drawablep->getNumFaces()) + { + LLGLEnable blend(GL_BLEND); + gGL.color4f(0,1,1,0.5f); + + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); + } + + // draw intersection point + glPushMatrix(); + glLoadMatrixd(gGLModelView); + LLVector3 translate = gDebugRaycastIntersection; + glTranslatef(translate.mV[0], translate.mV[1], translate.mV[2]); + LLCoordFrame orient; + orient.lookDir(gDebugRaycastNormal, gDebugRaycastBinormal); + LLMatrix4 rotation; + orient.getRotMatrixToParent(rotation); + glMultMatrixf((float*)rotation.mMatrix); + + gGL.color4f(1,0,0,0.5f); + drawBox(LLVector3(0, 0, 0), LLVector3(0.1f, 0.022f, 0.022f)); + gGL.color4f(0,1,0,0.5f); + drawBox(LLVector3(0, 0, 0), LLVector3(0.021f, 0.1f, 0.021f)); + gGL.color4f(0,0,1,0.5f); + drawBox(LLVector3(0, 0, 0), LLVector3(0.02f, 0.02f, 0.1f)); + glPopMatrix(); + + // draw bounding box of prim + const LLVector3* ext = drawablep->getSpatialExtents(); + + LLVector3 pos = (ext[0] + ext[1]) * 0.5f; + LLVector3 size = (ext[1] - ext[0]) * 0.5f; + + LLGLDepthTest depth(GL_FALSE, GL_TRUE); + gGL.color4f(0,0.5f,0.5f,1); + drawBoxOutline(pos, size); + + } +} + class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable> { public: @@ -2381,6 +2410,11 @@ public: { renderLights(drawable); } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) + { + renderRaycast(drawable); + } } for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) @@ -2411,7 +2445,8 @@ void LLSpatialPartition::renderDebug() LLPipeline::RENDER_DEBUG_BBOXES | LLPipeline::RENDER_DEBUG_POINTS | LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY | - LLPipeline::RENDER_DEBUG_TEXTURE_ANIM)) + LLPipeline::RENDER_DEBUG_TEXTURE_ANIM | + LLPipeline::RENDER_DEBUG_RAYCAST)) { return; } @@ -2457,17 +2492,37 @@ BOOL LLSpatialPartition::isVisible(const LLVector3& v) return TRUE; } -class LLOctreePick : public LLSpatialGroup::OctreeTraveler +class LLOctreeIntersect : public LLSpatialGroup::OctreeTraveler { public: LLVector3 mStart; LLVector3 mEnd; - LLDrawable* mRet; + S32 *mFaceHit; + LLVector3 *mIntersection; + LLVector2 *mTexCoord; + LLVector3 *mNormal; + LLVector3 *mBinormal; + LLDrawable* mHit; - LLOctreePick(LLVector3 start, LLVector3 end) - : mStart(start), mEnd(end) + LLOctreeIntersect(LLVector3 start, LLVector3 end, + S32* face_hit, LLVector3* intersection, LLVector2* tex_coord, LLVector3* normal, LLVector3* binormal) + : mStart(start), + mEnd(end), + mFaceHit(face_hit), + mIntersection(intersection), + mTexCoord(tex_coord), + mNormal(normal), + mBinormal(binormal), + mHit(NULL) { - mRet = NULL; + } + + virtual void visit(const LLSpatialGroup::OctreeNode* branch) + { + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + { + check(*i); + } } virtual LLDrawable* check(const LLSpatialGroup::OctreeNode* node) @@ -2487,41 +2542,73 @@ public: size = group->mBounds[1]; center = group->mBounds[0]; - if (LLLineSegmentAABB(mStart, mEnd, center, size)) + LLVector3 local_start = mStart; + LLVector3 local_end = mEnd; + + if (group->mSpatialPartition->isBridge()) + { + LLMatrix4 local_matrix = group->mSpatialPartition->asBridge()->mDrawable->getRenderMatrix(); + local_matrix.invert(); + + local_start = mStart * local_matrix; + local_end = mEnd * local_matrix; + } + + if (LLLineSegmentBoxIntersect(local_start, local_end, center, size)) { check(child); } } - return mRet; + return mHit; } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) + virtual bool check(LLDrawable* drawable) { - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + if (drawable->isSpatialBridge()) { - check(*i); - } + LLSpatialPartition *part = drawable->asPartition(); + + check(part->mOctree); } - virtual bool check(LLDrawable* drawable) + else { LLViewerObject* vobj = drawable->getVObj(); - if (vobj->lineSegmentIntersect(mStart, mEnd)) + + if (vobj) + { + LLVector3 intersection; + if (vobj->lineSegmentIntersect(mStart, mEnd, -1, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal)) + { + mEnd = intersection; // shorten ray so we only find CLOSER hits + if (mIntersection) { - mRet = vobj->mDrawable; + *mIntersection = intersection; + } + + mHit = vobj->mDrawable; + } + } } return false; } }; -LLDrawable* LLSpatialPartition::pickDrawable(const LLVector3& start, const LLVector3& end, LLVector3& collision) +LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, + S32* face_hit, // return the face hit + LLVector3* intersection, // return the intersection point + LLVector2* tex_coord, // return the texture coordinates of the intersection point + LLVector3* normal, // return the surface normal at the intersection point + LLVector3* bi_normal // return the surface bi-normal at the intersection point + ) + { - LLOctreePick pick(start, end); - LLDrawable* ret = pick.check(mOctree); - collision.setVec(pick.mEnd); - return ret; + LLOctreeIntersect intersect(start, end, face_hit, intersection, tex_coord, normal, bi_normal); + LLDrawable* drawable = intersect.check(mOctree); + + return drawable; } LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 7e872915b9..d9a81d8b9e 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -300,7 +300,14 @@ public: LLSpatialGroup *put(LLDrawable *drawablep, BOOL was_visible = FALSE); BOOL remove(LLDrawable *drawablep, LLSpatialGroup *curp); - LLDrawable* pickDrawable(const LLVector3& start, const LLVector3& end, LLVector3& collision); + LLDrawable* lineSegmentIntersect(const LLVector3& start, const LLVector3& end, + S32* face_hit, // return the face hit + LLVector3* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector3* normal = NULL, // return the surface normal at the intersection point + LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point + ); + // If the drawable moves, move it here. virtual void move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate = FALSE); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index c522bd0697..83b5cdbb66 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -1452,13 +1452,15 @@ LLToolTexEyedropper::~LLToolTexEyedropper() BOOL LLToolTexEyedropper::handleMouseDown(S32 x, S32 y, MASK mask) { - LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); + // this will affect framerate on mouse down + const LLPickInfo& pick = gViewerWindow->pickImmediate(x, y, FALSE); + LLViewerObject* hit_obj = pick.getObject(); if (hit_obj && !hit_obj->isAvatar()) { - if( (0 <= gLastHitObjectFace) && (gLastHitObjectFace < hit_obj->getNumTEs()) ) + if( (0 <= pick.mObjectFace) && (pick.mObjectFace < hit_obj->getNumTEs()) ) { - LLViewerImage* image = hit_obj->getTEImage( gLastHitObjectFace ); + LLViewerImage* image = hit_obj->getTEImage( pick.mObjectFace ); if( image ) { if( mCallback ) diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp index 4efc6f74d4..9fd8044cca 100644 --- a/indra/newview/lltoolcomp.cpp +++ b/indra/newview/lltoolcomp.cpp @@ -145,18 +145,18 @@ LLToolCompInspect::~LLToolCompInspect() BOOL LLToolCompInspect::handleMouseDown(S32 x, S32 y, MASK mask) { mMouseDown = TRUE; - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback); return TRUE; } -void LLToolCompInspect::pickCallback(S32 x, S32 y, MASK mask) +void LLToolCompInspect::pickCallback(const LLPickInfo& pick_info) { - LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); + LLViewerObject* hit_obj = pick_info.getObject(); if (!LLToolCompInspect::getInstance()->mMouseDown) { // fast click on object, but mouse is already up...just do select - LLToolCompInspect::getInstance()->mSelectRect->handleObjectSelection(hit_obj, mask, gSavedSettings.getBOOL("EditLinkedParts"), FALSE); + LLToolCompInspect::getInstance()->mSelectRect->handleObjectSelection(pick_info, gSavedSettings.getBOOL("EditLinkedParts"), FALSE); return; } @@ -167,13 +167,13 @@ void LLToolCompInspect::pickCallback(S32 x, S32 y, MASK mask) LLEditMenuHandler::gEditMenuHandler = LLSelectMgr::getInstance(); } LLToolCompInspect::getInstance()->setCurrentTool( LLToolCompInspect::getInstance()->mSelectRect ); - LLToolCompInspect::getInstance()->mSelectRect->handleMouseDown( x, y, mask ); + LLToolCompInspect::getInstance()->mSelectRect->handlePick( pick_info ); } else { LLToolCompInspect::getInstance()->setCurrentTool( LLToolCompInspect::getInstance()->mSelectRect ); - LLToolCompInspect::getInstance()->mSelectRect->handleMouseDown( x, y, mask); + LLToolCompInspect::getInstance()->mSelectRect->handlePick( pick_info ); } } @@ -218,19 +218,19 @@ BOOL LLToolCompTranslate::handleHover(S32 x, S32 y, MASK mask) BOOL LLToolCompTranslate::handleMouseDown(S32 x, S32 y, MASK mask) { mMouseDown = TRUE; - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback, TRUE); + gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE); return TRUE; } -void LLToolCompTranslate::pickCallback(S32 x, S32 y, MASK mask) +void LLToolCompTranslate::pickCallback(const LLPickInfo& pick_info) { - LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); + LLViewerObject* hit_obj = pick_info.getObject(); - LLToolCompTranslate::getInstance()->mManip->highlightManipulators(x, y); + LLToolCompTranslate::getInstance()->mManip->highlightManipulators(pick_info.mMousePt.mX, pick_info.mMousePt.mY); if (!LLToolCompTranslate::getInstance()->mMouseDown) { // fast click on object, but mouse is already up...just do select - LLToolCompTranslate::getInstance()->mSelectRect->handleObjectSelection(hit_obj, mask, gSavedSettings.getBOOL("EditLinkedParts"), FALSE); + LLToolCompTranslate::getInstance()->mSelectRect->handleObjectSelection(pick_info, gSavedSettings.getBOOL("EditLinkedParts"), FALSE); return; } @@ -246,12 +246,12 @@ void LLToolCompTranslate::pickCallback(S32 x, S32 y, MASK mask) if( LLManip::LL_NO_PART != LLToolCompTranslate::getInstance()->mManip->getHighlightedPart() && can_move) { LLToolCompTranslate::getInstance()->setCurrentTool( LLToolCompTranslate::getInstance()->mManip ); - LLToolCompTranslate::getInstance()->mManip->handleMouseDownOnPart( x, y, mask ); + LLToolCompTranslate::getInstance()->mManip->handleMouseDownOnPart( pick_info.mMousePt.mX, pick_info.mMousePt.mY, pick_info.mKeyMask ); } else { LLToolCompTranslate::getInstance()->setCurrentTool( LLToolCompTranslate::getInstance()->mSelectRect ); - LLToolCompTranslate::getInstance()->mSelectRect->handleMouseDown( x, y, mask ); + LLToolCompTranslate::getInstance()->mSelectRect->handlePick( pick_info ); // *TODO: add toggle to trigger old click-drag functionality // LLToolCompTranslate::getInstance()->mManip->handleMouseDownOnPart( XY_part, x, y, mask); @@ -260,7 +260,7 @@ void LLToolCompTranslate::pickCallback(S32 x, S32 y, MASK mask) else { LLToolCompTranslate::getInstance()->setCurrentTool( LLToolCompTranslate::getInstance()->mSelectRect ); - LLToolCompTranslate::getInstance()->mSelectRect->handleMouseDown( x, y, mask); + LLToolCompTranslate::getInstance()->mSelectRect->handlePick( pick_info ); } } @@ -342,19 +342,19 @@ BOOL LLToolCompScale::handleHover(S32 x, S32 y, MASK mask) BOOL LLToolCompScale::handleMouseDown(S32 x, S32 y, MASK mask) { mMouseDown = TRUE; - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback); return TRUE; } -void LLToolCompScale::pickCallback(S32 x, S32 y, MASK mask) +void LLToolCompScale::pickCallback(const LLPickInfo& pick_info) { - LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); + LLViewerObject* hit_obj = pick_info.getObject(); - LLToolCompScale::getInstance()->mManip->highlightManipulators(x, y); + LLToolCompScale::getInstance()->mManip->highlightManipulators(pick_info.mMousePt.mX, pick_info.mMousePt.mY); if (!LLToolCompScale::getInstance()->mMouseDown) { // fast click on object, but mouse is already up...just do select - LLToolCompScale::getInstance()->mSelectRect->handleObjectSelection(hit_obj, mask, gSavedSettings.getBOOL("EditLinkedParts"), FALSE); + LLToolCompScale::getInstance()->mSelectRect->handleObjectSelection(pick_info, gSavedSettings.getBOOL("EditLinkedParts"), FALSE); return; } @@ -368,18 +368,18 @@ void LLToolCompScale::pickCallback(S32 x, S32 y, MASK mask) if( LLManip::LL_NO_PART != LLToolCompScale::getInstance()->mManip->getHighlightedPart() ) { LLToolCompScale::getInstance()->setCurrentTool( LLToolCompScale::getInstance()->mManip ); - LLToolCompScale::getInstance()->mManip->handleMouseDownOnPart( x, y, mask ); + LLToolCompScale::getInstance()->mManip->handleMouseDownOnPart( pick_info.mMousePt.mX, pick_info.mMousePt.mY, pick_info.mKeyMask ); } else { LLToolCompScale::getInstance()->setCurrentTool( LLToolCompScale::getInstance()->mSelectRect ); - LLToolCompScale::getInstance()->mSelectRect->handleMouseDown( x, y, mask ); + LLToolCompScale::getInstance()->mSelectRect->handlePick( pick_info ); } } else { LLToolCompScale::getInstance()->setCurrentTool( LLToolCompScale::getInstance()->mSelectRect ); - LLToolCompScale::getInstance()->mCur->handleMouseDown( x, y, mask ); + LLToolCompScale::getInstance()->mSelectRect->handlePick( pick_info ); } } @@ -457,15 +457,15 @@ BOOL LLToolCompCreate::handleMouseDown(S32 x, S32 y, MASK mask) BOOL handled = FALSE; mMouseDown = TRUE; - if ( !(mask == MASK_SHIFT) && !(mask == MASK_CONTROL) ) + if ( (mask == MASK_SHIFT) || (mask == MASK_CONTROL) ) { - setCurrentTool( mPlacer ); - handled = mPlacer->placeObject( x, y, mask ); + gViewerWindow->pickAsync(x, y, mask, pickCallback); + handled = TRUE; } else { - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback); - handled = TRUE; + setCurrentTool( mPlacer ); + handled = mPlacer->placeObject( x, y, mask ); } mObjectPlacedOnMouseDown = TRUE; @@ -473,15 +473,15 @@ BOOL LLToolCompCreate::handleMouseDown(S32 x, S32 y, MASK mask) return TRUE; } -void LLToolCompCreate::pickCallback(S32 x, S32 y, MASK mask) +void LLToolCompCreate::pickCallback(const LLPickInfo& pick_info) { // *NOTE: We mask off shift and control, so you cannot // multi-select multiple objects with the create tool. - mask = (mask & ~MASK_SHIFT); + MASK mask = (pick_info.mKeyMask & ~MASK_SHIFT); mask = (mask & ~MASK_CONTROL); LLToolCompCreate::getInstance()->setCurrentTool( LLToolCompCreate::getInstance()->mSelectRect ); - LLToolCompCreate::getInstance()->mSelectRect->handleMouseDown( x, y, mask); + LLToolCompCreate::getInstance()->mSelectRect->handlePick( pick_info ); } BOOL LLToolCompCreate::handleDoubleClick(S32 x, S32 y, MASK mask) @@ -543,19 +543,19 @@ BOOL LLToolCompRotate::handleHover(S32 x, S32 y, MASK mask) BOOL LLToolCompRotate::handleMouseDown(S32 x, S32 y, MASK mask) { mMouseDown = TRUE; - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback); return TRUE; } -void LLToolCompRotate::pickCallback(S32 x, S32 y, MASK mask) +void LLToolCompRotate::pickCallback(const LLPickInfo& pick_info) { - LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); + LLViewerObject* hit_obj = pick_info.getObject(); - LLToolCompRotate::getInstance()->mManip->highlightManipulators(x, y); + LLToolCompRotate::getInstance()->mManip->highlightManipulators(pick_info.mMousePt.mX, pick_info.mMousePt.mY); if (!LLToolCompRotate::getInstance()->mMouseDown) { // fast click on object, but mouse is already up...just do select - LLToolCompRotate::getInstance()->mSelectRect->handleObjectSelection(hit_obj, mask, gSavedSettings.getBOOL("EditLinkedParts"), FALSE); + LLToolCompRotate::getInstance()->mSelectRect->handleObjectSelection(pick_info, gSavedSettings.getBOOL("EditLinkedParts"), FALSE); return; } @@ -568,18 +568,18 @@ void LLToolCompRotate::pickCallback(S32 x, S32 y, MASK mask) if( LLManip::LL_NO_PART != LLToolCompRotate::getInstance()->mManip->getHighlightedPart() ) { LLToolCompRotate::getInstance()->setCurrentTool( LLToolCompRotate::getInstance()->mManip ); - LLToolCompRotate::getInstance()->mManip->handleMouseDownOnPart( x, y, mask ); + LLToolCompRotate::getInstance()->mManip->handleMouseDownOnPart( pick_info.mMousePt.mX, pick_info.mMousePt.mY, pick_info.mKeyMask ); } else { LLToolCompRotate::getInstance()->setCurrentTool( LLToolCompRotate::getInstance()->mSelectRect ); - LLToolCompRotate::getInstance()->mSelectRect->handleMouseDown( x, y, mask ); + LLToolCompRotate::getInstance()->mSelectRect->handlePick( pick_info ); } } else { LLToolCompRotate::getInstance()->setCurrentTool( LLToolCompRotate::getInstance()->mSelectRect ); - LLToolCompRotate::getInstance()->mCur->handleMouseDown( x, y, mask ); + LLToolCompRotate::getInstance()->mSelectRect->handlePick( pick_info ); } } diff --git a/indra/newview/lltoolcomp.h b/indra/newview/lltoolcomp.h index 8926cd34d2..5547a6d15b 100644 --- a/indra/newview/lltoolcomp.h +++ b/indra/newview/lltoolcomp.h @@ -37,6 +37,7 @@ class LLManip; class LLToolSelectRect; class LLToolPlacer; +class LLPickInfo; class LLView; class LLTextBox; @@ -114,7 +115,7 @@ public: virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - static void pickCallback(S32 x, S32 y, MASK mask); + static void pickCallback(const LLPickInfo& pick_info); }; //----------------------------------------------------------------------- @@ -135,7 +136,7 @@ public: virtual LLTool* getOverrideTool(MASK mask); - static void pickCallback(S32 x, S32 y, MASK mask); + static void pickCallback(const LLPickInfo& pick_info); }; //----------------------------------------------------------------------- @@ -156,7 +157,7 @@ public: virtual LLTool* getOverrideTool(MASK mask); - static void pickCallback(S32 x, S32 y, MASK mask); + static void pickCallback(const LLPickInfo& pick_info); }; @@ -178,7 +179,7 @@ public: virtual LLTool* getOverrideTool(MASK mask); - static void pickCallback(S32 x, S32 y, MASK mask); + static void pickCallback(const LLPickInfo& pick_info); protected: }; @@ -197,7 +198,7 @@ public: virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - static void pickCallback(S32 x, S32 y, MASK mask); + static void pickCallback(const LLPickInfo& pick_info); protected: LLToolPlacer* mPlacer; BOOL mObjectPlacedOnMouseDown; diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 940f5ba62d..109a11755b 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -988,32 +988,37 @@ void LLToolDragAndDrop::dragOrDrop3D( S32 x, S32 y, MASK mask, BOOL drop, EAccep mDrop = drop; if (mDrop) { - gPickFaces = TRUE; // don't allow drag and drop onto transparent objects - gViewerWindow->hitObjectOrLandGlobalImmediate(x, y, pickCallback, FALSE); + pickCallback(gViewerWindow->pickImmediate(x, y, FALSE)); } else { - // Don't pick faces during hover. Nothing currently requires per-face - // data. // don't allow drag and drop onto transparent objects - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback, FALSE); + gViewerWindow->pickAsync(x, y, mask, pickCallback, FALSE); } *acceptance = mLastAccept; } -void LLToolDragAndDrop::pickCallback(S32 x, S32 y, MASK mask) +void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info) { EDropTarget target = DT_NONE; S32 hit_face = -1; - LLViewerObject* hit_obj = gViewerWindow->lastNonFloraObjectHit(); + LLViewerObject* hit_obj = pick_info.getObject(); LLSelectMgr::getInstance()->unhighlightAll(); // Treat attachments as part of the avatar they are attached to. if (hit_obj) { + // don't allow drag and drop on grass, trees, etc. + if(pick_info.mPickType == LLPickInfo::PICK_FLORA) + { + LLToolDragAndDrop::getInstance()->mCursor = UI_CURSOR_NO; + gViewerWindow->getWindow()->setCursor( LLToolDragAndDrop::getInstance()->mCursor ); + return; + } + if(hit_obj->isAttachment() && !hit_obj->isHUDAttachment()) { LLVOAvatar* avatar = LLVOAvatar::findAvatarFromAttachment( hit_obj ); @@ -1044,12 +1049,12 @@ void LLToolDragAndDrop::pickCallback(S32 x, S32 y, MASK mask) else { target = DT_OBJECT; - hit_face = gLastHitNonFloraObjectFace; + hit_face = pick_info.mObjectFace; // if any item being dragged will be applied to the object under our cursor // highlight that object for (S32 i = 0; i < (S32)LLToolDragAndDrop::getInstance()->mCargoIDs.size(); i++) { - if (LLToolDragAndDrop::getInstance()->mCargoTypes[i] != DAD_OBJECT || (mask & MASK_CONTROL)) + if (LLToolDragAndDrop::getInstance()->mCargoTypes[i] != DAD_OBJECT || (pick_info.mKeyMask & MASK_CONTROL)) { LLSelectMgr::getInstance()->highlightObjectAndFamily(hit_obj); break; @@ -1057,7 +1062,7 @@ void LLToolDragAndDrop::pickCallback(S32 x, S32 y, MASK mask) } } } - else if(gLastHitLand) + else if(pick_info.mPickType == LLPickInfo::PICK_LAND) { target = DT_LAND; hit_face = -1; @@ -1073,7 +1078,7 @@ void LLToolDragAndDrop::pickCallback(S32 x, S32 y, MASK mask) (U32)LLToolDragAndDrop::getInstance()->mLastAccept, (U32)callMemberFunction((*LLToolDragAndDrop::getInstance()), LLToolDragAndDrop::getInstance()->sDragAndDrop3d[LLToolDragAndDrop::getInstance()->mCargoTypes[LLToolDragAndDrop::getInstance()->mCurItemIndex]][target]) - (hit_obj, hit_face, mask, FALSE)); + (hit_obj, hit_face, pick_info.mKeyMask, FALSE)); } if (LLToolDragAndDrop::getInstance()->mDrop && (U32)LLToolDragAndDrop::getInstance()->mLastAccept >= ACCEPT_YES_COPY_SINGLE) @@ -1095,7 +1100,7 @@ void LLToolDragAndDrop::pickCallback(S32 x, S32 y, MASK mask) // Call the right implementation function (U32)callMemberFunction((*LLToolDragAndDrop::getInstance()), LLToolDragAndDrop::getInstance()->sDragAndDrop3d[LLToolDragAndDrop::getInstance()->mCargoTypes[LLToolDragAndDrop::getInstance()->mCurItemIndex]][target]) - (hit_obj, hit_face, mask, TRUE); + (hit_obj, hit_face, pick_info.mKeyMask, TRUE); } } @@ -1142,7 +1147,7 @@ void LLToolDragAndDrop::pickCallback(S32 x, S32 y, MASK mask) llassert( FALSE ); } - LLToolDragAndDrop::getInstance()->mLastHitPos = gLastHitPosGlobal + gLastHitObjectOffset; + LLToolDragAndDrop::getInstance()->mLastHitPos = pick_info.mPosGlobal; LLToolDragAndDrop::getInstance()->mLastCameraPos = gAgent.getCameraPositionGlobal(); gViewerWindow->getWindow()->setCursor( LLToolDragAndDrop::getInstance()->mCursor ); diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 8f6d1713fa..8e2788a173 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -45,6 +45,7 @@ class LLToolDragAndDrop; class LLViewerRegion; class LLVOAvatar; +class LLPickInfo; class LLToolDragAndDrop : public LLTool, public LLSingleton<LLToolDragAndDrop> { @@ -106,7 +107,7 @@ protected: EAcceptance* acceptance); void dragOrDrop3D(S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* acceptance); - static void pickCallback(S32 x, S32 y, MASK mask); + static void pickCallback(const LLPickInfo& pick_info); protected: diff --git a/indra/newview/lltoolface.cpp b/indra/newview/lltoolface.cpp index 3248913182..138fc99606 100644 --- a/indra/newview/lltoolface.cpp +++ b/indra/newview/lltoolface.cpp @@ -82,17 +82,16 @@ BOOL LLToolFace::handleDoubleClick(S32 x, S32 y, MASK mask) BOOL LLToolFace::handleMouseDown(S32 x, S32 y, MASK mask) { - gPickFaces = TRUE; - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback); return TRUE; } -void LLToolFace::pickCallback(S32 x, S32 y, MASK mask) +void LLToolFace::pickCallback(const LLPickInfo& pick_info) { - LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); + LLViewerObject* hit_obj = pick_info.getObject(); if (hit_obj) { - S32 hit_face = gLastHitObjectFace; + S32 hit_face = pick_info.mObjectFace; if (hit_obj->isAvatar()) { @@ -102,7 +101,7 @@ void LLToolFace::pickCallback(S32 x, S32 y, MASK mask) // ...clicked on a world object, try to pick the appropriate face - if (mask & MASK_SHIFT) + if (pick_info.mKeyMask & MASK_SHIFT) { // If object not selected, need to inform sim if ( !hit_obj->isSelected() ) @@ -133,7 +132,7 @@ void LLToolFace::pickCallback(S32 x, S32 y, MASK mask) } else { - if (!(mask == MASK_SHIFT)) + if (!(pick_info.mKeyMask == MASK_SHIFT)) { LLSelectMgr::getInstance()->deselectAll(); } diff --git a/indra/newview/lltoolface.h b/indra/newview/lltoolface.h index f573bfa9c5..113dcc9fbd 100644 --- a/indra/newview/lltoolface.h +++ b/indra/newview/lltoolface.h @@ -35,6 +35,7 @@ #include "lltool.h" class LLViewerObject; +class LLPickInfo; class LLToolFace : public LLTool, public LLSingleton<LLToolFace> @@ -49,7 +50,7 @@ public: virtual void handleDeselect(); virtual void render(); // draw face highlights - static void pickCallback(S32 x, S32 y, MASK mask); + static void pickCallback(const LLPickInfo& pick_info); }; #endif diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp index b46d25583a..3fdf24bbc3 100644 --- a/indra/newview/lltoolfocus.cpp +++ b/indra/newview/lltoolfocus.cpp @@ -126,28 +126,28 @@ BOOL LLToolCamera::handleMouseDown(S32 x, S32 y, MASK mask) gViewerWindow->hideCursor(); - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback); // don't steal focus from UI return FALSE; } -void LLToolCamera::pickCallback(S32 x, S32 y, MASK mask) +void LLToolCamera::pickCallback(const LLPickInfo& pick_info) { if (!LLToolCamera::getInstance()->hasMouseCapture()) { return; } - LLToolCamera::getInstance()->mMouseDownX = x; - LLToolCamera::getInstance()->mMouseDownY = y; + LLToolCamera::getInstance()->mMouseDownX = pick_info.mMousePt.mX; + LLToolCamera::getInstance()->mMouseDownY = pick_info.mMousePt.mY; gViewerWindow->moveCursorToCenter(); // Potentially recenter if click outside rectangle - LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); + LLViewerObject* hit_obj = pick_info.getObject(); // Check for hit the sky, or some other invalid point - if (!hit_obj && gLastHitPosGlobal.isExactlyZero()) + if (!hit_obj && pick_info.mPosGlobal.isExactlyZero()) { LLToolCamera::getInstance()->mValidClickPoint = FALSE; return; @@ -195,29 +195,27 @@ void LLToolCamera::pickCallback(S32 x, S32 y, MASK mask) } } //RN: check to see if this is mouse-driving as opposed to ALT-zoom or Focus tool - else if (mask & MASK_ALT || + else if (pick_info.mKeyMask & MASK_ALT || (LLToolMgr::getInstance()->getCurrentTool()->getName() == "Camera")) { - LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); + LLViewerObject* hit_obj = pick_info.getObject(); if (hit_obj) { // ...clicked on a world object, so focus at its position - // Use "gLastHitPosGlobal" because it's correct for avatar heads, - // not pelvis. if (!hit_obj->isHUDAttachment()) { gAgent.setFocusOnAvatar(FALSE, ANIMATE); - gAgent.setFocusGlobal( gLastHitObjectOffset + gLastHitPosGlobal, gLastHitObjectID); + gAgent.setFocusGlobal(pick_info); } } - else if (!gLastHitPosGlobal.isExactlyZero()) + else if (!pick_info.mPosGlobal.isExactlyZero()) { // Hit the ground gAgent.setFocusOnAvatar(FALSE, ANIMATE); - gAgent.setFocusGlobal( gLastHitPosGlobal, gLastHitObjectID); + gAgent.setFocusGlobal(pick_info); } - if (!(mask & MASK_ALT) && + if (!(pick_info.mKeyMask & MASK_ALT) && gAgent.cameraThirdPerson() && gViewerWindow->getLeftMouseDown() && !gSavedSettings.getBOOL("FreezeTime") && @@ -238,7 +236,7 @@ void LLToolCamera::pickCallback(S32 x, S32 y, MASK mask) LLVector3d cam_pos = gAgent.getCameraPositionGlobal(); cam_pos -= LLVector3d(LLViewerCamera::getInstance()->getLeftAxis() * gAgent.calcCustomizeAvatarUIOffset( cam_pos )); - gAgent.setCameraPosAndFocusGlobal( cam_pos, gLastHitObjectOffset + gLastHitPosGlobal, gLastHitObjectID); + gAgent.setCameraPosAndFocusGlobal( cam_pos, pick_info.mPosGlobal, pick_info.mObjectID); } } diff --git a/indra/newview/lltoolfocus.h b/indra/newview/lltoolfocus.h index 2ed456b188..c8c748a1b0 100644 --- a/indra/newview/lltoolfocus.h +++ b/indra/newview/lltoolfocus.h @@ -34,6 +34,8 @@ #include "lltool.h" +class LLPickInfo; + class LLToolCamera : public LLTool, public LLSingleton<LLToolCamera> { @@ -52,7 +54,7 @@ public: virtual LLTool* getOverrideTool(MASK mask) { return NULL; } - static void pickCallback(S32 x, S32 y, MASK mask); + static void pickCallback(const LLPickInfo& pick_info); BOOL mouseSteerMode() { return mMouseSteering; } protected: diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp index a41e9381f6..13037c6a20 100644 --- a/indra/newview/lltoolgrab.cpp +++ b/indra/newview/lltoolgrab.cpp @@ -78,16 +78,6 @@ LLToolGrab::LLToolGrab( LLToolComposite* composite ) : LLTool( std::string("Grab"), composite ), mMode( GRAB_INACTIVE ), mVerticalDragging( FALSE ), - mHitLand(FALSE), - mHitObjectID(), - mGrabObject( NULL ), - mLastMouseX(0), - mLastMouseY(0), - mMouseDownX( -1 ), - mMouseDownY( -1 ), - mMouseMask(0), - mAccumDeltaX(0), - mAccumDeltaY(0), mHasMoved( FALSE ), mOutsideSlop(FALSE), mDeselectedThisClick(FALSE), @@ -138,24 +128,23 @@ BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask) llinfos << "LLToolGrab handleMouseDown" << llendl; } - mHitLand = FALSE; - // call the base class to propogate info to sim LLTool::handleMouseDown(x, y, mask); if (!gAgent.leftButtonGrabbed()) { // can grab transparent objects (how touch event propagates, scripters rely on this) - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback, TRUE); + gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE); } return TRUE; } -void LLToolGrab::pickCallback(S32 x, S32 y, MASK mask) +void LLToolGrab::pickCallback(const LLPickInfo& pick_info) { - LLViewerObject *objectp = gObjectList.findObject( gLastHitObjectID ); + LLToolGrab::getInstance()->mGrabPick = pick_info; + LLViewerObject *objectp = pick_info.getObject(); - BOOL extend_select = (mask & MASK_SHIFT); + BOOL extend_select = (pick_info.mKeyMask & MASK_SHIFT); if (!extend_select && !LLSelectMgr::getInstance()->getSelection()->isEmpty()) { @@ -172,23 +161,22 @@ void LLToolGrab::pickCallback(S32 x, S32 y, MASK mask) { LLToolGrab::getInstance()->setMouseCapture(TRUE); LLToolGrab::getInstance()->mMode = GRAB_NOOBJECT; - LLToolGrab::getInstance()->mHitObjectID.setNull(); + LLToolGrab::getInstance()->mGrabPick.mObjectID.setNull(); } else { - LLToolGrab::getInstance()->handleObjectHit(objectp, x, y, mask); + LLToolGrab::getInstance()->handleObjectHit(LLToolGrab::getInstance()->mGrabPick); } } -BOOL LLToolGrab::handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mask) +BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info) { - mMouseDownX = x; - mMouseDownY = y; - mMouseMask = mask; + mGrabPick = info; + LLViewerObject* objectp = mGrabPick.getObject(); if (gDebugClicks) { - llinfos << "LLToolGrab handleObjectHit " << mMouseDownX << "," << mMouseDownY << llendl; + llinfos << "LLToolGrab handleObjectHit " << info.mMousePt.mX << "," << info.mMousePt.mY << llendl; } if (NULL == objectp) // unexpected @@ -209,8 +197,6 @@ BOOL LLToolGrab::handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mas setMouseCapture( TRUE ); - mHitObjectID = objectp->getID(); - // Grabs always start from the root // objectp = (LLViewerObject *)objectp->getRoot(); @@ -230,13 +216,13 @@ BOOL LLToolGrab::handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mas if (gAgent.cameraMouselook() && !script_touch) { mMode = GRAB_LOCKED; + gViewerWindow->hideCursor(); + gViewerWindow->moveCursorToCenter(); } else { mMode = GRAB_NONPHYSICAL; } - gViewerWindow->hideCursor(); - gViewerWindow->moveCursorToCenter(); // Don't bail out here, go on and grab so buttons can get // their "touched" event. } @@ -261,20 +247,18 @@ BOOL LLToolGrab::handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mas // Always send "touched" message + mLastMouseX = gViewerWindow->getCurrentMouseX(); + mLastMouseY = gViewerWindow->getCurrentMouseY(); mAccumDeltaX = 0; mAccumDeltaY = 0; mHasMoved = FALSE; mOutsideSlop = FALSE; - mGrabObject = objectp; + mVerticalDragging = (info.mKeyMask == MASK_VERTICAL) || gGrabBtnVertical; - mGrabOffset.clearVec(); + startGrab(); - mVerticalDragging = (mask == MASK_VERTICAL) || gGrabBtnVertical; - - startGrab(x, y); - - if ((mask == MASK_SPIN) || gGrabBtnSpin) + if ((info.mKeyMask == MASK_SPIN) || gGrabBtnSpin) { startSpin(); } @@ -282,10 +266,10 @@ BOOL LLToolGrab::handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mas LLSelectMgr::getInstance()->updateSelectionCenter(); // update selection beam // update point at - LLViewerObject *edit_object = gObjectList.findObject(mHitObjectID); - if (edit_object) + LLViewerObject *edit_object = info.getObject(); + if (edit_object && info.mPickType != LLPickInfo::PICK_FLORA) { - LLVector3 local_edit_point = gAgent.getPosAgentFromGlobal(gLastHitNonFloraPosGlobal); + LLVector3 local_edit_point = gAgent.getPosAgentFromGlobal(info.mPosGlobal); local_edit_point -= edit_object->getPositionAgent(); local_edit_point = local_edit_point * ~edit_object->getRenderRotation(); gAgent.setPointAt(POINTAT_TARGET_GRAB, edit_object, local_edit_point ); @@ -307,10 +291,15 @@ BOOL LLToolGrab::handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mas void LLToolGrab::startSpin() { + LLViewerObject* objectp = mGrabPick.getObject(); + if (!objectp) + { + return; + } mSpinGrabbing = TRUE; // Was saveSelectedObjectTransform() - LLViewerObject *root = (LLViewerObject *)mGrabObject->getRoot(); + LLViewerObject *root = (LLViewerObject *)objectp->getRoot(); mSpinRotation = root->getRotation(); LLMessageSystem *msg = gMessageSystem; @@ -319,8 +308,8 @@ void LLToolGrab::startSpin() msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_ObjectData); - msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() ); - msg->sendMessage( mGrabObject->getRegion()->getHost() ); + msg->addUUIDFast(_PREHASH_ObjectID, mGrabPick.mObjectID ); + msg->sendMessage( objectp->getRegion()->getHost() ); } @@ -328,6 +317,12 @@ void LLToolGrab::stopSpin() { mSpinGrabbing = FALSE; + LLViewerObject* objectp = mGrabPick.getObject(); + if (!objectp) + { + return; + } + LLMessageSystem *msg = gMessageSystem; switch(mMode) { @@ -339,8 +334,8 @@ void LLToolGrab::stopSpin() msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_ObjectData); - msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() ); - msg->sendMessage( mGrabObject->getRegion()->getHost() ); + msg->addUUIDFast(_PREHASH_ObjectID, objectp->getID() ); + msg->sendMessage( objectp->getRegion()->getHost() ); break; case GRAB_NOOBJECT: @@ -352,11 +347,17 @@ void LLToolGrab::stopSpin() } -void LLToolGrab::startGrab(S32 x, S32 y) +void LLToolGrab::startGrab() { // Compute grab_offset in the OBJECT's root's coordinate frame // (sometimes root == object) - LLViewerObject *root = (LLViewerObject *)mGrabObject->getRoot(); + LLViewerObject* objectp = mGrabPick.getObject(); + if (!objectp) + { + return; + } + + LLViewerObject *root = (LLViewerObject *)objectp->getRoot(); // drag from center LLVector3d grab_start_global = root->getPositionGlobal(); @@ -365,7 +366,7 @@ void LLToolGrab::startGrab(S32 x, S32 y) // JC - This code looks wonky, but I believe it does the right thing. // Otherwise, when you grab a linked object set, it "pops" on the start // of the drag. - LLVector3d grab_offsetd = root->getPositionGlobal() - mGrabObject->getPositionGlobal(); + LLVector3d grab_offsetd = root->getPositionGlobal() - objectp->getPositionGlobal(); LLVector3 grab_offset; grab_offset.setVec(grab_offsetd); @@ -384,9 +385,16 @@ void LLToolGrab::startGrab(S32 x, S32 y) msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU32Fast(_PREHASH_LocalID, mGrabObject->mLocalID); + msg->addU32Fast(_PREHASH_LocalID, objectp->mLocalID); msg->addVector3Fast(_PREHASH_GrabOffset, grab_offset ); - msg->sendMessage( mGrabObject->getRegion()->getHost()); + msg->nextBlock("SurfaceInfo"); + msg->addVector3("UVCoord", LLVector3(mGrabPick.mUVCoords)); + msg->addVector3("STCoord", LLVector3(mGrabPick.mSTCoords)); + msg->addS32Fast(_PREHASH_FaceIndex, mGrabPick.mObjectFace); + msg->addVector3("Position", mGrabPick.mIntersection); + msg->addVector3("Normal", mGrabPick.mNormal); + msg->addVector3("Binormal", mGrabPick.mBinormal); + msg->sendMessage( objectp->getRegion()->getHost()); mGrabOffsetFromCenterInitial = grab_offset; mGrabHiddenOffsetFromCamera = mDragStartFromCamera; @@ -397,9 +405,6 @@ void LLToolGrab::startGrab(S32 x, S32 y) BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask) { - mLastMouseX = x; - mLastMouseY = y; - if (!gViewerWindow->getLeftMouseDown()) { gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB); @@ -411,9 +416,12 @@ BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask) switch( mMode ) { case GRAB_ACTIVE_CENTER: - case GRAB_NONPHYSICAL: handleHoverActive( x, y, mask ); // cursor hidden break; + + case GRAB_NONPHYSICAL: + handleHoverNonPhysical(x, y, mask); + break; case GRAB_INACTIVE: handleHoverInactive( x, y, mask ); // cursor set here @@ -426,18 +434,24 @@ BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask) } + mLastMouseX = x; + mLastMouseY = y; + return TRUE; } +const F32 GRAB_SENSITIVITY_X = 0.0075f; +const F32 GRAB_SENSITIVITY_Y = 0.0075f; + // Dragging. void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask) { - llassert( hasMouseCapture() ); - llassert( mGrabObject ); - if (mGrabObject->isDead()) + LLViewerObject* objectp = mGrabPick.getObject(); + if (!objectp || !hasMouseCapture() ) return; + if (objectp->isDead()) { // Bail out of drag because object has been killed setMouseCapture(FALSE); @@ -466,7 +480,7 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask) // ...switch to horizontal dragging mVerticalDragging = FALSE; - mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, mGrabObject); + mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, objectp); mDragStartFromCamera = mDragStartPointGlobal - gAgent.getCameraPositionGlobal(); } else if (!mVerticalDragging && (mask == MASK_VERTICAL) ) @@ -474,16 +488,13 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask) // ...switch to vertical dragging mVerticalDragging = TRUE; - mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, mGrabObject); + mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, objectp); mDragStartFromCamera = mDragStartPointGlobal - gAgent.getCameraPositionGlobal(); } const F32 RADIANS_PER_PIXEL_X = 0.01f; const F32 RADIANS_PER_PIXEL_Y = 0.01f; - const F32 SENSITIVITY_X = 0.0075f; - const F32 SENSITIVITY_Y = 0.0075f; - S32 dx = x - (gViewerWindow->getWindowWidth() / 2); S32 dy = y - (gViewerWindow->getWindowHeight() / 2); @@ -525,9 +536,9 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask) msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_ObjectData); - msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() ); + msg->addUUIDFast(_PREHASH_ObjectID, objectp->getID() ); msg->addQuatFast(_PREHASH_Rotation, mSpinRotation ); - msg->sendMessage( mGrabObject->getRegion()->getHost() ); + msg->sendMessage( objectp->getRegion()->getHost() ); } else { @@ -555,8 +566,8 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask) } mGrabHiddenOffsetFromCamera = mGrabHiddenOffsetFromCamera - + (x_part * (-dx * SENSITIVITY_X)) - + (y_part * ( dy * SENSITIVITY_Y)); + + (x_part * (-dx * GRAB_SENSITIVITY_X)) + + (y_part * ( dy * GRAB_SENSITIVITY_Y)); // Send the message to the viewer. @@ -640,7 +651,7 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask) && (grab_center_gl.mY > 24)) { // Transmit update to simulator - LLVector3 grab_pos_region = mGrabObject->getRegion()->getPosRegionFromGlobal( grab_point_global ); + LLVector3 grab_pos_region = objectp->getRegion()->getPosRegionFromGlobal( grab_point_global ); LLMessageSystem *msg = gMessageSystem; msg->newMessageFast(_PREHASH_ObjectGrabUpdate); @@ -648,11 +659,19 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask) msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_ObjectData); - msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() ); + msg->addUUIDFast(_PREHASH_ObjectID, objectp->getID() ); msg->addVector3Fast(_PREHASH_GrabOffsetInitial, mGrabOffsetFromCenterInitial ); msg->addVector3Fast(_PREHASH_GrabPosition, grab_pos_region ); msg->addU32Fast(_PREHASH_TimeSinceLast, dt_milliseconds ); - msg->sendMessage( mGrabObject->getRegion()->getHost() ); + msg->nextBlock("SurfaceInfo"); + msg->addVector3("UVCoord", LLVector3(mGrabPick.mUVCoords)); + msg->addVector3("STCoord", LLVector3(mGrabPick.mSTCoords)); + msg->addS32Fast(_PREHASH_FaceIndex, mGrabPick.mObjectFace); + msg->addVector3("Position", mGrabPick.mIntersection); + msg->addVector3("Normal", mGrabPick.mNormal); + msg->addVector3("Binormal", mGrabPick.mBinormal); + + msg->sendMessage( objectp->getRegion()->getHost() ); } } @@ -666,8 +685,8 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask) if (mHasMoved) { if (!gAgent.cameraMouselook() && - !mGrabObject->isHUDAttachment() && - mGrabObject->getRoot() == gAgent.getAvatarObject()->getRoot()) + !objectp->isHUDAttachment() && + objectp->getRoot() == gAgent.getAvatarObject()->getRoot()) { // force focus to point in space where we were looking previously gAgent.setFocusGlobal(gAgent.calcFocusPositionTargetGlobal(), LLUUID::null); @@ -686,6 +705,134 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask) } +void LLToolGrab::handleHoverNonPhysical(S32 x, S32 y, MASK mask) +{ + LLViewerObject* objectp = mGrabPick.getObject(); + if (!objectp || !hasMouseCapture() ) return; + if (objectp->isDead()) + { + // Bail out of drag because object has been killed + setMouseCapture(FALSE); + return; + } + + LLPickInfo pick = mGrabPick; + pick.mMousePt = LLCoordGL(x, y); + pick.getSurfaceInfo(); + + // compute elapsed time + F32 dt = mGrabTimer.getElapsedTimeAndResetF32(); + U32 dt_milliseconds = (U32) (1000.f * dt); + + // i'm not a big fan of the following code - it's been culled from the physical grab case. + // ideally these two would be nicely integrated - but the code in that method is a serious + // mess of spaghetti. so here we go: + + LLVector3 grab_pos_region(0,0,0); + + const BOOL SUPPORT_LLDETECTED_GRAB = TRUE; + if (SUPPORT_LLDETECTED_GRAB) + { + //-------------------------------------------------- + // Toggle vertical dragging + //-------------------------------------------------- + if (mVerticalDragging && !(mask == MASK_VERTICAL) && !gGrabBtnVertical) + { + mVerticalDragging = FALSE; + } + + else if (!mVerticalDragging && (mask == MASK_VERTICAL) ) + { + mVerticalDragging = TRUE; + } + + S32 dx = x - mLastMouseX; + S32 dy = y - mLastMouseY; + + if (dx != 0 || dy != 0) + { + mAccumDeltaX += dx; + mAccumDeltaY += dy; + + S32 dist_sq = mAccumDeltaX * mAccumDeltaX + mAccumDeltaY * mAccumDeltaY; + if (dist_sq > SLOP_DIST_SQ) + { + mOutsideSlop = TRUE; + } + + // mouse has moved + mHasMoved = TRUE; + + //------------------------------------------------------ + // Handle grabbing + //------------------------------------------------------ + + LLVector3d x_part; + x_part.setVec(LLViewerCamera::getInstance()->getLeftAxis()); + x_part.mdV[VZ] = 0.0; + x_part.normVec(); + + LLVector3d y_part; + if( mVerticalDragging ) + { + y_part.setVec(LLViewerCamera::getInstance()->getUpAxis()); + // y_part.setVec(0.f, 0.f, 1.f); + } + else + { + // drag toward camera + y_part = x_part % LLVector3d::z_axis; + y_part.mdV[VZ] = 0.0; + y_part.normVec(); + } + + mGrabHiddenOffsetFromCamera = mGrabHiddenOffsetFromCamera + + (x_part * (-dx * GRAB_SENSITIVITY_X)) + + (y_part * ( dy * GRAB_SENSITIVITY_Y)); + + } + + // need to return offset from mGrabStartPoint + LLVector3d grab_point_global = gAgent.getCameraPositionGlobal() + mGrabHiddenOffsetFromCamera; + grab_pos_region = objectp->getRegion()->getPosRegionFromGlobal( grab_point_global ); + } + + LLMessageSystem *msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectGrabUpdate); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addUUIDFast(_PREHASH_ObjectID, objectp->getID() ); + msg->addVector3Fast(_PREHASH_GrabOffsetInitial, mGrabOffsetFromCenterInitial ); + msg->addVector3Fast(_PREHASH_GrabPosition, grab_pos_region ); + msg->addU32Fast(_PREHASH_TimeSinceLast, dt_milliseconds ); + msg->nextBlock("SurfaceInfo"); + msg->addVector3("UVCoord", LLVector3(pick.mUVCoords)); + msg->addVector3("STCoord", LLVector3(pick.mSTCoords)); + msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace); + msg->addVector3("Position", pick.mIntersection); + msg->addVector3("Normal", pick.mNormal); + msg->addVector3("Binormal", pick.mBinormal); + + msg->sendMessage( objectp->getRegion()->getHost() ); + + // update point-at / look-at + if (pick.mObjectFace != -1) // if the intersection was on the surface of the obejct + { + LLVector3 local_edit_point = pick.mIntersection; + local_edit_point -= objectp->getPositionAgent(); + local_edit_point = local_edit_point * ~objectp->getRenderRotation(); + gAgent.setPointAt(POINTAT_TARGET_GRAB, objectp, local_edit_point ); + gAgent.setLookAt(LOOKAT_TARGET_SELECT, objectp, local_edit_point ); + } + + + + gViewerWindow->setCursor(UI_CURSOR_HAND); +} + + // Not dragging. Just showing affordances void LLToolGrab::handleHoverInactive(S32 x, S32 y, MASK mask) { @@ -726,7 +873,7 @@ void LLToolGrab::handleHoverFailed(S32 x, S32 y, MASK mask) } else { - S32 dist_sq = (x-mMouseDownX) * (x-mMouseDownX) + (y-mMouseDownY) * (y-mMouseDownY); + S32 dist_sq = (x-mGrabPick.mMousePt.mX) * (x-mGrabPick.mMousePt.mX) + (y-mGrabPick.mMousePt.mY) * (y-mGrabPick.mMousePt.mY); if( mOutsideSlop || dist_sq > SLOP_DIST_SQ ) { mOutsideSlop = TRUE; @@ -791,23 +938,27 @@ void LLToolGrab::stopEditing() void LLToolGrab::onMouseCaptureLost() { + LLViewerObject* objectp = mGrabPick.getObject(); + if (!objectp) + { + gViewerWindow->showCursor(); + return; + } // First, fix cursor placement if( !gAgent.cameraMouselook() - && (GRAB_ACTIVE_CENTER == mMode || GRAB_NONPHYSICAL == mMode)) + && (GRAB_ACTIVE_CENTER == mMode)) { - llassert( mGrabObject ); - - if (mGrabObject->isHUDAttachment()) + if (objectp->isHUDAttachment()) { // ...move cursor "naturally", as if it had moved when hidden - S32 x = mMouseDownX + mAccumDeltaX; - S32 y = mMouseDownY + mAccumDeltaY; + S32 x = mGrabPick.mMousePt.mX + mAccumDeltaX; + S32 y = mGrabPick.mMousePt.mY + mAccumDeltaY; LLUI::setCursorPositionScreen(x, y); } else if (mHasMoved) { // ...move cursor back to the center of the object - LLVector3 grab_point_agent = mGrabObject->getRenderPosition(); + LLVector3 grab_point_agent = objectp->getRenderPosition(); LLCoordGL gl_point; if (LLViewerCamera::getInstance()->projectPosAgentToScreen(grab_point_agent, gl_point)) @@ -818,19 +969,21 @@ void LLToolGrab::onMouseCaptureLost() else { // ...move cursor back to click position - LLUI::setCursorPositionScreen(mMouseDownX, mMouseDownY); + LLUI::setCursorPositionScreen(mGrabPick.mMousePt.mX, mGrabPick.mMousePt.mY); } gViewerWindow->showCursor(); } stopGrab(); + if (mSpinGrabbing) stopSpin(); + mMode = GRAB_INACTIVE; mHideBuildHighlight = FALSE; - mGrabObject = NULL; + mGrabPick.mObjectID.setNull(); LLSelectMgr::getInstance()->updateSelectionCenter(); gAgent.setPointAt(POINTAT_TARGET_CLEAR); @@ -842,6 +995,24 @@ void LLToolGrab::onMouseCaptureLost() void LLToolGrab::stopGrab() { + LLViewerObject* objectp = mGrabPick.getObject(); + if (!objectp) + { + return; + } + + LLPickInfo pick = mGrabPick; + + if (mMode == GRAB_NONPHYSICAL) + { + // for non-physical (touch) grabs, + // gather surface info for this degrab (mouse-up) + S32 x = gViewerWindow->getCurrentMouseX(); + S32 y = gViewerWindow->getCurrentMouseY(); + pick.mMousePt = LLCoordGL(x, y); + pick.getSurfaceInfo(); + } + // Next, send messages to simulator LLMessageSystem *msg = gMessageSystem; switch(mMode) @@ -854,11 +1025,18 @@ void LLToolGrab::stopGrab() msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU32Fast(_PREHASH_LocalID, mGrabObject->mLocalID); - msg->sendMessage(mGrabObject->getRegion()->getHost()); + msg->addU32Fast(_PREHASH_LocalID, objectp->mLocalID); + msg->nextBlock("SurfaceInfo"); + msg->addVector3("UVCoord", LLVector3(mGrabPick.mUVCoords)); + msg->addVector3("STCoord", LLVector3(mGrabPick.mSTCoords)); + msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace); + msg->addVector3("Position", pick.mIntersection); + msg->addVector3("Normal", pick.mNormal); + msg->addVector3("Binormal", pick.mBinormal); + + msg->sendMessage(objectp->getRegion()->getHost()); mVerticalDragging = FALSE; - mGrabOffset.clearVec(); break; case GRAB_NOOBJECT: @@ -880,14 +1058,12 @@ void LLToolGrab::render() BOOL LLToolGrab::isEditing() { - // Can't just compare to null directly due to "smart" pointer. - LLViewerObject *obj = mGrabObject; - return (obj != NULL); + return (mGrabPick.getObject().notNull()); } LLViewerObject* LLToolGrab::getEditingObject() { - return mGrabObject; + return mGrabPick.getObject(); } diff --git a/indra/newview/lltoolgrab.h b/indra/newview/lltoolgrab.h index d744c495a5..696ce0742a 100644 --- a/indra/newview/lltoolgrab.h +++ b/indra/newview/lltoolgrab.h @@ -37,10 +37,12 @@ #include "llquaternion.h" #include "llmemory.h" #include "lluuid.h" +#include "llviewerwindow.h" // for LLPickInfo class LLView; class LLTextBox; class LLViewerObject; +class LLPickInfo; class LLToolGrab : public LLTool, public LLSingleton<LLToolGrab> { @@ -69,15 +71,15 @@ public: LLVector3 getGrabOffset(S32 x, S32 y); // HACK // Capture the mouse and start grabbing. - BOOL handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mask); + BOOL handleObjectHit(const LLPickInfo& info); // Certain grabs should not highlight the "Build" toolbar button BOOL getHideBuildHighlight() { return mHideBuildHighlight; } - static void pickCallback(S32 x, S32 y, MASK mask); + static void pickCallback(const LLPickInfo& pick_info); private: LLVector3d getGrabPointGlobal(); - void startGrab(S32 x, S32 y); + void startGrab(); void stopGrab(); void startSpin(); @@ -85,6 +87,7 @@ private: void handleHoverSpin(S32 x, S32 y, MASK mask); void handleHoverActive(S32 x, S32 y, MASK mask); + void handleHoverNonPhysical(S32 x, S32 y, MASK mask); void handleHoverInactive(S32 x, S32 y, MASK mask); void handleHoverFailed(S32 x, S32 y, MASK mask); @@ -96,29 +99,26 @@ private: BOOL mVerticalDragging; BOOL mHitLand; - LLUUID mHitObjectID; // if hit something, its ID - LLPointer<LLViewerObject> mGrabObject; // the object currently being grabbed LLTimer mGrabTimer; // send simulator time between hover movements LLVector3 mGrabOffsetFromCenterInitial; // meters from CG of object - LLVector3 mGrabOffset; // how far cursor currently is from grab start point, meters LLVector3d mGrabHiddenOffsetFromCamera; // in cursor hidden drag, how far is grab offset from camera LLVector3d mDragStartPointGlobal; // projected into world LLVector3d mDragStartFromCamera; // drag start relative to camera + LLPickInfo mGrabPick; + S32 mLastMouseX; S32 mLastMouseY; - S32 mMouseDownX; - S32 mMouseDownY; - MASK mMouseMask; S32 mAccumDeltaX; // since cursor hidden, how far have you moved? S32 mAccumDeltaY; BOOL mHasMoved; // has mouse moved off center at all? BOOL mOutsideSlop; // has mouse moved outside center 5 pixels? BOOL mDeselectedThisClick; + BOOL mSpinGrabbing; LLQuaternion mSpinRotation; @@ -131,3 +131,4 @@ extern LLTool* gGrabTransientTool; #endif // LL_TOOLGRAB_H + diff --git a/indra/newview/lltoolindividual.cpp b/indra/newview/lltoolindividual.cpp index 3fa96cd84a..0e0524daa6 100644 --- a/indra/newview/lltoolindividual.cpp +++ b/indra/newview/lltoolindividual.cpp @@ -72,13 +72,13 @@ LLToolIndividual::~LLToolIndividual() BOOL LLToolIndividual::handleMouseDown(S32 x, S32 y, MASK mask) { - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback); return TRUE; } -void LLToolIndividual::pickCallback(S32 x, S32 y, MASK mask) +void LLToolIndividual::pickCallback(const LLPickInfo& pick_info) { - LLViewerObject* obj = gViewerWindow->lastObjectHit(); + LLViewerObject* obj = pick_info.getObject(); LLSelectMgr::getInstance()->deselectAll(); if(obj) { diff --git a/indra/newview/lltoolindividual.h b/indra/newview/lltoolindividual.h index 48a2365363..913e4ff2b8 100644 --- a/indra/newview/lltoolindividual.h +++ b/indra/newview/lltoolindividual.h @@ -34,6 +34,8 @@ #include "lltool.h" +class LLPickInfo; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class lltoolindividual // @@ -52,7 +54,7 @@ public: //virtual void handleDeselect(); //virtual void render(); - static void pickCallback(S32 x, S32 y, MASK mask); + static void pickCallback(const LLPickInfo& pick_info); protected: diff --git a/indra/newview/lltoolobjpicker.cpp b/indra/newview/lltoolobjpicker.cpp index 67e0db962f..ee9c24f269 100644 --- a/indra/newview/lltoolobjpicker.cpp +++ b/indra/newview/lltoolobjpicker.cpp @@ -69,7 +69,7 @@ BOOL LLToolObjPicker::handleMouseDown(S32 x, S32 y, MASK mask) if (! handled) { // didn't click in any UI object, so must have clicked in the world - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback); handled = TRUE; } else @@ -90,16 +90,10 @@ BOOL LLToolObjPicker::handleMouseDown(S32 x, S32 y, MASK mask) return handled; } -void LLToolObjPicker::pickCallback(S32 x, S32 y, MASK mask) +void LLToolObjPicker::pickCallback(const LLPickInfo& pick_info) { - // You must hit the body for this tool to think you hit the object. - LLViewerObject* objectp = NULL; - objectp = gObjectList.findObject( gLastHitObjectID ); - if (objectp) - { - LLToolObjPicker::getInstance()->mHitObjectID = objectp->mID; - LLToolObjPicker::getInstance()->mPicked = TRUE; - } + LLToolObjPicker::getInstance()->mHitObjectID = pick_info.mObjectID; + LLToolObjPicker::getInstance()->mPicked = pick_info.mObjectID.notNull(); } @@ -181,3 +175,4 @@ void LLToolObjPicker::handleDeselect() } + diff --git a/indra/newview/lltoolobjpicker.h b/indra/newview/lltoolobjpicker.h index 794d035a83..8d0c87c8ae 100644 --- a/indra/newview/lltoolobjpicker.h +++ b/indra/newview/lltoolobjpicker.h @@ -36,6 +36,8 @@ #include "v3math.h" #include "lluuid.h" +class LLPickInfo; + class LLToolObjPicker : public LLTool, public LLSingleton<LLToolObjPicker> { public: @@ -54,7 +56,7 @@ public: LLUUID getObjectID() const { return mHitObjectID; } - static void pickCallback(S32 x, S32 y, MASK mask); + static void pickCallback(const LLPickInfo& pick_info); protected: BOOL mPicked; diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index b6bcf9544d..b444cb8ce6 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -84,50 +84,48 @@ LLToolPie::LLToolPie() : LLTool(std::string("Select")), mPieMouseButtonDown( FALSE ), mGrabMouseButtonDown( FALSE ), - mHitLand( FALSE ), - mHitObjectID(), mMouseOutsideSlop( FALSE ) { } BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask) { - gPickFaces = TRUE; //left mouse down always picks transparent - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, leftMouseCallback, - TRUE, TRUE); + gViewerWindow->pickAsync(x, y, mask, leftMouseCallback, TRUE, TRUE); mGrabMouseButtonDown = TRUE; return TRUE; } // static -void LLToolPie::leftMouseCallback(S32 x, S32 y, MASK mask) +void LLToolPie::leftMouseCallback(const LLPickInfo& pick_info) { - LLToolPie::getInstance()->pickAndShowMenu(x, y, mask, FALSE); + LLToolPie::getInstance()->mPick = pick_info; + LLToolPie::getInstance()->pickAndShowMenu(FALSE); } BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask) { - // Pick faces in case they select "Copy Texture" and need that info. - gPickFaces = TRUE; // don't pick transparent so users can't "pay" transparent objects - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, rightMouseCallback, - FALSE, TRUE); + gViewerWindow->pickAsync(x, y, mask, rightMouseCallback, FALSE); mPieMouseButtonDown = TRUE; // don't steal focus from UI return FALSE; } // static -void LLToolPie::rightMouseCallback(S32 x, S32 y, MASK mask) +void LLToolPie::rightMouseCallback(const LLPickInfo& pick_info) { - LLToolPie::getInstance()->pickAndShowMenu(x, y, mask, TRUE); + LLToolPie::getInstance()->mPick = pick_info; + LLToolPie::getInstance()->pickAndShowMenu(TRUE); } // True if you selected an object. -BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show) +BOOL LLToolPie::pickAndShowMenu(BOOL always_show) { - if (!always_show && gLastHitParcelWall) + S32 x = mPick.mMousePt.mX; + S32 y = mPick.mMousePt.mY; + MASK mask = mPick.mKeyMask; + if (!always_show && mPick.mPickType == LLPickInfo::PICK_PARCEL_WALL) { LLParcel* parcel = LLViewerParcelMgr::getInstance()->getCollisionParcel(); if (parcel) @@ -151,25 +149,18 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show) } // didn't click in any UI object, so must have clicked in the world - LLViewerObject *object = gViewerWindow->lastObjectHit(); + LLViewerObject *object = mPick.getObject(); LLViewerObject *parent = NULL; - mHitLand = !object && !gLastHitPosGlobal.isExactlyZero(); - if (!mHitLand) + if (mPick.mPickType != LLPickInfo::PICK_LAND) { LLViewerParcelMgr::getInstance()->deselectLand(); } if (object) { - mHitObjectID = object->mID; - parent = object->getRootEdit(); } - else - { - mHitObjectID.setNull(); - } BOOL touchable = (object && object->flagHandleTouch()) || (parent && parent->flagHandleTouch()); @@ -206,19 +197,19 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show) { // pay event goes to object actually clicked on sClickActionObject = object; - sLeftClickSelection = LLToolSelect::handleObjectSelection(object, MASK_NONE, FALSE, TRUE); + sLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE); return TRUE; } break; case CLICK_ACTION_BUY: sClickActionObject = parent; - sLeftClickSelection = LLToolSelect::handleObjectSelection(parent, MASK_NONE, FALSE, TRUE); + sLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE); return TRUE; case CLICK_ACTION_OPEN: if (parent && parent->allowOpen()) { sClickActionObject = parent; - sLeftClickSelection = LLToolSelect::handleObjectSelection(parent, MASK_NONE, FALSE, TRUE); + sLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE); } return TRUE; case CLICK_ACTION_PLAY: @@ -239,12 +230,13 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show) { gGrabTransientTool = this; LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolGrab::getInstance() ); - return LLToolGrab::getInstance()->handleObjectHit( object, x, y, mask); + return LLToolGrab::getInstance()->handleObjectHit( mPick ); } - if (!object && gLastHitHUDIcon && gLastHitHUDIcon->getSourceObject()) + LLHUDIcon* last_hit_hud_icon = mPick.mHUDIcon; + if (!object && last_hit_hud_icon && last_hit_hud_icon->getSourceObject()) { - LLFloaterScriptDebug::show(gLastHitHUDIcon->getSourceObject()->getID()); + LLFloaterScriptDebug::show(last_hit_hud_icon->getSourceObject()->getID()); } // If left-click never selects or spawns a menu @@ -273,7 +265,7 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show) LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance()); gViewerWindow->hideCursor(); LLToolCamera::getInstance()->setMouseCapture(TRUE); - LLToolCamera::getInstance()->pickCallback(gViewerWindow->getCurrentMouseX(), gViewerWindow->getCurrentMouseY(), mask); + LLToolCamera::getInstance()->pickCallback(mPick); gAgent.setFocusOnAvatar(TRUE, TRUE); return TRUE; @@ -292,22 +284,22 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show) } // Can't ignore children here. - LLToolSelect::handleObjectSelection(object, mask, FALSE, TRUE); + LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE); // Spawn pie menu - if (mHitLand) + if (mPick.mPickType == LLPickInfo::PICK_LAND) { - LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt( gLastHitPosGlobal ); + LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt( mPick.mPosGlobal ); gMenuHolder->setParcelSelection(selection); gPieLand->show(x, y, mPieMouseButtonDown); // VEFFECT: ShowPie LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE); - effectp->setPositionGlobal(gLastHitPosGlobal); + effectp->setPositionGlobal(mPick.mPosGlobal); effectp->setColor(LLColor4U(gAgent.getEffectColor())); effectp->setDuration(0.25f); } - else if (mHitObjectID == gAgent.getID() ) + else if (mPick.mObjectID == gAgent.getID() ) { if(!gPieSelf) { @@ -377,7 +369,7 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show) // Don't show when you click on someone else, it freaks them // out. LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE); - effectp->setPositionGlobal(gLastHitPosGlobal); + effectp->setPositionGlobal(mPick.mPosGlobal); effectp->setColor(LLColor4U(gAgent.getEffectColor())); effectp->setDuration(0.25f); } @@ -544,7 +536,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) LLViewerObject *parent = NULL; if (gHoverView) { - object = gHoverView->getLastHoverObject(); + object = gViewerWindow->getHoverPick().getObject(); } if (object) @@ -581,7 +573,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask) { - LLViewerObject* obj = gViewerWindow->lastObjectHit(); + LLViewerObject* obj = mPick.getObject(); U8 click_action = final_click_action(obj); if (click_action != CLICK_ACTION_NONE) { @@ -626,18 +618,18 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask) if (gSavedSettings.getBOOL("DoubleClickAutoPilot")) { - if (gLastHitLand - && !gLastHitPosGlobal.isExactlyZero()) + if (mPick.mPickType == LLPickInfo::PICK_LAND + && !mPick.mPosGlobal.isExactlyZero()) { handle_go_to(); return TRUE; } - else if (gLastHitObjectID.notNull() - && !gLastHitPosGlobal.isExactlyZero()) + else if (mPick.mObjectID.notNull() + && !mPick.mPosGlobal.isExactlyZero()) { // Hit an object // HACK: Call the last hit position the point we hit on the object - gLastHitPosGlobal += gLastHitObjectOffset; + //gLastHitPosGlobal += gLastHitObjectOffset; handle_go_to(); return TRUE; } @@ -649,7 +641,7 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask) objects gets you into trouble. // If double-click on object or land, go there. - LLViewerObject *object = gViewerWindow->lastObjectHit(); + LLViewerObject *object = gViewerWindow->getLastPick().getObject(); if (object) { if (object->isAvatar()) @@ -756,10 +748,11 @@ static void handle_click_action_open_media(LLPointer<LLViewerObject> objectp) if (objectp.isNull()) return; // did we hit a valid face on the object? - if( gLastHitObjectFace < 0 || gLastHitObjectFace >= objectp->getNumTEs() ) return; + S32 face = LLToolPie::getInstance()->getPick().mObjectFace; + if( face < 0 || face >= objectp->getNumTEs() ) return; // is media playing on this face? - if (!LLViewerMedia::isActiveMediaTexture(objectp->getTE(gLastHitObjectFace)->getID())) + if (!LLViewerMedia::isActiveMediaTexture(objectp->getTE(face)->getID())) { handle_click_action_play(); return; diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h index 4963940840..a8103f23a0 100644 --- a/indra/newview/lltoolpie.h +++ b/indra/newview/lltoolpie.h @@ -34,6 +34,7 @@ #include "lltool.h" #include "lluuid.h" +#include "llviewerwindow.h" // for LLPickInfo class LLViewerObject; class LLObjectSelection; @@ -58,23 +59,25 @@ public: virtual void handleDeselect(); virtual LLTool* getOverrideTool(MASK mask); - static void leftMouseCallback(S32 x, S32 y, MASK mask); - static void rightMouseCallback(S32 x, S32 y, MASK mask); + LLPickInfo& getPick() { return mPick; } + + static void leftMouseCallback(const LLPickInfo& pick_info); + static void rightMouseCallback(const LLPickInfo& pick_info); static void selectionPropertiesReceived(); + protected: BOOL outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y); - BOOL pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL edit_menu); + BOOL pickAndShowMenu(BOOL edit_menu); BOOL useClickAction(BOOL always_show, MASK mask, LLViewerObject* object, LLViewerObject* parent); protected: BOOL mPieMouseButtonDown; BOOL mGrabMouseButtonDown; - BOOL mHitLand; - LLUUID mHitObjectID; BOOL mMouseOutsideSlop; // for this drag, has mouse moved outside slop region + LLPickInfo mPick; static LLPointer<LLViewerObject> sClickActionObject; static U8 sClickAction; static LLSafeHandle<LLObjectSelection> sLeftClickSelection; diff --git a/indra/newview/lltoolpipette.cpp b/indra/newview/lltoolpipette.cpp index a565e4361b..9456cd4472 100644 --- a/indra/newview/lltoolpipette.cpp +++ b/indra/newview/lltoolpipette.cpp @@ -67,9 +67,8 @@ BOOL LLToolPipette::handleMouseDown(S32 x, S32 y, MASK mask) { mSuccess = TRUE; mTooltipMsg.clear(); - gPickFaces = TRUE; setMouseCapture(TRUE); - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback); return TRUE; } @@ -88,8 +87,7 @@ BOOL LLToolPipette::handleHover(S32 x, S32 y, MASK mask) gViewerWindow->setCursor(mSuccess ? UI_CURSOR_PIPETTE : UI_CURSOR_NO); if (hasMouseCapture()) // mouse button is down { - gPickFaces = TRUE; - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback); + gViewerWindow->pickAsync(x, y, mask, pickCallback); return TRUE; } return FALSE; @@ -107,19 +105,19 @@ BOOL LLToolPipette::handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky return TRUE; } -void LLToolPipette::pickCallback(S32 x, S32 y, MASK mask) +void LLToolPipette::pickCallback(const LLPickInfo& pick_info) { - LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); + LLViewerObject* hit_obj = pick_info.getObject(); LLSelectMgr::getInstance()->unhighlightAll(); // if we clicked on a face of a valid prim, save off texture entry data if (hit_obj && hit_obj->getPCode() == LL_PCODE_VOLUME && - gLastHitObjectFace != -1) + pick_info.mObjectFace != -1) { //TODO: this should highlight the selected face only LLSelectMgr::getInstance()->highlightObjectOnly(hit_obj); - LLToolPipette::getInstance()->mTextureEntry = *hit_obj->getTE(gLastHitObjectFace); + LLToolPipette::getInstance()->mTextureEntry = *hit_obj->getTE(pick_info.mObjectFace); if (LLToolPipette::getInstance()->mSelectCallback) { LLToolPipette::getInstance()->mSelectCallback(LLToolPipette::getInstance()->mTextureEntry, LLToolPipette::getInstance()->mUserData); diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h index b88a6eebc8..5d5b27f964 100644 --- a/indra/newview/lltoolpipette.h +++ b/indra/newview/lltoolpipette.h @@ -41,6 +41,7 @@ #include "lltextureentry.h" class LLViewerObject; +class LLPickInfo; class LLToolPipette : public LLTool, public LLSingleton<LLToolPipette> @@ -58,7 +59,7 @@ public: void setSelectCallback(select_callback callback, void* user_data); void setResult(BOOL success, const std::string& msg); - static void pickCallback(S32 x, S32 y, MASK mask); + static void pickCallback(const LLPickInfo& pick_info); protected: LLTextureEntry mTextureEntry; diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp index 7d4d0397cc..8806d1465a 100644 --- a/indra/newview/lltoolplacer.cpp +++ b/indra/newview/lltoolplacer.cpp @@ -81,14 +81,22 @@ BOOL LLToolPlacer::raycastForNewObjPos( S32 x, S32 y, LLViewerObject** hit_obj, // Viewer-side pick to find the right sim to create the object on. // First find the surface the object will be created on. - gViewerWindow->hitObjectOrLandGlobalImmediate(x, y, NULL, FALSE); + LLPickInfo pick = gViewerWindow->pickImmediate(x, y, FALSE); // Note: use the frontmost non-flora version because (a) plants usually have lots of alpha and (b) pants' Havok // representations (if any) are NOT the same as their viewer representation. - *hit_obj = gObjectList.findObject( gLastHitNonFloraObjectID ); - *hit_face = gLastHitNonFloraObjectFace; - *b_hit_land = !(*hit_obj) && !gLastHitNonFloraPosGlobal.isExactlyZero(); - LLVector3d land_pos_global = gLastHitNonFloraPosGlobal; + if (pick.mPickType == LLPickInfo::PICK_FLORA) + { + *hit_obj = NULL; + *hit_face = -1; + } + else + { + *hit_obj = pick.getObject(); + *hit_face = pick.mObjectFace; + } + *b_hit_land = !(*hit_obj) && !pick.mPosGlobal.isExactlyZero(); + LLVector3d land_pos_global = pick.mPosGlobal; // Make sure there's a surface to place the new object on. BOOL bypass_sim_raycast = FALSE; diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp index 8f84013a26..e74cd58924 100644 --- a/indra/newview/lltoolselect.cpp +++ b/indra/newview/lltoolselect.cpp @@ -64,39 +64,24 @@ LLToolSelect::LLToolSelect( LLToolComposite* composite ) // True if you selected an object. BOOL LLToolSelect::handleMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - - // didn't click in any UI object, so must have clicked in the world - LLViewerObject* object = NULL; - - // You must hit the body for this tool to think you hit the object. - object = gObjectList.findObject( gLastHitObjectID ); - - if (object) - { - mSelectObjectID = object->getID(); - handled = TRUE; - } - else - { - mSelectObjectID.setNull(); - } + // do immediate pick query + mPick = gViewerWindow->pickImmediate(x, y, TRUE); // Pass mousedown to agent LLTool::handleMouseDown(x, y, mask); - return handled; + return mPick.getObject().notNull(); } -BOOL LLToolSelect::handleDoubleClick(S32 x, S32 y, MASK mask) -{ - //RN: double click to toggle individual/linked picking??? - return LLTool::handleDoubleClick(x, y, mask); -} // static -LLSafeHandle<LLObjectSelection> LLToolSelect::handleObjectSelection(LLViewerObject *object, MASK mask, BOOL ignore_group, BOOL temp_select) +LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pick, BOOL ignore_group, BOOL temp_select, BOOL select_root) { + LLViewerObject* object = pick.getObject(); + if (select_root) + { + object = object->getRootEdit(); + } BOOL select_owned = gSavedSettings.getBOOL("SelectOwnedOnly"); BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly"); @@ -108,14 +93,16 @@ LLSafeHandle<LLObjectSelection> LLToolSelect::handleObjectSelection(LLViewerObje LLSelectMgr::getInstance()->setForceSelection(TRUE); } - BOOL extend_select = (mask == MASK_SHIFT) || (mask == MASK_CONTROL); + BOOL extend_select = (pick.mKeyMask == MASK_SHIFT) || (pick.mKeyMask == MASK_CONTROL); // If no object, check for icon, then just deselect if (!object) { - if (gLastHitHUDIcon && gLastHitHUDIcon->getSourceObject()) + LLHUDIcon* last_hit_hud_icon = pick.mHUDIcon; + + if (last_hit_hud_icon && last_hit_hud_icon->getSourceObject()) { - LLFloaterScriptDebug::show(gLastHitHUDIcon->getSourceObject()->getID()); + LLFloaterScriptDebug::show(last_hit_hud_icon->getSourceObject()->getID()); } else if (!extend_select) { @@ -240,8 +227,7 @@ BOOL LLToolSelect::handleMouseUp(S32 x, S32 y, MASK mask) { mIgnoreGroup = gSavedSettings.getBOOL("EditLinkedParts"); - LLViewerObject* object = gObjectList.findObject(mSelectObjectID); - LLToolSelect::handleObjectSelection(object, mask, mIgnoreGroup, FALSE); + handleObjectSelection(mPick, mIgnoreGroup, FALSE); return LLTool::handleMouseUp(x, y, mask); } @@ -275,3 +261,4 @@ void LLToolSelect::onMouseCaptureLost() + diff --git a/indra/newview/lltoolselect.h b/indra/newview/lltoolselect.h index c3d10424b1..f6359863a8 100644 --- a/indra/newview/lltoolselect.h +++ b/indra/newview/lltoolselect.h @@ -35,6 +35,7 @@ #include "lltool.h" #include "v3math.h" #include "lluuid.h" +#include "llviewerwindow.h" // for LLPickInfo class LLObjectSelection; @@ -45,11 +46,10 @@ public: virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); virtual void stopEditing(); - static LLSafeHandle<LLObjectSelection> handleObjectSelection(LLViewerObject *object, MASK mask, BOOL ignore_group, BOOL temp_select); + static LLSafeHandle<LLObjectSelection> handleObjectSelection(const LLPickInfo& pick, BOOL ignore_group, BOOL temp_select, BOOL select_root = FALSE); virtual void onMouseCaptureLost(); virtual void handleDeselect(); @@ -57,6 +57,7 @@ public: protected: BOOL mIgnoreGroup; LLUUID mSelectObjectID; + LLPickInfo mPick; }; diff --git a/indra/newview/lltoolselectrect.cpp b/indra/newview/lltoolselectrect.cpp index 67d9e2da65..0d403bbb28 100644 --- a/indra/newview/lltoolselectrect.cpp +++ b/indra/newview/lltoolselectrect.cpp @@ -78,18 +78,26 @@ void dialog_refresh_all(void); BOOL LLToolSelectRect::handleMouseDown(S32 x, S32 y, MASK mask) { + handlePick(gViewerWindow->pickImmediate(x, y, TRUE)); + + LLTool::handleMouseDown(x, y, mask); + + return mPick.getObject().notNull(); +} + +void LLToolSelectRect::handlePick(const LLPickInfo& pick) +{ + mPick = pick; + // start dragging rectangle setMouseCapture( TRUE ); - mDragStartX = x; - mDragStartY = y; - mDragEndX = x; - mDragEndY = y; + mDragStartX = pick.mMousePt.mX; + mDragStartY = pick.mMousePt.mY; + mDragEndX = pick.mMousePt.mX; + mDragEndY = pick.mMousePt.mY; mMouseOutsideSlop = FALSE; - - LLToolSelect::handleMouseDown(x, y, mask); - return TRUE; } diff --git a/indra/newview/lltoolselectrect.h b/indra/newview/lltoolselectrect.h index d45f0a433c..63b8d26e24 100644 --- a/indra/newview/lltoolselectrect.h +++ b/indra/newview/lltoolselectrect.h @@ -46,6 +46,8 @@ public: virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual void draw(); // draw the select rectangle + void handlePick(const LLPickInfo& pick); + protected: void handleRectangleSelection(S32 x, S32 y, MASK mask); // true if you selected one BOOL outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index b2cf873a21..0e83ba1123 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -798,7 +798,12 @@ void render_hud_attachments() glh::matrix4f current_proj = glh_get_current_projection(); glh::matrix4f current_mod = glh_get_current_modelview(); - if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices(FALSE)) + // clamp target zoom level to reasonable values + gAgent.mHUDTargetZoom = llclamp(gAgent.mHUDTargetZoom, 0.1f, 1.f); + // smoothly interpolate current zoom level + gAgent.mHUDCurZoom = lerp(gAgent.mHUDCurZoom, gAgent.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f)); + + if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices()) { LLCamera hud_cam = *LLViewerCamera::getInstance(); LLVector3 origin = hud_cam.getOrigin(); @@ -856,52 +861,53 @@ void render_hud_attachments() glh_set_current_modelview(current_mod); } -BOOL setup_hud_matrices(BOOL for_select) +BOOL setup_hud_matrices() +{ + LLRect whole_screen = gViewerWindow->getVirtualWindowRect(); + + // apply camera zoom transform (for high res screenshots) + F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); + S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); + if (zoom_factor > 1.f) + { + S32 num_horizontal_tiles = llceil(zoom_factor); + S32 tile_width = llround((F32)gViewerWindow->getWindowWidth() / zoom_factor); + S32 tile_height = llround((F32)gViewerWindow->getWindowHeight() / zoom_factor); + int tile_y = sub_region / num_horizontal_tiles; + int tile_x = sub_region - (tile_y * num_horizontal_tiles); + glh::matrix4f mat; + + whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWindowHeight() - (tile_y * tile_height), tile_width, tile_height); + } + + return setup_hud_matrices(whole_screen); +} + +BOOL setup_hud_matrices(const LLRect& screen_region) { LLVOAvatar* my_avatarp = gAgent.getAvatarObject(); if (my_avatarp && my_avatarp->hasHUDAttachment()) { - if (!for_select) - { - // clamp target zoom level to reasonable values - my_avatarp->mHUDTargetZoom = llclamp(my_avatarp->mHUDTargetZoom, 0.1f, 1.f); - // smoothly interpolate current zoom level - my_avatarp->mHUDCurZoom = lerp(my_avatarp->mHUDCurZoom, my_avatarp->mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f)); - } - - F32 zoom_level = my_avatarp->mHUDCurZoom; - // clear z buffer and set up transform for hud - if (!for_select) - { - //glClear(GL_DEPTH_BUFFER_BIT); - } + F32 zoom_level = gAgent.mHUDCurZoom; LLBBox hud_bbox = my_avatarp->getHUDBBox(); - - // set up transform to encompass bounding box of HUD + // set up transform to keep HUD objects in front of camera glMatrixMode(GL_PROJECTION); F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); - if (for_select) - { - //RN: reset viewport to window extents so ortho screen is calculated with proper reference frame - gViewerWindow->setupViewport(); - } glh::matrix4f proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth); proj.element(2,2) = -0.01f; - // apply camera zoom transform (for high res screenshots) - F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); - S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); - if (zoom_factor > 1.f) - { - float offset = zoom_factor - 1.f; - int pos_y = sub_region / llceil(zoom_factor); - int pos_x = sub_region - (pos_y*llceil(zoom_factor)); - glh::matrix4f mat; - mat.set_scale(glh::vec3f(zoom_factor, zoom_factor, 1.f)); - mat.set_translate(glh::vec3f(LLViewerCamera::getInstance()->getAspect() * 0.5f * (offset - (F32)pos_x * 2.f), 0.5f * (offset - (F32)pos_y * 2.f), 0.f)); - proj *= mat; - } + F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect(); + + glh::matrix4f mat; + F32 scale_x = (F32)gViewerWindow->getWindowWidth() / (F32)screen_region.getWidth(); + F32 scale_y = (F32)gViewerWindow->getWindowHeight() / (F32)screen_region.getHeight(); + mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f)); + mat.set_translate( + glh::vec3f(clamp_rescale((F32)screen_region.getCenterX(), 0.f, (F32)gViewerWindow->getWindowWidth(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio), + clamp_rescale((F32)screen_region.getCenterY(), 0.f, (F32)gViewerWindow->getWindowHeight(), 0.5f * scale_y, -0.5f * scale_y), + 0.f)); + proj *= mat; glLoadMatrixf(proj.m); glh_set_current_projection(proj); @@ -909,9 +915,8 @@ BOOL setup_hud_matrices(BOOL for_select) glMatrixMode(GL_MODELVIEW); glh::matrix4f model((GLfloat*) OGL_TO_CFR_ROTATION); - glh::matrix4f mat; - mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f)); mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level)); + mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f)); model *= mat; glLoadMatrixf(model.m); @@ -1127,14 +1132,14 @@ void render_ui_2d() gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); // render outline for HUD - if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->mHUDCurZoom < 0.98f) + if (gAgent.getAvatarObject() && gAgent.mHUDCurZoom < 0.98f) { glPushMatrix(); S32 half_width = (gViewerWindow->getWindowWidth() / 2); S32 half_height = (gViewerWindow->getWindowHeight() / 2); glScalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f); glTranslatef((F32)half_width, (F32)half_height, 0.f); - F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom; + F32 zoom = gAgent.mHUDCurZoom; glScalef(zoom,zoom,1.f); gGL.color4fv(LLColor4::white.mV); gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 1586f8dc75..3f57b26fec 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -694,5 +694,3 @@ void LLViewerMedia::setMimeType(std::string mime_type) { sViewerMediaImpl.mMimeType = mime_type; } - - diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 347ddac797..a095c9e159 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1359,6 +1359,9 @@ void init_debug_rendering_menu(LLMenuGL* menu) sub_menu->append(new LLMenuItemCheckGL("Glow",&LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_GLOW)); + sub_menu->append(new LLMenuItemCheckGL("Raycasting", &LLPipeline::toggleRenderDebug, NULL, + &LLPipeline::toggleRenderDebugControl, + (void*)LLPipeline::RENDER_DEBUG_RAYCAST)); sub_menu->append(new LLMenuItemCheckGL("Show Depth Buffer", &menu_toggle_control, @@ -1628,7 +1631,11 @@ class LLObjectReportAbuse : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLFloaterReporter::showFromObject(gLastHitObjectID); + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + if (objectp) + { + LLFloaterReporter::showFromObject(objectp->getID()); + } return true; } }; @@ -1638,7 +1645,7 @@ class LLObjectEnableReportAbuse : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - bool new_value = !gLastHitObjectID.isNull(); + bool new_value = LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 0; gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } @@ -1648,7 +1655,7 @@ class LLObjectTouch : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLViewerObject* object = gObjectList.findObject(gLastHitObjectID); + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); if (!object) return true; LLMessageSystem *msg = gMessageSystem; @@ -1683,7 +1690,7 @@ class LLObjectEnableTouch : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLViewerObject* obj = gObjectList.findObject(gLastHitObjectID); + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); bool new_value = obj && obj->flagHandleTouch(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -1717,7 +1724,7 @@ void label_touch(std::string& label, void*) bool handle_object_open() { - LLViewerObject* obj = gObjectList.findObject(gLastHitObjectID); + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); if(!obj) return true; LLFloaterOpenObject::show(); @@ -1738,7 +1745,7 @@ class LLObjectEnableOpen : public view_listener_t { // Look for contents in root object, which is all the LLFloaterOpenObject // understands. - LLViewerObject* obj = gObjectList.findObject(gLastHitObjectID); + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); bool new_value = (obj != NULL); if (new_value) { @@ -1838,14 +1845,14 @@ class LLObjectBuild : public view_listener_t { // zoom in if we're looking at the avatar gAgent.setFocusOnAvatar(FALSE, ANIMATE); - gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID); + gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick()); gAgent.cameraZoomIn(0.666f); gAgent.cameraOrbitOver( 30.f * DEG_TO_RAD ); gViewerWindow->moveCursorToCenter(); } else if ( gSavedSettings.getBOOL("EditCameraMovement") ) { - gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID); + gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick()); gViewerWindow->moveCursorToCenter(); } @@ -1878,13 +1885,17 @@ class LLObjectEdit : public view_listener_t else { gAgent.setFocusOnAvatar(FALSE, ANIMATE); + LLViewerObject* selected_objectp = selection->getFirstRootObject(); + if (selected_objectp) + { // zoom in on object center instead of where we clicked, as we need to see the manipulator handles - gAgent.setFocusGlobal(gLastHitPosGlobal /*+ gLastHitObjectOffset*/, gLastHitObjectID); + gAgent.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID()); gAgent.cameraZoomIn(0.666f); gAgent.cameraOrbitOver( 30.f * DEG_TO_RAD ); gViewerWindow->moveCursorToCenter(); } } + } gFloaterTools->open(); /* Flawfinder: ignore */ @@ -1923,7 +1934,7 @@ class LLLandBuild : public view_listener_t { // zoom in if we're looking at the avatar gAgent.setFocusOnAvatar(FALSE, ANIMATE); - gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID); + gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick()); gAgent.cameraZoomIn(0.666f); gAgent.cameraOrbitOver( 30.f * DEG_TO_RAD ); gViewerWindow->moveCursorToCenter(); @@ -1931,7 +1942,7 @@ class LLLandBuild : public view_listener_t else if ( gSavedSettings.getBOOL("EditCameraMovement") ) { // otherwise just move focus - gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID); + gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick()); gViewerWindow->moveCursorToCenter(); } @@ -2049,15 +2060,19 @@ BOOL enable_has_attachments(void*) //--------------------------------------------------------------------------- void handle_follow(void *userdata) { - // follow a given avatar, ID in gLastHitObjectID - gAgent.startFollowPilot(gLastHitObjectID); + // follow a given avatar by ID + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + if (objectp) + { + gAgent.startFollowPilot(objectp->getID()); + } } class LLObjectEnableMute : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLViewerObject* object = gViewerWindow->lastObjectHit(); + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); bool new_value = (object != NULL); if (new_value) { @@ -2080,7 +2095,7 @@ class LLObjectMute : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLViewerObject* object = gViewerWindow->lastObjectHit(); + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); if (!object) return true; LLUUID id; @@ -2136,11 +2151,12 @@ bool handle_go_to() // JAMESDEBUG try simulator autopilot std::vector<std::string> strings; std::string val; - val = llformat("%g", gLastHitPosGlobal.mdV[VX]); + LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal; + val = llformat("%g", pos.mdV[VX]); strings.push_back(val); - val = llformat("%g", gLastHitPosGlobal.mdV[VY]); + val = llformat("%g", pos.mdV[VY]); strings.push_back(val); - val = llformat("%g", gLastHitPosGlobal.mdV[VZ]); + val = llformat("%g", pos.mdV[VZ]); strings.push_back(val); send_generic_message("autopilot", strings); @@ -2209,7 +2225,7 @@ class LLAvatarFreeze : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() ); + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getFirstObject() ); if( avatar ) { LLUUID* avatar_id = new LLUUID( avatar->getID() ); @@ -2259,7 +2275,7 @@ class LLAvatarDebug : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() ); + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getFirstObject() ); if( avatar ) { avatar->dumpLocalTextures(); @@ -2311,7 +2327,7 @@ class LLAvatarEject : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() ); + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getFirstObject() ); if( avatar ) { LLUUID* avatar_id = new LLUUID( avatar->getID() ); @@ -2341,7 +2357,7 @@ class LLAvatarEnableFreezeEject : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() ); + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getFirstObject() ); bool new_value = (avatar != NULL); if (new_value) @@ -2366,7 +2382,7 @@ class LLAvatarGiveCard : public view_listener_t bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { llinfos << "handle_give_card()" << llendl; - LLViewerObject* dest = gViewerWindow->lastObjectHit(); + LLViewerObject* dest = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); if(dest && dest->isAvatar()) { bool found_name = false; @@ -2605,9 +2621,9 @@ void handle_dump_region_object_cache(void*) void handle_dump_focus(void *) { - LLView *view = gFocusMgr.getKeyboardFocus(); - std::string name = view ? view->getName() : "(none)"; - llinfos << "Keyboard focus " << name << llendl; + LLUICtrl *ctrl = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); + + llinfos << "Keyboard focus " << (ctrl ? ctrl->getName() : "(none)") << llendl; } class LLSelfStandUp : public view_listener_t @@ -2823,7 +2839,7 @@ class LLAvatarEnableAddFriend : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLVOAvatar* avatar = find_avatar_from_object(gViewerWindow->lastObjectHit()); + LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getFirstObject()); bool new_value = avatar && !is_agent_friend(avatar->getID()); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; @@ -2870,10 +2886,12 @@ class LLEditEnableCustomizeAvatar : public view_listener_t } }; +// only works on pie menu bool handle_sit_or_stand() { - LLViewerObject *object = gObjectList.findObject(gLastHitNonFloraObjectID); - if (!object) + LLPickInfo pick = LLToolPie::getInstance()->getPick(); + LLViewerObject *object = pick.getObject();; + if (!object || pick.mPickType == LLPickInfo::PICK_FLORA) { return true; } @@ -2888,17 +2906,13 @@ bool handle_sit_or_stand() if (object && object->getPCode() == LL_PCODE_VOLUME) { - LLVector3d offset_double = gViewerWindow->lastNonFloraObjectHitOffset(); - LLVector3 offset_single; - offset_single.setVec(offset_double); - gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit); gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); gMessageSystem->nextBlockFast(_PREHASH_TargetObject); gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID); - gMessageSystem->addVector3Fast(_PREHASH_Offset, offset_single); + gMessageSystem->addVector3Fast(_PREHASH_Offset, pick.mObjectOffset); object->getRegion()->sendReliableMessage(); } @@ -2932,7 +2946,7 @@ class LLLandSit : public view_listener_t gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); LLViewerParcelMgr::getInstance()->deselectLand(); - LLVector3d posGlobal = gLastHitPosGlobal; + LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal; LLQuaternion target_rot; if (gAgent.getAvatarObject()) @@ -5028,7 +5042,7 @@ class LLAvatarInviteToGroup : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() ); + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getFirstObject() ); if(avatar) { invite_to_group(avatar->getID()); @@ -5041,7 +5055,7 @@ class LLAvatarAddFriend : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() ); + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getFirstObject() ); if(avatar && !is_agent_friend(avatar->getID())) { request_friendship(avatar->getID()); @@ -5114,11 +5128,11 @@ class LLEnablePayObject : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLVOAvatar* avatar = find_avatar_from_object(gViewerWindow->lastObjectHit()); + LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getFirstObject()); bool new_value = (avatar != NULL); if (!new_value) { - LLViewerObject* object = gViewerWindow->lastObjectHit(); + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); if( object ) { LLViewerObject *parent = (LLViewerObject *)object->getParent(); @@ -5138,8 +5152,9 @@ class LLObjectEnableSitOrStand : public view_listener_t bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { bool new_value = false; - LLViewerObject* dest_object = NULL; - if((dest_object = gObjectList.findObject(gLastHitObjectID))) + LLViewerObject* dest_object = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + + if(dest_object) { if(dest_object->getPCode() == LL_PCODE_VOLUME) { @@ -5502,7 +5517,11 @@ class LLShowAgentProfile : public view_listener_t } else if (userdata.asString() == "hit object") { - agent_id = gLastHitObjectID; + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + if (objectp) + { + agent_id = objectp->getID(); + } } else { @@ -5538,12 +5557,12 @@ void handle_focus(void *) { // zoom in if we're looking at the avatar gAgent.setFocusOnAvatar(FALSE, ANIMATE); - gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID); + gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick()); gAgent.cameraZoomIn(0.666f); } else { - gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID); + gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick()); } gViewerWindow->moveCursorToCenter(); @@ -5561,19 +5580,19 @@ class LLLandEdit : public view_listener_t { // zoom in if we're looking at the avatar gAgent.setFocusOnAvatar(FALSE, ANIMATE); - gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID); + gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick()); gAgent.cameraOrbitOver( F_PI * 0.25f ); gViewerWindow->moveCursorToCenter(); } else if ( gSavedSettings.getBOOL("EditCameraMovement") ) { - gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID); + gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick()); gViewerWindow->moveCursorToCenter(); } - LLViewerParcelMgr::getInstance()->selectParcelAt( gLastHitPosGlobal ); + LLViewerParcelMgr::getInstance()->selectParcelAt( LLToolPie::getInstance()->getPick().mPosGlobal ); gFloaterTools->showMore(TRUE); gFloaterView->bringToFront( gFloaterTools ); @@ -5611,13 +5630,13 @@ void handle_move(void*) { // zoom in if we're looking at the avatar gAgent.setFocusOnAvatar(FALSE, ANIMATE); - gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID); + gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick()); gAgent.cameraZoomIn(0.666f); } else { - gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID); + gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick()); } gViewerWindow->moveCursorToCenter(); @@ -5719,7 +5738,7 @@ class LLAttachmentDrop : public view_listener_t { // Called when the user clicked on an object attached to them // and selected "Drop". - LLViewerObject *object = gViewerWindow->lastObjectHit(); + LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); if (!object) { llwarns << "handle_drop_attachment() - no object to drop" << llendl; @@ -5819,7 +5838,7 @@ class LLAttachmentDetach : public view_listener_t { // Called when the user clicked on an object attached to them // and selected "Detach". - LLViewerObject *object = gViewerWindow->lastObjectHit(); + LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); if (!object) { llwarns << "handle_detach() - no object to detach" << llendl; @@ -5899,7 +5918,7 @@ class LLAttachmentEnableDrop : public view_listener_t // in your inventory. Therefore, we disable the drop option until the // item is in your inventory - LLViewerObject* object = gViewerWindow->lastObjectHit(); + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); LLViewerJointAttachment* attachment_pt = NULL; LLInventoryItem* item = NULL; @@ -5941,7 +5960,7 @@ class LLAttachmentEnableDrop : public view_listener_t BOOL enable_detach(void*) { - LLViewerObject* object = gViewerWindow->lastObjectHit(); + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); if (!object) return FALSE; if (!object->isAttachment()) return FALSE; @@ -6045,7 +6064,7 @@ class LLAvatarSendIM : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() ); + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getFirstObject() ); if(avatar) { std::string name("IM"); @@ -6821,7 +6840,11 @@ void handle_dump_avatar_local_textures(void*) void handle_debug_avatar_textures(void*) { - LLFloaterAvatarTextures::show(gLastHitObjectID); + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + if (objectp) + { + LLFloaterAvatarTextures::show(objectp->getID()); + } } void handle_grab_texture(void* data) diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 19025b34a4..1aa7d2c3ff 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -3039,7 +3039,7 @@ void LLViewerObject::updatePositionCaches() const const LLVector3d LLViewerObject::getPositionGlobal() const { - LLVector3d position_global = mRegionp->getPosGlobalFromRegion(getPositionRegion());; + LLVector3d position_global = mRegionp->getPosGlobalFromRegion(getPositionRegion()); if (isAttachment()) { @@ -3365,6 +3365,19 @@ LLViewerObject* LLViewerObject::getRootEdit() const return (LLViewerObject*)root; } + +BOOL LLViewerObject::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, + S32 face, + S32* face_hit, + LLVector3* intersection, + LLVector2* tex_coord, + LLVector3* normal, + LLVector3* bi_normal) +{ + return false; +} + + U8 LLViewerObject::getMediaType() const { if (mMedia) @@ -4836,11 +4849,6 @@ BOOL LLViewerObject::setFlags(U32 flags, BOOL state) return setit; } -BOOL LLViewerObject::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const -{ - return FALSE; -} - void LLViewerObject::applyAngularVelocity(F32 dt) { //do target omega here diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 0f0fa62ea1..a143589ee9 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -242,9 +242,15 @@ public: //detect if given line segment (in agent space) intersects with this viewer object. - //returns TRUE if intersection detected and moves end to the point of intersection - //closest to start. - virtual BOOL lineSegmentIntersect(const LLVector3& start, LLVector3& end) const; + //returns TRUE if intersection detected and returns information about intersection + virtual BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, + S32 face = -1, // which face to check, -1 = ALL_SIDES + S32* face_hit = NULL, // which face was hit + LLVector3* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector3* normal = NULL, // return the surface normal at the intersection point + LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point + ); virtual const LLVector3d getPositionGlobal() const; virtual const LLVector3 &getPositionRegion() const; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 8cd295b8a8..a37120451e 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1078,14 +1078,14 @@ void LLViewerObjectList::renderObjectBounds(const LLVector3 ¢er) { } - -U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parcel_wall, BOOL keep_pick_list) +void LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, const LLRect& screen_rect, BOOL pick_parcel_wall, BOOL render_transparent) { - gRenderForSelect = TRUE; + generatePickList(camera); + renderPickList(screen_rect, pick_parcel_wall, render_transparent); +} - // LLTimer pick_timer; - if (!keep_pick_list) - { +void LLViewerObjectList::generatePickList(LLCamera &camera) +{ LLViewerObject *objectp; S32 i; // Reset all of the GL names to zero. @@ -1199,11 +1199,14 @@ U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parce } LLHUDIcon::generatePickIDs(i * step, step); - - // At this point, we should only have live drawables/viewer objects - gPipeline.renderForSelect(mSelectPickList); - } } +} + +void LLViewerObjectList::renderPickList(const LLRect& screen_rect, BOOL pick_parcel_wall, BOOL render_transparent) +{ + gRenderForSelect = TRUE; + + gPipeline.renderForSelect(mSelectPickList, render_transparent, screen_rect); // // Render pass for selected objects @@ -1220,7 +1223,6 @@ U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parce //llinfos << "Rendered " << count << " for select" << llendl; //llinfos << "Took " << pick_timer.getElapsedTimeF32()*1000.f << "ms to pick" << llendl; - return 0; } LLViewerObject *LLViewerObjectList::getSelectedObject(const U32 object_id) @@ -1526,3 +1528,4 @@ bool LLViewerObjectList::OrphanInfo::operator!=(const OrphanInfo &rhs) const return !operator==(rhs); } + diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index b9b6ff243f..a5285930b2 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -108,7 +108,10 @@ public: void updateAvatarVisibility(); // Selection related stuff - U32 renderObjectsForSelect(LLCamera &camera, BOOL pick_parcel_wall = FALSE, BOOL keep_pick_list = FALSE); + void renderObjectsForSelect(LLCamera &camera, const LLRect& screen_rect, BOOL pick_parcel_wall = FALSE, BOOL render_transparent = TRUE); + void generatePickList(LLCamera &camera); + void renderPickList(const LLRect& screen_rect, BOOL pick_parcel_wall, BOOL render_transparent); + LLViewerObject *getSelectedObject(const U32 object_id); inline S32 getNumObjects() { return mObjects.count(); } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 0296aee8ca..4c575ff139 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -203,32 +203,8 @@ extern S32 gJamesInt; LLViewerWindow *gViewerWindow = NULL; LLVelocityBar *gVelocityBar = NULL; -LLVector3d gLastHitPosGlobal; -LLVector3d gLastHitObjectOffset; -LLUUID gLastHitObjectID; -S32 gLastHitObjectFace = -1; -BOOL gLastHitLand = FALSE; -F32 gLastHitUCoord; -F32 gLastHitVCoord; - - -LLVector3d gLastHitNonFloraPosGlobal; -LLVector3d gLastHitNonFloraObjectOffset; -LLUUID gLastHitNonFloraObjectID; -S32 gLastHitNonFloraObjectFace = -1; -BOOL gLastHitParcelWall = FALSE; - -S32 gLastHitUIElement = 0; -LLHUDIcon* gLastHitHUDIcon = NULL; BOOL gDebugSelect = FALSE; -U8 gLastPickAlpha = 255; -BOOL gUseGLPick = FALSE; - -// On the next pick pass (whenever that happens) -// should we try to pick individual faces? -// Cleared to FALSE every time a pick happens. -BOOL gPickFaces = FALSE; LLFrameTimer gMouseIdleTimer; LLFrameTimer gAwayTimer; @@ -239,6 +215,11 @@ BOOL gShowOverlayTitle = FALSE; BOOL gPickTransparent = TRUE; BOOL gDebugFastUIRender = FALSE; +LLViewerObject* gDebugRaycastObject = NULL; +LLVector3 gDebugRaycastIntersection; +LLVector2 gDebugRaycastTexCoord; +LLVector3 gDebugRaycastNormal; +LLVector3 gDebugRaycastBinormal; // HUD display lines in lower right BOOL gDisplayWindInfo = FALSE; @@ -256,9 +237,6 @@ const F32 MIN_AFK_TIME = 2.f; // minimum time after setting away state before co const F32 MAX_FAST_FRAME_TIME = 0.5f; const F32 FAST_FRAME_INCREMENT = 0.1f; -const S32 PICK_HALF_WIDTH = 5; -const S32 PICK_DIAMETER = 2 * PICK_HALF_WIDTH+1; - const F32 MIN_DISPLAY_SCALE = 0.85f; const S32 CONSOLE_BOTTOM_PAD = 40; @@ -1509,8 +1487,8 @@ LLViewerWindow::LLViewerWindow( mToolStored( NULL ), mSuppressToolbox( FALSE ), mHideCursorPermanent( FALSE ), - mPickPending(FALSE), - mIgnoreActivate( FALSE ) + mIgnoreActivate( FALSE ), + mHoverPick() { // Default to application directory. LLViewerWindow::sSnapshotBaseName = "Snapshot"; @@ -1618,8 +1596,6 @@ LLViewerWindow::LLViewerWindow( mCurrentMousePoint.mX = getWindowWidth() / 2; mCurrentMousePoint.mY = getWindowHeight() / 2; - mPickBuffer = new U8[PICK_DIAMETER * PICK_DIAMETER * 4]; - gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle"); mOverlayTitle = gSavedSettings.getString("OverlayTitle"); // Can't have spaces in settings.ini strings, so use underscores instead and convert them. @@ -2032,9 +2008,6 @@ LLViewerWindow::~LLViewerWindow() LLViewerImage::cleanupClass(); - delete[] mPickBuffer; - mPickBuffer = NULL; - llinfos << "Cleaning up select manager" << llendl; LLSelectMgr::getInstance()->cleanup(); @@ -2733,6 +2706,10 @@ BOOL LLViewerWindow::handlePerFrameHover() LLView::sMouseHandlerMessage.clear(); + S32 x = mCurrentMousePoint.mX; + S32 y = mCurrentMousePoint.mY; + MASK mask = gKeyboard->currentMask(TRUE); + //RN: fix for asynchronous notification of mouse leaving window not working LLCoordWindow mouse_pos; mWindow->getCursorPosition(&mouse_pos); @@ -2748,6 +2725,7 @@ BOOL LLViewerWindow::handlePerFrameHover() mMouseInWindow = TRUE; } + S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]); S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]); @@ -2778,10 +2756,6 @@ BOOL LLViewerWindow::handlePerFrameHover() return TRUE; } - S32 x = mCurrentMousePoint.mX; - S32 y = mCurrentMousePoint.mY; - MASK mask = gKeyboard->currentMask(TRUE); - // clean up current focus LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus(); if (cur_focus) @@ -3123,10 +3097,41 @@ BOOL LLViewerWindow::handlePerFrameHover() LLSelectMgr::getInstance()->deselectUnused(); } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) + { + gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, + NULL, + &gDebugRaycastIntersection, + &gDebugRaycastTexCoord, + &gDebugRaycastNormal, + &gDebugRaycastBinormal); + } + + static U16 frame_counter = 0; + static S32 previous_x = -1; + static S32 previous_y = -1; + + if (((previous_x != x) || (previous_y != y)) || + ((gSavedSettings.getBOOL("PerFrameHoverPick")) + && ((frame_counter % gSavedSettings.getS32("PerFrameHoverPickCount")) == 0))) + { + pickAsync(getCurrentMouseX(), getCurrentMouseY(), mask, hoverPickCallback, TRUE); + } + frame_counter++; + previous_x = x; + previous_y = y; + return handled; } +/* static */ +void LLViewerWindow::hoverPickCallback(const LLPickInfo& pick_info) +{ + gViewerWindow->mHoverPick = pick_info; +} + + void LLViewerWindow::saveLastMouse(const LLCoordGL &point) { // Store last mouse location. @@ -3220,7 +3225,7 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, glPushMatrix(); if (selection->getSelectType() == SELECT_TYPE_HUD) { - F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom; + F32 zoom = gAgent.mHUDCurZoom; glScalef(zoom, zoom, zoom); } @@ -3372,19 +3377,14 @@ BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewe return intersect; } -void LLViewerWindow::hitObjectOrLandGlobalAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(S32 x, S32 y, MASK mask), BOOL pick_transparent, BOOL pick_parcel_walls) +void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent, BOOL get_surface_info) { if (gNoRender) { return; } - glClear(GL_DEPTH_BUFFER_BIT); - gDepthDirty = TRUE; - - S32 scaled_x = llround((F32)x * mDisplayScale.mV[VX]); - S32 scaled_y = llround((F32)y_from_bot * mDisplayScale.mV[VY]); - + // push back pick info object BOOL in_build_mode = gFloaterTools && gFloaterTools->getVisible(); if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha) { @@ -3392,29 +3392,44 @@ void LLViewerWindow::hitObjectOrLandGlobalAsync(S32 x, S32 y_from_bot, MASK mask // "Show Debug Alpha" means no object actually transparent pick_transparent = TRUE; } - gPickTransparent = pick_transparent; - gUseGLPick = FALSE; - mPickCallback = callback; + // center initial pick frame buffer region under mouse cursor + // since that area is guaranteed to be onscreen and hence a valid + // part of the framebuffer + if (mPicks.empty()) + { + mPickScreenRegion.setCenterAndSize(x, y_from_bot, PICK_DIAMETER, PICK_DIAMETER); - // Default to not hitting anything - gLastHitPosGlobal.zeroVec(); - gLastHitObjectOffset.zeroVec(); - gLastHitObjectID.setNull(); - gLastHitObjectFace = -1; + if (mPickScreenRegion.mLeft < 0) mPickScreenRegion.translate(-mPickScreenRegion.mLeft, 0); + if (mPickScreenRegion.mBottom < 0) mPickScreenRegion.translate(0, -mPickScreenRegion.mBottom); + if (mPickScreenRegion.mRight > mWindowRect.getWidth() ) mPickScreenRegion.translate(mWindowRect.getWidth() - mPickScreenRegion.mRight, 0); + if (mPickScreenRegion.mTop > mWindowRect.getHeight() ) mPickScreenRegion.translate(0, mWindowRect.getHeight() - mPickScreenRegion.mTop); + } - gLastHitNonFloraPosGlobal.zeroVec(); - gLastHitNonFloraObjectOffset.zeroVec(); - gLastHitNonFloraObjectID.setNull(); - gLastHitNonFloraObjectFace = -1; + // set frame buffer region for picking results + // stack multiple picks left to right + LLRect screen_region = mPickScreenRegion; + screen_region.translate(mPicks.size() * PICK_DIAMETER, 0); - gLastHitParcelWall = FALSE; + LLPickInfo pick(LLCoordGL(x, y_from_bot), screen_region, mask, pick_transparent, get_surface_info, callback); + schedulePick(pick); +} + +void LLViewerWindow::schedulePick(LLPickInfo& pick_info) +{ + llassert_always(pick_info.mScreenRegion.notNull()); + mPicks.push_back(pick_info); + + S32 scaled_x = llround((F32)pick_info.mMousePt.mX * mDisplayScale.mV[VX]); + S32 scaled_y = llround((F32)pick_info.mMousePt.mY * mDisplayScale.mV[VY]); + + // Default to not hitting anything LLCamera pick_camera; pick_camera.setOrigin(LLViewerCamera::getInstance()->getOrigin()); pick_camera.setOriginAndLookAt(LLViewerCamera::getInstance()->getOrigin(), LLViewerCamera::getInstance()->getUpAxis(), - LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(x, y_from_bot)); + LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(pick_info.mMousePt.mX, pick_info.mMousePt.mY)); pick_camera.setView(0.5f*DEG_TO_RAD); pick_camera.setNear(LLViewerCamera::getInstance()->getNear()); pick_camera.setFar(LLViewerCamera::getInstance()->getFar()); @@ -3431,117 +3446,38 @@ void LLViewerWindow::hitObjectOrLandGlobalAsync(S32 x, S32 y_from_bot, MASK mask glPushMatrix(); glLoadIdentity(); - // build perspective transform and picking viewport - // Perform pick on a PICK_DIAMETER x PICK_DIAMETER pixel region around cursor point. - // Don't limit the select distance for this pick. - LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - (PICK_HALF_WIDTH + 2), scaled_y - (PICK_HALF_WIDTH + 2), PICK_DIAMETER + 4, PICK_DIAMETER + 4, FALSE); - // make viewport big enough to handle antialiased frame buffers - gGLViewport[0] = scaled_x - (PICK_HALF_WIDTH + 2); - gGLViewport[1] = scaled_y - (PICK_HALF_WIDTH + 2); - gGLViewport[2] = PICK_DIAMETER + 4; - gGLViewport[3] = PICK_DIAMETER + 4; - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - LLViewerCamera::updateFrustumPlanes(pick_camera); - stop_glerror(); - + // clear work area + { + LLGLState scissor_state(GL_SCISSOR_TEST); + scissor_state.enable(); + glScissor(pick_info.mScreenRegion.mLeft, pick_info.mScreenRegion.mBottom, pick_info.mScreenRegion.getWidth(), pick_info.mScreenRegion.getHeight()); glClearColor(0.f, 0.f, 0.f, 0.f); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); //glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - // Draw the objects so the user can select them. - // The starting ID is 1, since land is zero. - gObjectList.renderObjectsForSelect(pick_camera, pick_parcel_walls); - - stop_glerror(); - - // restore drawing state - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - setupViewport(); - - mPickPoint.set(x, y_from_bot); - mPickOffset.set(0, 0); - mPickMask = mask; - mPickPending = TRUE; - - // delay further event processing until we receive results of pick - mWindow->delayInputProcessing(); -} - -void LLViewerWindow::hitUIElementImmediate(S32 x, S32 y, void (*callback)(S32 x, S32 y, MASK mask)) -{ - // Performs the GL UI pick. - // Stores its results in global, gLastHitUIElement - if (gNoRender) - { - return; - } - - hitUIElementAsync(x, y, gKeyboard->currentMask(TRUE), NULL); - performPick(); - if (callback) - { - callback(x, y, gKeyboard->currentMask(TRUE)); - } -} - -//RN: this currently doesn't do anything -void LLViewerWindow::hitUIElementAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(S32 x, S32 y, MASK mask)) -{ - if (gNoRender) - { - return; } - -// F32 delta_time = gAlphaFadeTimer.getElapsedTimeAndResetF32(); - - gUseGLPick = FALSE; - mPickCallback = callback; - - // Default to not hitting anything - gLastHitUIElement = 0; - - LLCamera pick_camera; - pick_camera.setOrigin(LLViewerCamera::getInstance()->getOrigin()); - pick_camera.setOriginAndLookAt(LLViewerCamera::getInstance()->getOrigin(), - LLViewerCamera::getInstance()->getUpAxis(), - LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(x, y_from_bot)); - pick_camera.setView(0.5f*DEG_TO_RAD); - pick_camera.setNear(LLViewerCamera::getInstance()->getNear()); - pick_camera.setFar(LLViewerCamera::getInstance()->getFar()); - pick_camera.setAspect(1.f); - - // save our drawing state - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - - // build orthogonal transform and picking viewport + // build perspective transform and picking viewport // Perform pick on a PICK_DIAMETER x PICK_DIAMETER pixel region around cursor point. // Don't limit the select distance for this pick. - setup2DRender(); - const LLVector2& display_scale = getDisplayScale(); - glScalef(display_scale.mV[VX], display_scale.mV[VY], 1.f); + LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - PICK_HALF_WIDTH, scaled_y - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER, FALSE); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + // render for object picking // make viewport big enough to handle antialiased frame buffers - glViewport(x - (PICK_HALF_WIDTH + 2), y_from_bot - (PICK_HALF_WIDTH + 2), PICK_DIAMETER + 4, PICK_DIAMETER + 4); - stop_glerror(); + gGLViewport[0] = pick_info.mScreenRegion.mLeft; + gGLViewport[1] = pick_info.mScreenRegion.mBottom; + gGLViewport[2] = pick_info.mScreenRegion.getWidth(); + gGLViewport[3] = pick_info.mScreenRegion.getHeight(); - glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); + LLViewerCamera::updateFrustumPlanes(pick_camera); + stop_glerror(); // Draw the objects so the user can select them. // The starting ID is 1, since land is zero. - //drawForSelect(); + LLRect pick_region; + pick_region.setOriginAndSize(scaled_x - PICK_HALF_WIDTH, scaled_y - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER); + gObjectList.renderObjectsForSelect(pick_camera, pick_region, FALSE, pick_info.mPickTransparent); stop_glerror(); @@ -3551,309 +3487,121 @@ void LLViewerWindow::hitUIElementAsync(S32 x, S32 y_from_bot, MASK mask, void (* glMatrixMode(GL_MODELVIEW); glPopMatrix(); + setup3DRender(); + setup2DRender(); setupViewport(); - mPickPoint.set(x, y_from_bot); - mPickOffset.set(0, 0); - mPickMask = mask; - mPickPending = TRUE; + // delay further event processing until we receive results of pick + mWindow->delayInputProcessing(); } + void LLViewerWindow::performPick() { - if (gNoRender || !mPickPending) + if (gNoRender) { return; } - mPickPending = FALSE; - U32 te_offset = NO_FACE; - - // find pick region that is fully onscreen - LLCoordGL scaled_pick_point = mPickPoint; - scaled_pick_point.mX = llclamp(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX]), PICK_HALF_WIDTH, getWindowDisplayWidth() - PICK_HALF_WIDTH); - scaled_pick_point.mY = llclamp(llround((F32)mPickPoint.mY * mDisplayScale.mV[VY]), PICK_HALF_WIDTH, getWindowDisplayHeight() - PICK_HALF_WIDTH); - - glReadPixels(scaled_pick_point.mX - PICK_HALF_WIDTH, scaled_pick_point.mY - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer); - - S32 pixel_index = PICK_HALF_WIDTH * PICK_DIAMETER + PICK_HALF_WIDTH; - S32 name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2]; - gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3]; - - if (name >= (S32)GL_NAME_UI_RESERVED && name < (S32)GL_NAME_INDEX_OFFSET) - { - // hit a UI element - gLastHitUIElement = name; - if (mPickCallback) - { - mPickCallback(mPickPoint.mX, mPickPoint.mY, mPickMask); - } - } - - //imdebug("rgba rbga=bbba b=8 w=%d h=%d %p", PICK_DIAMETER, PICK_DIAMETER, mPickBuffer); - - S32 x_offset = mPickPoint.mX - llround((F32)scaled_pick_point.mX / mDisplayScale.mV[VX]); - S32 y_offset = mPickPoint.mY - llround((F32)scaled_pick_point.mY / mDisplayScale.mV[VY]); - - - // we hit nothing, scan surrounding pixels for something useful - if (!name) + if (!mPicks.empty()) { - S32 closest_distance = 10000; - //S32 closest_pick_name = 0; - for (S32 col = 0; col < PICK_DIAMETER; col++) + std::vector<LLPickInfo>::iterator pick_it; + for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it) { - for (S32 row = 0; row < PICK_DIAMETER; row++) - { - S32 distance_squared = (llabs(col - x_offset - PICK_HALF_WIDTH) * llabs(col - x_offset - PICK_HALF_WIDTH)) + (llabs(row - y_offset - PICK_HALF_WIDTH) * llabs(row - y_offset - PICK_HALF_WIDTH)); - pixel_index = row * PICK_DIAMETER + col; - S32 test_name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2]; - gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3]; - if (test_name && distance_squared < closest_distance) - { - closest_distance = distance_squared; - name = test_name; - gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3]; - mPickOffset.mX = col - PICK_HALF_WIDTH; - mPickOffset.mY = row - PICK_HALF_WIDTH; - } - } + pick_it->fetchResults(); } - } - if (name) - { - mPickPoint.mX += llround((F32)mPickOffset.mX * mDisplayScale.mV[VX]); - mPickPoint.mY += llround((F32)mPickOffset.mY * mDisplayScale.mV[VY]); - } - - if (gPickFaces) - { - te_offset = ((U32)name >> 20); - name &= 0x000fffff; - // don't clear gPickFaces, as we still need to check for UV coordinates + mLastPick = mPicks.back(); + mPicks.clear(); } - LLViewerObject *objectp = NULL; - - // Frontmost non-foreground object that isn't trees or grass - LLViewerObject* nonflora_objectp = NULL; - S32 nonflora_name = -1; - S32 nonflora_te_offset = NO_FACE; - - if (name == (S32)GL_NAME_PARCEL_WALL) - { - gLastHitParcelWall = TRUE; - } - - gLastHitHUDIcon = NULL; - - objectp = gObjectList.getSelectedObject(name); - if (objectp) - { - LLViewerObject* parent = (LLViewerObject*)(objectp->getParent()); - if (NULL == parent) { - // if you are the parent - parent = objectp; - } - if (objectp->mbCanSelect) - { - te_offset = (te_offset == 16) ? NO_FACE : te_offset; - - // If the hit object isn't a plant, store it as the frontmost non-flora object. - LLPCode pcode = objectp->getPCode(); - if( (LL_PCODE_LEGACY_GRASS != pcode) && - (LL_PCODE_LEGACY_TREE != pcode) && - (LL_PCODE_TREE_NEW != pcode)) - { - nonflora_objectp = objectp; - nonflora_name = name; - nonflora_te_offset = te_offset; - } - } - else - { - //llinfos << "Hit object you can't select" << llendl; - } - } - else - { - // was this name referring to a hud icon? - gLastHitHUDIcon = LLHUDIcon::handlePick(name); - } - - analyzeHit( - mPickPoint.mX, mPickPoint.mY, objectp, te_offset, - &gLastHitObjectID, &gLastHitObjectFace, &gLastHitPosGlobal, &gLastHitLand, &gLastHitUCoord, &gLastHitVCoord ); - - if (objectp && !gLastHitObjectID.isNull()) - { - gLastHitObjectOffset = gAgent.calcFocusOffset(objectp, mPickPoint.mX, mPickPoint.mY); - } +} - if( objectp == nonflora_objectp ) - { - gLastHitNonFloraObjectID = gLastHitObjectID; - gLastHitNonFloraObjectFace = gLastHitObjectFace; - gLastHitNonFloraPosGlobal = gLastHitPosGlobal; - gLastHitNonFloraObjectOffset= gLastHitObjectOffset; - } - else +// Performs the GL object/land pick. +LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent) +{ + if (gNoRender) { - analyzeHit( mPickPoint.mX, mPickPoint.mY, nonflora_objectp, nonflora_te_offset, - &gLastHitNonFloraObjectID, &gLastHitNonFloraObjectFace, &gLastHitNonFloraPosGlobal, - &gLastHitLand, &gLastHitUCoord, &gLastHitVCoord); - - if( nonflora_objectp ) - { - gLastHitNonFloraObjectOffset = gAgent.calcFocusOffset(nonflora_objectp, mPickPoint.mX, mPickPoint.mY); - } + return LLPickInfo(); } - if (mPickCallback) - { - mPickCallback(mPickPoint.mX, mPickPoint.mY, mPickMask); - } + pickAsync(x, y_from_bot, gKeyboard->currentMask(TRUE), NULL, pick_transparent); + // assume that pickAsync put the results in the back of the mPicks list + mLastPick = mPicks.back(); + mLastPick.fetchResults(); + mPicks.pop_back(); - gPickFaces = FALSE; + return mLastPick; } -// Performs the GL object/land pick. -// Stores its results in globals, gHit* -void LLViewerWindow::hitObjectOrLandGlobalImmediate(S32 x, S32 y_from_bot, void (*callback)(S32 x, S32 y, MASK mask), BOOL pick_transparent) +LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 depth, + LLViewerObject *this_object, + S32 this_face, + S32* face_hit, + LLVector3 *intersection, + LLVector2 *uv, + LLVector3 *normal, + LLVector3 *binormal) { - if (gNoRender) - { - return; - } - - hitObjectOrLandGlobalAsync(x, y_from_bot, gKeyboard->currentMask(TRUE), NULL, pick_transparent); - performPick(); - if (callback) + S32 x = mouse_x; + S32 y = mouse_y; + + if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position { - callback(x, y_from_bot, gKeyboard->currentMask(TRUE)); + x = getCurrentMouseX(); + y = getCurrentMouseY(); } -} -LLViewerObject* LLViewerWindow::getObjectUnderCursor(const F32 depth) -{ - S32 x = getCurrentMouseX(); - S32 y = getCurrentMouseY(); + // HUD coordinates of mouse + LLVector3 mouse_point_hud = mousePointHUD(x, y); + LLVector3 mouse_hud_start = mouse_point_hud - LLVector3(depth, 0, 0); + LLVector3 mouse_hud_end = mouse_point_hud + LLVector3(depth, 0, 0); + // world coordinates of mouse LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y); - LLVector3 camera_pos_global = LLViewerCamera::getInstance()->getOrigin(); - LLVector3 pick_end = camera_pos_global + mouse_direction_global * depth; - LLVector3 collision_point; - return gPipeline.pickObject(camera_pos_global, pick_end, collision_point); -} - -void LLViewerWindow::analyzeHit( - S32 x, // input - S32 y_from_bot, // input - LLViewerObject* objectp, // input - U32 te_offset, // input - LLUUID* hit_object_id_p,// output - S32* hit_face_p, // output - LLVector3d* hit_pos_p, // output - BOOL* hit_land, // output - F32* hit_u_coord, // output - F32* hit_v_coord) // output -{ - // Clean up inputs - S32 face = -1; - - if (te_offset != NO_FACE ) - { - face = te_offset; - } + LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin(); + LLVector3 mouse_world_start = mouse_point_global; + LLVector3 mouse_world_end = mouse_point_global + mouse_direction_global * depth; - *hit_land = FALSE; + + LLViewerObject* found = NULL; - if (objectp) + if (this_object) // check only this object { - if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH ) + if (this_object->isHUDAttachment()) // is a HUD object? { - // Hit land - *hit_land = TRUE; - - // put global position into land_pos - LLVector3d land_pos; - if (mousePointOnLandGlobal(x, y_from_bot, &land_pos)) + if (this_object->lineSegmentIntersect(mouse_hud_start, mouse_hud_end, this_face, + face_hit, intersection, uv, normal, binormal)) { - *hit_object_id_p = LLUUID::null; - *hit_face_p = -1; - - // Fudge the land focus a little bit above ground. - *hit_pos_p = land_pos + LLVector3d(0.f, 0.f, 0.1f); - //llinfos << "DEBUG Hit Land " << *hit_pos_p << llendl; - return; + found = this_object; } - else - { - //llinfos << "Hit land but couldn't find position" << llendl; - // Fall through to "Didn't hit anything" } - } - else + + else // is a world object { - *hit_object_id_p = objectp->mID; - *hit_face_p = face; - - // Hit an object - if (objectp->isAvatar()) + if (this_object->lineSegmentIntersect(mouse_world_start, mouse_world_end, this_face, + face_hit, intersection, uv, normal, binormal)) { - *hit_pos_p = gAgent.getPosGlobalFromAgent(((LLVOAvatar*)objectp)->mPelvisp->getWorldPosition()); + found = this_object; } - else if (objectp->mDrawable.notNull()) - { - *hit_pos_p = gAgent.getPosGlobalFromAgent(objectp->getRenderPosition()); } - else - { - // regular object - *hit_pos_p = objectp->getPositionGlobal(); } - if (gPickFaces && face > -1 && - objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME && - face < objectp->mDrawable->getNumFaces()) + else // check ALL objects { - // render red-blue gradient to get 1/256 precision - // then render green grid to get final 1/4096 precision - S32 scaled_x = llround((F32)x * mDisplayScale.mV[VX]); - S32 scaled_y = llround((F32)y_from_bot * mDisplayScale.mV[VY]); - const S32 UV_PICK_WIDTH = 41; - const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2; - U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4]; - S32 pick_face = face; - LLFace* facep = objectp->mDrawable->getFace(pick_face); - LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE); - glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH); - gPipeline.renderFaceForUVSelect(facep); - - glReadPixels(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, GL_RGBA, GL_UNSIGNED_BYTE, uv_pick_buffer); - U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)]; - *hit_u_coord = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f; - *hit_v_coord = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f; - } - else + found = gPipeline.lineSegmentIntersectInHUD(mouse_hud_start, mouse_hud_end, + face_hit, intersection, uv, normal, binormal); + + if (!found) // if not found in HUD, look in world: + { - *hit_u_coord = 0.f; - *hit_v_coord = 0.f; + found = gPipeline.lineSegmentIntersectInWorld(mouse_world_start, mouse_world_end, + face_hit, intersection, uv, normal, binormal); } - //llinfos << "DEBUG Hit Object " << *hit_pos_p << llendl; - return; - } } - // Didn't hit anything. - *hit_object_id_p = LLUUID::null; - *hit_face_p = -1; - *hit_pos_p = LLVector3d::zero; - *hit_u_coord = 0.f; - *hit_v_coord = 0.f; - //llinfos << "DEBUG Hit Nothing " << llendl; + return found; } // Returns unit vector relative to camera @@ -3884,6 +3632,18 @@ LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const return mouse_vector; } +LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const +{ + // find screen resolution + S32 height = getWindowHeight(); + S32 width = getWindowWidth(); + + // remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5 + F32 hud_x = -((F32)x - (F32)width/2.f) / height; + F32 hud_y = ((F32)y - (F32)height/2.f) / height; + + return LLVector3(0.f, hud_x, hud_y); +} // Returns unit vector relative to camera in camera space // indicating direction of point on screen x,y @@ -4249,8 +4009,7 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p LLHUDText::setDisplayText(FALSE) ; if (type == SNAPSHOT_TYPE_OBJECT_ID) { - gPickTransparent = FALSE; - gObjectList.renderObjectsForSelect(*LLViewerCamera::getInstance(), FALSE, FALSE); + gObjectList.renderPickList(gViewerWindow->getVirtualWindowRect(), FALSE, FALSE); } else { @@ -4452,6 +4211,8 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear()); F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear()); + gObjectList.generatePickList(*LLViewerCamera::getInstance()); + for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y) { S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);; @@ -4472,9 +4233,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei LLViewerCamera::getInstance()->setZoomParameters(scale_factor, subimage_x+(subimage_y*llceil(scale_factor))); setup3DRender(); setupViewport(); - BOOL first_time_through = (subimage_x + subimage_y == 0); - gPickTransparent = FALSE; - gObjectList.renderObjectsForSelect(*LLViewerCamera::getInstance(), FALSE, !first_time_through); + gObjectList.renderPickList(gViewerWindow->getVirtualWindowRect(), FALSE, FALSE); } else { @@ -4723,27 +4482,6 @@ void LLViewerWindow::setup2DRender() gl_state_for_2d(mWindowRect.getWidth(), mWindowRect.getHeight()); } -// Could cache the pointer from the last hitObjectOrLand here. -LLViewerObject *LLViewerWindow::lastObjectHit() -{ - return gObjectList.findObject( gLastHitObjectID ); -} - -const LLVector3d& LLViewerWindow::lastObjectHitOffset() -{ - return gLastHitObjectOffset; -} - -// Could cache the pointer from the last hitObjectOrLand here. -LLViewerObject *LLViewerWindow::lastNonFloraObjectHit() -{ - return gObjectList.findObject( gLastHitNonFloraObjectID ); -} - -const LLVector3d& LLViewerWindow::lastNonFloraObjectHitOffset() -{ - return gLastHitNonFloraObjectOffset; -} void LLViewerWindow::setShowProgress(const BOOL show) @@ -5166,46 +4904,7 @@ F32 LLViewerWindow::getDisplayAspectRatio() const void LLViewerWindow::drawPickBuffer() const { - if (mPickBuffer) - { - gGL.color4f(1,1,1,1); - gGL.pushMatrix(); - LLGLDisable no_blend(GL_BLEND); - LLGLDisable no_alpha_test(GL_ALPHA_TEST); - LLGLSNoTexture no_texture; - glPixelZoom(10.f, 10.f); - glRasterPos2f(((F32)mPickPoint.mX * mDisplayScale.mV[VX] + 10.f), - ((F32)mPickPoint.mY * mDisplayScale.mV[VY] + 10.f)); - glDrawPixels(PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer); - glPixelZoom(1.f, 1.f); - gGL.color4fv(LLColor4::white.mV); - gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] - (F32)(PICK_HALF_WIDTH)), - llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH)), - llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH)), - llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] - (F32)(PICK_HALF_WIDTH)), - FALSE); - gl_line_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] - (F32)(PICK_HALF_WIDTH)), - llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH)), - llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + 10.f), - llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f + 10.f)); - gl_line_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH)), - llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] - (F32)(PICK_HALF_WIDTH)), - llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f + 10.f), - llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + 10.f)); - gGL.translatef(10.f, 10.f, 0.f); - gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX]), - llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f), - llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f), - llround((F32)mPickPoint.mY * mDisplayScale.mV[VY]), - FALSE); - gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH + mPickOffset.mX)* 10.f), - llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH + mPickOffset.mY + 1) * 10.f), - llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH + mPickOffset.mX + 1) * 10.f), - llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH + mPickOffset.mY) * 10.f), - FALSE); - gGL.popMatrix(); - gGL.flush(); - } + mHoverPick.drawPickBuffer(); } void LLViewerWindow::calcDisplayScale() @@ -5394,3 +5093,342 @@ void* LLBottomPanel::createToolBar(void* data) gToolBar = new LLToolBar(); return gToolBar; } + +// +// LLPickInfo +// +LLPickInfo::LLPickInfo() + : mKeyMask(MASK_NONE), + mPickCallback(NULL), + mPickType(PICK_INVALID), + mWantSurfaceInfo(FALSE), + mObjectFace(-1), + mUVCoords(-1.f, -1.f), + mSTCoords(-1.f, -1.f), + mXYCoords(-1, -1), + mIntersection(), + mNormal(), + mBinormal(), + mHUDIcon(NULL), + mPickTransparent(FALSE) +{ +} + +LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, + const LLRect& screen_region, + MASK keyboard_mask, + BOOL pick_transparent, + BOOL pick_uv_coords, + void (*pick_callback)(const LLPickInfo& pick_info)) + : mMousePt(mouse_pos), + mScreenRegion(screen_region), + mKeyMask(keyboard_mask), + mPickCallback(pick_callback), + mPickType(PICK_INVALID), + mWantSurfaceInfo(pick_uv_coords), + mObjectFace(-1), + mUVCoords(-1.f, -1.f), + mSTCoords(-1.f, -1.f), + mXYCoords(-1, -1), + mNormal(), + mBinormal(), + mHUDIcon(NULL), + mPickTransparent(pick_transparent) +{ +} + +LLPickInfo::~LLPickInfo() +{ +} + +void LLPickInfo::fetchResults() +{ + // read back colors and depth values from buffer + glReadPixels(mScreenRegion.mLeft, mScreenRegion.mBottom, mScreenRegion.getWidth(), mScreenRegion.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer); + glReadPixels(mScreenRegion.mLeft, mScreenRegion.mBottom, mScreenRegion.getWidth(), mScreenRegion.getHeight(), GL_DEPTH_COMPONENT, GL_FLOAT, mPickDepthBuffer ); + + // find pick region that is fully onscreen + LLCoordGL scaled_pick_point;; + scaled_pick_point.mX = llclamp(llround((F32)mMousePt.mX * gViewerWindow->getDisplayScale().mV[VX]), PICK_HALF_WIDTH, gViewerWindow->getWindowDisplayWidth() - PICK_HALF_WIDTH); + scaled_pick_point.mY = llclamp(llround((F32)mMousePt.mY * gViewerWindow->getDisplayScale().mV[VY]), PICK_HALF_WIDTH, gViewerWindow->getWindowDisplayHeight() - PICK_HALF_WIDTH); + S32 pixel_index = PICK_HALF_WIDTH * PICK_DIAMETER + PICK_HALF_WIDTH; + S32 pick_id = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2]; + F32 depth = mPickDepthBuffer[pixel_index]; + + S32 x_offset = mMousePt.mX - llround((F32)scaled_pick_point.mX / gViewerWindow->getDisplayScale().mV[VX]); + S32 y_offset = mMousePt.mY - llround((F32)scaled_pick_point.mY / gViewerWindow->getDisplayScale().mV[VY]); + + mPickPt = mMousePt; + + // we hit nothing, scan surrounding pixels for something useful + if (!pick_id) + { + S32 closest_distance = 10000; + //S32 closest_pick_name = 0; + for (S32 col = 0; col < PICK_DIAMETER; col++) + { + for (S32 row = 0; row < PICK_DIAMETER; row++) + { + S32 distance_squared = (llabs(col - x_offset - PICK_HALF_WIDTH) * llabs(col - x_offset - PICK_HALF_WIDTH)) + (llabs(row - y_offset - PICK_HALF_WIDTH) * llabs(row - y_offset - PICK_HALF_WIDTH)); + pixel_index = row * PICK_DIAMETER + col; + S32 test_name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2]; + if (test_name && distance_squared < closest_distance) + { + closest_distance = distance_squared; + pick_id = test_name; + depth = mPickDepthBuffer[pixel_index]; + mPickPt.mX = mMousePt.mX + (col - PICK_HALF_WIDTH); + mPickPt.mY = mMousePt.mY + (row - PICK_HALF_WIDTH); + } + } + } + } + + U32 te_offset = ((U32)pick_id >> 20); + pick_id &= 0x000fffff; + + //unproject relative clicked coordinate from window coordinate using GL + GLint viewport[4]; + GLdouble modelview[16]; + GLdouble projection[16]; + GLfloat winX, winY; + GLdouble posX, posY, posZ; + + LLViewerObject* objectp = gObjectList.getSelectedObject(pick_id); + + if (pick_id == (S32)GL_NAME_PARCEL_WALL) + { + mPickType = PICK_PARCEL_WALL; + } + else if (objectp) + { + if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH ) + { + // Hit land + mPickType = PICK_LAND; + mObjectID.setNull(); // land has no id + + // put global position into land_pos + LLVector3d land_pos; + if (gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos)) + { + // Fudge the land focus a little bit above ground. + mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f; + } + } + else + { + if(isFlora(objectp)) + { + mPickType = PICK_FLORA; + } + else + { + mPickType = PICK_OBJECT; + } + mObjectOffset = gAgent.calcFocusOffset(objectp, mPickPt.mX, mPickPt.mY); + mObjectID = objectp->mID; + mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset; + + glh::matrix4f newModel((F32*)LLViewerCamera::getInstance()->getModelview().mMatrix); + + for(U32 i = 0; i < 16; ++i) + { + modelview[i] = newModel.m[i]; + projection[i] = LLViewerCamera::getInstance()->getProjection().mMatrix[i/4][i%4]; + } + glGetIntegerv( GL_VIEWPORT, viewport ); + + winX = ((F32)mPickPt.mX) * gViewerWindow->getDisplayScale().mV[VX]; + winY = ((F32)mPickPt.mY) * gViewerWindow->getDisplayScale().mV[VY]; + + gluUnProject( winX, winY, depth, modelview, projection, viewport, &posX, &posY, &posZ); + + mPosGlobal = gAgent.getPosGlobalFromAgent(LLVector3(posX, posY, posZ)); + + if (mWantSurfaceInfo) + { + getSurfaceInfo(); + } + } + } + else + { + // was this name referring to a hud icon? + mHUDIcon = LLHUDIcon::handlePick(pick_id); + if (mHUDIcon) + { + mPickType = PICK_ICON; + mPosGlobal = mHUDIcon->getPositionGlobal(); + } + } + + if (mPickCallback) + { + mPickCallback(*this); + } +} + +LLPointer<LLViewerObject> LLPickInfo::getObject() const +{ + return gObjectList.findObject( mObjectID ); +} + +void LLPickInfo::updateXYCoords() +{ + const LLTextureEntry* tep = getObject()->getTE(mObjectFace); + LLPointer<LLViewerImage> imagep = gImageList.getImage(tep->getID()); + if(mUVCoords.mV[VX] >= 0.f && mUVCoords.mV[VY] >= 0.f && imagep.notNull()) + { + LLCoordGL coords; + + coords.mX = llround(mUVCoords.mV[VX] * (F32)imagep->getWidth()); + coords.mY = llround(mUVCoords.mV[VY] * (F32)imagep->getHeight()); + + gViewerWindow->getWindow()->convertCoords(coords, &mXYCoords); + } +} + +void LLPickInfo::drawPickBuffer() const +{ + if (mPickBuffer) + { + gGL.pushMatrix(); + LLGLDisable no_blend(GL_BLEND); + LLGLDisable no_alpha_test(GL_ALPHA_TEST); + LLGLSNoTexture no_texture; + glPixelZoom(10.f, 10.f); + LLVector2 display_scale = gViewerWindow->getDisplayScale(); + glRasterPos2f(((F32)mMousePt.mX * display_scale.mV[VX] + 10.f), + ((F32)mMousePt.mY * display_scale.mV[VY] + 10.f)); + glDrawPixels(PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer); + glPixelZoom(1.f, 1.f); + gGL.color4fv(LLColor4::white.mV); + gl_rect_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] - (F32)(PICK_HALF_WIDTH)), + llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_HALF_WIDTH)), + llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_HALF_WIDTH)), + llround((F32)mMousePt.mY * display_scale.mV[VY] - (F32)(PICK_HALF_WIDTH)), + FALSE); + gl_line_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] - (F32)(PICK_HALF_WIDTH)), + llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_HALF_WIDTH)), + llround((F32)mMousePt.mX * display_scale.mV[VX] + 10.f), + llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f + 10.f)); + gl_line_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_HALF_WIDTH)), + llround((F32)mMousePt.mY * display_scale.mV[VY] - (F32)(PICK_HALF_WIDTH)), + llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f + 10.f), + llround((F32)mMousePt.mY * display_scale.mV[VY] + 10.f)); + gGL.translatef(10.f, 10.f, 0.f); + gl_rect_2d(llround((F32)mPickPt.mX * display_scale.mV[VX]), + llround((F32)mPickPt.mY * display_scale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f), + llround((F32)mPickPt.mX * display_scale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f), + llround((F32)mPickPt.mY * display_scale.mV[VY]), + FALSE); + gl_rect_2d(llround((F32)mPickPt.mX * display_scale.mV[VX]), + llround((F32)mPickPt.mY * display_scale.mV[VY] + 10.f), + llround((F32)mPickPt.mX * display_scale.mV[VX] + 10.f), + llround((F32)mPickPt.mY * display_scale.mV[VY]), + FALSE); + gGL.popMatrix(); + } +} + +void LLPickInfo::getSurfaceInfo() +{ + // set values to uninitialized - this is what we return if no intersection is found + mObjectFace = -1; + mUVCoords = LLVector2(-1, -1); + mSTCoords = LLVector2(-1, -1); + mXYCoords = LLCoordScreen(-1, -1); + mIntersection = LLVector3(0,0,0); + mNormal = LLVector3(0,0,0); + mBinormal = LLVector3(0,0,0); + + LLViewerObject* objectp = getObject(); + + if (objectp) + { + if (gViewerWindow->cursorIntersect(llround((F32)mMousePt.mX), llround((F32)mMousePt.mY), 1024.f, + objectp, -1, + &mObjectFace, + &mIntersection, + &mSTCoords, + &mNormal, + &mBinormal)) + { + // if we succeeded with the intersect above, compute the texture coordinates: + + if (objectp->mDrawable.notNull()) + { + LLFace* facep = objectp->mDrawable->getFace(mObjectFace); + + mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal); + } + + // and XY coords: + updateXYCoords(); + + } + } +} + + +/* code to get UV via a special UV render - removed in lieu of raycast method +LLVector2 LLPickInfo::pickUV() +{ + LLVector2 result(-1.f, -1.f); + + LLViewerObject* objectp = getObject(); + if (!objectp) + { + return result; + } + + if (mObjectFace > -1 && + objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME && + mObjectFace < objectp->mDrawable->getNumFaces()) + { + S32 scaled_x = llround((F32)mPickPt.mX * gViewerWindow->getDisplayScale().mV[VX]); + S32 scaled_y = llround((F32)mPickPt.mY * gViewerWindow->getDisplayScale().mV[VY]); + const S32 UV_PICK_WIDTH = 5; + const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2; + U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4]; + LLFace* facep = objectp->mDrawable->getFace(mObjectFace); + if (facep) + { + LLGLState scissor_state(GL_SCISSOR_TEST); + scissor_state.enable(); + LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE); + //glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH); + glScissor(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH); + + glClear(GL_DEPTH_BUFFER_BIT); + + facep->renderSelectedUV(); + + glReadPixels(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, GL_RGBA, GL_UNSIGNED_BYTE, uv_pick_buffer); + U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)]; + + result.mV[VX] = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f; + result.mV[VY] = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f; + } + } + + return result; +} */ + + +//static +bool LLPickInfo::isFlora(LLViewerObject* object) +{ + if (!object) return false; + + LLPCode pcode = object->getPCode(); + + if( (LL_PCODE_LEGACY_GRASS == pcode) + || (LL_PCODE_LEGACY_TREE == pcode) + || (LL_PCODE_TREE_NEW == pcode)) + { + return true; + } + return false; +} diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 5c0eae61be..c7d02cb720 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -60,6 +60,70 @@ class LLTextBox; class LLImageRaw; class LLHUDIcon; +#define PICK_HALF_WIDTH 5 +#define PICK_DIAMETER (2 * PICK_HALF_WIDTH + 1) + +class LLPickInfo +{ +public: + LLPickInfo(); + LLPickInfo(const LLCoordGL& mouse_pos, + const LLRect& screen_region, + MASK keyboard_mask, + BOOL pick_transparent, + BOOL pick_surface_info, + void (*pick_callback)(const LLPickInfo& pick_info)); + ~LLPickInfo(); + + void fetchResults(); + LLPointer<LLViewerObject> getObject() const; + LLUUID getObjectID() const { return mObjectID; } + void drawPickBuffer() const; + + static bool isFlora(LLViewerObject* object); + + typedef enum e_pick_type + { + PICK_OBJECT, + PICK_FLORA, + PICK_LAND, + PICK_ICON, + PICK_PARCEL_WALL, + PICK_INVALID + } EPickType; + +public: + LLCoordGL mMousePt; + MASK mKeyMask; + void (*mPickCallback)(const LLPickInfo& pick_info); + + EPickType mPickType; + LLCoordGL mPickPt; + LLVector3d mPosGlobal; + LLVector3 mObjectOffset; + LLUUID mObjectID; + S32 mObjectFace; + LLHUDIcon* mHUDIcon; + LLVector3 mIntersection; + LLVector2 mUVCoords; + LLVector2 mSTCoords; + LLCoordScreen mXYCoords; + LLVector3 mNormal; + LLVector3 mBinormal; + BOOL mPickTransparent; + LLRect mScreenRegion; + void getSurfaceInfo(); + +private: + void updateXYCoords(); + + BOOL mWantSurfaceInfo; // do we populate mUVCoord, mNormal, mBinormal? + U8 mPickBuffer[PICK_DIAMETER * PICK_DIAMETER * 4]; + F32 mPickDepthBuffer[PICK_DIAMETER * PICK_DIAMETER]; + BOOL mPickParcelWall; + +}; + #define MAX_IMAGE_SIZE 6144 //6 * 1024, max snapshot image size 6144 * 6144 class LLViewerWindow : public LLWindowCallbacks @@ -143,6 +207,9 @@ public: BOOL getLeftMouseDown() const { return mLeftMouseDown; } BOOL getRightMouseDown() const { return mRightMouseDown; } + const LLPickInfo& getLastPick() const { return mLastPick; } + const LLPickInfo& getHoverPick() const { return mHoverPick; } + LLUICtrl* getTopCtrl() const; BOOL hasTopCtrl(LLView* view) const; @@ -150,10 +217,10 @@ public: void setup3DRender(); void setup2DRender(); - BOOL isPickPending() { return mPickPending; } - LLVector3 mouseDirectionGlobal(const S32 x, const S32 y) const; LLVector3 mouseDirectionCamera(const S32 x, const S32 y) const; + LLVector3 mousePointHUD(const S32 x, const S32 y) const; + // Is window of our application frontmost? BOOL getActive() const { return mActive; } @@ -244,20 +311,27 @@ public: void renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud ); void performPick(); - void hitObjectOrLandGlobalAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(S32 x, S32 y, MASK mask), BOOL pick_transparent = FALSE, BOOL pick_parcel_walls = FALSE); - void hitObjectOrLandGlobalImmediate(S32 x, S32 y, void (*callback)(S32 x, S32 y, MASK mask), BOOL pick_transparent); + void pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& pick_info), + BOOL pick_transparent = FALSE, BOOL get_surface_info = FALSE); + LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent); + static void hoverPickCallback(const LLPickInfo& pick_info); + + LLViewerObject* cursorIntersect(S32 mouse_x = -1, S32 mouse_y = -1, F32 depth = 512.f, + LLViewerObject *this_object = NULL, + S32 this_face = -1, + S32* face_hit = NULL, + LLVector3 *intersection = NULL, + LLVector2 *uv = NULL, + LLVector3 *normal = NULL, + LLVector3 *binormal = NULL); - void hitUIElementAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(S32 x, S32 y, MASK mask)); - void hitUIElementImmediate(S32 x, S32 y, void (*callback)(S32 x, S32 y, MASK mask)); - - LLViewerObject* getObjectUnderCursor(const F32 depth = 16.0f); // Returns a pointer to the last object hit - LLViewerObject *lastObjectHit(); - LLViewerObject *lastNonFloraObjectHit(); + //LLViewerObject *getObject(); + //LLViewerObject *lastNonFloraObjectHit(); - const LLVector3d& lastObjectHitOffset(); - const LLVector3d& lastNonFloraObjectHitOffset(); + //const LLVector3d& getObjectOffset(); + //const LLVector3d& lastNonFloraObjectHitOffset(); // mousePointOnLand() returns true if found point BOOL mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_pos_global); @@ -306,19 +380,7 @@ private: void stopGL(BOOL save_state = TRUE); void restoreGL(const std::string& progress_message = LLStringUtil::null); void initFonts(F32 zoom_factor = 1.f); - - void analyzeHit( - S32 x, // input - S32 y_from_bot, // input - LLViewerObject* objectp, // input - U32 te_offset, // input - LLUUID* hit_object_id_p,// output - S32* hit_face_p, // output - LLVector3d* hit_pos_p, // output - BOOL* hit_land, // output - F32* hit_u_coord, // output - F32* hit_v_coord); // output - + void schedulePick(LLPickInfo& pick_info); public: LLWindow* mWindow; // graphical window object @@ -354,16 +416,14 @@ protected: BOOL mSuppressToolbox; // sometimes hide the toolbox, despite // having a camera tool selected BOOL mHideCursorPermanent; // true during drags, mouselook - LLCoordGL mPickPoint; - LLCoordGL mPickOffset; - MASK mPickMask; - BOOL mPickPending; - void (*mPickCallback)(S32 x, S32 y, MASK mask); + LLPickInfo mLastPick; + LLPickInfo mHoverPick; + std::vector<LLPickInfo> mPicks; + LLRect mPickScreenRegion; // area of frame buffer for rendering pick frames (generally follows mouse to avoid going offscreen) std::string mOverlayTitle; // Used for special titles such as "Second Life - Special E3 2003 Beta" BOOL mIgnoreActivate; - U8* mPickBuffer; std::string mInitAlert; // Window / GL initialization requires an alert @@ -398,9 +458,7 @@ void toggle_first_person(); void toggle_build(void*); void reset_viewer_state_on_sim(void); void update_saved_window_size(const std::string& control,S32 delta_width, S32 delta_height); -// -// Constants -// + // @@ -414,28 +472,15 @@ extern LLFrameTimer gMouseIdleTimer; // how long has it been since the mouse l extern LLFrameTimer gAwayTimer; // tracks time before setting the avatar away state to true extern LLFrameTimer gAwayTriggerTimer; // how long the avatar has been away -extern LLVector3d gLastHitPosGlobal; -extern LLVector3d gLastHitObjectOffset; -extern LLUUID gLastHitObjectID; -extern S32 gLastHitObjectFace; -extern BOOL gLastHitLand; -extern F32 gLastHitUCoord; -extern F32 gLastHitVCoord; - - -extern LLVector3d gLastHitNonFloraPosGlobal; -extern LLVector3d gLastHitNonFloraObjectOffset; -extern LLUUID gLastHitNonFloraObjectID; -extern S32 gLastHitNonFloraObjectFace; - -extern S32 gLastHitUIElement; -extern LLHUDIcon* gLastHitHUDIcon; -extern BOOL gLastHitParcelWall; extern BOOL gDebugSelect; -extern BOOL gPickFaces; -extern BOOL gPickTransparent; extern BOOL gDebugFastUIRender; +extern LLViewerObject* gDebugRaycastObject; +extern LLVector3 gDebugRaycastIntersection; +extern LLVector2 gDebugRaycastTexCoord; +extern LLVector3 gDebugRaycastNormal; +extern LLVector3 gDebugRaycastBinormal; + extern S32 CHAT_BAR_HEIGHT; extern BOOL gDisplayCameraPos; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 287f063757..47090d5c65 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -622,8 +622,6 @@ LLVOAvatar::LLVOAvatar( LLViewerRegion* regionp) : LLViewerObject(id, pcode, regionp), - mHUDTargetZoom(1.f), - mHUDCurZoom(1.f), mLastHeadBakedID( IMG_DEFAULT_AVATAR ), mLastUpperBodyBakedID( IMG_DEFAULT_AVATAR ), mLastLowerBodyBakedID( IMG_DEFAULT_AVATAR ), @@ -3250,7 +3248,8 @@ void LLVOAvatar::idleUpdateTractorBeam() } else { - mBeam->setPositionGlobal(gLastHitNonFloraPosGlobal + gLastHitNonFloraObjectOffset); + const LLPickInfo& pick = gViewerWindow->getLastPick(); + mBeam->setPositionGlobal(pick.mPosGlobal); } } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 54fd7d370f..ff846c8d83 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -636,8 +636,6 @@ public: // special purpose joint for HUD attachments //-------------------------------------------------------------------- LLViewerJoint *mScreenp; - F32 mHUDTargetZoom; - F32 mHUDCurZoom; //-------------------------------------------------------------------- // mesh objects for skinned avatar diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index b84f8d8e4b..1e1f8be859 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1893,26 +1893,42 @@ LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const { - return dir * ~getRenderRotation(); + LLVector3 ret = dir * ~getRenderRotation(); + + LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); + ret.scaleVec(objScale); + + return ret; } LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const { LLVector3 ret = dir; - ret.scaleVec(getScale()); + LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); + ret.scaleVec(objScale); ret = ret * getRenderRotation(); ret += getRenderPosition(); return ret; } -BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const +LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const { - return FALSE; + LLVector3 ret = dir; + LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + ret.scaleVec(invObjScale); + ret = ret * getRenderRotation(); + + return ret; +} + + +BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face, S32 *face_hitp, + LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) -#if 0 // needs to be rewritten to use face extents instead of volume bounds +{ LLVolume* volume = getVolume(); - BOOL ret = FALSE; if (volume) { LLVector3 v_start, v_end, v_dir; @@ -1920,17 +1936,38 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) co v_start = agentPositionToVolume(start); v_end = agentPositionToVolume(end); - if (LLLineSegmentAABB(v_start, v_end, volume->mBounds[0], volume->mBounds[1])) + S32 face_hit = volume->lineSegmentIntersect(v_start, v_end, face, + intersection, tex_coord, normal, bi_normal); + if (face_hit >= 0) { - if (volume->lineSegmentIntersect(v_start, v_end) >= 0) + if (face_hitp != NULL) + { + *face_hitp = face_hit; + } + + if (intersection != NULL) + { + *intersection = volumePositionToAgent(*intersection); // must map back to agent space + } + + if (normal != NULL) + { + *normal = volumeDirectionToAgent(*normal); + (*normal).normVec(); + } + + if (bi_normal != NULL) { - end = volumePositionToAgent(v_end); - ret = TRUE; + *bi_normal = volumeDirectionToAgent(*bi_normal); + (*bi_normal).normVec(); } + + + return TRUE; } } - return ret; -#endif + + return FALSE; } U32 LLVOVolume::getPartitionType() const diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index d7b72f7a18..262d4ecc8d 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -111,10 +111,20 @@ public: const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; } /*virtual*/ const LLMatrix4 getRenderMatrix() const; - /*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, LLVector3& end) const; + + /*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, + S32 face = -1, // which face to check, -1 = ALL_SIDES + S32* face_hit = NULL, // which face was hit + LLVector3* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector3* normal = NULL, // return the surface normal at the intersection point + LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point + ); + LLVector3 agentPositionToVolume(const LLVector3& pos) const; LLVector3 agentDirectionToVolume(const LLVector3& dir) const; LLVector3 volumePositionToAgent(const LLVector3& dir) const; + LLVector3 volumeDirectionToAgent(const LLVector3& dir) const; BOOL getVolumeChanged() const { return mVolumeChanged; } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index f9a18bf192..c24d1b882a 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2188,6 +2188,7 @@ void LLPipeline::renderHighlights() // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD) // Render highlighted faces. + LLGLSPipelineAlpha gls_pipeline_alpha; LLColor4 color(1.f, 1.f, 1.f, 0.5f); LLGLEnable color_mat(GL_COLOR_MATERIAL); disableLights(); @@ -2341,7 +2342,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING)) { - gObjectList.renderObjectsForSelect(camera); + gObjectList.renderObjectsForSelect(camera, gViewerWindow->getVirtualWindowRect()); } else if (gSavedSettings.getBOOL("RenderDeferred")) { @@ -2591,7 +2592,7 @@ void LLPipeline::renderDebug() gGL.flush(); } -void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects) +void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render_transparent, const LLRect& screen_rect) { assertInitialized(); @@ -2644,7 +2645,7 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects) } LLGLEnable alpha_test(GL_ALPHA_TEST); - if (gPickTransparent) + if (render_transparent) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.f); } @@ -2689,14 +2690,7 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects) glh::matrix4f save_proj(glh_get_current_projection()); glh::matrix4f save_model(glh_get_current_modelview()); - U32 viewport[4]; - - for (U32 i = 0; i < 4; i++) - { - viewport[i] = gGLViewport[i]; - } - - setup_hud_matrices(TRUE); + setup_hud_matrices(screen_rect); for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); iter != avatarp->mAttachmentPoints.end(); ) { @@ -2748,11 +2742,6 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects) glh_set_current_modelview(save_model); - for (U32 i = 0; i < 4; i++) - { - gGLViewport[i] = viewport[i]; - } - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); } gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); @@ -2762,11 +2751,6 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects) gGL.setColorMask(true, true); } -void LLPipeline::renderFaceForUVSelect(LLFace* facep) -{ - if (facep) facep->renderSelectedUV(); -} - void LLPipeline::rebuildPools() { LLMemType mt(LLMemType::MTYPE_PIPELINE); @@ -3959,7 +3943,13 @@ BOOL LLPipeline::getProcessBeacons(void* data) return sRenderProcessBeacons; } -LLViewerObject* LLPipeline::pickObject(const LLVector3 &start, const LLVector3 &end, LLVector3 &collision) +LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end, + S32* face_hit, + LLVector3* intersection, // return the intersection point + LLVector2* tex_coord, // return the texture coordinates of the intersection point + LLVector3* normal, // return the surface normal at the intersection point + LLVector3* bi_normal // return the surface bi-normal at the intersection point + ) { LLDrawable* drawable = NULL; @@ -3967,10 +3957,45 @@ LLViewerObject* LLPipeline::pickObject(const LLVector3 &start, const LLVector3 & iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; - LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_VOLUME); + + for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++) + { + if ((j == LLViewerRegion::PARTITION_VOLUME) || (j == LLViewerRegion::PARTITION_BRIDGE)) // only check these partitions for now + { + LLSpatialPartition* part = region->getSpatialPartition(j); + if (part) + { + LLDrawable* hit = part->lineSegmentIntersect(start, end, face_hit, intersection, tex_coord, normal, bi_normal); + if (hit) + { + drawable = hit; + } + } + } + } + } + return drawable ? drawable->getVObj().get() : NULL; +} + +LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector3& start, const LLVector3& end, + S32* face_hit, + LLVector3* intersection, // return the intersection point + LLVector2* tex_coord, // return the texture coordinates of the intersection point + LLVector3* normal, // return the surface normal at the intersection point + LLVector3* bi_normal // return the surface bi-normal at the intersection point + ) +{ + LLDrawable* drawable = NULL; + + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD); if (part) { - LLDrawable* hit = part->pickDrawable(start, end, collision); + LLDrawable* hit = part->lineSegmentIntersect(start, end, face_hit, intersection, tex_coord, normal, bi_normal); if (hit) { drawable = hit; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index e98be79120..ac2c32fedd 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -65,8 +65,8 @@ typedef enum e_avatar_skinning_method BOOL compute_min_max(LLMatrix4& box, LLVector2& min, LLVector2& max); // Shouldn't be defined here! bool LLRayAABB(const LLVector3 ¢er, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon = 0); -BOOL LLLineSegmentAABB(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size); -BOOL setup_hud_matrices(BOOL for_select); +BOOL setup_hud_matrices(); // use whole screen to render hud +BOOL setup_hud_matrices(const LLRect& screen_region); // specify portion of screen (in pixels) to render hud attachments from (for picking) glh::matrix4f glh_copy_matrix(GLdouble* src); glh::matrix4f glh_get_current_modelview(); void glh_set_current_modelview(const glh::matrix4f& mat); @@ -129,8 +129,21 @@ public: void markTextured(LLDrawable *drawablep); void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE); - //get the object between start and end that's closest to start. Return the point of collision in collision. - LLViewerObject* pickObject(const LLVector3 &start, const LLVector3 &end, LLVector3 &collision); + //get the object between start and end that's closest to start. + LLViewerObject* lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end, + S32* face_hit, // return the face hit + LLVector3* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector3* normal = NULL, // return the surface normal at the intersection point + LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point + ); + LLViewerObject* lineSegmentIntersectInHUD(const LLVector3& start, const LLVector3& end, + S32* face_hit, // return the face hit + LLVector3* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector3* normal = NULL, // return the surface normal at the intersection point + LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point + ); // Something about these textures has changed. Dirty them. void dirtyPoolObjectTextures(const std::set<LLViewerImage*>& textures); @@ -185,8 +198,7 @@ public: void renderHighlights(); void renderDebug(); - void renderForSelect(std::set<LLViewerObject*>& objects); - void renderFaceForUVSelect(LLFace* facep); + void renderForSelect(std::set<LLViewerObject*>& objects, BOOL render_transparent, const LLRect& screen_rect); void rebuildPools(); // Rebuild pools void findReferences(LLDrawable *drawablep); // Find the lists which have references to this object @@ -329,7 +341,8 @@ public: RENDER_DEBUG_TEXTURE_ANIM = 0x080000, RENDER_DEBUG_LIGHTS = 0x100000, RENDER_DEBUG_BATCH_SIZE = 0x200000, - RENDER_DEBUG_SHAME = 0x400000, + RENDER_DEBUG_RAYCAST = 0x400000, + RENDER_DEBUG_SHAME = 0x800000 }; public: |