Files
SingularityViewer/indra/newview/llhoverview.cpp
Aleric Inglewood 38957ff531 Reduce calls to LLHoverView::updateText
Basically to avoid calling LLTrans::getString 250 times per second,
and seeing
INFO: log_sStringTemplates_accesses: LLTrans::getString/findString called 19000 in total.
INFO: log_sStringTemplates_accesses: LLTrans::getString/findString called 20000 in total.
etc, every 40 seconds in the log.
2013-11-26 22:09:46 +01:00

910 lines
23 KiB
C++

/**
* @file llhoverview.cpp
* @brief LLHoverView class implementation
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
// self include
#include "llhoverview.h"
// Library includes
#include "llfontgl.h"
#include "message.h"
#include "llgl.h"
#include "llrender.h"
#include "llfontgl.h"
#include "llparcel.h"
#include "lldbstrings.h"
#include "llclickaction.h"
// Viewer includes
#include "llagent.h"
#include "llagentcamera.h"
#include "llavatarnamecache.h"
#include "llcachename.h"
#include "llviewercontrol.h"
#include "lldrawable.h"
#include "llpermissions.h"
#include "llresmgr.h"
#include "llselectmgr.h"
#include "lltrans.h"
#include "lltoolmgr.h"
#include "lltoolpie.h"
#include "lltoolselectland.h"
#include "llui.h"
#include "llviewercamera.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
#include "llglheaders.h"
#include "llviewertexturelist.h"
//#include "lltoolobjpicker.h"
#include "llhudmanager.h" // HACK for creating flex obj's
#include "llviewermenu.h"
#include "llviewermedia.h"
#include "llmediaentry.h"
#include "llhudmanager.h" // For testing effects
#include "llhudeffect.h"
#include "hippogridmanager.h"
// [RLVa:KB]
#include "rlvhandler.h"
// [/RLVa:KB]
//
// Constants
//
const char* DEFAULT_DESC = "(No Description)";
const F32 DELAY_BEFORE_SHOW_TIP = 0.35f;
const F32 DELAY_BEFORE_REFRESH_TIP = 0.50f;
//
// Local globals
//
LLHoverView *gHoverView = NULL;
//
// Static member functions
//
BOOL LLHoverView::sShowHoverTips = TRUE;
//
// Member functions
//
LLHoverView::LLHoverView(const std::string& name, const LLRect& rect)
: LLView(name, rect, FALSE)
{
mDoneHoverPick = FALSE;
mStartHoverPickTimer = FALSE;
mHoverActive = FALSE;
mUseHover = TRUE;
mTyping = FALSE;
mHoverOffset.clearVec();
//<singu>
mLastTextHoverObject = NULL;
//</singu>
}
LLHoverView::~LLHoverView()
{
}
void LLHoverView::updateHover(LLTool* current_tool)
{
BOOL picking_tool = ( current_tool == LLToolPie::getInstance()
|| current_tool == LLToolSelectLand::getInstance() );
mUseHover = !gAgentCamera.cameraMouselook()
&& picking_tool
&& !mTyping;
if (mUseHover)
{
if ((gViewerWindow->getMouseVelocityStat()->getPrev(0) < 0.01f)
&& (LLViewerCamera::getInstance()->getAngularVelocityStat()->getPrev(0) < 0.01f)
&& (LLViewerCamera::getInstance()->getVelocityStat()->getPrev(0) < 0.01f))
{
if (!mStartHoverPickTimer)
{
mStartHoverTimer.reset();
mStartHoverPickTimer = TRUE;
// Clear the existing text so that we do not briefly show the wrong data.
mText.clear();
//<singu>
mLastTextHoverObject = NULL;
//</singu>
}
if (mDoneHoverPick)
{
// Just update the hover data
updateText();
}
else if (mStartHoverTimer.getElapsedTimeF32() > DELAY_BEFORE_SHOW_TIP)
{
gViewerWindow->pickAsync(gViewerWindow->getCurrentMouseX(),
gViewerWindow->getCurrentMouseY(), 0, pickCallback );
}
}
else
{
cancelHover();
}
}
}
void LLHoverView::pickCallback(const LLPickInfo& pick_info)
{
gHoverView->mLastPickInfo = pick_info;
LLViewerObject* hit_obj = pick_info.getObject();
if (hit_obj)
{
gHoverView->setHoverActive(TRUE);
LLSelectMgr::getInstance()->setHoverObject(hit_obj, pick_info.mObjectFace);
gHoverView->mLastHoverObject = hit_obj;
gHoverView->mHoverOffset = pick_info.mObjectOffset;
}
else
{
gHoverView->mLastHoverObject = NULL;
}
// We didn't hit an object, but we did hit land.
if (!hit_obj && pick_info.mPosGlobal != LLVector3d::zero)
{
gHoverView->setHoverActive(TRUE);
gHoverView->mHoverLandGlobal = pick_info.mPosGlobal;
LLViewerParcelMgr::getInstance()->setHoverParcel( gHoverView->mHoverLandGlobal );
}
else
{
gHoverView->mHoverLandGlobal = LLVector3d::zero;
}
gHoverView->mDoneHoverPick = TRUE;
}
void LLHoverView::setTyping(BOOL b)
{
mTyping = b;
}
void LLHoverView::cancelHover()
{
mStartHoverTimer.reset();
mDoneHoverPick = FALSE;
mStartHoverPickTimer = FALSE;
LLSelectMgr::getInstance()->setHoverObject(NULL);
// Can't do this, some code relies on hover object still being
// set after the hover is cancelled! Dammit. JC
// mLastHoverObject = NULL;
setHoverActive(FALSE);
}
void LLHoverView::resetLastHoverObject()
{
mLastHoverObject = NULL;
}
void LLHoverView::updateText()
{
LLViewerObject* hit_object = getLastHoverObject();
std::string line;
//<singu>
if (hit_object == mLastTextHoverObject &&
!(mLastTextHoverObjectTimer.getStarted() && mLastTextHoverObjectTimer.hasExpired()))
{
// mText is already up to date.
return;
}
mLastTextHoverObject = hit_object;
mLastTextHoverObjectTimer.stop();
bool retrieving_data = false;
//</singu>
mText.clear();
if ( hit_object )
{
if ( hit_object->isHUDAttachment() )
{
// no hover tips for HUD elements, since they can obscure
// what the HUD is displaying
return;
}
if ( hit_object->isAttachment() )
{
// get root of attachment then parent, which is avatar
LLViewerObject* root_edit = hit_object->getRootEdit();
if (!root_edit)
{
// Strange parenting issue, don't show any text
return;
}
hit_object = (LLViewerObject*)root_edit->getParent();
if (!hit_object)
{
// another strange parenting issue, bail out
return;
}
}
line.clear();
if (hit_object->isAvatar())
{
LLNameValue* title = hit_object->getNVPair("Title");
LLNameValue* firstname = hit_object->getNVPair("FirstName");
LLNameValue* lastname = hit_object->getNVPair("LastName");
if (firstname && lastname)
{
// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
{
line = RlvStrings::getAnonym(line.append(firstname->getString()).append(1, ' ').append(lastname->getString()));
}
else
{
// [/RLVa:KB]
std::string complete_name;
if (!LLAvatarNameCache::getPNSName(hit_object->getID(), complete_name))
complete_name = firstname->getString() + std::string(" ") + lastname->getString();
if (title)
{
line.append(title->getString());
line.append(1, ' ');
}
line += complete_name;
// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
}
// [/RLVa:KB]
}
else
{
line.append(LLTrans::getString("TooltipPerson"));
}
mText.push_back(line);
}
else
{
//
// We have hit a regular object (not an avatar or attachment)
//
//
// Default prefs will suppress display unless the object is interactive
//
BOOL suppressObjectHoverDisplay = !gSavedSettings.getBOOL("ShowAllObjectHoverTip");
LLSelectNode *nodep = LLSelectMgr::getInstance()->getHoverNode();
if (nodep)
{
line.clear();
bool for_copy = nodep->mValid && nodep->mPermissions->getMaskEveryone() & PERM_COPY && hit_object && hit_object->permCopy();
bool for_sale = nodep->mValid && for_sale_selection(nodep);
bool has_media = false;
bool is_time_based_media = false;
bool is_web_based_media = false;
bool is_media_playing = false;
bool is_media_displaying = false;
// Does this face have media?
const LLTextureEntry* tep = hit_object ? hit_object->getTE(mLastPickInfo.mObjectFace) : NULL;
if(tep)
{
has_media = tep->hasMedia();
const LLMediaEntry* mep = has_media ? tep->getMediaData() : NULL;
if (mep)
{
viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
LLPluginClassMedia* media_plugin = NULL;
if (media_impl.notNull() && (media_impl->hasMedia()))
{
is_media_displaying = true;
//LLStringUtil::format_map_t args;
media_plugin = media_impl->getMediaPlugin();
if(media_plugin)
{
if(media_plugin->pluginSupportsMediaTime())
{
is_time_based_media = true;
is_web_based_media = false;
//args["[CurrentURL]"] = media_impl->getMediaURL();
is_media_playing = media_impl->isMediaPlaying();
}
else
{
is_time_based_media = false;
is_web_based_media = true;
//args["[CurrentURL]"] = media_plugin->getLocation();
}
//tooltip_msg.append(LLTrans::getString("CurrentURL", args));
}
}
}
}
// Avoid showing tip over media that's displaying unless it's for sale
// also check the primary node since sometimes it can have an action even though
// the root node doesn't
if(!suppressObjectHoverDisplay || !is_media_displaying || for_sale)
{
if (nodep->mName.empty())
{
line.append(LLTrans::getString("TooltipNoName"));
}
else
{
line.append( nodep->mName );
}
mText.push_back(line);
if (!nodep->mDescription.empty()
&& nodep->mDescription != DEFAULT_DESC)
{
mText.push_back( nodep->mDescription );
}
// Line: "Owner: James Linden"
line.clear();
line.append(LLTrans::getString("TooltipOwner") + " ");
if (nodep->mValid)
{
LLUUID owner;
std::string name;
if (!nodep->mPermissions->isGroupOwned())
{
owner = nodep->mPermissions->getOwner();
if (LLUUID::null == owner)
{
line.append(LLTrans::getString("TooltipPublic"));
}
else if(LLAvatarNameCache::getPNSName(owner, name))
{
// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
{
name = RlvStrings::getAnonym(name);
}
// [/RLVa:KB]
line.append(name);
}
else
{
line.append(LLTrans::getString("RetrievingData"));
retrieving_data = true;
}
}
else
{
std::string name;
owner = nodep->mPermissions->getGroup();
if (gCacheName->getGroupName(owner, name))
{
line.append(name);
line.append(LLTrans::getString("TooltipIsGroup"));
}
else
{
line.append(LLTrans::getString("RetrievingData"));
retrieving_data = true;
}
}
}
else
{
line.append(LLTrans::getString("RetrievingData"));
retrieving_data = true;
}
mText.push_back(line);
// Build a line describing any special properties of this object.
LLViewerObject *object = hit_object;
LLViewerObject *parent = (LLViewerObject *)object->getParent();
if (object &&
(object->flagUsePhysics() ||
object->flagScripted() ||
object->flagHandleTouch() || (parent && parent->flagHandleTouch()) ||
object->flagTakesMoney() || (parent && parent->flagTakesMoney()) ||
object->flagAllowInventoryAdd() ||
object->flagTemporary() ||
object->flagPhantom()) )
{
line.clear();
if (object->flagScripted())
{
line.append(LLTrans::getString("TooltipFlagScript") + " ");
}
if (object->flagUsePhysics())
{
line.append(LLTrans::getString("TooltipFlagPhysics") + " ");
}
if (object->flagHandleTouch() || (parent && parent->flagHandleTouch()) )
{
line.append(LLTrans::getString("TooltipFlagTouch") + " ");
suppressObjectHoverDisplay = FALSE; // Show tip
}
if (object->flagTakesMoney() || (parent && parent->flagTakesMoney()) )
{
line.append(gHippoGridManager->getConnectedGrid()->getCurrencySymbol() + " ");
suppressObjectHoverDisplay = FALSE; // Show tip
}
if (object->flagAllowInventoryAdd())
{
line.append(LLTrans::getString("TooltipFlagDropInventory") + " ");
suppressObjectHoverDisplay = FALSE; // Show tip
}
if (object->flagPhantom())
{
line.append(LLTrans::getString("TooltipFlagPhantom") + " ");
}
if (object->flagTemporary())
{
line.append(LLTrans::getString("TooltipFlagTemporary") + " ");
}
if (object->flagUsePhysics() ||
object->flagHandleTouch() ||
(parent && parent->flagHandleTouch()) )
{
line.append(LLTrans::getString("TooltipFlagRightClickMenu") + " ");
}
mText.push_back(line);
}
// Free to copy / For Sale: L$
line.clear();
if (nodep->mValid)
{
if (for_copy)
{
line.append(LLTrans::getString("TooltipFreeToCopy"));
suppressObjectHoverDisplay = FALSE; // Show tip
}
else if (for_sale)
{
LLStringUtil::format_map_t args;
args["[AMOUNT]"] = llformat("%d", nodep->mSaleInfo.getSalePrice());
line.append(LLTrans::getString("TooltipForSaleL$", args));
suppressObjectHoverDisplay = FALSE; // Show tip
}
else
{
// Nothing if not for sale
// line.append("Not for sale");
}
}
else
{
LLStringUtil::format_map_t args;
args["[MESSAGE]"] = LLTrans::getString("RetrievingData");
retrieving_data = true;
line.append(LLTrans::getString("TooltipForSaleMsg", args));
}
mText.push_back(line);
line.clear();
S32 prim_count = LLSelectMgr::getInstance()->getHoverObjects()->getObjectCount();
line.append(llformat("Prims: %d", prim_count));
mText.push_back(line);
line.clear();
line.append("Position: ");
LLViewerRegion *region = gAgent.getRegion();
LLVector3 position = region->getPosRegionFromGlobal(hit_object->getPositionGlobal());//regionp->getOriginAgent();
LLVector3 mypos = region->getPosRegionFromGlobal(gAgent.getPositionGlobal());
LLVector3 delta = position - mypos;
F32 distance = (F32)delta.magVec();
line.append(llformat("<%.02f,%.02f,%.02f>",position.mV[0],position.mV[1],position.mV[2]));
mText.push_back(line);
line.clear();
line.append(llformat("Distance: %.02fm",distance));
mText.push_back(line);
}
else
{
suppressObjectHoverDisplay = TRUE;
}
// If the hover tip shouldn't be shown, delete all the object text
if (suppressObjectHoverDisplay)
{
mText.clear();
}
}
}
}
else if ( mHoverLandGlobal != LLVector3d::zero )
{
//
// Do not show hover for land unless prefs are set to allow it.
//
if (!gSavedSettings.getBOOL("ShowLandHoverTip")) return;
// Didn't hit an object, but since we have a land point we
// must be hovering over land.
LLParcel* hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel();
LLUUID owner;
if ( hover_parcel )
{
owner = hover_parcel->getOwnerID();
}
// Line: "Land"
line.clear();
line.append(LLTrans::getString("TooltipLand"));
if (hover_parcel)
{
// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-0.2.0b
line.append( (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
? hover_parcel->getName() : RlvStrings::getString(RLV_STRING_HIDDEN_PARCEL) );
// [/RLVa:KB]
//line.append(hover_parcel->getName());
}
mText.push_back(line);
// Line: "Owner: James Linden"
line.clear();
line.append(LLTrans::getString("TooltipOwner") + " ");
if ( hover_parcel )
{
std::string name;
if (LLUUID::null == owner)
{
line.append(LLTrans::getString("TooltipPublic"));
}
else if (hover_parcel->getIsGroupOwned())
{
if (gCacheName->getGroupName(owner, name))
{
line.append(name);
line.append(LLTrans::getString("TooltipIsGroup"));
}
else
{
line.append(LLTrans::getString("RetrievingData"));
retrieving_data = true;
}
}
else if(gCacheName->getFullName(owner, name))
{
// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b
line.append( (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? name : RlvStrings::getAnonym(name));
// [/RLVa:KB]
//line.append(name);
}
else
{
line.append(LLTrans::getString("RetrievingData"));
retrieving_data = true;
}
}
else
{
line.append(LLTrans::getString("RetrievingData"));
retrieving_data = true;
}
mText.push_back(line);
// Line: "no fly, not safe, no build"
// Don't display properties for your land. This is just
// confusing, because you can do anything on your own land.
if ( hover_parcel && owner != gAgent.getID() )
{
S32 words = 0;
line.clear();
// JC - Keep this in the same order as the checkboxes
// on the land info panel
if ( !hover_parcel->getAllowModify() )
{
if ( hover_parcel->getAllowGroupModify() )
{
line.append(LLTrans::getString("TooltipFlagGroupBuild"));
}
else
{
line.append(LLTrans::getString("TooltipFlagNoBuild"));
}
words++;
}
if ( !hover_parcel->getAllowTerraform() )
{
if (words) line.append(", ");
line.append(LLTrans::getString("TooltipFlagNoEdit"));
words++;
}
if ( hover_parcel->getAllowDamage() )
{
if (words) line.append(", ");
line.append(LLTrans::getString("TooltipFlagNotSafe"));
words++;
}
// Maybe we should reflect the estate's block fly bit here as well? DK 12/1/04
if ( !hover_parcel->getAllowFly() )
{
if (words) line.append(", ");
line.append(LLTrans::getString("TooltipFlagNoFly"));
words++;
}
if ( !hover_parcel->getAllowOtherScripts() )
{
if (words) line.append(", ");
if ( hover_parcel->getAllowGroupScripts() )
{
line.append(LLTrans::getString("TooltipFlagGroupScripts"));
}
else
{
line.append(LLTrans::getString("TooltipFlagNoScripts"));
}
words++;
}
if (words)
{
mText.push_back(line);
}
}
if (hover_parcel && hover_parcel->getParcelFlag(PF_FOR_SALE))
{
LLStringUtil::format_map_t args;
args["[AMOUNT]"] = llformat("%d", hover_parcel->getSalePrice());
line = LLTrans::getString("TooltipForSaleL$", args);
mText.push_back(line);
}
}
//<singu>
if (retrieving_data)
{
// Keep doing this twice per second, until all data was retrieved.
mLastTextHoverObjectTimer.start(DELAY_BEFORE_REFRESH_TIP);
}
//</singu>
}
void LLHoverView::draw()
{
if ( !isHovering() )
{
return;
}
// To toggle off hover tips, you have to just suppress the draw.
// The picking is still needed to do cursor changes over physical
// and scripted objects. JC
// if (!sShowHoverTips)
// [RLVa:KB] - Checked: 2010-01-02 (RLVa-1.1.0l) | Modified: RLVa-1.1.0l
#ifdef RLV_EXTENSION_CMD_INTERACT
if ( (!sShowHoverTips) || (gRlvHandler.hasBehaviour(RLV_BHVR_INTERACT)) )
#else
if (!sShowHoverTips)
#endif // RLV_EXTENSION_CMD_INTERACT
// [/RLVa:KB]
{
return;
}
const F32 MAX_HOVER_DISPLAY_SECS = 5.f;
if (mHoverTimer.getElapsedTimeF32() > MAX_HOVER_DISPLAY_SECS)
{
return;
}
const F32 MAX_ALPHA = 0.9f;
//const F32 STEADY_ALPHA = 0.3f;
F32 alpha;
if (mHoverActive)
{
alpha = 1.f;
if (isHoveringObject())
{
// look at object
LLViewerObject *hover_object = getLastHoverObject();
if (hover_object->isAvatar())
{
gAgentCamera.setLookAt(LOOKAT_TARGET_HOVER, getLastHoverObject(), LLVector3::zero);
}
else
{
gAgentCamera.setLookAt(LOOKAT_TARGET_HOVER, getLastHoverObject(), mHoverOffset);
}
}
}
else
{
alpha = llmax(0.f, MAX_ALPHA - mHoverTimer.getElapsedTimeF32()*2.f);
}
// Bail out if no text to display
if (mText.empty())
{
return;
}
// Don't draw if no alpha
if (alpha <= 0.f)
{
return;
}
LLUIImagePtr box_imagep = LLUI::getUIImage("rounded_square.tga");
LLUIImagePtr shadow_imagep = LLUI::getUIImage("rounded_square_soft.tga");
const LLFontGL* fontp = LLResMgr::getInstance()->getRes(LLFONT_SANSSERIF_SMALL);
// Render text.
LLColor4 text_color = gColors.getColor("ToolTipTextColor");
// LLColor4 border_color = gColors.getColor("ToolTipBorderColor");
LLColor4 bg_color = gColors.getColor("ToolTipBgColor");
LLColor4 shadow_color = gColors.getColor("ColorDropShadow");
// Could decrease the alpha here. JC
//text_color.mV[VALPHA] = alpha;
//border_color.mV[VALPHA] = alpha;
//bg_color.mV[VALPHA] = alpha;
S32 max_width = 0;
S32 num_lines = mText.size();
for (text_list_t::iterator iter = mText.begin(); iter != mText.end(); ++iter)
{
max_width = llmax(max_width, (S32)fontp->getWidth(*iter));
}
S32 left = mHoverPos.mX + 10;
S32 top = mHoverPos.mY - 16;
S32 right = mHoverPos.mX + max_width + 30;
S32 bottom = mHoverPos.mY - 24 - llfloor(num_lines*fontp->getLineHeight());
// Push down if there's a one-click icon
if (mHoverActive
&& isHoveringObject()
&& mLastHoverObject->getClickAction() != CLICK_ACTION_NONE)
{
const S32 CLICK_OFFSET = 10;
top -= CLICK_OFFSET;
bottom -= CLICK_OFFSET;
}
// Make sure the rect is completely visible
LLRect old_rect = getRect();
setRect( LLRect(left, top, right, bottom ) );
translateIntoRect( gViewerWindow->getVirtualWindowRect(), FALSE );
left = getRect().mLeft;
top = getRect().mTop;
right = getRect().mRight;
bottom = getRect().mBottom;
setRect(old_rect);
LLGLSUIDefault gls_ui;
shadow_color.mV[VALPHA] = 0.7f * alpha;
S32 shadow_offset = gSavedSettings.getS32("DropShadowTooltip");
shadow_imagep->draw(LLRect(left + shadow_offset, top - shadow_offset, right + shadow_offset, bottom - shadow_offset), shadow_color);
bg_color.mV[VALPHA] = alpha;
box_imagep->draw(LLRect(left, top, right, bottom), bg_color);
S32 cur_offset = top - 4;
for (text_list_t::iterator iter = mText.begin(); iter != mText.end(); ++iter)
{
fontp->renderUTF8(*iter, 0, left + 10, cur_offset, text_color, LLFontGL::LEFT, LLFontGL::TOP);
cur_offset -= llfloor(fontp->getLineHeight());
}
}
void LLHoverView::setHoverActive(const BOOL active)
{
if (active != mHoverActive)
{
mHoverTimer.reset();
}
mHoverActive = active;
if (active)
{
mHoverPos = gViewerWindow->getCurrentMouse();
}
}
BOOL LLHoverView::isHoveringLand() const
{
return !mHoverLandGlobal.isExactlyZero();
}
BOOL LLHoverView::isHoveringObject() const
{
return !mLastHoverObject.isNull() && !mLastHoverObject->isDead();
}
LLViewerObject* LLHoverView::getLastHoverObject() const
{
if (!mLastHoverObject.isNull() && !mLastHoverObject->isDead())
{
return mLastHoverObject;
}
else
{
return NULL;
}
}
// EOF