diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llviewerwindow.cpp | 1617 |
1 files changed, 761 insertions, 856 deletions
diff --git a/linden/indra/newview/llviewerwindow.cpp b/linden/indra/newview/llviewerwindow.cpp index 3954cf0..1f5dd44 100644 --- a/linden/indra/newview/llviewerwindow.cpp +++ b/linden/indra/newview/llviewerwindow.cpp | |||
@@ -29,17 +29,17 @@ | |||
29 | * $/LicenseInfo$ | 29 | * $/LicenseInfo$ |
30 | */ | 30 | */ |
31 | 31 | ||
32 | // system library includes | ||
33 | #include <stdio.h> | ||
34 | #include <iostream> | ||
35 | #include <fstream> | ||
36 | |||
32 | #include "llviewerprecompiledheaders.h" | 37 | #include "llviewerprecompiledheaders.h" |
33 | 38 | ||
34 | #include "llpanellogin.h" | 39 | #include "llpanellogin.h" |
35 | #include "llviewerkeyboard.h" | 40 | #include "llviewerkeyboard.h" |
36 | #include "llviewerwindow.h" | 41 | #include "llviewerwindow.h" |
37 | 42 | ||
38 | // system library includes | ||
39 | #include <stdio.h> | ||
40 | #include <iostream> | ||
41 | #include <fstream> | ||
42 | |||
43 | #include "llviewquery.h" | 43 | #include "llviewquery.h" |
44 | #include "llxmltree.h" | 44 | #include "llxmltree.h" |
45 | //#include "llviewercamera.h" | 45 | //#include "llviewercamera.h" |
@@ -47,9 +47,6 @@ | |||
47 | 47 | ||
48 | #include "llvoiceclient.h" // for push-to-talk button handling | 48 | #include "llvoiceclient.h" // for push-to-talk button handling |
49 | 49 | ||
50 | #ifdef SABINRIG | ||
51 | #include "cbw.h" | ||
52 | #endif //SABINRIG | ||
53 | 50 | ||
54 | // | 51 | // |
55 | // TODO: Many of these includes are unnecessary. Remove them. | 52 | // TODO: Many of these includes are unnecessary. Remove them. |
@@ -60,6 +57,7 @@ | |||
60 | #include "indra_constants.h" | 57 | #include "indra_constants.h" |
61 | #include "llassetstorage.h" | 58 | #include "llassetstorage.h" |
62 | #include "llfontgl.h" | 59 | #include "llfontgl.h" |
60 | #include "llmousehandler.h" | ||
63 | #include "llrect.h" | 61 | #include "llrect.h" |
64 | #include "llsky.h" | 62 | #include "llsky.h" |
65 | #include "llstring.h" | 63 | #include "llstring.h" |
@@ -112,7 +110,6 @@ | |||
112 | #include "llframestatview.h" | 110 | #include "llframestatview.h" |
113 | #include "llgesturemgr.h" | 111 | #include "llgesturemgr.h" |
114 | #include "llglheaders.h" | 112 | #include "llglheaders.h" |
115 | #include "llhippo.h" | ||
116 | #include "llhoverview.h" | 113 | #include "llhoverview.h" |
117 | #include "llhudmanager.h" | 114 | #include "llhudmanager.h" |
118 | #include "llhudview.h" | 115 | #include "llhudview.h" |
@@ -192,7 +189,7 @@ | |||
192 | // | 189 | // |
193 | // Globals | 190 | // Globals |
194 | // | 191 | // |
195 | void render_ui_and_swap(); | 192 | void render_ui(); |
196 | LLBottomPanel* gBottomPanel = NULL; | 193 | LLBottomPanel* gBottomPanel = NULL; |
197 | 194 | ||
198 | extern BOOL gDebugClicks; | 195 | extern BOOL gDebugClicks; |
@@ -204,32 +201,8 @@ extern S32 gJamesInt; | |||
204 | LLViewerWindow *gViewerWindow = NULL; | 201 | LLViewerWindow *gViewerWindow = NULL; |
205 | LLVelocityBar *gVelocityBar = NULL; | 202 | LLVelocityBar *gVelocityBar = NULL; |
206 | 203 | ||
207 | LLVector3d gLastHitPosGlobal; | ||
208 | LLVector3d gLastHitObjectOffset; | ||
209 | LLUUID gLastHitObjectID; | ||
210 | S32 gLastHitObjectFace = -1; | ||
211 | BOOL gLastHitLand = FALSE; | ||
212 | F32 gLastHitUCoord; | ||
213 | F32 gLastHitVCoord; | ||
214 | |||
215 | |||
216 | LLVector3d gLastHitNonFloraPosGlobal; | ||
217 | LLVector3d gLastHitNonFloraObjectOffset; | ||
218 | LLUUID gLastHitNonFloraObjectID; | ||
219 | S32 gLastHitNonFloraObjectFace = -1; | ||
220 | BOOL gLastHitParcelWall = FALSE; | ||
221 | |||
222 | S32 gLastHitUIElement = 0; | ||
223 | LLHUDIcon* gLastHitHUDIcon = NULL; | ||
224 | 204 | ||
225 | BOOL gDebugSelect = FALSE; | 205 | BOOL gDebugSelect = FALSE; |
226 | U8 gLastPickAlpha = 255; | ||
227 | BOOL gUseGLPick = FALSE; | ||
228 | |||
229 | // On the next pick pass (whenever that happens) | ||
230 | // should we try to pick individual faces? | ||
231 | // Cleared to FALSE every time a pick happens. | ||
232 | BOOL gPickFaces = FALSE; | ||
233 | 206 | ||
234 | LLFrameTimer gMouseIdleTimer; | 207 | LLFrameTimer gMouseIdleTimer; |
235 | LLFrameTimer gAwayTimer; | 208 | LLFrameTimer gAwayTimer; |
@@ -240,6 +213,11 @@ BOOL gShowOverlayTitle = FALSE; | |||
240 | BOOL gPickTransparent = TRUE; | 213 | BOOL gPickTransparent = TRUE; |
241 | 214 | ||
242 | BOOL gDebugFastUIRender = FALSE; | 215 | BOOL gDebugFastUIRender = FALSE; |
216 | LLViewerObject* gDebugRaycastObject = NULL; | ||
217 | LLVector3 gDebugRaycastIntersection; | ||
218 | LLVector2 gDebugRaycastTexCoord; | ||
219 | LLVector3 gDebugRaycastNormal; | ||
220 | LLVector3 gDebugRaycastBinormal; | ||
243 | 221 | ||
244 | // HUD display lines in lower right | 222 | // HUD display lines in lower right |
245 | BOOL gDisplayWindInfo = FALSE; | 223 | BOOL gDisplayWindInfo = FALSE; |
@@ -257,120 +235,17 @@ const F32 MIN_AFK_TIME = 2.f; // minimum time after setting away state before co | |||
257 | const F32 MAX_FAST_FRAME_TIME = 0.5f; | 235 | const F32 MAX_FAST_FRAME_TIME = 0.5f; |
258 | const F32 FAST_FRAME_INCREMENT = 0.1f; | 236 | const F32 FAST_FRAME_INCREMENT = 0.1f; |
259 | 237 | ||
260 | const S32 PICK_HALF_WIDTH = 5; | 238 | const F32 MIN_DISPLAY_SCALE = 0.75f; |
261 | const S32 PICK_DIAMETER = 2 * PICK_HALF_WIDTH+1; | ||
262 | |||
263 | const F32 MIN_DISPLAY_SCALE = 0.85f; | ||
264 | 239 | ||
265 | const S32 CONSOLE_BOTTOM_PAD = 40; | 240 | const S32 CONSOLE_BOTTOM_PAD = 40; |
266 | #ifdef SABINRIG | ||
267 | /// ALL RIG STUFF | ||
268 | bool rigControl = false; | ||
269 | bool voltDisplay = true; | ||
270 | bool nominalX = false; | ||
271 | bool nominalY = false; | ||
272 | static F32 nomerX = 0.0f; | ||
273 | static F32 nomerY = 0.0f; | ||
274 | const BOARD_NUM = 0; // rig stuff! | ||
275 | const ADRANGE = BIP10VOLTS; // rig stuff! | ||
276 | static unsigned short DataVal; // rig stuff! | ||
277 | static F32 oldValueX = 0; | ||
278 | static F32 newValueX = 50; | ||
279 | static F32 oldValueY = 0; | ||
280 | static F32 newValueY = 50; | ||
281 | static S32 mouseX = 50; | ||
282 | static S32 mouseY = 50; | ||
283 | static float VoltageX = 50; // rig stuff! | ||
284 | static float VoltageY = 50; // rig stuff! | ||
285 | static float nVoltX = 0; | ||
286 | static float nVoltY = 0; | ||
287 | static F32 temp1 = 50.f; | ||
288 | static F32 temp2 = 20.f; | ||
289 | LLCoordGL new_gl; | ||
290 | #endif //SABINRIG | ||
291 | |||
292 | char LLViewerWindow::sSnapshotBaseName[LL_MAX_PATH]; | ||
293 | char LLViewerWindow::sSnapshotDir[LL_MAX_PATH]; | ||
294 | |||
295 | char LLViewerWindow::sMovieBaseName[LL_MAX_PATH]; | ||
296 | |||
297 | extern void toggle_debug_menus(void*); | ||
298 | |||
299 | #ifdef SABINRIG | ||
300 | // static | ||
301 | void LLViewerWindow::printFeedback() | ||
302 | { | ||
303 | if(rigControl == true) | ||
304 | { | ||
305 | cbAIn (BOARD_NUM, 0, ADRANGE, &DataVal); | ||
306 | cbToEngUnits (BOARD_NUM,ADRANGE,DataVal,&VoltageX); //Convert raw to voltage for X-axis | ||
307 | cbAIn (BOARD_NUM, 1, ADRANGE, &DataVal); | ||
308 | cbToEngUnits (BOARD_NUM,ADRANGE,DataVal,&VoltageY); //Convert raw to voltage for Y-axis | ||
309 | if(voltDisplay == true) | ||
310 | { | ||
311 | llinfos << "Current Voltages - X:" << VoltageX << " Y:" << VoltageY << llendl; //Display voltage | ||
312 | } | ||
313 | |||
314 | if(nVoltX == 0) | ||
315 | { | ||
316 | nVoltX = VoltageX; | ||
317 | nVoltY = VoltageY; //First time setup of nominal values. | ||
318 | } | ||
319 | |||
320 | newValueX = VoltageX; | ||
321 | newValueY = VoltageY; //Take in current voltage and set to a separate value for adjustment. | ||
322 | |||
323 | mouseX = mCurrentMousePoint.mX; | ||
324 | mouseY = mCurrentMousePoint.mY; //Take in current cursor position and set to separate value for adjustment. | ||
325 | |||
326 | if( abs(newValueX - nVoltX) > nomerX ) | ||
327 | { | ||
328 | if( (newValueX - oldValueX) < 0) | ||
329 | { | ||
330 | mouseX += (S32)( ((newValueX - oldValueX)*.5)) * -temp; | ||
331 | } | ||
332 | else | ||
333 | { | ||
334 | mouseX += (S32)( ((newValueX - oldValueX)*.5) * temp1); | ||
335 | } | ||
336 | } | ||
337 | else | ||
338 | { | ||
339 | mouseX = getWindowWidth() / 2; | ||
340 | } | ||
341 | if( abs(newValueY - nVoltY) > nomerY ) | ||
342 | { | ||
343 | if( (newValueY - oldValueY) < 0) | ||
344 | { | ||
345 | mouseY += (S32)( ((newValueY - oldValueY)*(newValueY - oldValueY)) * -temp2); | ||
346 | } | ||
347 | else | ||
348 | { | ||
349 | mouseY += (S32)( ((newValueY - oldValueY)*(newValueY - oldValueY)) * temp2); | ||
350 | } | ||
351 | } | ||
352 | else | ||
353 | { | ||
354 | mouseY = getWindowHeight() / 2; | ||
355 | } | ||
356 | //mouseX += (S32)( (newValueX - nVoltX) * temp1 + 0.5 ); | ||
357 | // (newValueX - oldValueX) = difference between current position and nominal position | ||
358 | // * temp1 = the amplification of the number that sets sensitivity | ||
359 | // + 0.5 = fixes rounding errors | ||
360 | |||
361 | 241 | ||
362 | //mouseY += (S32)( (newValueY - nVoltY) * temp2 + 0.5 ); //Algorithm to adjust voltage for mouse adjustment. | 242 | std::string LLViewerWindow::sSnapshotBaseName; |
243 | std::string LLViewerWindow::sSnapshotDir; | ||
363 | 244 | ||
364 | oldValueX = newValueX; | 245 | std::string LLViewerWindow::sMovieBaseName; |
365 | oldValueY = newValueY; | ||
366 | 246 | ||
367 | new_gl.mX = mouseX; | 247 | extern void toggle_debug_menus(void*); |
368 | new_gl.mY = mouseY; //Setup final coordinate to move mouse to. | ||
369 | 248 | ||
370 | setCursorPosition(new_gl); //Set final cursor position | ||
371 | } | ||
372 | } | ||
373 | #endif //SABINRIG | ||
374 | 249 | ||
375 | //////////////////////////////////////////////////////////////////////////// | 250 | //////////////////////////////////////////////////////////////////////////// |
376 | // | 251 | // |
@@ -597,7 +472,7 @@ public: | |||
597 | ypos += y_inc; | 472 | ypos += y_inc; |
598 | } | 473 | } |
599 | // only display these messages if we are actually rendering beacons at this moment | 474 | // only display these messages if we are actually rendering beacons at this moment |
600 | if (LLPipeline::getRenderBeacons(NULL) && LLPipeline::getProcessBeacons(NULL)) | 475 | if (LLPipeline::getRenderBeacons(NULL) && gSavedSettings.getBOOL("BeaconAlwaysOn")) |
601 | { | 476 | { |
602 | if (LLPipeline::getRenderParticleBeacons(NULL)) | 477 | if (LLPipeline::getRenderParticleBeacons(NULL)) |
603 | { | 478 | { |
@@ -658,6 +533,21 @@ void LLViewerWindow::updateDebugText() | |||
658 | // LLViewerWindow | 533 | // LLViewerWindow |
659 | // | 534 | // |
660 | 535 | ||
536 | bool LLViewerWindow::shouldShowToolTipFor(LLMouseHandler *mh) | ||
537 | { | ||
538 | if (mToolTip && mh) | ||
539 | { | ||
540 | LLMouseHandler::EShowToolTip showlevel = mh->getShowToolTip(); | ||
541 | |||
542 | return ( | ||
543 | showlevel == LLMouseHandler::SHOW_ALWAYS || | ||
544 | (showlevel == LLMouseHandler::SHOW_IF_NOT_BLOCKED && | ||
545 | !mToolTipBlocked) | ||
546 | ); | ||
547 | } | ||
548 | return false; | ||
549 | } | ||
550 | |||
661 | BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask) | 551 | BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask) |
662 | { | 552 | { |
663 | S32 x = pos.mX; | 553 | S32 x = pos.mX; |
@@ -665,7 +555,7 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask | |||
665 | x = llround((F32)x / mDisplayScale.mV[VX]); | 555 | x = llround((F32)x / mDisplayScale.mV[VX]); |
666 | y = llround((F32)y / mDisplayScale.mV[VY]); | 556 | y = llround((F32)y / mDisplayScale.mV[VY]); |
667 | 557 | ||
668 | LLView::sMouseHandlerMessage = ""; | 558 | LLView::sMouseHandlerMessage.clear(); |
669 | 559 | ||
670 | if (gDebugClicks) | 560 | if (gDebugClicks) |
671 | { | 561 | { |
@@ -687,11 +577,7 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask | |||
687 | gMouseIdleTimer.reset(); | 577 | gMouseIdleTimer.reset(); |
688 | 578 | ||
689 | // Hide tooltips on mousedown | 579 | // Hide tooltips on mousedown |
690 | if( mToolTip ) | 580 | mToolTipBlocked = TRUE; |
691 | { | ||
692 | mToolTipBlocked = TRUE; | ||
693 | mToolTip->setVisible( FALSE ); | ||
694 | } | ||
695 | 581 | ||
696 | // Also hide hover info on mousedown | 582 | // Also hide hover info on mousedown |
697 | if (gHoverView) | 583 | if (gHoverView) |
@@ -731,7 +617,7 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask | |||
731 | } | 617 | } |
732 | else | 618 | else |
733 | { | 619 | { |
734 | setTopCtrl(NULL); | 620 | gFocusMgr.setTopCtrl(NULL); |
735 | } | 621 | } |
736 | } | 622 | } |
737 | 623 | ||
@@ -773,7 +659,7 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma | |||
773 | x = llround((F32)x / mDisplayScale.mV[VX]); | 659 | x = llround((F32)x / mDisplayScale.mV[VX]); |
774 | y = llround((F32)y / mDisplayScale.mV[VY]); | 660 | y = llround((F32)y / mDisplayScale.mV[VY]); |
775 | 661 | ||
776 | LLView::sMouseHandlerMessage = ""; | 662 | LLView::sMouseHandlerMessage.clear(); |
777 | 663 | ||
778 | if (gDebugClicks) | 664 | if (gDebugClicks) |
779 | { | 665 | { |
@@ -814,7 +700,7 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma | |||
814 | } | 700 | } |
815 | else | 701 | else |
816 | { | 702 | { |
817 | setTopCtrl(NULL); | 703 | gFocusMgr.setTopCtrl(NULL); |
818 | } | 704 | } |
819 | } | 705 | } |
820 | 706 | ||
@@ -853,7 +739,7 @@ BOOL LLViewerWindow::handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask) | |||
853 | x = llround((F32)x / mDisplayScale.mV[VX]); | 739 | x = llround((F32)x / mDisplayScale.mV[VX]); |
854 | y = llround((F32)y / mDisplayScale.mV[VY]); | 740 | y = llround((F32)y / mDisplayScale.mV[VY]); |
855 | 741 | ||
856 | LLView::sMouseHandlerMessage = ""; | 742 | LLView::sMouseHandlerMessage.clear(); |
857 | 743 | ||
858 | if (gDebugClicks) | 744 | if (gDebugClicks) |
859 | { | 745 | { |
@@ -944,7 +830,7 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK | |||
944 | x = llround((F32)x / mDisplayScale.mV[VX]); | 830 | x = llround((F32)x / mDisplayScale.mV[VX]); |
945 | y = llround((F32)y / mDisplayScale.mV[VY]); | 831 | y = llround((F32)y / mDisplayScale.mV[VY]); |
946 | 832 | ||
947 | LLView::sMouseHandlerMessage = ""; | 833 | LLView::sMouseHandlerMessage.clear(); |
948 | 834 | ||
949 | if (gDebugClicks) | 835 | if (gDebugClicks) |
950 | { | 836 | { |
@@ -1004,7 +890,7 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK | |||
1004 | } | 890 | } |
1005 | else | 891 | else |
1006 | { | 892 | { |
1007 | setTopCtrl(NULL); | 893 | gFocusMgr.setTopCtrl(NULL); |
1008 | } | 894 | } |
1009 | } | 895 | } |
1010 | 896 | ||
@@ -1051,7 +937,7 @@ BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK m | |||
1051 | x = llround((F32)x / mDisplayScale.mV[VX]); | 937 | x = llround((F32)x / mDisplayScale.mV[VX]); |
1052 | y = llround((F32)y / mDisplayScale.mV[VY]); | 938 | y = llround((F32)y / mDisplayScale.mV[VY]); |
1053 | 939 | ||
1054 | LLView::sMouseHandlerMessage = ""; | 940 | LLView::sMouseHandlerMessage.clear(); |
1055 | 941 | ||
1056 | // Don't care about caps lock for mouse events. | 942 | // Don't care about caps lock for mouse events. |
1057 | if (gDebugClicks) | 943 | if (gDebugClicks) |
@@ -1150,6 +1036,7 @@ BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK | |||
1150 | return TRUE; | 1036 | return TRUE; |
1151 | } | 1037 | } |
1152 | 1038 | ||
1039 | // WARNING: this is potentially called multiple times per frame | ||
1153 | void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask) | 1040 | void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask) |
1154 | { | 1041 | { |
1155 | S32 x = pos.mX; | 1042 | S32 x = pos.mX; |
@@ -1177,13 +1064,9 @@ void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask | |||
1177 | gAgent.clearAFK(); | 1064 | gAgent.clearAFK(); |
1178 | } | 1065 | } |
1179 | 1066 | ||
1180 | if(mToolTip && mouse_actually_moved) | 1067 | if(mouse_actually_moved) |
1181 | { | 1068 | { |
1182 | mToolTipBlocked = FALSE; // Blocking starts on keyboard events and (only) ends here. | 1069 | mToolTipBlocked = FALSE; |
1183 | if( mToolTip->getVisible() && !mToolTipStickyRect.pointInRect( x, y ) ) | ||
1184 | { | ||
1185 | mToolTip->setVisible( FALSE ); | ||
1186 | } | ||
1187 | } | 1070 | } |
1188 | 1071 | ||
1189 | // Activate the hover picker on mouse move. | 1072 | // Activate the hover picker on mouse move. |
@@ -1406,24 +1289,23 @@ BOOL LLViewerWindow::handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S | |||
1406 | //SetBKColor(hdc, RGB(255, 255, 255)); | 1289 | //SetBKColor(hdc, RGB(255, 255, 255)); |
1407 | FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255))); | 1290 | FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255))); |
1408 | 1291 | ||
1409 | LLString name_str; | 1292 | std::string name_str; |
1410 | gAgent.getName(name_str); | 1293 | gAgent.getName(name_str); |
1411 | 1294 | ||
1412 | S32 len; | 1295 | std::string temp_str; |
1413 | char temp_str[255]; /* Flawfinder: ignore */ | 1296 | temp_str = llformat( "%s FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", /* Flawfinder: ignore */ |
1414 | snprintf(temp_str, sizeof(temp_str), "%s FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", /* Flawfinder: ignore */ | ||
1415 | name_str.c_str(), | 1297 | name_str.c_str(), |
1416 | LLViewerStats::getInstance()->mFPSStat.getMeanPerSec(), | 1298 | LLViewerStats::getInstance()->mFPSStat.getMeanPerSec(), |
1417 | LLViewerStats::getInstance()->mSimPhysicsFPS.getPrev(0), | 1299 | LLViewerStats::getInstance()->mSimPhysicsFPS.getPrev(0), |
1418 | LLViewerStats::getInstance()->mSimTimeDilation.getPrev(0)); | 1300 | LLViewerStats::getInstance()->mSimTimeDilation.getPrev(0)); |
1419 | len = strlen(temp_str); /* Flawfinder: ignore */ | 1301 | S32 len = temp_str.length(); |
1420 | TextOutA(hdc, 0, 0, temp_str, len); | 1302 | TextOutA(hdc, 0, 0, temp_str.c_str(), len); |
1421 | 1303 | ||
1422 | 1304 | ||
1423 | LLVector3d pos_global = gAgent.getPositionGlobal(); | 1305 | LLVector3d pos_global = gAgent.getPositionGlobal(); |
1424 | snprintf(temp_str, sizeof(temp_str), "Avatar pos %6.1lf %6.1lf %6.1lf", pos_global.mdV[0], pos_global.mdV[1], pos_global.mdV[2]); /* Flawfinder: ignore */ | 1306 | temp_str = llformat( "Avatar pos %6.1lf %6.1lf %6.1lf", pos_global.mdV[0], pos_global.mdV[1], pos_global.mdV[2]); |
1425 | len = strlen(temp_str); /* Flawfinder: ignore */ | 1307 | len = temp_str.length(); |
1426 | TextOutA(hdc, 0, 25, temp_str, len); | 1308 | TextOutA(hdc, 0, 25, temp_str.c_str(), len); |
1427 | 1309 | ||
1428 | TextOutA(hdc, 0, 50, "Set \"DisableRendering FALSE\" in settings.ini file to reenable", 61); | 1310 | TextOutA(hdc, 0, 50, "Set \"DisableRendering FALSE\" in settings.ini file to reenable", 61); |
1429 | EndPaint(window_handle, &ps); | 1311 | EndPaint(window_handle, &ps); |
@@ -1492,7 +1374,7 @@ BOOL LLViewerWindow::handleDeviceChange(LLWindow *window) | |||
1492 | // Classes | 1374 | // Classes |
1493 | // | 1375 | // |
1494 | LLViewerWindow::LLViewerWindow( | 1376 | LLViewerWindow::LLViewerWindow( |
1495 | char* title, char* name, | 1377 | const std::string& title, const std::string& name, |
1496 | S32 x, S32 y, | 1378 | S32 x, S32 y, |
1497 | S32 width, S32 height, | 1379 | S32 width, S32 height, |
1498 | BOOL fullscreen, BOOL ignore_pixel_depth) | 1380 | BOOL fullscreen, BOOL ignore_pixel_depth) |
@@ -1511,14 +1393,14 @@ LLViewerWindow::LLViewerWindow( | |||
1511 | mToolStored( NULL ), | 1393 | mToolStored( NULL ), |
1512 | mSuppressToolbox( FALSE ), | 1394 | mSuppressToolbox( FALSE ), |
1513 | mHideCursorPermanent( FALSE ), | 1395 | mHideCursorPermanent( FALSE ), |
1514 | mPickPending(FALSE), | 1396 | mCursorHidden(FALSE), |
1515 | mIgnoreActivate( FALSE ) | 1397 | mIgnoreActivate( FALSE ), |
1398 | mHoverPick() | ||
1516 | { | 1399 | { |
1517 | // Default to application directory. | 1400 | // Default to application directory. |
1518 | strcpy(LLViewerWindow::sSnapshotBaseName, "Snapshot"); /* Flawfinder: ignore */ | 1401 | LLViewerWindow::sSnapshotBaseName = "Snapshot"; |
1519 | strcpy(LLViewerWindow::sMovieBaseName, "SLmovie"); /* Flawfinder: ignore */ | 1402 | LLViewerWindow::sMovieBaseName = "SLmovie"; |
1520 | LLViewerWindow::sSnapshotDir[0] = '\0'; | 1403 | resetSnapshotLoc(); |
1521 | |||
1522 | 1404 | ||
1523 | // create window | 1405 | // create window |
1524 | mWindow = LLWindowManager::createWindow( | 1406 | mWindow = LLWindowManager::createWindow( |
@@ -1621,12 +1503,10 @@ LLViewerWindow::LLViewerWindow( | |||
1621 | mCurrentMousePoint.mX = getWindowWidth() / 2; | 1503 | mCurrentMousePoint.mX = getWindowWidth() / 2; |
1622 | mCurrentMousePoint.mY = getWindowHeight() / 2; | 1504 | mCurrentMousePoint.mY = getWindowHeight() / 2; |
1623 | 1505 | ||
1624 | mPickBuffer = new U8[PICK_DIAMETER * PICK_DIAMETER * 4]; | ||
1625 | |||
1626 | gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle"); | 1506 | gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle"); |
1627 | mOverlayTitle = gSavedSettings.getString("OverlayTitle"); | 1507 | mOverlayTitle = gSavedSettings.getString("OverlayTitle"); |
1628 | // Can't have spaces in settings.ini strings, so use underscores instead and convert them. | 1508 | // Can't have spaces in settings.ini strings, so use underscores instead and convert them. |
1629 | LLString::replaceChar(mOverlayTitle, '_', ' '); | 1509 | LLStringUtil::replaceChar(mOverlayTitle, '_', ' '); |
1630 | 1510 | ||
1631 | LLAlertDialog::setDisplayCallback(alertCallback); // call this before calling any modal dialogs | 1511 | LLAlertDialog::setDisplayCallback(alertCallback); // call this before calling any modal dialogs |
1632 | 1512 | ||
@@ -1757,7 +1637,7 @@ void LLViewerWindow::initBase() | |||
1757 | mRootView->addChild(gNotifyBoxView, -2); | 1637 | mRootView->addChild(gNotifyBoxView, -2); |
1758 | 1638 | ||
1759 | // Tooltips go above floaters | 1639 | // Tooltips go above floaters |
1760 | mToolTip = new LLTextBox( "tool tip", LLRect(0, 1, 1, 0 ) ); | 1640 | mToolTip = new LLTextBox( std::string("tool tip"), LLRect(0, 1, 1, 0 ) ); |
1761 | mToolTip->setHPad( 4 ); | 1641 | mToolTip->setHPad( 4 ); |
1762 | mToolTip->setVPad( 2 ); | 1642 | mToolTip->setVPad( 2 ); |
1763 | mToolTip->setColor( gColors.getColor( "ToolTipTextColor" ) ); | 1643 | mToolTip->setColor( gColors.getColor( "ToolTipTextColor" ) ); |
@@ -1770,14 +1650,14 @@ void LLViewerWindow::initBase() | |||
1770 | mToolTip->setVisible( FALSE ); | 1650 | mToolTip->setVisible( FALSE ); |
1771 | 1651 | ||
1772 | // Add the progress bar view (startup view), which overrides everything | 1652 | // Add the progress bar view (startup view), which overrides everything |
1773 | mProgressView = new LLProgressView("ProgressView", full_window); | 1653 | mProgressView = new LLProgressView(std::string("ProgressView"), full_window); |
1774 | mRootView->addChild(mProgressView); | 1654 | mRootView->addChild(mProgressView); |
1775 | setShowProgress(FALSE); | 1655 | setShowProgress(FALSE); |
1776 | setProgressCancelButtonVisible(FALSE, ""); | 1656 | setProgressCancelButtonVisible(FALSE); |
1777 | } | 1657 | } |
1778 | 1658 | ||
1779 | 1659 | ||
1780 | void adjust_rect_top_left(const LLString& control, const LLRect& window) | 1660 | void adjust_rect_top_left(const std::string& control, const LLRect& window) |
1781 | { | 1661 | { |
1782 | LLRect r = gSavedSettings.getRect(control); | 1662 | LLRect r = gSavedSettings.getRect(control); |
1783 | if (r.mLeft == 0 && r.mBottom == 0) | 1663 | if (r.mLeft == 0 && r.mBottom == 0) |
@@ -1787,7 +1667,7 @@ void adjust_rect_top_left(const LLString& control, const LLRect& window) | |||
1787 | } | 1667 | } |
1788 | } | 1668 | } |
1789 | 1669 | ||
1790 | void adjust_rect_top_center(const LLString& control, const LLRect& window) | 1670 | void adjust_rect_top_center(const std::string& control, const LLRect& window) |
1791 | { | 1671 | { |
1792 | LLRect r = gSavedSettings.getRect(control); | 1672 | LLRect r = gSavedSettings.getRect(control); |
1793 | if (r.mLeft == 0 && r.mBottom == 0) | 1673 | if (r.mLeft == 0 && r.mBottom == 0) |
@@ -1800,7 +1680,7 @@ void adjust_rect_top_center(const LLString& control, const LLRect& window) | |||
1800 | } | 1680 | } |
1801 | } | 1681 | } |
1802 | 1682 | ||
1803 | void adjust_rect_top_right(const LLString& control, const LLRect& window) | 1683 | void adjust_rect_top_right(const std::string& control, const LLRect& window) |
1804 | { | 1684 | { |
1805 | LLRect r = gSavedSettings.getRect(control); | 1685 | LLRect r = gSavedSettings.getRect(control); |
1806 | if (r.mLeft == 0 && r.mBottom == 0) | 1686 | if (r.mLeft == 0 && r.mBottom == 0) |
@@ -1813,7 +1693,7 @@ void adjust_rect_top_right(const LLString& control, const LLRect& window) | |||
1813 | } | 1693 | } |
1814 | } | 1694 | } |
1815 | 1695 | ||
1816 | void adjust_rect_bottom_center(const LLString& control, const LLRect& window) | 1696 | void adjust_rect_bottom_center(const std::string& control, const LLRect& window) |
1817 | { | 1697 | { |
1818 | LLRect r = gSavedSettings.getRect(control); | 1698 | LLRect r = gSavedSettings.getRect(control); |
1819 | if (r.mLeft == 0 && r.mBottom == 0) | 1699 | if (r.mLeft == 0 && r.mBottom == 0) |
@@ -1829,7 +1709,7 @@ void adjust_rect_bottom_center(const LLString& control, const LLRect& window) | |||
1829 | } | 1709 | } |
1830 | } | 1710 | } |
1831 | 1711 | ||
1832 | void adjust_rect_centered_partial_zoom(const LLString& control, | 1712 | void adjust_rect_centered_partial_zoom(const std::string& control, |
1833 | const LLRect& window) | 1713 | const LLRect& window) |
1834 | { | 1714 | { |
1835 | LLRect rect = gSavedSettings.getRect(control); | 1715 | LLRect rect = gSavedSettings.getRect(control); |
@@ -1868,8 +1748,6 @@ void LLViewerWindow::adjustRectanglesForFirstUse(const LLRect& window) | |||
1868 | 1748 | ||
1869 | adjust_rect_top_left("FloaterLandRect5", window); | 1749 | adjust_rect_top_left("FloaterLandRect5", window); |
1870 | 1750 | ||
1871 | adjust_rect_top_left("FloaterHUDRect2", window); | ||
1872 | |||
1873 | adjust_rect_top_left("FloaterFindRect2", window); | 1751 | adjust_rect_top_left("FloaterFindRect2", window); |
1874 | 1752 | ||
1875 | adjust_rect_top_left("FloaterGestureRect2", window); | 1753 | adjust_rect_top_left("FloaterGestureRect2", window); |
@@ -1891,8 +1769,29 @@ void LLViewerWindow::adjustRectanglesForFirstUse(const LLRect& window) | |||
1891 | r.getHeight()); | 1769 | r.getHeight()); |
1892 | gSavedSettings.setRect("FloaterInventoryRect", r); | 1770 | gSavedSettings.setRect("FloaterInventoryRect", r); |
1893 | } | 1771 | } |
1772 | |||
1773 | // adjust_rect_top_left("FloaterHUDRect2", window); | ||
1774 | |||
1775 | // slightly off center to be left of the avatar. | ||
1776 | r = gSavedSettings.getRect("FloaterHUDRect2"); | ||
1777 | if (r.mLeft == 0 && r.mBottom == 0) | ||
1778 | { | ||
1779 | r.setOriginAndSize( | ||
1780 | window.getWidth()/4 - r.getWidth()/2, | ||
1781 | 2*window.getHeight()/3 - r.getHeight()/2, | ||
1782 | r.getWidth(), | ||
1783 | r.getHeight()); | ||
1784 | gSavedSettings.setRect("FloaterHUDRect2", r); | ||
1785 | } | ||
1894 | } | 1786 | } |
1895 | 1787 | ||
1788 | //Rectangles need to be adjusted after the window is constructed | ||
1789 | //in order for proper centering to take place | ||
1790 | void LLViewerWindow::adjustControlRectanglesForFirstUse(const LLRect& window) | ||
1791 | { | ||
1792 | adjust_rect_bottom_center("FloaterMoveRect2", window); | ||
1793 | adjust_rect_top_center("FloaterCameraRect3", window); | ||
1794 | } | ||
1896 | 1795 | ||
1897 | void LLViewerWindow::initWorldUI() | 1796 | void LLViewerWindow::initWorldUI() |
1898 | { | 1797 | { |
@@ -1909,7 +1808,7 @@ void LLViewerWindow::initWorldUI() | |||
1909 | mRootView->addChild(gBottomPanel); | 1808 | mRootView->addChild(gBottomPanel); |
1910 | 1809 | ||
1911 | // View for hover information | 1810 | // View for hover information |
1912 | gHoverView = new LLHoverView("gHoverView", full_window); | 1811 | gHoverView = new LLHoverView(std::string("gHoverView"), full_window); |
1913 | gHoverView->setVisible(TRUE); | 1812 | gHoverView->setVisible(TRUE); |
1914 | mRootView->addChild(gHoverView); | 1813 | mRootView->addChild(gHoverView); |
1915 | 1814 | ||
@@ -1917,7 +1816,7 @@ void LLViewerWindow::initWorldUI() | |||
1917 | // Map | 1816 | // Map |
1918 | // | 1817 | // |
1919 | // TODO: Move instance management into class | 1818 | // TODO: Move instance management into class |
1920 | gFloaterMap = new LLFloaterMap("Map"); | 1819 | gFloaterMap = new LLFloaterMap(std::string("Map")); |
1921 | gFloaterMap->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT); | 1820 | gFloaterMap->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT); |
1922 | 1821 | ||
1923 | // keep onscreen | 1822 | // keep onscreen |
@@ -1933,7 +1832,7 @@ void LLViewerWindow::initWorldUI() | |||
1933 | LLRect morph_view_rect = full_window; | 1832 | LLRect morph_view_rect = full_window; |
1934 | morph_view_rect.stretch( -STATUS_BAR_HEIGHT ); | 1833 | morph_view_rect.stretch( -STATUS_BAR_HEIGHT ); |
1935 | morph_view_rect.mTop = full_window.mTop - 32; | 1834 | morph_view_rect.mTop = full_window.mTop - 32; |
1936 | gMorphView = new LLMorphView("gMorphView", morph_view_rect ); | 1835 | gMorphView = new LLMorphView(std::string("gMorphView"), morph_view_rect ); |
1937 | mRootView->addChild(gMorphView); | 1836 | mRootView->addChild(gMorphView); |
1938 | gMorphView->setVisible(FALSE); | 1837 | gMorphView->setVisible(FALSE); |
1939 | 1838 | ||
@@ -1960,7 +1859,7 @@ void LLViewerWindow::initWorldUI() | |||
1960 | S32 menu_bar_height = gMenuBarView->getRect().getHeight(); | 1859 | S32 menu_bar_height = gMenuBarView->getRect().getHeight(); |
1961 | LLRect root_rect = getRootView()->getRect(); | 1860 | LLRect root_rect = getRootView()->getRect(); |
1962 | LLRect status_rect(0, root_rect.getHeight(), root_rect.getWidth(), root_rect.getHeight() - menu_bar_height); | 1861 | LLRect status_rect(0, root_rect.getHeight(), root_rect.getWidth(), root_rect.getHeight() - menu_bar_height); |
1963 | gStatusBar = new LLStatusBar("status", status_rect); | 1862 | gStatusBar = new LLStatusBar(std::string("status"), status_rect); |
1964 | gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); | 1863 | gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); |
1965 | 1864 | ||
1966 | gStatusBar->reshape(root_rect.getWidth(), gStatusBar->getRect().getHeight(), TRUE); | 1865 | gStatusBar->reshape(root_rect.getWidth(), gStatusBar->getRect().getHeight(), TRUE); |
@@ -1977,10 +1876,11 @@ void LLViewerWindow::initWorldUI() | |||
1977 | } | 1876 | } |
1978 | } | 1877 | } |
1979 | 1878 | ||
1980 | 1879 | // Destroy the UI | |
1981 | LLViewerWindow::~LLViewerWindow() | 1880 | void LLViewerWindow::shutdownViews() |
1982 | { | 1881 | { |
1983 | delete mDebugText; | 1882 | delete mDebugText; |
1883 | mDebugText = NULL; | ||
1984 | 1884 | ||
1985 | gSavedSettings.setS32("FloaterViewBottom", gFloaterView->getRect().mBottom); | 1885 | gSavedSettings.setS32("FloaterViewBottom", gFloaterView->getRect().mBottom); |
1986 | 1886 | ||
@@ -2010,7 +1910,10 @@ LLViewerWindow::~LLViewerWindow() | |||
2010 | 1910 | ||
2011 | delete mToolTip; | 1911 | delete mToolTip; |
2012 | mToolTip = NULL; | 1912 | mToolTip = NULL; |
2013 | 1913 | } | |
1914 | |||
1915 | void LLViewerWindow::shutdownGL() | ||
1916 | { | ||
2014 | //-------------------------------------------------------- | 1917 | //-------------------------------------------------------- |
2015 | // Shutdown GL cleanly. Order is very important here. | 1918 | // Shutdown GL cleanly. Order is very important here. |
2016 | //-------------------------------------------------------- | 1919 | //-------------------------------------------------------- |
@@ -2035,9 +1938,6 @@ LLViewerWindow::~LLViewerWindow() | |||
2035 | 1938 | ||
2036 | LLViewerImage::cleanupClass(); | 1939 | LLViewerImage::cleanupClass(); |
2037 | 1940 | ||
2038 | delete[] mPickBuffer; | ||
2039 | mPickBuffer = NULL; | ||
2040 | |||
2041 | llinfos << "Cleaning up select manager" << llendl; | 1941 | llinfos << "Cleaning up select manager" << llendl; |
2042 | LLSelectMgr::getInstance()->cleanup(); | 1942 | LLSelectMgr::getInstance()->cleanup(); |
2043 | 1943 | ||
@@ -2049,8 +1949,11 @@ LLViewerWindow::~LLViewerWindow() | |||
2049 | stopGL(FALSE); | 1949 | stopGL(FALSE); |
2050 | stop_glerror(); | 1950 | stop_glerror(); |
2051 | } | 1951 | } |
1952 | } | ||
2052 | 1953 | ||
2053 | 1954 | // shutdownViews() and shutdownGL() need to be called first | |
1955 | LLViewerWindow::~LLViewerWindow() | ||
1956 | { | ||
2054 | llinfos << "Destroying Window" << llendl; | 1957 | llinfos << "Destroying Window" << llendl; |
2055 | destroyWindow(); | 1958 | destroyWindow(); |
2056 | } | 1959 | } |
@@ -2064,6 +1967,8 @@ void LLViewerWindow::setCursor( ECursorType c ) | |||
2064 | void LLViewerWindow::showCursor() | 1967 | void LLViewerWindow::showCursor() |
2065 | { | 1968 | { |
2066 | mWindow->showCursor(); | 1969 | mWindow->showCursor(); |
1970 | |||
1971 | mCursorHidden = FALSE; | ||
2067 | } | 1972 | } |
2068 | 1973 | ||
2069 | void LLViewerWindow::hideCursor() | 1974 | void LLViewerWindow::hideCursor() |
@@ -2076,6 +1981,8 @@ void LLViewerWindow::hideCursor() | |||
2076 | 1981 | ||
2077 | // And hide the cursor | 1982 | // And hide the cursor |
2078 | mWindow->hideCursor(); | 1983 | mWindow->hideCursor(); |
1984 | |||
1985 | mCursorHidden = TRUE; | ||
2079 | } | 1986 | } |
2080 | 1987 | ||
2081 | void LLViewerWindow::sendShapeToSim() | 1988 | void LLViewerWindow::sendShapeToSim() |
@@ -2215,7 +2122,7 @@ void LLViewerWindow::setNormalControlsVisible( BOOL visible ) | |||
2215 | 2122 | ||
2216 | void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) | 2123 | void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) |
2217 | { | 2124 | { |
2218 | LLString::format_map_t args; | 2125 | LLStringUtil::format_map_t args; |
2219 | LLColor4 new_bg_color; | 2126 | LLColor4 new_bg_color; |
2220 | 2127 | ||
2221 | if(god_mode && LLViewerLogin::getInstance()->isInProductionGrid()) | 2128 | if(god_mode && LLViewerLogin::getInstance()->isInProductionGrid()) |
@@ -2287,7 +2194,7 @@ void LLViewerWindow::draw() | |||
2287 | if (gSavedSettings.getBOOL("DisplayTimecode")) | 2194 | if (gSavedSettings.getBOOL("DisplayTimecode")) |
2288 | { | 2195 | { |
2289 | // draw timecode block | 2196 | // draw timecode block |
2290 | char text[256]; /* Flawfinder: ignore */ | 2197 | std::string text; |
2291 | 2198 | ||
2292 | glLoadIdentity(); | 2199 | glLoadIdentity(); |
2293 | 2200 | ||
@@ -2425,11 +2332,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) | |||
2425 | } | 2332 | } |
2426 | 2333 | ||
2427 | // Hide tooltips on keypress | 2334 | // Hide tooltips on keypress |
2428 | if(mToolTip ) | 2335 | mToolTipBlocked = TRUE; // block until next time mouse is moved |
2429 | { | ||
2430 | mToolTipBlocked = TRUE; // block until next time mouse is moved | ||
2431 | mToolTip->setVisible( FALSE ); | ||
2432 | } | ||
2433 | 2336 | ||
2434 | // Also hide hover info on keypress | 2337 | // Also hide hover info on keypress |
2435 | if (gHoverView) | 2338 | if (gHoverView) |
@@ -2461,32 +2364,9 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) | |||
2461 | } | 2364 | } |
2462 | } | 2365 | } |
2463 | 2366 | ||
2464 | // Example "bug" for bug reporter web page | ||
2465 | if ((MASK_SHIFT & mask) | ||
2466 | && (MASK_ALT & mask) | ||
2467 | && (MASK_CONTROL & mask) | ||
2468 | && ('H' == key || 'h' == key)) | ||
2469 | { | ||
2470 | trigger_hippo_bug(NULL); | ||
2471 | } | ||
2472 | |||
2473 | // handle escape key | 2367 | // handle escape key |
2474 | if (key == KEY_ESCAPE && mask == MASK_NONE) | 2368 | //if (key == KEY_ESCAPE && mask == MASK_NONE) |
2475 | { | 2369 | //{ |
2476 | if (gMenuHolder && gMenuHolder->hideMenus()) | ||
2477 | { | ||
2478 | return TRUE; | ||
2479 | } | ||
2480 | |||
2481 | //if quit from menu, turn off the Keyboardmode for the menu. | ||
2482 | if(LLMenuGL::getKeyboardMode()) | ||
2483 | LLMenuGL::setKeyboardMode(FALSE); | ||
2484 | |||
2485 | if (gFocusMgr.getTopCtrl()) | ||
2486 | { | ||
2487 | gFocusMgr.setTopCtrl(NULL); | ||
2488 | return TRUE; | ||
2489 | } | ||
2490 | 2370 | ||
2491 | // *TODO: get this to play well with mouselook and hidden | 2371 | // *TODO: get this to play well with mouselook and hidden |
2492 | // cursor modes, etc, and re-enable. | 2372 | // cursor modes, etc, and re-enable. |
@@ -2495,7 +2375,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) | |||
2495 | // gFocusMgr.setMouseCapture(NULL); | 2375 | // gFocusMgr.setMouseCapture(NULL); |
2496 | // return TRUE; | 2376 | // return TRUE; |
2497 | //} | 2377 | //} |
2498 | } | 2378 | //} |
2499 | 2379 | ||
2500 | // let menus handle navigation keys | 2380 | // let menus handle navigation keys |
2501 | if (gMenuBarView && gMenuBarView->handleKey(key, mask, TRUE)) | 2381 | if (gMenuBarView && gMenuBarView->handleKey(key, mask, TRUE)) |
@@ -2667,7 +2547,7 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask) | |||
2667 | 2547 | ||
2668 | void LLViewerWindow::handleScrollWheel(S32 clicks) | 2548 | void LLViewerWindow::handleScrollWheel(S32 clicks) |
2669 | { | 2549 | { |
2670 | LLView::sMouseHandlerMessage = ""; | 2550 | LLView::sMouseHandlerMessage.clear(); |
2671 | 2551 | ||
2672 | gMouseIdleTimer.reset(); | 2552 | gMouseIdleTimer.reset(); |
2673 | 2553 | ||
@@ -2743,7 +2623,11 @@ BOOL LLViewerWindow::handlePerFrameHover() | |||
2743 | { | 2623 | { |
2744 | static std::string last_handle_msg; | 2624 | static std::string last_handle_msg; |
2745 | 2625 | ||
2746 | LLView::sMouseHandlerMessage = ""; | 2626 | LLView::sMouseHandlerMessage.clear(); |
2627 | |||
2628 | S32 x = mCurrentMousePoint.mX; | ||
2629 | S32 y = mCurrentMousePoint.mY; | ||
2630 | MASK mask = gKeyboard->currentMask(TRUE); | ||
2747 | 2631 | ||
2748 | //RN: fix for asynchronous notification of mouse leaving window not working | 2632 | //RN: fix for asynchronous notification of mouse leaving window not working |
2749 | LLCoordWindow mouse_pos; | 2633 | LLCoordWindow mouse_pos; |
@@ -2760,6 +2644,7 @@ BOOL LLViewerWindow::handlePerFrameHover() | |||
2760 | mMouseInWindow = TRUE; | 2644 | mMouseInWindow = TRUE; |
2761 | } | 2645 | } |
2762 | 2646 | ||
2647 | |||
2763 | S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]); | 2648 | S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]); |
2764 | S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]); | 2649 | S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]); |
2765 | 2650 | ||
@@ -2790,10 +2675,6 @@ BOOL LLViewerWindow::handlePerFrameHover() | |||
2790 | return TRUE; | 2675 | return TRUE; |
2791 | } | 2676 | } |
2792 | 2677 | ||
2793 | S32 x = mCurrentMousePoint.mX; | ||
2794 | S32 y = mCurrentMousePoint.mY; | ||
2795 | MASK mask = gKeyboard->currentMask(TRUE); | ||
2796 | |||
2797 | // clean up current focus | 2678 | // clean up current focus |
2798 | LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus(); | 2679 | LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus(); |
2799 | if (cur_focus) | 2680 | if (cur_focus) |
@@ -2829,13 +2710,6 @@ BOOL LLViewerWindow::handlePerFrameHover() | |||
2829 | } | 2710 | } |
2830 | } | 2711 | } |
2831 | 2712 | ||
2832 | gPipeline.sRenderProcessBeacons = FALSE; | ||
2833 | KEY key = gKeyboard->currentKey(); | ||
2834 | if (((mask & MASK_CONTROL) && ('N' == key || 'n' == key)) || gSavedSettings.getBOOL("BeaconAlwaysOn")) | ||
2835 | { | ||
2836 | gPipeline.sRenderProcessBeacons = TRUE; | ||
2837 | } | ||
2838 | |||
2839 | BOOL handled = FALSE; | 2713 | BOOL handled = FALSE; |
2840 | 2714 | ||
2841 | BOOL handled_by_top_ctrl = FALSE; | 2715 | BOOL handled_by_top_ctrl = FALSE; |
@@ -2884,9 +2758,9 @@ BOOL LLViewerWindow::handlePerFrameHover() | |||
2884 | } | 2758 | } |
2885 | else if (LLView::sDebugMouseHandling) | 2759 | else if (LLView::sDebugMouseHandling) |
2886 | { | 2760 | { |
2887 | if (last_handle_msg != "") | 2761 | if (last_handle_msg != LLStringUtil::null) |
2888 | { | 2762 | { |
2889 | last_handle_msg = ""; | 2763 | last_handle_msg.clear(); |
2890 | llinfos << "Hover not handled by view" << llendl; | 2764 | llinfos << "Hover not handled by view" << llendl; |
2891 | } | 2765 | } |
2892 | } | 2766 | } |
@@ -2928,10 +2802,9 @@ BOOL LLViewerWindow::handlePerFrameHover() | |||
2928 | 2802 | ||
2929 | } | 2803 | } |
2930 | 2804 | ||
2931 | //llinfos << (mToolTipBlocked ? "BLOCKED" : "NOT BLOCKED") << llendl; | ||
2932 | // Show a new tool tip (or update one that is alrady shown) | 2805 | // Show a new tool tip (or update one that is alrady shown) |
2933 | BOOL tool_tip_handled = FALSE; | 2806 | BOOL tool_tip_handled = FALSE; |
2934 | LLString tool_tip_msg; | 2807 | std::string tool_tip_msg; |
2935 | F32 tooltip_delay = gSavedSettings.getF32( "ToolTipDelay" ); | 2808 | F32 tooltip_delay = gSavedSettings.getF32( "ToolTipDelay" ); |
2936 | //HACK: hack for tool-based tooltips which need to pop up more quickly | 2809 | //HACK: hack for tool-based tooltips which need to pop up more quickly |
2937 | //Also for show xui names as tooltips debug mode | 2810 | //Also for show xui names as tooltips debug mode |
@@ -2940,38 +2813,48 @@ BOOL LLViewerWindow::handlePerFrameHover() | |||
2940 | tooltip_delay = gSavedSettings.getF32( "DragAndDropToolTipDelay" ); | 2813 | tooltip_delay = gSavedSettings.getF32( "DragAndDropToolTipDelay" ); |
2941 | } | 2814 | } |
2942 | if( handled && | 2815 | if( handled && |
2943 | !mToolTipBlocked && | 2816 | gMouseIdleTimer.getElapsedTimeF32() > tooltip_delay && |
2944 | (gMouseIdleTimer.getElapsedTimeF32() > tooltip_delay) && | 2817 | !mWindow->isCursorHidden() ) |
2945 | !mWindow->isCursorHidden() ) | ||
2946 | { | 2818 | { |
2947 | LLRect screen_sticky_rect; | 2819 | LLRect screen_sticky_rect; |
2948 | 2820 | LLMouseHandler *mh; | |
2821 | S32 local_x, local_y; | ||
2949 | if (mouse_captor) | 2822 | if (mouse_captor) |
2950 | { | 2823 | { |
2951 | S32 local_x, local_y; | 2824 | mouse_captor->screenPointToLocal(x, y, &local_x, &local_y); |
2952 | mouse_captor->screenPointToLocal( x, y, &local_x, &local_y ); | 2825 | mh = mouse_captor; |
2953 | tool_tip_handled = mouse_captor->handleToolTip( local_x, local_y, tool_tip_msg, &screen_sticky_rect ); | ||
2954 | } | 2826 | } |
2955 | else if (handled_by_top_ctrl) | 2827 | else if (handled_by_top_ctrl) |
2956 | { | 2828 | { |
2957 | S32 local_x, local_y; | 2829 | top_ctrl->screenPointToLocal(x, y, &local_x, &local_y); |
2958 | top_ctrl->screenPointToLocal( x, y, &local_x, &local_y ); | 2830 | mh = top_ctrl; |
2959 | tool_tip_handled = top_ctrl->handleToolTip( local_x, local_y, tool_tip_msg, &screen_sticky_rect ); | ||
2960 | } | 2831 | } |
2961 | else | 2832 | else |
2962 | { | 2833 | { |
2963 | tool_tip_handled = mRootView->handleToolTip(x, y, tool_tip_msg, &screen_sticky_rect ); | 2834 | local_x = x; local_y = y; |
2835 | mh = mRootView; | ||
2964 | } | 2836 | } |
2965 | 2837 | ||
2966 | if( tool_tip_handled && !tool_tip_msg.empty() ) | 2838 | BOOL tooltip_vis = FALSE; |
2839 | if (shouldShowToolTipFor(mh)) | ||
2967 | { | 2840 | { |
2968 | mToolTipStickyRect = screen_sticky_rect; | 2841 | tool_tip_handled = mh->handleToolTip(local_x, local_y, tool_tip_msg, &screen_sticky_rect ); |
2969 | mToolTip->setWrappedText( tool_tip_msg, 200 ); | 2842 | |
2970 | mToolTip->reshapeToFitText(); | 2843 | if( tool_tip_handled && !tool_tip_msg.empty() ) |
2971 | mToolTip->setOrigin( x, y ); | 2844 | { |
2972 | LLRect virtual_window_rect(0, getWindowHeight(), getWindowWidth(), 0); | 2845 | mToolTipStickyRect = screen_sticky_rect; |
2973 | mToolTip->translateIntoRect( virtual_window_rect, FALSE ); | 2846 | mToolTip->setWrappedText( tool_tip_msg, 200 ); |
2974 | mToolTip->setVisible( TRUE ); | 2847 | mToolTip->reshapeToFitText(); |
2848 | mToolTip->setOrigin( x, y ); | ||
2849 | LLRect virtual_window_rect(0, getWindowHeight(), getWindowWidth(), 0); | ||
2850 | mToolTip->translateIntoRect( virtual_window_rect, FALSE ); | ||
2851 | tooltip_vis = TRUE; | ||
2852 | } | ||
2853 | } | ||
2854 | |||
2855 | if (mToolTip) | ||
2856 | { | ||
2857 | mToolTip->setVisible( tooltip_vis ); | ||
2975 | } | 2858 | } |
2976 | } | 2859 | } |
2977 | 2860 | ||
@@ -3135,10 +3018,65 @@ BOOL LLViewerWindow::handlePerFrameHover() | |||
3135 | LLSelectMgr::getInstance()->deselectUnused(); | 3018 | LLSelectMgr::getInstance()->deselectUnused(); |
3136 | } | 3019 | } |
3137 | 3020 | ||
3021 | if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) | ||
3022 | { | ||
3023 | gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, | ||
3024 | NULL, | ||
3025 | &gDebugRaycastIntersection, | ||
3026 | &gDebugRaycastTexCoord, | ||
3027 | &gDebugRaycastNormal, | ||
3028 | &gDebugRaycastBinormal); | ||
3029 | } | ||
3030 | |||
3031 | |||
3032 | // per frame picking - for tooltips and changing cursor over interactive objects | ||
3033 | static S32 previous_x = -1; | ||
3034 | static S32 previous_y = -1; | ||
3035 | static BOOL mouse_moved_since_pick = FALSE; | ||
3036 | |||
3037 | if ((previous_x != x) || (previous_y != y)) | ||
3038 | mouse_moved_since_pick = TRUE; | ||
3039 | |||
3040 | BOOL do_pick = FALSE; | ||
3041 | |||
3042 | F32 picks_moving = gSavedSettings.getF32("PicksPerSecondMouseMoving"); | ||
3043 | if ((mouse_moved_since_pick) && (picks_moving > 0.0) && (mPickTimer.getElapsedTimeF32() > 1.0f / picks_moving)) | ||
3044 | { | ||
3045 | do_pick = TRUE; | ||
3046 | } | ||
3047 | |||
3048 | F32 picks_stationary = gSavedSettings.getF32("PicksPerSecondMouseStationary"); | ||
3049 | if ((!mouse_moved_since_pick) && (picks_stationary > 0.0) && (mPickTimer.getElapsedTimeF32() > 1.0f / picks_stationary)) | ||
3050 | { | ||
3051 | do_pick = TRUE; | ||
3052 | } | ||
3053 | |||
3054 | if (getCursorHidden()) | ||
3055 | { | ||
3056 | do_pick = FALSE; | ||
3057 | } | ||
3058 | |||
3059 | if (do_pick) | ||
3060 | { | ||
3061 | mouse_moved_since_pick = FALSE; | ||
3062 | mPickTimer.reset(); | ||
3063 | pickAsync(getCurrentMouseX(), getCurrentMouseY(), mask, hoverPickCallback, TRUE); | ||
3064 | } | ||
3065 | |||
3066 | previous_x = x; | ||
3067 | previous_y = y; | ||
3068 | |||
3138 | return handled; | 3069 | return handled; |
3139 | } | 3070 | } |
3140 | 3071 | ||
3141 | 3072 | ||
3073 | /* static */ | ||
3074 | void LLViewerWindow::hoverPickCallback(const LLPickInfo& pick_info) | ||
3075 | { | ||
3076 | gViewerWindow->mHoverPick = pick_info; | ||
3077 | } | ||
3078 | |||
3079 | |||
3142 | void LLViewerWindow::saveLastMouse(const LLCoordGL &point) | 3080 | void LLViewerWindow::saveLastMouse(const LLCoordGL &point) |
3143 | { | 3081 | { |
3144 | // Store last mouse location. | 3082 | // Store last mouse location. |
@@ -3232,7 +3170,7 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, | |||
3232 | glPushMatrix(); | 3170 | glPushMatrix(); |
3233 | if (selection->getSelectType() == SELECT_TYPE_HUD) | 3171 | if (selection->getSelectType() == SELECT_TYPE_HUD) |
3234 | { | 3172 | { |
3235 | F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom; | 3173 | F32 zoom = gAgent.mHUDCurZoom; |
3236 | glScalef(zoom, zoom, zoom); | 3174 | glScalef(zoom, zoom, zoom); |
3237 | } | 3175 | } |
3238 | 3176 | ||
@@ -3384,19 +3322,14 @@ BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewe | |||
3384 | return intersect; | 3322 | return intersect; |
3385 | } | 3323 | } |
3386 | 3324 | ||
3387 | 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) | 3325 | void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent, BOOL get_surface_info) |
3388 | { | 3326 | { |
3389 | if (gNoRender) | 3327 | if (gNoRender) |
3390 | { | 3328 | { |
3391 | return; | 3329 | return; |
3392 | } | 3330 | } |
3393 | 3331 | ||
3394 | glClear(GL_DEPTH_BUFFER_BIT); | 3332 | // push back pick info object |
3395 | gDepthDirty = TRUE; | ||
3396 | |||
3397 | S32 scaled_x = llround((F32)x * mDisplayScale.mV[VX]); | ||
3398 | S32 scaled_y = llround((F32)y_from_bot * mDisplayScale.mV[VY]); | ||
3399 | |||
3400 | BOOL in_build_mode = gFloaterTools && gFloaterTools->getVisible(); | 3333 | BOOL in_build_mode = gFloaterTools && gFloaterTools->getVisible(); |
3401 | if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha) | 3334 | if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha) |
3402 | { | 3335 | { |
@@ -3404,129 +3337,62 @@ void LLViewerWindow::hitObjectOrLandGlobalAsync(S32 x, S32 y_from_bot, MASK mask | |||
3404 | // "Show Debug Alpha" means no object actually transparent | 3337 | // "Show Debug Alpha" means no object actually transparent |
3405 | pick_transparent = TRUE; | 3338 | pick_transparent = TRUE; |
3406 | } | 3339 | } |
3407 | gPickTransparent = pick_transparent; | ||
3408 | |||
3409 | gUseGLPick = FALSE; | ||
3410 | mPickCallback = callback; | ||
3411 | |||
3412 | // Default to not hitting anything | ||
3413 | gLastHitPosGlobal.zeroVec(); | ||
3414 | gLastHitObjectOffset.zeroVec(); | ||
3415 | gLastHitObjectID.setNull(); | ||
3416 | gLastHitObjectFace = -1; | ||
3417 | |||
3418 | gLastHitNonFloraPosGlobal.zeroVec(); | ||
3419 | gLastHitNonFloraObjectOffset.zeroVec(); | ||
3420 | gLastHitNonFloraObjectID.setNull(); | ||
3421 | gLastHitNonFloraObjectFace = -1; | ||
3422 | |||
3423 | gLastHitParcelWall = FALSE; | ||
3424 | |||
3425 | LLCamera pick_camera; | ||
3426 | pick_camera.setOrigin(LLViewerCamera::getInstance()->getOrigin()); | ||
3427 | pick_camera.setOriginAndLookAt(LLViewerCamera::getInstance()->getOrigin(), | ||
3428 | LLViewerCamera::getInstance()->getUpAxis(), | ||
3429 | LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(x, y_from_bot)); | ||
3430 | pick_camera.setView(0.5f*DEG_TO_RAD); | ||
3431 | pick_camera.setNear(LLViewerCamera::getInstance()->getNear()); | ||
3432 | pick_camera.setFar(LLViewerCamera::getInstance()->getFar()); | ||
3433 | pick_camera.setAspect(1.f); | ||
3434 | |||
3435 | // save our drawing state | ||
3436 | // *TODO: should we be saving using the new method here using | ||
3437 | // glh_get_current_projection/glh_set_current_projection? -brad | ||
3438 | glMatrixMode(GL_MODELVIEW); | ||
3439 | glPushMatrix(); | ||
3440 | glLoadIdentity(); | ||
3441 | |||
3442 | glMatrixMode(GL_PROJECTION); | ||
3443 | glPushMatrix(); | ||
3444 | glLoadIdentity(); | ||
3445 | |||
3446 | // build perspective transform and picking viewport | ||
3447 | // Perform pick on a PICK_DIAMETER x PICK_DIAMETER pixel region around cursor point. | ||
3448 | // Don't limit the select distance for this pick. | ||
3449 | LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - (PICK_HALF_WIDTH + 2), scaled_y - (PICK_HALF_WIDTH + 2), PICK_DIAMETER + 4, PICK_DIAMETER + 4, FALSE); | ||
3450 | // make viewport big enough to handle antialiased frame buffers | ||
3451 | gGLViewport[0] = scaled_x - (PICK_HALF_WIDTH + 2); | ||
3452 | gGLViewport[1] = scaled_y - (PICK_HALF_WIDTH + 2); | ||
3453 | gGLViewport[2] = PICK_DIAMETER + 4; | ||
3454 | gGLViewport[3] = PICK_DIAMETER + 4; | ||
3455 | glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); | ||
3456 | LLViewerCamera::updateFrustumPlanes(pick_camera); | ||
3457 | stop_glerror(); | ||
3458 | 3340 | ||
3459 | glClearColor(0.f, 0.f, 0.f, 0.f); | 3341 | // center initial pick frame buffer region under mouse cursor |
3460 | glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | 3342 | // since that area is guaranteed to be onscreen and hence a valid |
3461 | //glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | 3343 | // part of the framebuffer |
3462 | 3344 | if (mPicks.empty()) | |
3463 | // Draw the objects so the user can select them. | 3345 | { |
3464 | // The starting ID is 1, since land is zero. | 3346 | mPickScreenRegion.setCenterAndSize(x, y_from_bot, PICK_DIAMETER, PICK_DIAMETER); |
3465 | gObjectList.renderObjectsForSelect(pick_camera, pick_parcel_walls); | ||
3466 | |||
3467 | stop_glerror(); | ||
3468 | 3347 | ||
3469 | // restore drawing state | 3348 | if (mPickScreenRegion.mLeft < 0) mPickScreenRegion.translate(-mPickScreenRegion.mLeft, 0); |
3470 | glMatrixMode(GL_PROJECTION); | 3349 | if (mPickScreenRegion.mBottom < 0) mPickScreenRegion.translate(0, -mPickScreenRegion.mBottom); |
3471 | glPopMatrix(); | 3350 | if (mPickScreenRegion.mRight > mWindowRect.getWidth() ) mPickScreenRegion.translate(mWindowRect.getWidth() - mPickScreenRegion.mRight, 0); |
3472 | glMatrixMode(GL_MODELVIEW); | 3351 | if (mPickScreenRegion.mTop > mWindowRect.getHeight() ) mPickScreenRegion.translate(0, mWindowRect.getHeight() - mPickScreenRegion.mTop); |
3473 | glPopMatrix(); | 3352 | } |
3474 | 3353 | ||
3475 | setupViewport(); | 3354 | // set frame buffer region for picking results |
3355 | // stack multiple picks left to right | ||
3356 | LLRect screen_region = mPickScreenRegion; | ||
3357 | screen_region.translate(mPicks.size() * PICK_DIAMETER, 0); | ||
3476 | 3358 | ||
3477 | mPickPoint.set(x, y_from_bot); | 3359 | LLPickInfo pick(LLCoordGL(x, y_from_bot), screen_region, mask, pick_transparent, get_surface_info, callback); |
3478 | mPickOffset.set(0, 0); | ||
3479 | mPickMask = mask; | ||
3480 | mPickPending = TRUE; | ||
3481 | 3360 | ||
3482 | // delay further event processing until we receive results of pick | 3361 | schedulePick(pick); |
3483 | mWindow->delayInputProcessing(); | ||
3484 | } | 3362 | } |
3485 | 3363 | ||
3486 | void LLViewerWindow::hitUIElementImmediate(S32 x, S32 y, void (*callback)(S32 x, S32 y, MASK mask)) | 3364 | void LLViewerWindow::schedulePick(LLPickInfo& pick_info) |
3487 | { | 3365 | { |
3488 | // Performs the GL UI pick. | 3366 | if (mPicks.size() >= 1024 || mWindow->getMinimized()) |
3489 | // Stores its results in global, gLastHitUIElement | 3367 | { //something went wrong, picks are being scheduled but not processed |
3490 | if (gNoRender) | 3368 | |
3491 | { | 3369 | if (pick_info.mPickCallback) |
3492 | return; | 3370 | { |
3493 | } | 3371 | pick_info.mPickCallback(pick_info); |
3372 | } | ||
3494 | 3373 | ||
3495 | hitUIElementAsync(x, y, gKeyboard->currentMask(TRUE), NULL); | ||
3496 | performPick(); | ||
3497 | if (callback) | ||
3498 | { | ||
3499 | callback(x, y, gKeyboard->currentMask(TRUE)); | ||
3500 | } | ||
3501 | } | ||
3502 | |||
3503 | //RN: this currently doesn't do anything | ||
3504 | void LLViewerWindow::hitUIElementAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(S32 x, S32 y, MASK mask)) | ||
3505 | { | ||
3506 | if (gNoRender) | ||
3507 | { | ||
3508 | return; | 3374 | return; |
3509 | } | 3375 | } |
3510 | 3376 | llassert_always(pick_info.mScreenRegion.notNull()); | |
3511 | // F32 delta_time = gAlphaFadeTimer.getElapsedTimeAndResetF32(); | 3377 | mPicks.push_back(pick_info); |
3512 | 3378 | ||
3513 | gUseGLPick = FALSE; | 3379 | S32 scaled_x = llround((F32)pick_info.mMousePt.mX * mDisplayScale.mV[VX]); |
3514 | mPickCallback = callback; | 3380 | S32 scaled_y = llround((F32)pick_info.mMousePt.mY * mDisplayScale.mV[VY]); |
3515 | 3381 | ||
3516 | // Default to not hitting anything | 3382 | // Default to not hitting anything |
3517 | gLastHitUIElement = 0; | ||
3518 | |||
3519 | LLCamera pick_camera; | 3383 | LLCamera pick_camera; |
3520 | pick_camera.setOrigin(LLViewerCamera::getInstance()->getOrigin()); | 3384 | pick_camera.setOrigin(LLViewerCamera::getInstance()->getOrigin()); |
3521 | pick_camera.setOriginAndLookAt(LLViewerCamera::getInstance()->getOrigin(), | 3385 | pick_camera.setOriginAndLookAt(LLViewerCamera::getInstance()->getOrigin(), |
3522 | LLViewerCamera::getInstance()->getUpAxis(), | 3386 | LLViewerCamera::getInstance()->getUpAxis(), |
3523 | LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(x, y_from_bot)); | 3387 | LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(pick_info.mMousePt.mX, pick_info.mMousePt.mY)); |
3524 | pick_camera.setView(0.5f*DEG_TO_RAD); | 3388 | pick_camera.setView(0.5f*DEG_TO_RAD); |
3525 | pick_camera.setNear(LLViewerCamera::getInstance()->getNear()); | 3389 | pick_camera.setNear(LLViewerCamera::getInstance()->getNear()); |
3526 | pick_camera.setFar(LLViewerCamera::getInstance()->getFar()); | 3390 | pick_camera.setFar(LLViewerCamera::getInstance()->getFar()); |
3527 | pick_camera.setAspect(1.f); | 3391 | pick_camera.setAspect(1.f); |
3528 | 3392 | ||
3529 | // save our drawing state | 3393 | // save our drawing state |
3394 | // *TODO: should we be saving using the new method here using | ||
3395 | // glh_get_current_projection/glh_set_current_projection? -brad | ||
3530 | glMatrixMode(GL_MODELVIEW); | 3396 | glMatrixMode(GL_MODELVIEW); |
3531 | glPushMatrix(); | 3397 | glPushMatrix(); |
3532 | glLoadIdentity(); | 3398 | glLoadIdentity(); |
@@ -3535,25 +3401,39 @@ void LLViewerWindow::hitUIElementAsync(S32 x, S32 y_from_bot, MASK mask, void (* | |||
3535 | glPushMatrix(); | 3401 | glPushMatrix(); |
3536 | glLoadIdentity(); | 3402 | glLoadIdentity(); |
3537 | 3403 | ||
3538 | // build orthogonal transform and picking viewport | 3404 | // clear work area |
3405 | { | ||
3406 | LLGLState scissor_state(GL_SCISSOR_TEST); | ||
3407 | scissor_state.enable(); | ||
3408 | glScissor(pick_info.mScreenRegion.mLeft, pick_info.mScreenRegion.mBottom, pick_info.mScreenRegion.getWidth(), pick_info.mScreenRegion.getHeight()); | ||
3409 | glClearColor(0.f, 0.f, 0.f, 0.f); | ||
3410 | glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | ||
3411 | //glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | ||
3412 | } | ||
3413 | |||
3414 | // build perspective transform and picking viewport | ||
3539 | // Perform pick on a PICK_DIAMETER x PICK_DIAMETER pixel region around cursor point. | 3415 | // Perform pick on a PICK_DIAMETER x PICK_DIAMETER pixel region around cursor point. |
3540 | // Don't limit the select distance for this pick. | 3416 | // Don't limit the select distance for this pick. |
3541 | setup2DRender(); | 3417 | LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - PICK_HALF_WIDTH, scaled_y - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER, FALSE); |
3542 | const LLVector2& display_scale = getDisplayScale(); | ||
3543 | glScalef(display_scale.mV[VX], display_scale.mV[VY], 1.f); | ||
3544 | 3418 | ||
3545 | gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); | 3419 | // render for object picking |
3546 | 3420 | ||
3547 | // make viewport big enough to handle antialiased frame buffers | 3421 | // make viewport big enough to handle antialiased frame buffers |
3548 | glViewport(x - (PICK_HALF_WIDTH + 2), y_from_bot - (PICK_HALF_WIDTH + 2), PICK_DIAMETER + 4, PICK_DIAMETER + 4); | 3422 | gGLViewport[0] = pick_info.mScreenRegion.mLeft; |
3549 | stop_glerror(); | 3423 | gGLViewport[1] = pick_info.mScreenRegion.mBottom; |
3424 | gGLViewport[2] = pick_info.mScreenRegion.getWidth(); | ||
3425 | gGLViewport[3] = pick_info.mScreenRegion.getHeight(); | ||
3550 | 3426 | ||
3551 | glClearColor(0.f, 0.f, 0.f, 0.f); | 3427 | glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); |
3552 | glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); | 3428 | LLViewerCamera::updateFrustumPlanes(pick_camera); |
3429 | stop_glerror(); | ||
3553 | 3430 | ||
3554 | // Draw the objects so the user can select them. | 3431 | // Draw the objects so the user can select them. |
3555 | // The starting ID is 1, since land is zero. | 3432 | // The starting ID is 1, since land is zero. |
3556 | //drawForSelect(); | 3433 | LLRect pick_region; |
3434 | pick_region.setOriginAndSize(pick_info.mMousePt.mX - PICK_HALF_WIDTH, | ||
3435 | pick_info.mMousePt.mY - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER); | ||
3436 | gObjectList.renderObjectsForSelect(pick_camera, pick_region, FALSE, pick_info.mPickTransparent); | ||
3557 | 3437 | ||
3558 | stop_glerror(); | 3438 | stop_glerror(); |
3559 | 3439 | ||
@@ -3563,309 +3443,135 @@ void LLViewerWindow::hitUIElementAsync(S32 x, S32 y_from_bot, MASK mask, void (* | |||
3563 | glMatrixMode(GL_MODELVIEW); | 3443 | glMatrixMode(GL_MODELVIEW); |
3564 | glPopMatrix(); | 3444 | glPopMatrix(); |
3565 | 3445 | ||
3446 | setup3DRender(); | ||
3447 | setup2DRender(); | ||
3566 | setupViewport(); | 3448 | setupViewport(); |
3567 | 3449 | ||
3568 | mPickPoint.set(x, y_from_bot); | 3450 | // delay further event processing until we receive results of pick |
3569 | mPickOffset.set(0, 0); | 3451 | mWindow->delayInputProcessing(); |
3570 | mPickMask = mask; | ||
3571 | mPickPending = TRUE; | ||
3572 | } | 3452 | } |
3573 | 3453 | ||
3454 | |||
3574 | void LLViewerWindow::performPick() | 3455 | void LLViewerWindow::performPick() |
3575 | { | 3456 | { |
3576 | if (gNoRender || !mPickPending) | 3457 | if (gNoRender) |
3577 | { | 3458 | { |
3578 | return; | 3459 | return; |
3579 | } | 3460 | } |
3580 | 3461 | ||
3581 | mPickPending = FALSE; | 3462 | if (!mPicks.empty()) |
3582 | U32 te_offset = NO_FACE; | ||
3583 | |||
3584 | // find pick region that is fully onscreen | ||
3585 | LLCoordGL scaled_pick_point = mPickPoint; | ||
3586 | scaled_pick_point.mX = llclamp(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX]), PICK_HALF_WIDTH, getWindowDisplayWidth() - PICK_HALF_WIDTH); | ||
3587 | scaled_pick_point.mY = llclamp(llround((F32)mPickPoint.mY * mDisplayScale.mV[VY]), PICK_HALF_WIDTH, getWindowDisplayHeight() - PICK_HALF_WIDTH); | ||
3588 | |||
3589 | 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); | ||
3590 | |||
3591 | S32 pixel_index = PICK_HALF_WIDTH * PICK_DIAMETER + PICK_HALF_WIDTH; | ||
3592 | S32 name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2]; | ||
3593 | gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3]; | ||
3594 | |||
3595 | if (name >= (S32)GL_NAME_UI_RESERVED && name < (S32)GL_NAME_INDEX_OFFSET) | ||
3596 | { | ||
3597 | // hit a UI element | ||
3598 | gLastHitUIElement = name; | ||
3599 | if (mPickCallback) | ||
3600 | { | ||
3601 | mPickCallback(mPickPoint.mX, mPickPoint.mY, mPickMask); | ||
3602 | } | ||
3603 | } | ||
3604 | |||
3605 | //imdebug("rgba rbga=bbba b=8 w=%d h=%d %p", PICK_DIAMETER, PICK_DIAMETER, mPickBuffer); | ||
3606 | |||
3607 | S32 x_offset = mPickPoint.mX - llround((F32)scaled_pick_point.mX / mDisplayScale.mV[VX]); | ||
3608 | S32 y_offset = mPickPoint.mY - llround((F32)scaled_pick_point.mY / mDisplayScale.mV[VY]); | ||
3609 | |||
3610 | |||
3611 | // we hit nothing, scan surrounding pixels for something useful | ||
3612 | if (!name) | ||
3613 | { | 3463 | { |
3614 | S32 closest_distance = 10000; | 3464 | std::vector<LLPickInfo>::iterator pick_it; |
3615 | //S32 closest_pick_name = 0; | 3465 | for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it) |
3616 | for (S32 col = 0; col < PICK_DIAMETER; col++) | ||
3617 | { | 3466 | { |
3618 | for (S32 row = 0; row < PICK_DIAMETER; row++) | 3467 | pick_it->fetchResults(); |
3619 | { | ||
3620 | 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)); | ||
3621 | pixel_index = row * PICK_DIAMETER + col; | ||
3622 | S32 test_name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2]; | ||
3623 | gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3]; | ||
3624 | if (test_name && distance_squared < closest_distance) | ||
3625 | { | ||
3626 | closest_distance = distance_squared; | ||
3627 | name = test_name; | ||
3628 | gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3]; | ||
3629 | mPickOffset.mX = col - PICK_HALF_WIDTH; | ||
3630 | mPickOffset.mY = row - PICK_HALF_WIDTH; | ||
3631 | } | ||
3632 | } | ||
3633 | } | 3468 | } |
3634 | } | ||
3635 | |||
3636 | if (name) | ||
3637 | { | ||
3638 | mPickPoint.mX += llround((F32)mPickOffset.mX * mDisplayScale.mV[VX]); | ||
3639 | mPickPoint.mY += llround((F32)mPickOffset.mY * mDisplayScale.mV[VY]); | ||
3640 | } | ||
3641 | |||
3642 | if (gPickFaces) | ||
3643 | { | ||
3644 | te_offset = ((U32)name >> 20); | ||
3645 | name &= 0x000fffff; | ||
3646 | // don't clear gPickFaces, as we still need to check for UV coordinates | ||
3647 | } | ||
3648 | |||
3649 | LLViewerObject *objectp = NULL; | ||
3650 | 3469 | ||
3651 | // Frontmost non-foreground object that isn't trees or grass | 3470 | mLastPick = mPicks.back(); |
3652 | LLViewerObject* nonflora_objectp = NULL; | 3471 | mPicks.clear(); |
3653 | S32 nonflora_name = -1; | ||
3654 | S32 nonflora_te_offset = NO_FACE; | ||
3655 | |||
3656 | if (name == (S32)GL_NAME_PARCEL_WALL) | ||
3657 | { | ||
3658 | gLastHitParcelWall = TRUE; | ||
3659 | } | 3472 | } |
3473 | } | ||
3660 | 3474 | ||
3661 | gLastHitHUDIcon = NULL; | 3475 | void LLViewerWindow::returnEmptyPicks() |
3662 | 3476 | { | |
3663 | objectp = gObjectList.getSelectedObject(name); | 3477 | std::vector<LLPickInfo>::iterator pick_it; |
3664 | if (objectp) | 3478 | for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it) |
3665 | { | 3479 | { |
3666 | LLViewerObject* parent = (LLViewerObject*)(objectp->getParent()); | 3480 | mLastPick = *pick_it; |
3667 | if (NULL == parent) { | 3481 | // just trigger callback with empty results |
3668 | // if you are the parent | 3482 | if (pick_it->mPickCallback) |
3669 | parent = objectp; | ||
3670 | } | ||
3671 | if (objectp->mbCanSelect) | ||
3672 | { | ||
3673 | te_offset = (te_offset == 16) ? NO_FACE : te_offset; | ||
3674 | |||
3675 | // If the hit object isn't a plant, store it as the frontmost non-flora object. | ||
3676 | LLPCode pcode = objectp->getPCode(); | ||
3677 | if( (LL_PCODE_LEGACY_GRASS != pcode) && | ||
3678 | (LL_PCODE_LEGACY_TREE != pcode) && | ||
3679 | (LL_PCODE_TREE_NEW != pcode)) | ||
3680 | { | ||
3681 | nonflora_objectp = objectp; | ||
3682 | nonflora_name = name; | ||
3683 | nonflora_te_offset = te_offset; | ||
3684 | } | ||
3685 | } | ||
3686 | else | ||
3687 | { | 3483 | { |
3688 | //llinfos << "Hit object you can't select" << llendl; | 3484 | pick_it->mPickCallback(*pick_it); |
3689 | } | 3485 | } |
3690 | } | 3486 | } |
3691 | else | 3487 | mPicks.clear(); |
3692 | { | 3488 | } |
3693 | // was this name referring to a hud icon? | ||
3694 | gLastHitHUDIcon = LLHUDIcon::handlePick(name); | ||
3695 | } | ||
3696 | |||
3697 | analyzeHit( | ||
3698 | mPickPoint.mX, mPickPoint.mY, objectp, te_offset, | ||
3699 | &gLastHitObjectID, &gLastHitObjectFace, &gLastHitPosGlobal, &gLastHitLand, &gLastHitUCoord, &gLastHitVCoord ); | ||
3700 | |||
3701 | if (objectp && !gLastHitObjectID.isNull()) | ||
3702 | { | ||
3703 | gLastHitObjectOffset = gAgent.calcFocusOffset(objectp, mPickPoint.mX, mPickPoint.mY); | ||
3704 | } | ||
3705 | 3489 | ||
3706 | if( objectp == nonflora_objectp ) | 3490 | // Performs the GL object/land pick. |
3707 | { | 3491 | LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent) |
3708 | gLastHitNonFloraObjectID = gLastHitObjectID; | 3492 | { |
3709 | gLastHitNonFloraObjectFace = gLastHitObjectFace; | 3493 | if (gNoRender) |
3710 | gLastHitNonFloraPosGlobal = gLastHitPosGlobal; | ||
3711 | gLastHitNonFloraObjectOffset= gLastHitObjectOffset; | ||
3712 | } | ||
3713 | else | ||
3714 | { | 3494 | { |
3715 | analyzeHit( mPickPoint.mX, mPickPoint.mY, nonflora_objectp, nonflora_te_offset, | 3495 | return LLPickInfo(); |
3716 | &gLastHitNonFloraObjectID, &gLastHitNonFloraObjectFace, &gLastHitNonFloraPosGlobal, | ||
3717 | &gLastHitLand, &gLastHitUCoord, &gLastHitVCoord); | ||
3718 | |||
3719 | if( nonflora_objectp ) | ||
3720 | { | ||
3721 | gLastHitNonFloraObjectOffset = gAgent.calcFocusOffset(nonflora_objectp, mPickPoint.mX, mPickPoint.mY); | ||
3722 | } | ||
3723 | } | 3496 | } |
3724 | 3497 | ||
3725 | if (mPickCallback) | 3498 | pickAsync(x, y_from_bot, gKeyboard->currentMask(TRUE), NULL, pick_transparent); |
3726 | { | 3499 | // assume that pickAsync put the results in the back of the mPicks list |
3727 | mPickCallback(mPickPoint.mX, mPickPoint.mY, mPickMask); | 3500 | mLastPick = mPicks.back(); |
3728 | } | 3501 | mLastPick.fetchResults(); |
3502 | mPicks.pop_back(); | ||
3729 | 3503 | ||
3730 | gPickFaces = FALSE; | 3504 | return mLastPick; |
3731 | } | 3505 | } |
3732 | 3506 | ||
3733 | // Performs the GL object/land pick. | 3507 | LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 depth, |
3734 | // Stores its results in globals, gHit* | 3508 | LLViewerObject *this_object, |
3735 | void LLViewerWindow::hitObjectOrLandGlobalImmediate(S32 x, S32 y_from_bot, void (*callback)(S32 x, S32 y, MASK mask), BOOL pick_transparent) | 3509 | S32 this_face, |
3510 | S32* face_hit, | ||
3511 | LLVector3 *intersection, | ||
3512 | LLVector2 *uv, | ||
3513 | LLVector3 *normal, | ||
3514 | LLVector3 *binormal) | ||
3736 | { | 3515 | { |
3737 | if (gNoRender) | 3516 | S32 x = mouse_x; |
3738 | { | 3517 | S32 y = mouse_y; |
3739 | return; | 3518 | |
3740 | } | 3519 | if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position |
3741 | |||
3742 | hitObjectOrLandGlobalAsync(x, y_from_bot, gKeyboard->currentMask(TRUE), NULL, pick_transparent); | ||
3743 | performPick(); | ||
3744 | if (callback) | ||
3745 | { | 3520 | { |
3746 | callback(x, y_from_bot, gKeyboard->currentMask(TRUE)); | 3521 | x = getCurrentMouseX(); |
3522 | y = getCurrentMouseY(); | ||
3747 | } | 3523 | } |
3748 | } | ||
3749 | 3524 | ||
3750 | LLViewerObject* LLViewerWindow::getObjectUnderCursor(const F32 depth) | 3525 | // HUD coordinates of mouse |
3751 | { | 3526 | LLVector3 mouse_point_hud = mousePointHUD(x, y); |
3752 | S32 x = getCurrentMouseX(); | 3527 | LLVector3 mouse_hud_start = mouse_point_hud - LLVector3(depth, 0, 0); |
3753 | S32 y = getCurrentMouseY(); | 3528 | LLVector3 mouse_hud_end = mouse_point_hud + LLVector3(depth, 0, 0); |
3754 | 3529 | ||
3530 | // world coordinates of mouse | ||
3755 | LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y); | 3531 | LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y); |
3756 | LLVector3 camera_pos_global = LLViewerCamera::getInstance()->getOrigin(); | 3532 | LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin(); |
3757 | LLVector3 pick_end = camera_pos_global + mouse_direction_global * depth; | 3533 | LLVector3 mouse_world_start = mouse_point_global; |
3758 | LLVector3 collision_point; | 3534 | LLVector3 mouse_world_end = mouse_point_global + mouse_direction_global * depth; |
3759 | return gPipeline.pickObject(camera_pos_global, pick_end, collision_point); | ||
3760 | } | ||
3761 | |||
3762 | void LLViewerWindow::analyzeHit( | ||
3763 | S32 x, // input | ||
3764 | S32 y_from_bot, // input | ||
3765 | LLViewerObject* objectp, // input | ||
3766 | U32 te_offset, // input | ||
3767 | LLUUID* hit_object_id_p,// output | ||
3768 | S32* hit_face_p, // output | ||
3769 | LLVector3d* hit_pos_p, // output | ||
3770 | BOOL* hit_land, // output | ||
3771 | F32* hit_u_coord, // output | ||
3772 | F32* hit_v_coord) // output | ||
3773 | { | ||
3774 | // Clean up inputs | ||
3775 | S32 face = -1; | ||
3776 | |||
3777 | if (te_offset != NO_FACE ) | ||
3778 | { | ||
3779 | face = te_offset; | ||
3780 | } | ||
3781 | 3535 | ||
3782 | *hit_land = FALSE; | 3536 | |
3537 | LLViewerObject* found = NULL; | ||
3783 | 3538 | ||
3784 | if (objectp) | 3539 | if (this_object) // check only this object |
3785 | { | 3540 | { |
3786 | if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH ) | 3541 | if (this_object->isHUDAttachment()) // is a HUD object? |
3787 | { | 3542 | { |
3788 | // Hit land | 3543 | if (this_object->lineSegmentIntersect(mouse_hud_start, mouse_hud_end, this_face, |
3789 | *hit_land = TRUE; | 3544 | face_hit, intersection, uv, normal, binormal)) |
3790 | |||
3791 | // put global position into land_pos | ||
3792 | LLVector3d land_pos; | ||
3793 | if (mousePointOnLandGlobal(x, y_from_bot, &land_pos)) | ||
3794 | { | 3545 | { |
3795 | *hit_object_id_p = LLUUID::null; | 3546 | found = this_object; |
3796 | *hit_face_p = -1; | ||
3797 | |||
3798 | // Fudge the land focus a little bit above ground. | ||
3799 | *hit_pos_p = land_pos + LLVector3d(0.f, 0.f, 0.1f); | ||
3800 | //llinfos << "DEBUG Hit Land " << *hit_pos_p << llendl; | ||
3801 | return; | ||
3802 | } | 3547 | } |
3803 | else | ||
3804 | { | ||
3805 | //llinfos << "Hit land but couldn't find position" << llendl; | ||
3806 | // Fall through to "Didn't hit anything" | ||
3807 | } | 3548 | } |
3808 | } | 3549 | |
3809 | else | 3550 | else // is a world object |
3810 | { | 3551 | { |
3811 | *hit_object_id_p = objectp->mID; | 3552 | if (this_object->lineSegmentIntersect(mouse_world_start, mouse_world_end, this_face, |
3812 | *hit_face_p = face; | 3553 | face_hit, intersection, uv, normal, binormal)) |
3813 | |||
3814 | // Hit an object | ||
3815 | if (objectp->isAvatar()) | ||
3816 | { | 3554 | { |
3817 | *hit_pos_p = gAgent.getPosGlobalFromAgent(((LLVOAvatar*)objectp)->mPelvisp->getWorldPosition()); | 3555 | found = this_object; |
3818 | } | 3556 | } |
3819 | else if (objectp->mDrawable.notNull()) | ||
3820 | { | ||
3821 | *hit_pos_p = gAgent.getPosGlobalFromAgent(objectp->getRenderPosition()); | ||
3822 | } | 3557 | } |
3823 | else | ||
3824 | { | ||
3825 | // regular object | ||
3826 | *hit_pos_p = objectp->getPositionGlobal(); | ||
3827 | } | 3558 | } |
3828 | 3559 | ||
3829 | if (gPickFaces && face > -1 && | 3560 | else // check ALL objects |
3830 | objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME && | ||
3831 | face < objectp->mDrawable->getNumFaces()) | ||
3832 | { | 3561 | { |
3833 | // render red-blue gradient to get 1/256 precision | 3562 | found = gPipeline.lineSegmentIntersectInHUD(mouse_hud_start, mouse_hud_end, |
3834 | // then render green grid to get final 1/4096 precision | 3563 | face_hit, intersection, uv, normal, binormal); |
3835 | S32 scaled_x = llround((F32)x * mDisplayScale.mV[VX]); | 3564 | |
3836 | S32 scaled_y = llround((F32)y_from_bot * mDisplayScale.mV[VY]); | 3565 | if (!found) // if not found in HUD, look in world: |
3837 | const S32 UV_PICK_WIDTH = 41; | 3566 | |
3838 | const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2; | ||
3839 | U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4]; | ||
3840 | S32 pick_face = face; | ||
3841 | LLFace* facep = objectp->mDrawable->getFace(pick_face); | ||
3842 | LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE); | ||
3843 | glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH); | ||
3844 | gPipeline.renderFaceForUVSelect(facep); | ||
3845 | |||
3846 | 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); | ||
3847 | U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)]; | ||
3848 | *hit_u_coord = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f; | ||
3849 | *hit_v_coord = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f; | ||
3850 | } | ||
3851 | else | ||
3852 | { | 3567 | { |
3853 | *hit_u_coord = 0.f; | 3568 | found = gPipeline.lineSegmentIntersectInWorld(mouse_world_start, mouse_world_end, |
3854 | *hit_v_coord = 0.f; | 3569 | face_hit, intersection, uv, normal, binormal); |
3855 | } | 3570 | } |
3856 | 3571 | ||
3857 | //llinfos << "DEBUG Hit Object " << *hit_pos_p << llendl; | ||
3858 | return; | ||
3859 | } | ||
3860 | } | 3572 | } |
3861 | 3573 | ||
3862 | // Didn't hit anything. | 3574 | return found; |
3863 | *hit_object_id_p = LLUUID::null; | ||
3864 | *hit_face_p = -1; | ||
3865 | *hit_pos_p = LLVector3d::zero; | ||
3866 | *hit_u_coord = 0.f; | ||
3867 | *hit_v_coord = 0.f; | ||
3868 | //llinfos << "DEBUG Hit Nothing " << llendl; | ||
3869 | } | 3575 | } |
3870 | 3576 | ||
3871 | // Returns unit vector relative to camera | 3577 | // Returns unit vector relative to camera |
@@ -3896,6 +3602,18 @@ LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const | |||
3896 | return mouse_vector; | 3602 | return mouse_vector; |
3897 | } | 3603 | } |
3898 | 3604 | ||
3605 | LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const | ||
3606 | { | ||
3607 | // find screen resolution | ||
3608 | S32 height = getWindowHeight(); | ||
3609 | S32 width = getWindowWidth(); | ||
3610 | |||
3611 | // remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5 | ||
3612 | F32 hud_x = -((F32)x - (F32)width/2.f) / height; | ||
3613 | F32 hud_y = ((F32)y - (F32)height/2.f) / height; | ||
3614 | |||
3615 | return LLVector3(0.f, hud_x, hud_y); | ||
3616 | } | ||
3899 | 3617 | ||
3900 | // Returns unit vector relative to camera in camera space | 3618 | // Returns unit vector relative to camera in camera space |
3901 | // indicating direction of point on screen x,y | 3619 | // indicating direction of point on screen x,y |
@@ -4064,14 +3782,14 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d | |||
4064 | } | 3782 | } |
4065 | 3783 | ||
4066 | // Saves an image to the harddrive as "SnapshotX" where X >= 1. | 3784 | // Saves an image to the harddrive as "SnapshotX" where X >= 1. |
4067 | BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw, const LLString& extension_in) | 3785 | BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image) |
4068 | { | 3786 | { |
4069 | if (! raw) | 3787 | if (!image) |
4070 | { | 3788 | { |
4071 | return FALSE; | 3789 | return FALSE; |
4072 | } | 3790 | } |
4073 | 3791 | ||
4074 | LLString extension(extension_in); | 3792 | std::string extension("." + image->getExtension()); |
4075 | if (extension.empty()) | 3793 | if (extension.empty()) |
4076 | { | 3794 | { |
4077 | extension = (gSavedSettings.getBOOL("CompressSnapshotsToDisk")) ? ".j2c" : ".bmp"; | 3795 | extension = (gSavedSettings.getBOOL("CompressSnapshotsToDisk")) ? ".j2c" : ".bmp"; |
@@ -4082,101 +3800,62 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw, const LLString& extensio | |||
4082 | pick_type = LLFilePicker::FFSAVE_J2C; | 3800 | pick_type = LLFilePicker::FFSAVE_J2C; |
4083 | else if (extension == ".bmp") | 3801 | else if (extension == ".bmp") |
4084 | pick_type = LLFilePicker::FFSAVE_BMP; | 3802 | pick_type = LLFilePicker::FFSAVE_BMP; |
3803 | else if (extension == ".jpg") | ||
3804 | pick_type = LLFilePicker::FFSAVE_JPEG; | ||
3805 | else if (extension == ".png") | ||
3806 | pick_type = LLFilePicker::FFSAVE_PNG; | ||
4085 | else if (extension == ".tga") | 3807 | else if (extension == ".tga") |
4086 | pick_type = LLFilePicker::FFSAVE_TGA; | 3808 | pick_type = LLFilePicker::FFSAVE_TGA; |
4087 | else | 3809 | else |
4088 | pick_type = LLFilePicker::FFSAVE_ALL; // ??? | 3810 | pick_type = LLFilePicker::FFSAVE_ALL; // ??? |
4089 | 3811 | ||
4090 | // Get a directory if this is the first time. | 3812 | // Get a base file location if needed. |
4091 | if (strlen(sSnapshotDir) == 0) /* Flawfinder: ignore */ | 3813 | if ( ! isSnapshotLocSet()) |
4092 | { | 3814 | { |
4093 | LLString proposed_name( sSnapshotBaseName ); | 3815 | std::string proposed_name( sSnapshotBaseName ); |
4094 | proposed_name.append( extension ); | 3816 | proposed_name.append( extension ); |
4095 | 3817 | ||
4096 | // pick a directory in which to save | 3818 | // pick a directory in which to save |
4097 | LLFilePicker& picker = LLFilePicker::instance(); | 3819 | LLFilePicker& picker = LLFilePicker::instance(); |
4098 | if (!picker.getSaveFile(pick_type, proposed_name.c_str())) | 3820 | if (!picker.getSaveFile(pick_type, proposed_name)) |
4099 | { | 3821 | { |
4100 | // Clicked cancel | 3822 | // Clicked cancel |
4101 | return FALSE; | 3823 | return FALSE; |
4102 | } | 3824 | } |
4103 | 3825 | ||
4104 | // Copy the directory + file name | 3826 | // Copy the directory + file name |
4105 | char directory[LL_MAX_PATH]; /* Flawfinder: ignore */ | 3827 | std::string filepath = picker.getFirstFile(); |
4106 | strncpy(directory, picker.getFirstFile(), LL_MAX_PATH -1); /* Flawfinder: ignore */ | ||
4107 | directory[LL_MAX_PATH -1] = '\0'; | ||
4108 | |||
4109 | // Smash the file extension | ||
4110 | S32 length = strlen(directory); /* Flawfinder: ignore */ | ||
4111 | S32 index = length; | ||
4112 | |||
4113 | // Back up over extension | ||
4114 | index -= extension.length(); | ||
4115 | if (index >= 0 && directory[index] == '.') | ||
4116 | { | ||
4117 | directory[index] = '\0'; | ||
4118 | } | ||
4119 | else | ||
4120 | { | ||
4121 | index = length; | ||
4122 | } | ||
4123 | |||
4124 | // Find trailing backslash | ||
4125 | while (index >= 0 && directory[index] != gDirUtilp->getDirDelimiter()[0]) | ||
4126 | { | ||
4127 | index--; | ||
4128 | } | ||
4129 | |||
4130 | // If we found one, truncate the string there | ||
4131 | if (index >= 0) | ||
4132 | { | ||
4133 | if (index + 1 <= length) | ||
4134 | { | ||
4135 | strncpy(LLViewerWindow::sSnapshotBaseName, directory + index + 1, LL_MAX_PATH -1); /* Flawfinder: ignore */ | ||
4136 | LLViewerWindow::sSnapshotBaseName[LL_MAX_PATH -1] = '\0'; | ||
4137 | } | ||
4138 | 3828 | ||
4139 | index++; | 3829 | LLViewerWindow::sSnapshotBaseName = gDirUtilp->getBaseFileName(filepath, true); |
4140 | directory[index] = '\0'; | 3830 | LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filepath); |
4141 | strncpy(LLViewerWindow::sSnapshotDir, directory, LL_MAX_PATH -1); /* Flawfinder: ignore */ | ||
4142 | LLViewerWindow::sSnapshotDir[LL_MAX_PATH -1] = '\0'; | ||
4143 | } | ||
4144 | } | 3831 | } |
4145 | 3832 | ||
4146 | // Look for an unused file name | 3833 | // Look for an unused file name |
4147 | LLString filepath; | 3834 | std::string filepath; |
4148 | S32 i = 1; | 3835 | S32 i = 1; |
4149 | S32 err = 0; | 3836 | S32 err = 0; |
4150 | 3837 | ||
4151 | do | 3838 | do |
4152 | { | 3839 | { |
4153 | filepath = sSnapshotDir; | 3840 | filepath = sSnapshotDir; |
3841 | filepath += gDirUtilp->getDirDelimiter(); | ||
4154 | filepath += sSnapshotBaseName; | 3842 | filepath += sSnapshotBaseName; |
4155 | filepath += llformat("_%.3d",i); | 3843 | filepath += llformat("_%.3d",i); |
4156 | filepath += extension; | 3844 | filepath += extension; |
4157 | 3845 | ||
4158 | struct stat stat_info; | 3846 | llstat stat_info; |
4159 | err = mWindow->stat( filepath.c_str(), &stat_info ); | 3847 | err = LLFile::stat( filepath, &stat_info ); |
4160 | i++; | 3848 | i++; |
4161 | } | 3849 | } |
4162 | while( -1 != err ); // search until the file is not found (i.e., stat() gives an error). | 3850 | while( -1 != err ); // search until the file is not found (i.e., stat() gives an error). |
4163 | 3851 | ||
4164 | LLPointer<LLImageFormatted> formatted_image = LLImageFormatted::createFromExtension(extension); | 3852 | return image->save(filepath); |
4165 | LLImageBase::setSizeOverride(TRUE); | ||
4166 | BOOL success = formatted_image->encode(raw, 0.0f); | ||
4167 | if( success ) | ||
4168 | { | ||
4169 | success = formatted_image->save(filepath); | ||
4170 | } | ||
4171 | else | ||
4172 | { | ||
4173 | llwarns << "Unable to encode bmp snapshot" << llendl; | ||
4174 | } | ||
4175 | LLImageBase::setSizeOverride(FALSE); | ||
4176 | |||
4177 | return success; | ||
4178 | } | 3853 | } |
4179 | 3854 | ||
3855 | void LLViewerWindow::resetSnapshotLoc() | ||
3856 | { | ||
3857 | sSnapshotDir.clear(); | ||
3858 | } | ||
4180 | 3859 | ||
4181 | static S32 BORDERHEIGHT = 0; | 3860 | static S32 BORDERHEIGHT = 0; |
4182 | static S32 BORDERWIDTH = 0; | 3861 | static S32 BORDERWIDTH = 0; |
@@ -4211,7 +3890,7 @@ void LLViewerWindow::movieSize(S32 new_width, S32 new_height) | |||
4211 | } | 3890 | } |
4212 | } | 3891 | } |
4213 | 3892 | ||
4214 | BOOL LLViewerWindow::saveSnapshot( const LLString& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) | 3893 | BOOL LLViewerWindow::saveSnapshot( const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) |
4215 | { | 3894 | { |
4216 | llinfos << "Saving snapshot to: " << filepath << llendl; | 3895 | llinfos << "Saving snapshot to: " << filepath << llendl; |
4217 | 3896 | ||
@@ -4300,13 +3979,12 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p | |||
4300 | LLHUDText::setDisplayText(FALSE) ; | 3979 | LLHUDText::setDisplayText(FALSE) ; |
4301 | if (type == SNAPSHOT_TYPE_OBJECT_ID) | 3980 | if (type == SNAPSHOT_TYPE_OBJECT_ID) |
4302 | { | 3981 | { |
4303 | gPickTransparent = FALSE; | 3982 | gObjectList.renderPickList(gViewerWindow->getVirtualWindowRect(), FALSE, FALSE); |
4304 | gObjectList.renderObjectsForSelect(*LLViewerCamera::getInstance(), FALSE, FALSE); | ||
4305 | } | 3983 | } |
4306 | else | 3984 | else |
4307 | { | 3985 | { |
4308 | display(do_rebuild, 1.0f, 0, TRUE); | 3986 | display(do_rebuild, 1.0f, 0, TRUE); |
4309 | render_ui_and_swap(); | 3987 | render_ui(); |
4310 | } | 3988 | } |
4311 | 3989 | ||
4312 | S32 glformat, gltype, glpixel_length ; | 3990 | S32 glformat, gltype, glpixel_length ; |
@@ -4456,7 +4134,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei | |||
4456 | window_width = snapshot_width; | 4134 | window_width = snapshot_width; |
4457 | window_height = snapshot_height; | 4135 | window_height = snapshot_height; |
4458 | scale_factor = 1.f; | 4136 | scale_factor = 1.f; |
4459 | mWindowRect.set(0, 0, snapshot_width, snapshot_height); | 4137 | mWindowRect.set(0, snapshot_height, snapshot_width, 0); |
4460 | target.bindTarget(); | 4138 | target.bindTarget(); |
4461 | } | 4139 | } |
4462 | } | 4140 | } |
@@ -4483,7 +4161,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei | |||
4483 | image_buffer_x = llfloor(snapshot_width*scale_factor) ; | 4161 | image_buffer_x = llfloor(snapshot_width*scale_factor) ; |
4484 | image_buffer_y = llfloor(snapshot_height *scale_factor) ; | 4162 | image_buffer_y = llfloor(snapshot_height *scale_factor) ; |
4485 | } | 4163 | } |
4486 | raw->resize(image_buffer_x, image_buffer_y, type == SNAPSHOT_TYPE_DEPTH ? 4 : 3); | 4164 | raw->resize(image_buffer_x, image_buffer_y, 3); |
4487 | if(raw->isBufferInvalid()) | 4165 | if(raw->isBufferInvalid()) |
4488 | { | 4166 | { |
4489 | return FALSE ; | 4167 | return FALSE ; |
@@ -4503,6 +4181,8 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei | |||
4503 | F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear()); | 4181 | F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear()); |
4504 | F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear()); | 4182 | F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear()); |
4505 | 4183 | ||
4184 | gObjectList.generatePickList(*LLViewerCamera::getInstance()); | ||
4185 | |||
4506 | for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y) | 4186 | for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y) |
4507 | { | 4187 | { |
4508 | S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);; | 4188 | S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);; |
@@ -4523,13 +4203,13 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei | |||
4523 | LLViewerCamera::getInstance()->setZoomParameters(scale_factor, subimage_x+(subimage_y*llceil(scale_factor))); | 4203 | LLViewerCamera::getInstance()->setZoomParameters(scale_factor, subimage_x+(subimage_y*llceil(scale_factor))); |
4524 | setup3DRender(); | 4204 | setup3DRender(); |
4525 | setupViewport(); | 4205 | setupViewport(); |
4526 | BOOL first_time_through = (subimage_x + subimage_y == 0); | 4206 | gObjectList.renderPickList(gViewerWindow->getVirtualWindowRect(), FALSE, FALSE); |
4527 | gPickTransparent = FALSE; | ||
4528 | gObjectList.renderObjectsForSelect(*LLViewerCamera::getInstance(), FALSE, !first_time_through); | ||
4529 | } | 4207 | } |
4530 | else | 4208 | else |
4531 | { | 4209 | { |
4532 | display(do_rebuild, scale_factor, subimage_x+(subimage_y*llceil(scale_factor)), use_fbo); | 4210 | display(do_rebuild, scale_factor, subimage_x+(subimage_y*llceil(scale_factor)), TRUE); |
4211 | // Required for showing the GUI in snapshots? See DEV-16350 for details. JC | ||
4212 | render_ui(); | ||
4533 | } | 4213 | } |
4534 | 4214 | ||
4535 | S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width); | 4215 | S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width); |
@@ -4538,49 +4218,43 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei | |||
4538 | llmax(0, (window_width * (subimage_x + 1)) - (buffer_x_offset + raw->getWidth()))); | 4218 | llmax(0, (window_width * (subimage_x + 1)) - (buffer_x_offset + raw->getWidth()))); |
4539 | for(U32 out_y = 0; out_y < read_height ; out_y++) | 4219 | for(U32 out_y = 0; out_y < read_height ; out_y++) |
4540 | { | 4220 | { |
4221 | S32 output_buffer_offset = ( | ||
4222 | (out_y * (raw->getWidth())) // ...plus iterated y... | ||
4223 | + (window_width * subimage_x) // ...plus subimage start in x... | ||
4224 | + (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y... | ||
4225 | - output_buffer_offset_x // ...minus buffer padding x... | ||
4226 | - (output_buffer_offset_y * (raw->getWidth())) // ...minus buffer padding y... | ||
4227 | ) * raw->getComponents(); | ||
4541 | if (type == SNAPSHOT_TYPE_OBJECT_ID || type == SNAPSHOT_TYPE_COLOR) | 4228 | if (type == SNAPSHOT_TYPE_OBJECT_ID || type == SNAPSHOT_TYPE_COLOR) |
4542 | { | 4229 | { |
4543 | glReadPixels( | 4230 | glReadPixels( |
4544 | subimage_x_offset, out_y + subimage_y_offset, | 4231 | subimage_x_offset, out_y + subimage_y_offset, |
4545 | read_width, 1, | 4232 | read_width, 1, |
4546 | GL_RGB, GL_UNSIGNED_BYTE, | 4233 | GL_RGB, GL_UNSIGNED_BYTE, |
4547 | raw->getData() + // current output pixel is beginning of buffer... | 4234 | raw->getData() + output_buffer_offset |
4548 | ( | ||
4549 | (out_y * (raw->getWidth())) // ...plus iterated y... | ||
4550 | + (window_width * subimage_x) // ...plus subimage start in x... | ||
4551 | + (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y... | ||
4552 | - output_buffer_offset_x // ...minus buffer padding x... | ||
4553 | - (output_buffer_offset_y * (raw->getWidth())) // ...minus buffer padding y... | ||
4554 | ) * 3 // times 3 bytes per pixel | ||
4555 | ); | 4235 | ); |
4556 | } | 4236 | } |
4557 | else // SNAPSHOT_TYPE_DEPTH | 4237 | else // SNAPSHOT_TYPE_DEPTH |
4558 | { | 4238 | { |
4559 | S32 output_buffer_offset = ( | 4239 | LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values |
4560 | (out_y * (raw->getWidth())) // ...plus iterated y... | ||
4561 | + (window_width * subimage_x) // ...plus subimage start in x... | ||
4562 | + (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y... | ||
4563 | - output_buffer_offset_x // ...minus buffer padding x... | ||
4564 | - (output_buffer_offset_y * (raw->getWidth())) // ...minus buffer padding y... | ||
4565 | ) * 4; // times 4 bytes per pixel | ||
4566 | |||
4567 | glReadPixels( | 4240 | glReadPixels( |
4568 | subimage_x_offset, out_y + subimage_y_offset, | 4241 | subimage_x_offset, out_y + subimage_y_offset, |
4569 | read_width, 1, | 4242 | read_width, 1, |
4570 | GL_DEPTH_COMPONENT, GL_FLOAT, | 4243 | GL_DEPTH_COMPONENT, GL_FLOAT, |
4571 | raw->getData() + output_buffer_offset// current output pixel is beginning of buffer... | 4244 | depth_line_buffer->getData()// current output pixel is beginning of buffer... |
4572 | ); | 4245 | ); |
4573 | 4246 | ||
4574 | for (S32 i = output_buffer_offset; i < output_buffer_offset + (S32)read_width * 4; i += 4) | 4247 | for (S32 i = 0; i < (S32)read_width; i++) |
4575 | { | 4248 | { |
4576 | F32 depth_float = *(F32*)(raw->getData() + i); | 4249 | F32 depth_float = *(F32*)(depth_line_buffer->getData() + (i * sizeof(F32))); |
4577 | 4250 | ||
4578 | F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2)); | 4251 | F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2)); |
4579 | U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar()); | 4252 | U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar()); |
4580 | *(raw->getData() + i + 0) = depth_byte; | 4253 | //write converted scanline out to result image |
4581 | *(raw->getData() + i + 1) = depth_byte; | 4254 | for(S32 j = 0; j < raw->getComponents(); j++) |
4582 | *(raw->getData() + i + 2) = depth_byte; | 4255 | { |
4583 | *(raw->getData() + i + 3) = 255; | 4256 | *(raw->getData() + output_buffer_offset + (i * raw->getComponents()) + j) = depth_byte; |
4257 | } | ||
4584 | } | 4258 | } |
4585 | } | 4259 | } |
4586 | } | 4260 | } |
@@ -4618,7 +4292,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei | |||
4618 | 4292 | ||
4619 | // Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding) | 4293 | // Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding) |
4620 | // Note: this formula depends on the number of components being 3. Not obvious, but it's correct. | 4294 | // Note: this formula depends on the number of components being 3. Not obvious, but it's correct. |
4621 | image_width += (image_width * (type == SNAPSHOT_TYPE_DEPTH ? 4 : 3)) % 4 ; | 4295 | image_width += (image_width * 3) % 4; |
4622 | 4296 | ||
4623 | BOOL ret = TRUE ; | 4297 | BOOL ret = TRUE ; |
4624 | // Resize image | 4298 | // Resize image |
@@ -4665,7 +4339,7 @@ void LLViewerWindow::destroyWindow() | |||
4665 | void LLViewerWindow::drawMouselookInstructions() | 4339 | void LLViewerWindow::drawMouselookInstructions() |
4666 | { | 4340 | { |
4667 | // Draw instructions for mouselook ("Press ESC to leave Mouselook" in a box at the top of the screen.) | 4341 | // Draw instructions for mouselook ("Press ESC to leave Mouselook" in a box at the top of the screen.) |
4668 | const char* instructions = "Press ESC to leave Mouselook."; | 4342 | const std::string instructions = "Press ESC to leave Mouselook."; |
4669 | const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ); | 4343 | const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ); |
4670 | 4344 | ||
4671 | const S32 INSTRUCTIONS_PAD = 5; | 4345 | const S32 INSTRUCTIONS_PAD = 5; |
@@ -4691,39 +4365,6 @@ void LLViewerWindow::drawMouselookInstructions() | |||
4691 | } | 4365 | } |
4692 | 4366 | ||
4693 | 4367 | ||
4694 | // These functions are here only because LLViewerWindow used to do the work that gFocusMgr does now. | ||
4695 | // They let other objects continue to work without change. | ||
4696 | |||
4697 | void LLViewerWindow::setKeyboardFocus(LLUICtrl* new_focus) | ||
4698 | { | ||
4699 | gFocusMgr.setKeyboardFocus( new_focus ); | ||
4700 | } | ||
4701 | |||
4702 | LLUICtrl* LLViewerWindow::getKeyboardFocus() | ||
4703 | { | ||
4704 | return gFocusMgr.getKeyboardFocus(); | ||
4705 | } | ||
4706 | |||
4707 | BOOL LLViewerWindow::hasKeyboardFocus(const LLUICtrl* possible_focus) const | ||
4708 | { | ||
4709 | return possible_focus == gFocusMgr.getKeyboardFocus(); | ||
4710 | } | ||
4711 | |||
4712 | BOOL LLViewerWindow::childHasKeyboardFocus(const LLView* parent) const | ||
4713 | { | ||
4714 | return gFocusMgr.childHasKeyboardFocus( parent ); | ||
4715 | } | ||
4716 | |||
4717 | void LLViewerWindow::setMouseCapture(LLMouseHandler* new_captor) | ||
4718 | { | ||
4719 | gFocusMgr.setMouseCapture( new_captor ); | ||
4720 | } | ||
4721 | |||
4722 | LLMouseHandler* LLViewerWindow::getMouseCaptor() const | ||
4723 | { | ||
4724 | return gFocusMgr.getMouseCapture(); | ||
4725 | } | ||
4726 | |||
4727 | S32 LLViewerWindow::getWindowHeight() const | 4368 | S32 LLViewerWindow::getWindowHeight() const |
4728 | { | 4369 | { |
4729 | return mVirtualWindowRect.getHeight(); | 4370 | return mVirtualWindowRect.getHeight(); |
@@ -4744,21 +4385,6 @@ S32 LLViewerWindow::getWindowDisplayWidth() const | |||
4744 | return mWindowRect.getWidth(); | 4385 | return mWindowRect.getWidth(); |
4745 | } | 4386 | } |
4746 | 4387 | ||
4747 | LLUICtrl* LLViewerWindow::getTopCtrl() const | ||
4748 | { | ||
4749 | return gFocusMgr.getTopCtrl(); | ||
4750 | } | ||
4751 | |||
4752 | BOOL LLViewerWindow::hasTopCtrl(LLView* view) const | ||
4753 | { | ||
4754 | return view == gFocusMgr.getTopCtrl(); | ||
4755 | } | ||
4756 | |||
4757 | void LLViewerWindow::setTopCtrl(LLUICtrl* new_top) | ||
4758 | { | ||
4759 | gFocusMgr.setTopCtrl( new_top ); | ||
4760 | } | ||
4761 | |||
4762 | void LLViewerWindow::setupViewport(S32 x_offset, S32 y_offset) | 4388 | void LLViewerWindow::setupViewport(S32 x_offset, S32 y_offset) |
4763 | { | 4389 | { |
4764 | gGLViewport[0] = x_offset; | 4390 | gGLViewport[0] = x_offset; |
@@ -4778,27 +4404,6 @@ void LLViewerWindow::setup2DRender() | |||
4778 | gl_state_for_2d(mWindowRect.getWidth(), mWindowRect.getHeight()); | 4404 | gl_state_for_2d(mWindowRect.getWidth(), mWindowRect.getHeight()); |
4779 | } | 4405 | } |
4780 | 4406 | ||
4781 | // Could cache the pointer from the last hitObjectOrLand here. | ||
4782 | LLViewerObject *LLViewerWindow::lastObjectHit() | ||
4783 | { | ||
4784 | return gObjectList.findObject( gLastHitObjectID ); | ||
4785 | } | ||
4786 | |||
4787 | const LLVector3d& LLViewerWindow::lastObjectHitOffset() | ||
4788 | { | ||
4789 | return gLastHitObjectOffset; | ||
4790 | } | ||
4791 | |||
4792 | // Could cache the pointer from the last hitObjectOrLand here. | ||
4793 | LLViewerObject *LLViewerWindow::lastNonFloraObjectHit() | ||
4794 | { | ||
4795 | return gObjectList.findObject( gLastHitNonFloraObjectID ); | ||
4796 | } | ||
4797 | |||
4798 | const LLVector3d& LLViewerWindow::lastNonFloraObjectHitOffset() | ||
4799 | { | ||
4800 | return gLastHitNonFloraObjectOffset; | ||
4801 | } | ||
4802 | 4407 | ||
4803 | 4408 | ||
4804 | void LLViewerWindow::setShowProgress(const BOOL show) | 4409 | void LLViewerWindow::setShowProgress(const BOOL show) |
@@ -4824,7 +4429,7 @@ void LLViewerWindow::moveProgressViewToFront() | |||
4824 | } | 4429 | } |
4825 | } | 4430 | } |
4826 | 4431 | ||
4827 | void LLViewerWindow::setProgressString(const LLString& string) | 4432 | void LLViewerWindow::setProgressString(const std::string& string) |
4828 | { | 4433 | { |
4829 | if (mProgressView) | 4434 | if (mProgressView) |
4830 | { | 4435 | { |
@@ -4832,7 +4437,7 @@ void LLViewerWindow::setProgressString(const LLString& string) | |||
4832 | } | 4437 | } |
4833 | } | 4438 | } |
4834 | 4439 | ||
4835 | void LLViewerWindow::setProgressMessage(const LLString& msg) | 4440 | void LLViewerWindow::setProgressMessage(const std::string& msg) |
4836 | { | 4441 | { |
4837 | if(mProgressView) | 4442 | if(mProgressView) |
4838 | { | 4443 | { |
@@ -4848,7 +4453,7 @@ void LLViewerWindow::setProgressPercent(const F32 percent) | |||
4848 | } | 4453 | } |
4849 | } | 4454 | } |
4850 | 4455 | ||
4851 | void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const LLString& label ) | 4456 | void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const std::string& label ) |
4852 | { | 4457 | { |
4853 | if (mProgressView) | 4458 | if (mProgressView) |
4854 | { | 4459 | { |
@@ -4916,7 +4521,7 @@ void LLViewerWindow::stopGL(BOOL save_state) | |||
4916 | } | 4521 | } |
4917 | } | 4522 | } |
4918 | 4523 | ||
4919 | void LLViewerWindow::restoreGL(const LLString& progress_message) | 4524 | void LLViewerWindow::restoreGL(const std::string& progress_message) |
4920 | { | 4525 | { |
4921 | if (gGLManager.mIsDisabled) | 4526 | if (gGLManager.mIsDisabled) |
4922 | { | 4527 | { |
@@ -5154,7 +4759,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, | |||
5154 | 4759 | ||
5155 | if (!result_first_try) | 4760 | if (!result_first_try) |
5156 | { | 4761 | { |
5157 | LLStringBase<char>::format_map_t args; | 4762 | LLStringUtil::format_map_t args; |
5158 | args["[RESX]"] = llformat("%d",size.mX); | 4763 | args["[RESX]"] = llformat("%d",size.mX); |
5159 | args["[RESY]"] = llformat("%d",size.mY); | 4764 | args["[RESY]"] = llformat("%d",size.mY); |
5160 | alertXml("ResolutionSwitchFail", args); | 4765 | alertXml("ResolutionSwitchFail", args); |
@@ -5221,46 +4826,7 @@ F32 LLViewerWindow::getDisplayAspectRatio() const | |||
5221 | 4826 | ||
5222 | void LLViewerWindow::drawPickBuffer() const | 4827 | void LLViewerWindow::drawPickBuffer() const |
5223 | { | 4828 | { |
5224 | if (mPickBuffer) | 4829 | mHoverPick.drawPickBuffer(); |
5225 | { | ||
5226 | gGL.color4f(1,1,1,1); | ||
5227 | gGL.pushMatrix(); | ||
5228 | LLGLDisable no_blend(GL_BLEND); | ||
5229 | LLGLDisable no_alpha_test(GL_ALPHA_TEST); | ||
5230 | LLGLSNoTexture no_texture; | ||
5231 | glPixelZoom(10.f, 10.f); | ||
5232 | glRasterPos2f(((F32)mPickPoint.mX * mDisplayScale.mV[VX] + 10.f), | ||
5233 | ((F32)mPickPoint.mY * mDisplayScale.mV[VY] + 10.f)); | ||
5234 | glDrawPixels(PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer); | ||
5235 | glPixelZoom(1.f, 1.f); | ||
5236 | gGL.color4fv(LLColor4::white.mV); | ||
5237 | gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] - (F32)(PICK_HALF_WIDTH)), | ||
5238 | llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH)), | ||
5239 | llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH)), | ||
5240 | llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] - (F32)(PICK_HALF_WIDTH)), | ||
5241 | FALSE); | ||
5242 | gl_line_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] - (F32)(PICK_HALF_WIDTH)), | ||
5243 | llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH)), | ||
5244 | llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + 10.f), | ||
5245 | llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f + 10.f)); | ||
5246 | gl_line_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH)), | ||
5247 | llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] - (F32)(PICK_HALF_WIDTH)), | ||
5248 | llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f + 10.f), | ||
5249 | llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + 10.f)); | ||
5250 | gGL.translatef(10.f, 10.f, 0.f); | ||
5251 | gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX]), | ||
5252 | llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f), | ||
5253 | llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f), | ||
5254 | llround((F32)mPickPoint.mY * mDisplayScale.mV[VY]), | ||
5255 | FALSE); | ||
5256 | gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH + mPickOffset.mX)* 10.f), | ||
5257 | llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH + mPickOffset.mY + 1) * 10.f), | ||
5258 | llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH + mPickOffset.mX + 1) * 10.f), | ||
5259 | llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH + mPickOffset.mY) * 10.f), | ||
5260 | FALSE); | ||
5261 | gGL.popMatrix(); | ||
5262 | gGL.flush(); | ||
5263 | } | ||
5264 | } | 4830 | } |
5265 | 4831 | ||
5266 | void LLViewerWindow::calcDisplayScale() | 4832 | void LLViewerWindow::calcDisplayScale() |
@@ -5327,11 +4893,11 @@ bool LLViewerWindow::alertCallback(S32 modal) | |||
5327 | LLAlertDialog* LLViewerWindow::alertXml(const std::string& xml_filename, | 4893 | LLAlertDialog* LLViewerWindow::alertXml(const std::string& xml_filename, |
5328 | LLAlertDialog::alert_callback_t callback, void* user_data) | 4894 | LLAlertDialog::alert_callback_t callback, void* user_data) |
5329 | { | 4895 | { |
5330 | LLString::format_map_t args; | 4896 | LLStringUtil::format_map_t args; |
5331 | return alertXml( xml_filename, args, callback, user_data ); | 4897 | return alertXml( xml_filename, args, callback, user_data ); |
5332 | } | 4898 | } |
5333 | 4899 | ||
5334 | LLAlertDialog* LLViewerWindow::alertXml(const std::string& xml_filename, const LLString::format_map_t& args, | 4900 | LLAlertDialog* LLViewerWindow::alertXml(const std::string& xml_filename, const LLStringUtil::format_map_t& args, |
5335 | LLAlertDialog::alert_callback_t callback, void* user_data) | 4901 | LLAlertDialog::alert_callback_t callback, void* user_data) |
5336 | { | 4902 | { |
5337 | if (gNoRender) | 4903 | if (gNoRender) |
@@ -5355,10 +4921,10 @@ LLAlertDialog* LLViewerWindow::alertXml(const std::string& xml_filename, const L | |||
5355 | return LLAlertDialog::showXml( xml_filename, args, callback, user_data ); | 4921 | return LLAlertDialog::showXml( xml_filename, args, callback, user_data ); |
5356 | } | 4922 | } |
5357 | 4923 | ||
5358 | LLAlertDialog* LLViewerWindow::alertXmlEditText(const std::string& xml_filename, const LLString::format_map_t& args, | 4924 | LLAlertDialog* LLViewerWindow::alertXmlEditText(const std::string& xml_filename, const LLStringUtil::format_map_t& args, |
5359 | LLAlertDialog::alert_callback_t callback, void* user_data, | 4925 | LLAlertDialog::alert_callback_t callback, void* user_data, |
5360 | LLAlertDialog::alert_text_callback_t text_callback, void *text_data, | 4926 | LLAlertDialog::alert_text_callback_t text_callback, void *text_data, |
5361 | const LLString::format_map_t& edit_args, BOOL draw_asterixes) | 4927 | const LLStringUtil::format_map_t& edit_args, BOOL draw_asterixes) |
5362 | { | 4928 | { |
5363 | if (gNoRender) | 4929 | if (gNoRender) |
5364 | { | 4930 | { |
@@ -5395,7 +4961,7 @@ LLAlertDialog* LLViewerWindow::alertXmlEditText(const std::string& xml_filename, | |||
5395 | //////////////////////////////////////////////////////////////////////////// | 4961 | //////////////////////////////////////////////////////////////////////////// |
5396 | 4962 | ||
5397 | LLBottomPanel::LLBottomPanel(const LLRect &rect) : | 4963 | LLBottomPanel::LLBottomPanel(const LLRect &rect) : |
5398 | LLPanel("", rect, FALSE), | 4964 | LLPanel(LLStringUtil::null, rect, FALSE), |
5399 | mIndicator(NULL) | 4965 | mIndicator(NULL) |
5400 | { | 4966 | { |
5401 | // bottom panel is focus root, so Tab moves through the toolbar and button bar, and overlay | 4967 | // bottom panel is focus root, so Tab moves through the toolbar and button bar, and overlay |
@@ -5449,3 +5015,342 @@ void* LLBottomPanel::createToolBar(void* data) | |||
5449 | gToolBar = new LLToolBar(); | 5015 | gToolBar = new LLToolBar(); |
5450 | return gToolBar; | 5016 | return gToolBar; |
5451 | } | 5017 | } |
5018 | |||
5019 | // | ||
5020 | // LLPickInfo | ||
5021 | // | ||
5022 | LLPickInfo::LLPickInfo() | ||
5023 | : mKeyMask(MASK_NONE), | ||
5024 | mPickCallback(NULL), | ||
5025 | mPickType(PICK_INVALID), | ||
5026 | mWantSurfaceInfo(FALSE), | ||
5027 | mObjectFace(-1), | ||
5028 | mUVCoords(-1.f, -1.f), | ||
5029 | mSTCoords(-1.f, -1.f), | ||
5030 | mXYCoords(-1, -1), | ||
5031 | mIntersection(), | ||
5032 | mNormal(), | ||
5033 | mBinormal(), | ||
5034 | mHUDIcon(NULL), | ||
5035 | mPickTransparent(FALSE) | ||
5036 | { | ||
5037 | } | ||
5038 | |||
5039 | LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, | ||
5040 | const LLRect& screen_region, | ||
5041 | MASK keyboard_mask, | ||
5042 | BOOL pick_transparent, | ||
5043 | BOOL pick_uv_coords, | ||
5044 | void (*pick_callback)(const LLPickInfo& pick_info)) | ||
5045 | : mMousePt(mouse_pos), | ||
5046 | mScreenRegion(screen_region), | ||
5047 | mKeyMask(keyboard_mask), | ||
5048 | mPickCallback(pick_callback), | ||
5049 | mPickType(PICK_INVALID), | ||
5050 | mWantSurfaceInfo(pick_uv_coords), | ||
5051 | mObjectFace(-1), | ||
5052 | mUVCoords(-1.f, -1.f), | ||
5053 | mSTCoords(-1.f, -1.f), | ||
5054 | mXYCoords(-1, -1), | ||
5055 | mNormal(), | ||
5056 | mBinormal(), | ||
5057 | mHUDIcon(NULL), | ||
5058 | mPickTransparent(pick_transparent) | ||
5059 | { | ||
5060 | } | ||
5061 | |||
5062 | LLPickInfo::~LLPickInfo() | ||
5063 | { | ||
5064 | } | ||
5065 | |||
5066 | void LLPickInfo::fetchResults() | ||
5067 | { | ||
5068 | // read back colors and depth values from buffer | ||
5069 | glReadPixels(mScreenRegion.mLeft, mScreenRegion.mBottom, mScreenRegion.getWidth(), mScreenRegion.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer); | ||
5070 | glReadPixels(mScreenRegion.mLeft, mScreenRegion.mBottom, mScreenRegion.getWidth(), mScreenRegion.getHeight(), GL_DEPTH_COMPONENT, GL_FLOAT, mPickDepthBuffer ); | ||
5071 | |||
5072 | // find pick region that is fully onscreen | ||
5073 | LLCoordGL scaled_pick_point;; | ||
5074 | scaled_pick_point.mX = llclamp(llround((F32)mMousePt.mX * gViewerWindow->getDisplayScale().mV[VX]), PICK_HALF_WIDTH, gViewerWindow->getWindowDisplayWidth() - PICK_HALF_WIDTH); | ||
5075 | scaled_pick_point.mY = llclamp(llround((F32)mMousePt.mY * gViewerWindow->getDisplayScale().mV[VY]), PICK_HALF_WIDTH, gViewerWindow->getWindowDisplayHeight() - PICK_HALF_WIDTH); | ||
5076 | S32 pixel_index = PICK_HALF_WIDTH * PICK_DIAMETER + PICK_HALF_WIDTH; | ||
5077 | S32 pick_id = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2]; | ||
5078 | F32 depth = mPickDepthBuffer[pixel_index]; | ||
5079 | |||
5080 | S32 x_offset = mMousePt.mX - llround((F32)scaled_pick_point.mX / gViewerWindow->getDisplayScale().mV[VX]); | ||
5081 | S32 y_offset = mMousePt.mY - llround((F32)scaled_pick_point.mY / gViewerWindow->getDisplayScale().mV[VY]); | ||
5082 | |||
5083 | mPickPt = mMousePt; | ||
5084 | |||
5085 | // we hit nothing, scan surrounding pixels for something useful | ||
5086 | if (!pick_id) | ||
5087 | { | ||
5088 | S32 closest_distance = 10000; | ||
5089 | //S32 closest_pick_name = 0; | ||
5090 | for (S32 col = 0; col < PICK_DIAMETER; col++) | ||
5091 | { | ||
5092 | for (S32 row = 0; row < PICK_DIAMETER; row++) | ||
5093 | { | ||
5094 | 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)); | ||
5095 | pixel_index = row * PICK_DIAMETER + col; | ||
5096 | S32 test_name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2]; | ||
5097 | if (test_name && distance_squared < closest_distance) | ||
5098 | { | ||
5099 | closest_distance = distance_squared; | ||
5100 | pick_id = test_name; | ||
5101 | depth = mPickDepthBuffer[pixel_index]; | ||
5102 | mPickPt.mX = mMousePt.mX + (col - PICK_HALF_WIDTH); | ||
5103 | mPickPt.mY = mMousePt.mY + (row - PICK_HALF_WIDTH); | ||
5104 | } | ||
5105 | } | ||
5106 | } | ||
5107 | } | ||
5108 | |||
5109 | U32 te_offset = ((U32)pick_id >> 20); | ||
5110 | pick_id &= 0x000fffff; | ||
5111 | |||
5112 | //unproject relative clicked coordinate from window coordinate using GL | ||
5113 | GLint viewport[4]; | ||
5114 | GLdouble modelview[16]; | ||
5115 | GLdouble projection[16]; | ||
5116 | GLfloat winX, winY; | ||
5117 | GLdouble posX, posY, posZ; | ||
5118 | |||
5119 | LLViewerObject* objectp = gObjectList.getSelectedObject(pick_id); | ||
5120 | |||
5121 | if (pick_id == (S32)GL_NAME_PARCEL_WALL) | ||
5122 | { | ||
5123 | mPickType = PICK_PARCEL_WALL; | ||
5124 | } | ||
5125 | else if (objectp) | ||
5126 | { | ||
5127 | if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH ) | ||
5128 | { | ||
5129 | // Hit land | ||
5130 | mPickType = PICK_LAND; | ||
5131 | mObjectID.setNull(); // land has no id | ||
5132 | |||
5133 | // put global position into land_pos | ||
5134 | LLVector3d land_pos; | ||
5135 | if (gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos)) | ||
5136 | { | ||
5137 | // Fudge the land focus a little bit above ground. | ||
5138 | mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f; | ||
5139 | } | ||
5140 | } | ||
5141 | else | ||
5142 | { | ||
5143 | if(isFlora(objectp)) | ||
5144 | { | ||
5145 | mPickType = PICK_FLORA; | ||
5146 | } | ||
5147 | else | ||
5148 | { | ||
5149 | mPickType = PICK_OBJECT; | ||
5150 | } | ||
5151 | mObjectOffset = gAgent.calcFocusOffset(objectp, mPickPt.mX, mPickPt.mY); | ||
5152 | mObjectID = objectp->mID; | ||
5153 | mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset; | ||
5154 | |||
5155 | glh::matrix4f newModel((F32*)LLViewerCamera::getInstance()->getModelview().mMatrix); | ||
5156 | |||
5157 | for(U32 i = 0; i < 16; ++i) | ||
5158 | { | ||
5159 | modelview[i] = newModel.m[i]; | ||
5160 | projection[i] = LLViewerCamera::getInstance()->getProjection().mMatrix[i/4][i%4]; | ||
5161 | } | ||
5162 | glGetIntegerv( GL_VIEWPORT, viewport ); | ||
5163 | |||
5164 | winX = ((F32)mPickPt.mX) * gViewerWindow->getDisplayScale().mV[VX]; | ||
5165 | winY = ((F32)mPickPt.mY) * gViewerWindow->getDisplayScale().mV[VY]; | ||
5166 | |||
5167 | gluUnProject( winX, winY, depth, modelview, projection, viewport, &posX, &posY, &posZ); | ||
5168 | |||
5169 | mPosGlobal = gAgent.getPosGlobalFromAgent(LLVector3(posX, posY, posZ)); | ||
5170 | |||
5171 | if (mWantSurfaceInfo) | ||
5172 | { | ||
5173 | getSurfaceInfo(); | ||
5174 | } | ||
5175 | } | ||
5176 | } | ||
5177 | else | ||
5178 | { | ||
5179 | // was this name referring to a hud icon? | ||
5180 | mHUDIcon = LLHUDIcon::handlePick(pick_id); | ||
5181 | if (mHUDIcon) | ||
5182 | { | ||
5183 | mPickType = PICK_ICON; | ||
5184 | mPosGlobal = mHUDIcon->getPositionGlobal(); | ||
5185 | } | ||
5186 | } | ||
5187 | |||
5188 | if (mPickCallback) | ||
5189 | { | ||
5190 | mPickCallback(*this); | ||
5191 | } | ||
5192 | } | ||
5193 | |||
5194 | LLPointer<LLViewerObject> LLPickInfo::getObject() const | ||
5195 | { | ||
5196 | return gObjectList.findObject( mObjectID ); | ||
5197 | } | ||
5198 | |||
5199 | void LLPickInfo::updateXYCoords() | ||
5200 | { | ||
5201 | const LLTextureEntry* tep = getObject()->getTE(mObjectFace); | ||
5202 | LLPointer<LLViewerImage> imagep = gImageList.getImage(tep->getID()); | ||
5203 | if(mUVCoords.mV[VX] >= 0.f && mUVCoords.mV[VY] >= 0.f && imagep.notNull()) | ||
5204 | { | ||
5205 | LLCoordGL coords; | ||
5206 | |||
5207 | coords.mX = llround(mUVCoords.mV[VX] * (F32)imagep->getWidth()); | ||
5208 | coords.mY = llround(mUVCoords.mV[VY] * (F32)imagep->getHeight()); | ||
5209 | |||
5210 | gViewerWindow->getWindow()->convertCoords(coords, &mXYCoords); | ||
5211 | } | ||
5212 | } | ||
5213 | |||
5214 | void LLPickInfo::drawPickBuffer() const | ||
5215 | { | ||
5216 | if (mPickBuffer) | ||
5217 | { | ||
5218 | gGL.pushMatrix(); | ||
5219 | LLGLDisable no_blend(GL_BLEND); | ||
5220 | LLGLDisable no_alpha_test(GL_ALPHA_TEST); | ||
5221 | LLGLSNoTexture no_texture; | ||
5222 | glPixelZoom(10.f, 10.f); | ||
5223 | LLVector2 display_scale = gViewerWindow->getDisplayScale(); | ||
5224 | glRasterPos2f(((F32)mMousePt.mX * display_scale.mV[VX] + 10.f), | ||
5225 | ((F32)mMousePt.mY * display_scale.mV[VY] + 10.f)); | ||
5226 | glDrawPixels(PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer); | ||
5227 | glPixelZoom(1.f, 1.f); | ||
5228 | gGL.color4fv(LLColor4::white.mV); | ||
5229 | gl_rect_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] - (F32)(PICK_HALF_WIDTH)), | ||
5230 | llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_HALF_WIDTH)), | ||
5231 | llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_HALF_WIDTH)), | ||
5232 | llround((F32)mMousePt.mY * display_scale.mV[VY] - (F32)(PICK_HALF_WIDTH)), | ||
5233 | FALSE); | ||
5234 | gl_line_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] - (F32)(PICK_HALF_WIDTH)), | ||
5235 | llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_HALF_WIDTH)), | ||
5236 | llround((F32)mMousePt.mX * display_scale.mV[VX] + 10.f), | ||
5237 | llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f + 10.f)); | ||
5238 | gl_line_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_HALF_WIDTH)), | ||
5239 | llround((F32)mMousePt.mY * display_scale.mV[VY] - (F32)(PICK_HALF_WIDTH)), | ||
5240 | llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f + 10.f), | ||
5241 | llround((F32)mMousePt.mY * display_scale.mV[VY] + 10.f)); | ||
5242 | gGL.translatef(10.f, 10.f, 0.f); | ||
5243 | gl_rect_2d(llround((F32)mPickPt.mX * display_scale.mV[VX]), | ||
5244 | llround((F32)mPickPt.mY * display_scale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f), | ||
5245 | llround((F32)mPickPt.mX * display_scale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f), | ||
5246 | llround((F32)mPickPt.mY * display_scale.mV[VY]), | ||
5247 | FALSE); | ||
5248 | gl_rect_2d(llround((F32)mPickPt.mX * display_scale.mV[VX]), | ||
5249 | llround((F32)mPickPt.mY * display_scale.mV[VY] + 10.f), | ||
5250 | llround((F32)mPickPt.mX * display_scale.mV[VX] + 10.f), | ||
5251 | llround((F32)mPickPt.mY * display_scale.mV[VY]), | ||
5252 | FALSE); | ||
5253 | gGL.popMatrix(); | ||
5254 | } | ||
5255 | } | ||
5256 | |||
5257 | void LLPickInfo::getSurfaceInfo() | ||
5258 | { | ||
5259 | // set values to uninitialized - this is what we return if no intersection is found | ||
5260 | mObjectFace = -1; | ||
5261 | mUVCoords = LLVector2(-1, -1); | ||
5262 | mSTCoords = LLVector2(-1, -1); | ||
5263 | mXYCoords = LLCoordScreen(-1, -1); | ||
5264 | mIntersection = LLVector3(0,0,0); | ||
5265 | mNormal = LLVector3(0,0,0); | ||
5266 | mBinormal = LLVector3(0,0,0); | ||
5267 | |||
5268 | LLViewerObject* objectp = getObject(); | ||
5269 | |||
5270 | if (objectp) | ||
5271 | { | ||
5272 | if (gViewerWindow->cursorIntersect(llround((F32)mMousePt.mX), llround((F32)mMousePt.mY), 1024.f, | ||
5273 | objectp, -1, | ||
5274 | &mObjectFace, | ||
5275 | &mIntersection, | ||
5276 | &mSTCoords, | ||
5277 | &mNormal, | ||
5278 | &mBinormal)) | ||
5279 | { | ||
5280 | // if we succeeded with the intersect above, compute the texture coordinates: | ||
5281 | |||
5282 | if (objectp->mDrawable.notNull()) | ||
5283 | { | ||
5284 | LLFace* facep = objectp->mDrawable->getFace(mObjectFace); | ||
5285 | |||
5286 | mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal); | ||
5287 | } | ||
5288 | |||
5289 | // and XY coords: | ||
5290 | updateXYCoords(); | ||
5291 | |||
5292 | } | ||
5293 | } | ||
5294 | } | ||
5295 | |||
5296 | |||
5297 | /* code to get UV via a special UV render - removed in lieu of raycast method | ||
5298 | LLVector2 LLPickInfo::pickUV() | ||
5299 | { | ||
5300 | LLVector2 result(-1.f, -1.f); | ||
5301 | |||
5302 | LLViewerObject* objectp = getObject(); | ||
5303 | if (!objectp) | ||
5304 | { | ||
5305 | return result; | ||
5306 | } | ||
5307 | |||
5308 | if (mObjectFace > -1 && | ||
5309 | objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME && | ||
5310 | mObjectFace < objectp->mDrawable->getNumFaces()) | ||
5311 | { | ||
5312 | S32 scaled_x = llround((F32)mPickPt.mX * gViewerWindow->getDisplayScale().mV[VX]); | ||
5313 | S32 scaled_y = llround((F32)mPickPt.mY * gViewerWindow->getDisplayScale().mV[VY]); | ||
5314 | const S32 UV_PICK_WIDTH = 5; | ||
5315 | const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2; | ||
5316 | U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4]; | ||
5317 | LLFace* facep = objectp->mDrawable->getFace(mObjectFace); | ||
5318 | if (facep) | ||
5319 | { | ||
5320 | LLGLState scissor_state(GL_SCISSOR_TEST); | ||
5321 | scissor_state.enable(); | ||
5322 | LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE); | ||
5323 | //glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH); | ||
5324 | glScissor(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH); | ||
5325 | |||
5326 | glClear(GL_DEPTH_BUFFER_BIT); | ||
5327 | |||
5328 | facep->renderSelectedUV(); | ||
5329 | |||
5330 | 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); | ||
5331 | U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)]; | ||
5332 | |||
5333 | result.mV[VX] = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f; | ||
5334 | result.mV[VY] = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f; | ||
5335 | } | ||
5336 | } | ||
5337 | |||
5338 | return result; | ||
5339 | } */ | ||
5340 | |||
5341 | |||
5342 | //static | ||
5343 | bool LLPickInfo::isFlora(LLViewerObject* object) | ||
5344 | { | ||
5345 | if (!object) return false; | ||
5346 | |||
5347 | LLPCode pcode = object->getPCode(); | ||
5348 | |||
5349 | if( (LL_PCODE_LEGACY_GRASS == pcode) | ||
5350 | || (LL_PCODE_LEGACY_TREE == pcode) | ||
5351 | || (LL_PCODE_TREE_NEW == pcode)) | ||
5352 | { | ||
5353 | return true; | ||
5354 | } | ||
5355 | return false; | ||
5356 | } | ||