00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034
00035 #include "llhoverview.h"
00036
00037
00038 #include "llfontgl.h"
00039 #include "message.h"
00040 #include "llgl.h"
00041 #include "llglimmediate.h"
00042 #include "llfontgl.h"
00043 #include "llparcel.h"
00044 #include "lldbstrings.h"
00045 #include "llclickaction.h"
00046
00047
00048 #include "llagent.h"
00049 #include "llcachename.h"
00050 #include "llviewercontrol.h"
00051 #include "lldrawable.h"
00052 #include "llpermissions.h"
00053 #include "llresmgr.h"
00054 #include "llselectmgr.h"
00055 #include "lltrans.h"
00056 #include "lltoolmgr.h"
00057 #include "lltoolpie.h"
00058 #include "lltoolselectland.h"
00059 #include "llui.h"
00060 #include "llviewercamera.h"
00061 #include "llviewerobject.h"
00062 #include "llviewerobjectlist.h"
00063 #include "llviewerparcelmgr.h"
00064 #include "llviewerregion.h"
00065 #include "llviewerwindow.h"
00066 #include "llglheaders.h"
00067 #include "llviewerimagelist.h"
00068
00069 #include "llhudmanager.h"
00070
00071 #include "llhudmanager.h"
00072 #include "llhudeffect.h"
00073
00074
00075
00076
00077 const char* DEFAULT_DESC = "(No Description)";
00078 const F32 DELAY_BEFORE_SHOW_TIP = 0.35f;
00079
00080
00081
00082
00083
00084 LLHoverView *gHoverView = NULL;
00085
00086
00087
00088
00089 BOOL LLHoverView::sShowHoverTips = TRUE;
00090
00091
00092
00093
00094
00095 LLHoverView::LLHoverView(const std::string& name, const LLRect& rect)
00096 : LLView(name, rect, FALSE)
00097 {
00098 mDoneHoverPick = FALSE;
00099 mStartHoverPickTimer = FALSE;
00100 mHoverActive = FALSE;
00101 mUseHover = TRUE;
00102 mTyping = FALSE;
00103 mHoverOffset.clearVec();
00104 }
00105
00106 LLHoverView::~LLHoverView()
00107 {
00108 }
00109
00110 void LLHoverView::updateHover(LLTool* current_tool)
00111 {
00112 BOOL picking_tool = ( current_tool == LLToolPie::getInstance()
00113 || current_tool == LLToolSelectLand::getInstance() );
00114
00115 mUseHover = !gAgent.cameraMouselook()
00116 && picking_tool
00117 && !mTyping;
00118 if (mUseHover)
00119 {
00120 if ((gViewerWindow->getMouseVelocityStat()->getPrev(0) < 0.01f)
00121 && (LLViewerCamera::getInstance()->getAngularVelocityStat()->getPrev(0) < 0.01f)
00122 && (LLViewerCamera::getInstance()->getVelocityStat()->getPrev(0) < 0.01f))
00123 {
00124 if (!mStartHoverPickTimer)
00125 {
00126 mStartHoverTimer.reset();
00127 mStartHoverPickTimer = TRUE;
00128
00129 mText.clear();
00130 }
00131
00132 if (mDoneHoverPick)
00133 {
00134
00135 updateText();
00136 }
00137 else if (mStartHoverTimer.getElapsedTimeF32() > DELAY_BEFORE_SHOW_TIP)
00138 {
00139 gViewerWindow->hitObjectOrLandGlobalAsync(gViewerWindow->getCurrentMouseX(),
00140 gViewerWindow->getCurrentMouseY(), 0, pickCallback );
00141 }
00142 }
00143 else
00144 {
00145 cancelHover();
00146 }
00147 }
00148
00149 }
00150
00151 void LLHoverView::pickCallback(S32 x, S32 y, MASK mask)
00152 {
00153 LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
00154
00155 if (hit_obj)
00156 {
00157 gHoverView->setHoverActive(TRUE);
00158 LLSelectMgr::getInstance()->setHoverObject(hit_obj);
00159 gHoverView->mLastHoverObject = hit_obj;
00160 gHoverView->mHoverOffset = gViewerWindow->lastObjectHitOffset();
00161 }
00162 else
00163 {
00164 gHoverView->mLastHoverObject = NULL;
00165 }
00166
00167
00168 if (!hit_obj && gLastHitPosGlobal != LLVector3d::zero)
00169 {
00170 gHoverView->setHoverActive(TRUE);
00171 gHoverView->mHoverLandGlobal = gLastHitPosGlobal;
00172 LLViewerParcelMgr::getInstance()->requestHoverParcelProperties( gHoverView->mHoverLandGlobal );
00173 }
00174 else
00175 {
00176 gHoverView->mHoverLandGlobal = LLVector3d::zero;
00177 }
00178
00179 gHoverView->mDoneHoverPick = TRUE;
00180 }
00181
00182 void LLHoverView::setTyping(BOOL b)
00183 {
00184 mTyping = b;
00185 }
00186
00187
00188 void LLHoverView::cancelHover()
00189 {
00190 mStartHoverTimer.reset();
00191 mDoneHoverPick = FALSE;
00192 mStartHoverPickTimer = FALSE;
00193
00194 LLSelectMgr::getInstance()->setHoverObject(NULL);
00195
00196
00197
00198
00199 setHoverActive(FALSE);
00200 }
00201
00202 void LLHoverView::resetLastHoverObject()
00203 {
00204 mLastHoverObject = NULL;
00205 }
00206
00207 void LLHoverView::updateText()
00208 {
00209 LLViewerObject* hit_object = getLastHoverObject();
00210 std::string line;
00211
00212 mText.clear();
00213 if ( hit_object )
00214 {
00215 if ( hit_object->isHUDAttachment() )
00216 {
00217
00218
00219 return;
00220 }
00221
00222 if ( hit_object->isAttachment() )
00223 {
00224
00225 LLViewerObject* root_edit = hit_object->getRootEdit();
00226 if (!root_edit)
00227 {
00228
00229 return;
00230 }
00231 hit_object = (LLViewerObject*)root_edit->getParent();
00232 if (!hit_object)
00233 {
00234
00235 return;
00236 }
00237 }
00238
00239 line.clear();
00240 if (hit_object->isAvatar())
00241 {
00242 LLNameValue* title = hit_object->getNVPair("Title");
00243 LLNameValue* firstname = hit_object->getNVPair("FirstName");
00244 LLNameValue* lastname = hit_object->getNVPair("LastName");
00245 if (firstname && lastname)
00246 {
00247 if (title)
00248 {
00249 line.append(title->getString());
00250 line.append(1, ' ');
00251 }
00252 line.append(firstname->getString());
00253 line.append(1, ' ');
00254 line.append(lastname->getString());
00255 }
00256 else
00257 {
00258 line.append(LLTrans::getString("TooltipPerson"));
00259 }
00260 mText.push_back(line);
00261 }
00262 else
00263 {
00264
00265
00266
00267
00268
00269
00270
00271 BOOL suppressObjectHoverDisplay = !gSavedSettings.getBOOL("ShowAllObjectHoverTip");
00272
00273 LLSelectNode *nodep = LLSelectMgr::getInstance()->getHoverNode();;
00274 if (nodep)
00275 {
00276 line.clear();
00277 if (nodep->mName.empty())
00278 {
00279 line.append(LLTrans::getString("TooltipNoName"));
00280 }
00281 else
00282 {
00283 line.append( nodep->mName );
00284 }
00285 mText.push_back(line);
00286
00287 if (!nodep->mDescription.empty()
00288 && nodep->mDescription != DEFAULT_DESC)
00289 {
00290 mText.push_back( nodep->mDescription );
00291 }
00292
00293
00294 line.clear();
00295 line.append(LLTrans::getString("TooltipOwner") + " ");
00296
00297 if (nodep->mValid)
00298 {
00299 LLUUID owner;
00300 std::string name;
00301 if (!nodep->mPermissions->isGroupOwned())
00302 {
00303 owner = nodep->mPermissions->getOwner();
00304 if (LLUUID::null == owner)
00305 {
00306 line.append(LLTrans::getString("TooltipPublic"));
00307 }
00308 else if(gCacheName->getFullName(owner, name))
00309 {
00310 line.append(name);
00311 }
00312 else
00313 {
00314 line.append(LLTrans::getString("RetrievingData"));
00315 }
00316 }
00317 else
00318 {
00319 std::string name;
00320 owner = nodep->mPermissions->getGroup();
00321 if (gCacheName->getGroupName(owner, name))
00322 {
00323 line.append(name);
00324 line.append(LLTrans::getString("TooltipIsGroup"));
00325 }
00326 else
00327 {
00328 line.append(LLTrans::getString("RetrievingData"));
00329 }
00330 }
00331 }
00332 else
00333 {
00334 line.append(LLTrans::getString("RetrievingData"));
00335 }
00336 mText.push_back(line);
00337
00338
00339 LLViewerObject *object = hit_object;
00340 LLViewerObject *parent = (LLViewerObject *)object->getParent();
00341
00342 if (object &&
00343 (object->usePhysics() ||
00344 object->flagScripted() ||
00345 object->flagHandleTouch() || (parent && parent->flagHandleTouch()) ||
00346 object->flagTakesMoney() || (parent && parent->flagTakesMoney()) ||
00347 object->flagAllowInventoryAdd() ||
00348 object->flagTemporary() ||
00349 object->flagPhantom()) )
00350 {
00351 line.clear();
00352 if (object->flagScripted())
00353 {
00354
00355 line.append(LLTrans::getString("TooltipFlagScript") + " ");
00356 }
00357
00358 if (object->usePhysics())
00359 {
00360 line.append(LLTrans::getString("TooltipFlagPhysics") + " ");
00361 }
00362
00363 if (object->flagHandleTouch() || (parent && parent->flagHandleTouch()) )
00364 {
00365 line.append(LLTrans::getString("TooltipFlagTouch") + " ");
00366 suppressObjectHoverDisplay = FALSE;
00367 }
00368
00369 if (object->flagTakesMoney() || (parent && parent->flagTakesMoney()) )
00370 {
00371 line.append(LLTrans::getString("TooltipFlagL$") + " ");
00372 suppressObjectHoverDisplay = FALSE;
00373 }
00374
00375 if (object->flagAllowInventoryAdd())
00376 {
00377 line.append(LLTrans::getString("TooltipFlagDropInventory") + " ");
00378 suppressObjectHoverDisplay = FALSE;
00379 }
00380
00381 if (object->flagPhantom())
00382 {
00383 line.append(LLTrans::getString("TooltipFlagPhantom") + " ");
00384 }
00385
00386 if (object->flagTemporary())
00387 {
00388 line.append(LLTrans::getString("TooltipFlagTemporary") + " ");
00389 }
00390
00391 if (object->usePhysics() ||
00392 object->flagHandleTouch() ||
00393 (parent && parent->flagHandleTouch()) )
00394 {
00395 line.append(LLTrans::getString("TooltipFlagRightClickMenu") + " ");
00396 }
00397 mText.push_back(line);
00398 }
00399
00400
00401 line.clear();
00402 if (nodep->mValid)
00403 {
00404 BOOL for_copy = nodep->mPermissions->getMaskEveryone() & PERM_COPY && object->permCopy();
00405 BOOL for_sale = nodep->mSaleInfo.isForSale() &&
00406 nodep->mPermissions->getMaskOwner() & PERM_TRANSFER &&
00407 (nodep->mPermissions->getMaskOwner() & PERM_COPY ||
00408 nodep->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY);
00409 if (for_copy)
00410 {
00411 line.append(LLTrans::getString("TooltipFreeToCopy"));
00412 suppressObjectHoverDisplay = FALSE;
00413 }
00414 else if (for_sale)
00415 {
00416 LLString::format_map_t args;
00417 args["[AMOUNT]"] = nodep->mSaleInfo.getSalePrice();
00418 line.append(LLTrans::getString("TooltipForSaleL$", args));
00419 suppressObjectHoverDisplay = FALSE;
00420 }
00421 else
00422 {
00423
00424
00425 }
00426 }
00427 else
00428 {
00429 LLString::format_map_t args;
00430 args["[MESSAGE]"] = LLTrans::getString("RetrievingData");
00431 line.append(LLTrans::getString("TooltipForSaleMsg", args));
00432 }
00433 mText.push_back(line);
00434 }
00435
00436
00437 if (suppressObjectHoverDisplay)
00438 {
00439 mText.clear();
00440 }
00441 }
00442 }
00443 else if ( mHoverLandGlobal != LLVector3d::zero )
00444 {
00445
00446
00447
00448
00449 if (!gSavedSettings.getBOOL("ShowLandHoverTip")) return;
00450
00451
00452
00453
00454 LLParcel* hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel();
00455 LLUUID owner;
00456 S32 width = 0;
00457 S32 height = 0;
00458
00459 if ( hover_parcel )
00460 {
00461 owner = hover_parcel->getOwnerID();
00462 width = S32(LLViewerParcelMgr::getInstance()->getHoverParcelWidth());
00463 height = S32(LLViewerParcelMgr::getInstance()->getHoverParcelHeight());
00464 }
00465
00466
00467 line.clear();
00468 line.append(LLTrans::getString("TooltipLand"));
00469 if (hover_parcel)
00470 {
00471 line.append(hover_parcel->getName());
00472 }
00473 mText.push_back(line);
00474
00475
00476 line.clear();
00477 line.append(LLTrans::getString("TooltipOwner") + " ");
00478
00479 if ( hover_parcel )
00480 {
00481 std::string name;
00482 if (LLUUID::null == owner)
00483 {
00484 line.append(LLTrans::getString("TooltipPublic"));
00485 }
00486 else if (hover_parcel->getIsGroupOwned())
00487 {
00488 if (gCacheName->getGroupName(owner, name))
00489 {
00490 line.append(name);
00491 line.append(LLTrans::getString("TooltipIsGroup"));
00492 }
00493 else
00494 {
00495 line.append(LLTrans::getString("RetrievingData"));
00496 }
00497 }
00498 else if(gCacheName->getFullName(owner, name))
00499 {
00500 line.append(name);
00501 }
00502 else
00503 {
00504 line.append(LLTrans::getString("RetrievingData"));
00505 }
00506 }
00507 else
00508 {
00509 line.append(LLTrans::getString("RetrievingData"));
00510 }
00511 mText.push_back(line);
00512
00513
00514
00515
00516
00517 if ( hover_parcel && owner != gAgent.getID() )
00518 {
00519 S32 words = 0;
00520
00521 line.clear();
00522
00523
00524 if ( !hover_parcel->getAllowModify() )
00525 {
00526 if ( hover_parcel->getAllowGroupModify() )
00527 {
00528 line.append(LLTrans::getString("TooltipFlagGroupBuild"));
00529 }
00530 else
00531 {
00532 line.append(LLTrans::getString("TooltipFlagNoBuild"));
00533 }
00534 words++;
00535 }
00536
00537 if ( !hover_parcel->getAllowTerraform() )
00538 {
00539 if (words) line.append(", ");
00540 line.append(LLTrans::getString("TooltipFlagNoEdit"));
00541 words++;
00542 }
00543
00544 if ( hover_parcel->getAllowDamage() )
00545 {
00546 if (words) line.append(", ");
00547 line.append(LLTrans::getString("TooltipFlagNotSafe"));
00548 words++;
00549 }
00550
00551
00552 if ( !hover_parcel->getAllowFly() )
00553 {
00554 if (words) line.append(", ");
00555 line.append(LLTrans::getString("TooltipFlagNoFly"));
00556 words++;
00557 }
00558
00559 if ( !hover_parcel->getAllowOtherScripts() )
00560 {
00561 if (words) line.append(", ");
00562 if ( hover_parcel->getAllowGroupScripts() )
00563 {
00564 line.append(LLTrans::getString("TooltipFlagGroupScripts"));
00565 }
00566 else
00567 {
00568 line.append(LLTrans::getString("TooltipFlagNoScripts"));
00569 }
00570
00571 words++;
00572 }
00573
00574 if (words)
00575 {
00576 mText.push_back(line);
00577 }
00578 }
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 if (hover_parcel && hover_parcel->getParcelFlag(PF_FOR_SALE))
00590 {
00591 LLString::format_map_t args;
00592 args["[AMOUNT]"] = hover_parcel->getSalePrice();
00593 line = LLTrans::getString("TooltipForSaleL$", args);
00594 mText.push_back(line);
00595 }
00596 }
00597 }
00598
00599
00600 void LLHoverView::draw()
00601 {
00602 if ( !isHovering() )
00603 {
00604 return;
00605 }
00606
00607
00608
00609
00610 if (!sShowHoverTips)
00611 {
00612 return;
00613 }
00614
00615 const F32 MAX_HOVER_DISPLAY_SECS = 5.f;
00616 if (mHoverTimer.getElapsedTimeF32() > MAX_HOVER_DISPLAY_SECS)
00617 {
00618 return;
00619 }
00620
00621 const F32 MAX_ALPHA = 0.9f;
00622
00623 F32 alpha;
00624 if (mHoverActive)
00625 {
00626 alpha = 1.f;
00627
00628 if (isHoveringObject())
00629 {
00630
00631 LLViewerObject *hover_object = getLastHoverObject();
00632 if (hover_object->isAvatar())
00633 {
00634 gAgent.setLookAt(LOOKAT_TARGET_HOVER, getLastHoverObject(), LLVector3::zero);
00635 }
00636 else
00637 {
00638 LLVector3 local_offset((F32)mHoverOffset.mdV[VX], (F32)mHoverOffset.mdV[VY], (F32)mHoverOffset.mdV[VZ]);
00639 gAgent.setLookAt(LOOKAT_TARGET_HOVER, getLastHoverObject(), local_offset);
00640 }
00641 }
00642 }
00643 else
00644 {
00645 alpha = llmax(0.f, MAX_ALPHA - mHoverTimer.getElapsedTimeF32()*2.f);
00646 }
00647
00648
00649 if (mText.empty())
00650 {
00651 return;
00652 }
00653
00654
00655 if (alpha <= 0.f)
00656 {
00657 return;
00658 }
00659
00660 LLUIImagePtr box_imagep = LLUI::getUIImage("rounded_square.tga");
00661 LLUIImagePtr shadow_imagep = LLUI::getUIImage("rounded_square_soft.tga");
00662
00663 const LLFontGL* fontp = LLResMgr::getInstance()->getRes(LLFONT_SANSSERIF_SMALL);
00664
00665
00666 LLColor4 text_color = gColors.getColor("ToolTipTextColor");
00667
00668 LLColor4 bg_color = gColors.getColor("ToolTipBgColor");
00669 LLColor4 shadow_color = gColors.getColor("ColorDropShadow");
00670
00671
00672
00673
00674
00675
00676 S32 max_width = 0;
00677 S32 num_lines = mText.size();
00678 for (text_list_t::iterator iter = mText.begin(); iter != mText.end(); ++iter)
00679 {
00680 max_width = llmax(max_width, (S32)fontp->getWidth(*iter));
00681 }
00682
00683 S32 left = mHoverPos.mX + 10;
00684 S32 top = mHoverPos.mY - 16;
00685 S32 right = mHoverPos.mX + max_width + 30;
00686 S32 bottom = mHoverPos.mY - 24 - llfloor(num_lines*fontp->getLineHeight());
00687
00688
00689 if (mHoverActive
00690 && isHoveringObject()
00691 && mLastHoverObject->getClickAction() != CLICK_ACTION_NONE)
00692 {
00693 const S32 CLICK_OFFSET = 10;
00694 top -= CLICK_OFFSET;
00695 bottom -= CLICK_OFFSET;
00696 }
00697
00698
00699 LLRect old_rect = getRect();
00700 setRect( LLRect(left, top, right, bottom ) );
00701 translateIntoRect( gViewerWindow->getVirtualWindowRect(), FALSE );
00702 left = getRect().mLeft;
00703 top = getRect().mTop;
00704 right = getRect().mRight;
00705 bottom = getRect().mBottom;
00706 setRect(old_rect);
00707
00708 LLGLSUIDefault gls_ui;
00709
00710 shadow_color.mV[VALPHA] = 0.7f * alpha;
00711 S32 shadow_offset = gSavedSettings.getS32("DropShadowTooltip");
00712 shadow_imagep->draw(LLRect(left + shadow_offset, top - shadow_offset, right + shadow_offset, bottom - shadow_offset), shadow_color);
00713
00714 bg_color.mV[VALPHA] = alpha;
00715 box_imagep->draw(LLRect(left, top, right, bottom), bg_color);
00716
00717 S32 cur_offset = top - 4;
00718 for (text_list_t::iterator iter = mText.begin(); iter != mText.end(); ++iter)
00719 {
00720 fontp->renderUTF8(*iter, 0, left + 10, cur_offset, text_color, LLFontGL::LEFT, LLFontGL::TOP);
00721 cur_offset -= llfloor(fontp->getLineHeight());
00722 }
00723 }
00724
00725 void LLHoverView::setHoverActive(const BOOL active)
00726 {
00727 if (active != mHoverActive)
00728 {
00729 mHoverTimer.reset();
00730 }
00731
00732 mHoverActive = active;
00733
00734 if (active)
00735 {
00736 mHoverPos = gViewerWindow->getCurrentMouse();
00737 }
00738 }
00739
00740
00741 BOOL LLHoverView::isHoveringLand() const
00742 {
00743 return !mHoverLandGlobal.isExactlyZero();
00744 }
00745
00746
00747 BOOL LLHoverView::isHoveringObject() const
00748 {
00749 return !mLastHoverObject.isNull() && !mLastHoverObject->isDead();
00750 }
00751
00752
00753 LLViewerObject* LLHoverView::getLastHoverObject() const
00754 {
00755 if (!mLastHoverObject.isNull() && !mLastHoverObject->isDead())
00756 {
00757 return mLastHoverObject;
00758 }
00759 else
00760 {
00761 return NULL;
00762 }
00763 }
00764
00765