diff options
Diffstat (limited to 'indra/newview/llvoavatar.cpp')
-rw-r--r-- | indra/newview/llvoavatar.cpp | 381 |
1 files changed, 260 insertions, 121 deletions
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index d566b4d147..06d8ae4def 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -44,6 +44,7 @@ #include <ctype.h> #include "llaudioengine.h" +#include "llcachename.h" #include "noise.h" #include "sound_ids.h" @@ -51,8 +52,10 @@ #include "llagentcamera.h" #include "llagentwearables.h" #include "llanimationstates.h" +#include "llavatarnamecache.h" #include "llavatarpropertiesprocessor.h" #include "llviewercontrol.h" +#include "llcallingcard.h" // IDEVO for LLAvatarTracker #include "lldrawpoolavatar.h" #include "lldriverparam.h" #include "lleditingmotion.h" @@ -61,6 +64,8 @@ #include "llheadrotmotion.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" +#include "llhudnametag.h" +#include "llhudtext.h" // for mText/mDebugText #include "llkeyframefallmotion.h" #include "llkeyframestandmotion.h" #include "llkeyframewalkmotion.h" @@ -659,12 +664,14 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mAppearanceAnimating(FALSE), mNameString(), mTitle(), - mNameAway(FALSE), - mNameBusy(FALSE), - mNameMute(FALSE), + mNameAway(false), + mNameBusy(false), + mNameMute(false), + mNameAppearance(false), + mNameFriend(false), + mNameAlpha(0.f), mRenderGroupTitles(sRenderGroupTitles), - mNameAppearance(FALSE), - mNameCloud(FALSE), + mNameCloud(false), mFirstTEMessageReceived( FALSE ), mFirstAppearanceMessageReceived( FALSE ), mCulled( FALSE ), @@ -2779,8 +2786,18 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) && gSavedSettings.getS32("AvatarNameTagMode") )); } - if ( render_name ) + if ( !render_name ) { + if (mNameText) + { + // ...clean up old name tag + mNameText->markDead(); + mNameText = NULL; + sNumVisibleChatBubbles--; + } + return; + } + BOOL new_name = FALSE; if (visible_chat != mVisibleChat) { @@ -2796,7 +2813,6 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) // First Calculate Alpha // If alpha > 0, create mNameText if necessary, otherwise delete it - { F32 alpha = 0.f; if (mAppAngle > 5.f) { @@ -2817,66 +2833,62 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) alpha = (mAppAngle-2.f)/3.f; } - if (alpha > 0.f) + if (alpha <= 0.f) { + if (mNameText) + { + mNameText->markDead(); + mNameText = NULL; + sNumVisibleChatBubbles--; + } + return; + } + if (!mNameText) { - mNameText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT); - mNameText->setMass(10.f); + mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject( + LLHUDObject::LL_HUD_NAME_TAG) ); + //mNameText->setMass(10.f); mNameText->setSourceObject(this); - mNameText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP); + mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP); mNameText->setVisibleOffScreen(TRUE); mNameText->setMaxLines(11); mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - mNameText->setUseBubble(TRUE); sNumVisibleChatBubbles++; new_name = TRUE; } - LLColor4 avatar_name_color = LLUIColorTable::instance().getColor( "AvatarNameColor" ); - avatar_name_color.setAlpha(alpha); - mNameText->setColor(avatar_name_color); + LLVector3 name_position = idleUpdateNameTagPosition(root_pos_last); + mNameText->setPositionAgent(name_position); - LLQuaternion root_rot = mRoot.getWorldRotation(); - mNameText->setUsePixelSize(TRUE); - LLVector3 pixel_right_vec; - LLVector3 pixel_up_vec; - LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec); - LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin(); - camera_to_av.normalize(); - LLVector3 local_camera_at = camera_to_av * ~root_rot; - LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis(); - local_camera_up.normalize(); - local_camera_up = local_camera_up * ~root_rot; + idleUpdateNameTagText(new_name); - local_camera_up.scaleVec(mBodySize * 0.5f); - local_camera_at.scaleVec(mBodySize * 0.5f); + idleUpdateNameTagAlpha(new_name, alpha); +} - LLVector3 name_position = mRoot.getWorldPosition() + - (local_camera_up * root_rot) - - (projected_vec(local_camera_at * root_rot, camera_to_av)); - name_position += pixel_up_vec * 15.f; - mNameText->setPositionAgent(name_position); - } - else if (mNameText) +void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) { - mNameText->markDead(); - mNameText = NULL; - sNumVisibleChatBubbles--; - } - } - LLNameValue *title = getNVPair("Title"); LLNameValue* firstname = getNVPair("FirstName"); LLNameValue* lastname = getNVPair("LastName"); - if (mNameText.notNull() && firstname && lastname) + // Avatars must have a first and last name + if (!firstname || !lastname) return; + + bool is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end(); + bool is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end(); + bool is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end(); + bool is_muted; + if (isSelf()) + { + is_muted = false; + } + else { - const BOOL is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end(); - const BOOL is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end(); - const BOOL is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end(); - const BOOL is_muted = isSelf() ? FALSE : LLMuteList::getInstance()->isMuted(getID()); - const BOOL is_cloud = getIsCloud(); + is_muted = LLMuteList::getInstance()->isMuted(getID()); + } + bool is_friend = LLAvatarTracker::instance().isBuddy(getID()); + bool is_cloud = getIsCloud(); if (gSavedSettings.getBOOL("DebugAvatarRezTime")) { @@ -2901,105 +2913,129 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) } } - if (mNameString.empty() || - new_name || - (!title && !mTitle.empty()) || - (title && mTitle != title->getString()) || - (is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute) + // Rebuild name tag if state change detected + if (mNameString.empty() + || new_name + || (!title && !mTitle.empty()) + || (title && mTitle != title->getString()) + || is_away != mNameAway + || is_busy != mNameBusy + || is_muted != mNameMute || is_appearance != mNameAppearance - || is_cloud != mNameCloud - ) - { - std::string line; - if (!sRenderGroupTitles) - { - // If all group titles are turned off, stack first name - // on a line above last name - line += firstname->getString(); - line += "\n"; - } - else if (title && title->getString() && title->getString()[0] != '\0') + || is_friend != mNameFriend + || is_cloud != mNameCloud) { - line += title->getString(); - LLStringFn::replace_ascii_controlchars(line,LL_UNKNOWN_CHAR); - line += "\n"; - line += firstname->getString(); - } - else - { - line += firstname->getString(); - } + LLColor4 name_tag_color = getNameTagColor(is_friend); - line += " "; - line += lastname->getString(); - BOOL need_comma = FALSE; + clearNameTag(); - if (is_away || is_muted || is_busy) + if (is_away || is_muted || is_busy || is_appearance) { - line += " ("; + std::string line; if (is_away) { line += LLTrans::getString("AvatarAway"); - need_comma = TRUE; + line += ", "; } if (is_busy) { - if (need_comma) + line += LLTrans::getString("AvatarBusy"); + line += ", "; + } + if (is_muted) { + line += LLTrans::getString("AvatarMuted"); line += ", "; } - line += LLTrans::getString("AvatarBusy"); - need_comma = TRUE; + if (is_appearance) + { + line += LLTrans::getString("AvatarEditingAppearance"); + line += ", "; } - if (is_muted) + if (is_cloud) { - if (need_comma) + line += LLTrans::getString("LoadingData"); + line += ", "; + } + // trim last ", " + line.resize( line.length() - 2 ); + LLColor4 status_color = + LLUIColorTable::getInstance()->getColor("NameTagStatus"); + addNameTagLine(line, status_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerifSmall()); + } + + if (sRenderGroupTitles + && title && title->getString() && title->getString()[0] != '\0') { - line += ", "; + LLColor4 group_color = + LLUIColorTable::getInstance()->getColor("NameTagGroup"); + std::string title_str = title->getString(); + LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR); + addNameTagLine(title_str, group_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerifSmall()); } - line += LLTrans::getString("AvatarMuted"); - need_comma = TRUE; + + static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames"); + static LLUICachedControl<bool> show_usernames("NameTagShowUsernames"); + + if (LLAvatarNameCache::useDisplayNames()) + { + LLAvatarName av_name; + if (!LLAvatarNameCache::get(getID(), &av_name)) + { + // ...call this function back when the name arrives + // and force a rebuild + LLAvatarNameCache::get(getID(), + boost::bind(&LLVOAvatar::clearNameTag, this)); } - line += ")"; + + // Might be blank if name not available yet, that's OK + if (show_display_names) + { + addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerif()); } - if (is_cloud) + // Suppress SLID display if display name matches exactly (ugh) + if (show_usernames && !av_name.mIsDisplayNameDefault) { - line += "\n"; - line += "(" + LLTrans::getString("LoadingData") + ")"; + // *HACK: Desaturate the color + LLColor4 username_color = name_tag_color * 0.83f; + addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerifSmall()); + } } - else if (is_appearance) + else { - line += "\n"; - line += LLTrans::getString("AvatarEditingAppearance"); + const LLFontGL* font = LLFontGL::getFontSansSerif(); + std::string full_name = + LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); + addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font); } + mNameAway = is_away; mNameBusy = is_busy; mNameMute = is_muted; mNameAppearance = is_appearance; + mNameFriend = is_friend; mNameCloud = is_cloud; mTitle = title ? title->getString() : ""; LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR); - mNameString = utf8str_to_wstring(line); new_name = TRUE; } - if (visible_chat) + if (mVisibleChat) { - mNameText->setDropShadow(TRUE); mNameText->setFont(LLFontGL::getFontSansSerif()); - mNameText->setTextAlignment(LLHUDText::ALIGN_TEXT_LEFT); + mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); - if (new_name) - { - mNameText->setLabel(mNameString); - } char line[MAX_STRING]; /* Flawfinder: ignore */ line[0] = '\0'; std::deque<LLChat>::iterator chat_iter = mChats.begin(); mNameText->clearString(); - LLColor4 new_chat = LLUIColorTable::instance().getColor( "AvatarNameColor" ); + LLColor4 new_chat = LLUIColorTable::instance().getColor( "NameTagChat" ); LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) @@ -3026,17 +3062,17 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) if (chat_fade_amt < 1.f) { F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); - mNameText->addLine(utf8str_to_wstring(chat_iter->mText), lerp(new_chat, normal_chat, u), style); + mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); } else if (chat_fade_amt < 2.f) { F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); - mNameText->addLine(utf8str_to_wstring(chat_iter->mText), lerp(normal_chat, old_chat, u), style); + mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); } else if (chat_fade_amt < 3.f) { // *NOTE: only remove lines down to minimum number - mNameText->addLine(utf8str_to_wstring(chat_iter->mText), old_chat, style); + mNameText->addLine(chat_iter->mText, old_chat, style); } } mNameText->setVisibleOffScreen(TRUE); @@ -3061,24 +3097,129 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) } else { - mNameText->setFont(LLFontGL::getFontSansSerif()); - mNameText->setTextAlignment(LLHUDText::ALIGN_TEXT_CENTER); + // ...not using chat bubbles, just names + mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER); mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); mNameText->setVisibleOffScreen(FALSE); - if (new_name) + } +} + +void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font) +{ + llassert(mNameText); + if (mVisibleChat) + { + mNameText->addLabel(line); + } + else + { + mNameText->addLine(line, color, (LLFontGL::StyleFlags)style, font); + } + mNameString += line; + mNameString += '\n'; +} + +void LLVOAvatar::clearNameTag() +{ + mNameString.clear(); + if (mNameText) { mNameText->setLabel(""); - mNameText->setString(mNameString); + mNameText->setString( "" ); + } +} + +//static +void LLVOAvatar::invalidateNameTag(const LLUUID& agent_id) +{ + LLViewerObject* obj = gObjectList.findObject(agent_id); + if (!obj) return; + + LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(obj); + if (!avatar) return; + + avatar->clearNameTag(); +} + +//static +void LLVOAvatar::invalidateNameTags() +{ + std::vector<LLCharacter*>::iterator it = LLCharacter::sInstances.begin(); + for ( ; it != LLCharacter::sInstances.end(); ++it) + { + LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*it); + if (!avatar) continue; + if (avatar->isDead()) continue; + + avatar->clearNameTag(); } } + +// Compute name tag position during idle update +LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) +{ + LLQuaternion root_rot = mRoot.getWorldRotation(); + LLVector3 pixel_right_vec; + LLVector3 pixel_up_vec; + LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec); + LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin(); + camera_to_av.normalize(); + LLVector3 local_camera_at = camera_to_av * ~root_rot; + LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis(); + local_camera_up.normalize(); + local_camera_up = local_camera_up * ~root_rot; + + local_camera_up.scaleVec(mBodySize * 0.5f); + local_camera_at.scaleVec(mBodySize * 0.5f); + + LLVector3 name_position = mRoot.getWorldPosition() + + (local_camera_up * root_rot) - + (projected_vec(local_camera_at * root_rot, camera_to_av)); + name_position += pixel_up_vec * 15.f; + return name_position; + } + +void LLVOAvatar::idleUpdateNameTagAlpha(BOOL new_name, F32 alpha) +{ + llassert(mNameText); + + if (new_name + || alpha != mNameAlpha) + { + mNameText->setAlpha(alpha); + mNameAlpha = alpha; + } +} + +LLColor4 LLVOAvatar::getNameTagColor(bool is_friend) +{ + static LLUICachedControl<bool> show_friends("NameTagShowFriends"); + const char* color_name; + if (show_friends && is_friend) + { + color_name = "NameTagFriend"; + } + else if (LLAvatarNameCache::useDisplayNames()) + { + // ...color based on whether username "matches" a computed display + // name + LLAvatarName av_name; + if (LLAvatarNameCache::get(getID(), &av_name) + && av_name.mIsDisplayNameDefault) + { + color_name = "NameTagMatch"; } + else + { + color_name = "NameTagMismatch"; } - else if (mNameText) + } + else { - mNameText->markDead(); - mNameText = NULL; - sNumVisibleChatBubbles--; + // ...not using display names + color_name = "NameTagLegacy"; } + return LLUIColorTable::getInstance()->getColor( color_name ); } //-------------------------------------------------------------------- @@ -6763,7 +6904,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) { releaseComponentTextures(); } - + // parse visual params S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam); bool drop_visual_params_debug = gSavedSettings.getBOOL("BlockSomeAvatarAppearanceVisualParams") && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing @@ -6856,9 +6997,9 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // re-request appearance, hoping that it comes back with a shape next time llinfos << "Re-requesting AvatarAppearance for object: " << getID() << llendl; LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID()); - } - else - { + } + else + { llinfos << "That's okay, we already have a non-default shape for object: " << getID() << llendl; // we don't really care. } @@ -7750,9 +7891,7 @@ std::string LLVOAvatar::getFullname() const LLNameValue* last = getNVPair("LastName"); if (first && last) { - name += first->getString(); - name += " "; - name += last->getString(); + name = LLCacheName::buildFullName( first->getString(), last->getString() ); } return name; |