aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llviewerwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llviewerwindow.cpp1617
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//
195void render_ui_and_swap(); 192void render_ui();
196LLBottomPanel* gBottomPanel = NULL; 193LLBottomPanel* gBottomPanel = NULL;
197 194
198extern BOOL gDebugClicks; 195extern BOOL gDebugClicks;
@@ -204,32 +201,8 @@ extern S32 gJamesInt;
204LLViewerWindow *gViewerWindow = NULL; 201LLViewerWindow *gViewerWindow = NULL;
205LLVelocityBar *gVelocityBar = NULL; 202LLVelocityBar *gVelocityBar = NULL;
206 203
207LLVector3d gLastHitPosGlobal;
208LLVector3d gLastHitObjectOffset;
209LLUUID gLastHitObjectID;
210S32 gLastHitObjectFace = -1;
211BOOL gLastHitLand = FALSE;
212F32 gLastHitUCoord;
213F32 gLastHitVCoord;
214
215
216LLVector3d gLastHitNonFloraPosGlobal;
217LLVector3d gLastHitNonFloraObjectOffset;
218LLUUID gLastHitNonFloraObjectID;
219S32 gLastHitNonFloraObjectFace = -1;
220BOOL gLastHitParcelWall = FALSE;
221
222S32 gLastHitUIElement = 0;
223LLHUDIcon* gLastHitHUDIcon = NULL;
224 204
225BOOL gDebugSelect = FALSE; 205BOOL gDebugSelect = FALSE;
226U8 gLastPickAlpha = 255;
227BOOL 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.
232BOOL gPickFaces = FALSE;
233 206
234LLFrameTimer gMouseIdleTimer; 207LLFrameTimer gMouseIdleTimer;
235LLFrameTimer gAwayTimer; 208LLFrameTimer gAwayTimer;
@@ -240,6 +213,11 @@ BOOL gShowOverlayTitle = FALSE;
240BOOL gPickTransparent = TRUE; 213BOOL gPickTransparent = TRUE;
241 214
242BOOL gDebugFastUIRender = FALSE; 215BOOL gDebugFastUIRender = FALSE;
216LLViewerObject* gDebugRaycastObject = NULL;
217LLVector3 gDebugRaycastIntersection;
218LLVector2 gDebugRaycastTexCoord;
219LLVector3 gDebugRaycastNormal;
220LLVector3 gDebugRaycastBinormal;
243 221
244// HUD display lines in lower right 222// HUD display lines in lower right
245BOOL gDisplayWindInfo = FALSE; 223BOOL gDisplayWindInfo = FALSE;
@@ -257,120 +235,17 @@ const F32 MIN_AFK_TIME = 2.f; // minimum time after setting away state before co
257const F32 MAX_FAST_FRAME_TIME = 0.5f; 235const F32 MAX_FAST_FRAME_TIME = 0.5f;
258const F32 FAST_FRAME_INCREMENT = 0.1f; 236const F32 FAST_FRAME_INCREMENT = 0.1f;
259 237
260const S32 PICK_HALF_WIDTH = 5; 238const F32 MIN_DISPLAY_SCALE = 0.75f;
261const S32 PICK_DIAMETER = 2 * PICK_HALF_WIDTH+1;
262
263const F32 MIN_DISPLAY_SCALE = 0.85f;
264 239
265const S32 CONSOLE_BOTTOM_PAD = 40; 240const S32 CONSOLE_BOTTOM_PAD = 40;
266#ifdef SABINRIG
267/// ALL RIG STUFF
268bool rigControl = false;
269bool voltDisplay = true;
270bool nominalX = false;
271bool nominalY = false;
272static F32 nomerX = 0.0f;
273static F32 nomerY = 0.0f;
274const BOARD_NUM = 0; // rig stuff!
275const ADRANGE = BIP10VOLTS; // rig stuff!
276static unsigned short DataVal; // rig stuff!
277static F32 oldValueX = 0;
278static F32 newValueX = 50;
279static F32 oldValueY = 0;
280static F32 newValueY = 50;
281static S32 mouseX = 50;
282static S32 mouseY = 50;
283static float VoltageX = 50; // rig stuff!
284static float VoltageY = 50; // rig stuff!
285static float nVoltX = 0;
286static float nVoltY = 0;
287static F32 temp1 = 50.f;
288static F32 temp2 = 20.f;
289LLCoordGL new_gl;
290#endif //SABINRIG
291
292char LLViewerWindow::sSnapshotBaseName[LL_MAX_PATH];
293char LLViewerWindow::sSnapshotDir[LL_MAX_PATH];
294
295char LLViewerWindow::sMovieBaseName[LL_MAX_PATH];
296
297extern void toggle_debug_menus(void*);
298
299#ifdef SABINRIG
300// static
301void 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. 242std::string LLViewerWindow::sSnapshotBaseName;
243std::string LLViewerWindow::sSnapshotDir;
363 244
364 oldValueX = newValueX; 245std::string LLViewerWindow::sMovieBaseName;
365 oldValueY = newValueY;
366 246
367 new_gl.mX = mouseX; 247extern 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
536bool 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
661BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask) 551BOOL 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
1153void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask) 1040void 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//
1494LLViewerWindow::LLViewerWindow( 1376LLViewerWindow::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
1780void adjust_rect_top_left(const LLString& control, const LLRect& window) 1660void 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
1790void adjust_rect_top_center(const LLString& control, const LLRect& window) 1670void 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
1803void adjust_rect_top_right(const LLString& control, const LLRect& window) 1683void 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
1816void adjust_rect_bottom_center(const LLString& control, const LLRect& window) 1696void 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
1832void adjust_rect_centered_partial_zoom(const LLString& control, 1712void 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
1790void LLViewerWindow::adjustControlRectanglesForFirstUse(const LLRect& window)
1791{
1792 adjust_rect_bottom_center("FloaterMoveRect2", window);
1793 adjust_rect_top_center("FloaterCameraRect3", window);
1794}
1896 1795
1897void LLViewerWindow::initWorldUI() 1796void 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
1981LLViewerWindow::~LLViewerWindow() 1880void 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
1915void 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
1955LLViewerWindow::~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 )
2064void LLViewerWindow::showCursor() 1967void LLViewerWindow::showCursor()
2065{ 1968{
2066 mWindow->showCursor(); 1969 mWindow->showCursor();
1970
1971 mCursorHidden = FALSE;
2067} 1972}
2068 1973
2069void LLViewerWindow::hideCursor() 1974void 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
2081void LLViewerWindow::sendShapeToSim() 1988void LLViewerWindow::sendShapeToSim()
@@ -2215,7 +2122,7 @@ void LLViewerWindow::setNormalControlsVisible( BOOL visible )
2215 2122
2216void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) 2123void 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
2668void LLViewerWindow::handleScrollWheel(S32 clicks) 2548void 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 */
3074void LLViewerWindow::hoverPickCallback(const LLPickInfo& pick_info)
3075{
3076 gViewerWindow->mHoverPick = pick_info;
3077}
3078
3079
3142void LLViewerWindow::saveLastMouse(const LLCoordGL &point) 3080void 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
3387void 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) 3325void 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
3486void LLViewerWindow::hitUIElementImmediate(S32 x, S32 y, void (*callback)(S32 x, S32 y, MASK mask)) 3364void 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
3504void 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
3574void LLViewerWindow::performPick() 3455void 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; 3475void 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 { 3491LLPickInfo 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. 3507LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 depth,
3734// Stores its results in globals, gHit* 3508 LLViewerObject *this_object,
3735void 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
3750LLViewerObject* 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
3762void 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
3605LLVector3 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.
4067BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw, const LLString& extension_in) 3785BOOL 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
3855void LLViewerWindow::resetSnapshotLoc()
3856{
3857 sSnapshotDir.clear();
3858}
4180 3859
4181static S32 BORDERHEIGHT = 0; 3860static S32 BORDERHEIGHT = 0;
4182static S32 BORDERWIDTH = 0; 3861static S32 BORDERWIDTH = 0;
@@ -4211,7 +3890,7 @@ void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
4211 } 3890 }
4212} 3891}
4213 3892
4214BOOL LLViewerWindow::saveSnapshot( const LLString& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) 3893BOOL 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()
4665void LLViewerWindow::drawMouselookInstructions() 4339void 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
4697void LLViewerWindow::setKeyboardFocus(LLUICtrl* new_focus)
4698{
4699 gFocusMgr.setKeyboardFocus( new_focus );
4700}
4701
4702LLUICtrl* LLViewerWindow::getKeyboardFocus()
4703{
4704 return gFocusMgr.getKeyboardFocus();
4705}
4706
4707BOOL LLViewerWindow::hasKeyboardFocus(const LLUICtrl* possible_focus) const
4708{
4709 return possible_focus == gFocusMgr.getKeyboardFocus();
4710}
4711
4712BOOL LLViewerWindow::childHasKeyboardFocus(const LLView* parent) const
4713{
4714 return gFocusMgr.childHasKeyboardFocus( parent );
4715}
4716
4717void LLViewerWindow::setMouseCapture(LLMouseHandler* new_captor)
4718{
4719 gFocusMgr.setMouseCapture( new_captor );
4720}
4721
4722LLMouseHandler* LLViewerWindow::getMouseCaptor() const
4723{
4724 return gFocusMgr.getMouseCapture();
4725}
4726
4727S32 LLViewerWindow::getWindowHeight() const 4368S32 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
4747LLUICtrl* LLViewerWindow::getTopCtrl() const
4748{
4749 return gFocusMgr.getTopCtrl();
4750}
4751
4752BOOL LLViewerWindow::hasTopCtrl(LLView* view) const
4753{
4754 return view == gFocusMgr.getTopCtrl();
4755}
4756
4757void LLViewerWindow::setTopCtrl(LLUICtrl* new_top)
4758{
4759 gFocusMgr.setTopCtrl( new_top );
4760}
4761
4762void LLViewerWindow::setupViewport(S32 x_offset, S32 y_offset) 4388void 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.
4782LLViewerObject *LLViewerWindow::lastObjectHit()
4783{
4784 return gObjectList.findObject( gLastHitObjectID );
4785}
4786
4787const LLVector3d& LLViewerWindow::lastObjectHitOffset()
4788{
4789 return gLastHitObjectOffset;
4790}
4791
4792// Could cache the pointer from the last hitObjectOrLand here.
4793LLViewerObject *LLViewerWindow::lastNonFloraObjectHit()
4794{
4795 return gObjectList.findObject( gLastHitNonFloraObjectID );
4796}
4797
4798const LLVector3d& LLViewerWindow::lastNonFloraObjectHitOffset()
4799{
4800 return gLastHitNonFloraObjectOffset;
4801}
4802 4407
4803 4408
4804void LLViewerWindow::setShowProgress(const BOOL show) 4409void LLViewerWindow::setShowProgress(const BOOL show)
@@ -4824,7 +4429,7 @@ void LLViewerWindow::moveProgressViewToFront()
4824 } 4429 }
4825} 4430}
4826 4431
4827void LLViewerWindow::setProgressString(const LLString& string) 4432void 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
4835void LLViewerWindow::setProgressMessage(const LLString& msg) 4440void 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
4851void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const LLString& label ) 4456void 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
4919void LLViewerWindow::restoreGL(const LLString& progress_message) 4524void 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
5222void LLViewerWindow::drawPickBuffer() const 4827void 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
5266void LLViewerWindow::calcDisplayScale() 4832void LLViewerWindow::calcDisplayScale()
@@ -5327,11 +4893,11 @@ bool LLViewerWindow::alertCallback(S32 modal)
5327LLAlertDialog* LLViewerWindow::alertXml(const std::string& xml_filename, 4893LLAlertDialog* 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
5334LLAlertDialog* LLViewerWindow::alertXml(const std::string& xml_filename, const LLString::format_map_t& args, 4900LLAlertDialog* 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
5358LLAlertDialog* LLViewerWindow::alertXmlEditText(const std::string& xml_filename, const LLString::format_map_t& args, 4924LLAlertDialog* 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
5397LLBottomPanel::LLBottomPanel(const LLRect &rect) : 4963LLBottomPanel::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//
5022LLPickInfo::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
5039LLPickInfo::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
5062LLPickInfo::~LLPickInfo()
5063{
5064}
5065
5066void 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
5194LLPointer<LLViewerObject> LLPickInfo::getObject() const
5195{
5196 return gObjectList.findObject( mObjectID );
5197}
5198
5199void 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
5214void 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
5257void 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
5298LLVector2 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
5343bool 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}