From f04aabde96c26278ffd44a2f6c5e3680a81c1fbe Mon Sep 17 00:00:00 2001 From: Shyotl Date: Wed, 30 May 2012 19:14:11 -0500 Subject: [PATCH] Updated client tagging system. Client tags only looked up in opensim, and most logic pulled out into its own singleton. --- indra/llprimitive/llprimitive.cpp | 18 +- indra/llprimitive/llprimitive.h | 4 +- .../newview/app_settings/settings_ascent.xml | 2 +- indra/newview/ascentprefsvan.cpp | 61 +- indra/newview/llagent.cpp | 48 +- indra/newview/llagent.h | 6 - indra/newview/llfloateravatarlist.cpp | 16 +- indra/newview/llviewercontrol.cpp | 26 - indra/newview/llviewermenu.cpp | 7 +- indra/newview/llviewermessage.cpp | 52 +- indra/newview/llvoavatar.cpp | 1845 ++++++++--------- indra/newview/llvoavatar.h | 113 +- indra/newview/llvoavatarself.cpp | 7 +- .../skins/default/xui/en-us/strings.xml | 3 + 14 files changed, 1040 insertions(+), 1168 deletions(-) diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index f6ecbc953..83ea3e3eb 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -1076,9 +1076,8 @@ S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 dat // Pack information about all texture entries into container: // { TextureEntry Variable 2 } // Includes information about image ID, color, scale S,T, offset S,T and rotation -BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys, int shield, std::string client_str) const +BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const { - LLUUID client_tag = LLUUID(client_str); const U32 MAX_TES = 32; U8 image_ids[MAX_TES*16]; @@ -1097,8 +1096,6 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys, int shield, std::strin U8 *cur_ptr = packed_buffer; S32 last_face_index = llmin((U32) getNumTEs(), MAX_TES) - 1; - - if (client_str == "c228d1cf-4b5d-4ba8-84f4-899a0796aa97") shield = 0; if (last_face_index > -1) { @@ -1108,18 +1105,7 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys, int shield, std::strin for (face_index = 0; face_index <= last_face_index; face_index++) { // Directly sending image_ids is not safe! - if(shield && !(face_index == 20 || face_index == 8 || face_index == 9 || face_index == 10 || face_index == 11 || face_index == 18 || face_index == 19)) - { - S8 f_f_i = face_index; - if(face_index == 0)f_f_i = 64; - if(face_index == 5)f_f_i = 9; - if(face_index == 6)f_f_i = 10; - if(face_index == 3)f_f_i = 11; - if(f_f_i == face_index)memcpy(&image_ids[face_index*16],LLUUID("c228d1cf-4b5d-4ba8-84f4-899a0796aa97").mData,16); - else if(f_f_i == 64)memcpy(&image_ids[face_index*16],client_tag.mData,16); - else memcpy(&image_ids[face_index*16],LLUUID("4934f1bf-3b1f-cf4f-dbdf-a72550d05bc6").mData,16);//grey block - } - else memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); /* Flawfinder: ignore */ + memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); /* Flawfinder: ignore */ // Cast LLColor4 to LLColor4U coloru.setVec( getTE(face_index)->getColor() ); diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 7fe47fb01..5808ffc3c 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -334,7 +334,7 @@ public: // Modify texture entry properties inline BOOL validTE(const U8 te_num) const; - LLTextureEntry *getTE(const U8 te_num) const; + LLTextureEntry* getTE(const U8 te_num) const; virtual void setNumTEs(const U8 num_tes); virtual void setAllTETextures(const LLUUID &tex_id); @@ -364,7 +364,7 @@ public: void copyTEs(const LLPrimitive *primitive); S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const; S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type); - BOOL packTEMessage(LLMessageSystem *mesgsys, int shield = 0, std::string client_str = "") const; + BOOL packTEMessage(LLMessageSystem *mesgsys) const; BOOL packTEMessage(LLDataPacker &dp) const; S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name); S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num); // Variable num of blocks diff --git a/indra/newview/app_settings/settings_ascent.xml b/indra/newview/app_settings/settings_ascent.xml index 949c66a93..bcd1c2864 100644 --- a/indra/newview/app_settings/settings_ascent.xml +++ b/indra/newview/app_settings/settings_ascent.xml @@ -271,7 +271,7 @@ AscentShowFriendsTag Comment - Show friends client tags as (Friend), and colorize them specially. + Show friends' client tags as (Friend). Persist 1 Type diff --git a/indra/newview/ascentprefsvan.cpp b/indra/newview/ascentprefsvan.cpp index 245a33af2..53f0d5751 100644 --- a/indra/newview/ascentprefsvan.cpp +++ b/indra/newview/ascentprefsvan.cpp @@ -131,25 +131,16 @@ void LLPrefsAscentVan::onCommitTextModified(LLUICtrl* ctrl, void* userdata) //static void LLPrefsAscentVan::onManualClientUpdate(void* data) { - LLChat chat; - chat.mSourceType = CHAT_SOURCE_SYSTEM; - chat.mText = llformat("Definitions already up-to-date."); - if (LLVOAvatar::updateClientTags()) - { - chat.mText = llformat("Client definitions updated."); - LLVOAvatar::loadClientTags(); - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - LLVOAvatar* avatarp = (LLVOAvatar*) *iter; - if(avatarp) - { - LLVector3 root_pos_last = avatarp->mRoot.getWorldPosition(); - avatarp->mClientTag = ""; - } - } - } - LLFloaterChat::addChat(chat); + LLChat chat("Definitions already up-to-date."); + chat.mSourceType = CHAT_SOURCE_SYSTEM; + if(SHClientTagMgr::instance().fetchDefinitions()) + { + if(SHClientTagMgr::instance().parseDefinitions()) + chat.mText="Client definitons updated."; + else + chat.mText="Failed to parse updated definitions."; + } + LLFloaterChat::addChat(chat); } //static @@ -159,32 +150,8 @@ void LLPrefsAscentVan::onCommitCheckBox(LLUICtrl* ctrl, void* user_data) // llinfos << "Control named " << ctrl->getControlName() << llendl; - if (ctrl->getName() == "show_friend_tag_check") + if (ctrl->getName() == "use_status_check") { - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - LLVOAvatar* avatarp = (LLVOAvatar*) *iter; - if(avatarp) - { - LLVector3 root_pos_last = avatarp->mRoot.getWorldPosition(); - avatarp->mClientTag = ""; - } - } - } - else if (ctrl->getName() == "use_status_check") - { - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - LLVOAvatar* avatarp = (LLVOAvatar*) *iter; - if(avatarp) - { - LLVector3 root_pos_last = avatarp->mRoot.getWorldPosition(); - avatarp->mClientTag = ""; - } - } - BOOL showCustomColors = gSavedSettings.getBOOL("AscentUseStatusColors"); self->childSetEnabled("friends_color_textbox", showCustomColors); self->childSetEnabled("friend_color_swatch", showCustomColors); @@ -200,12 +167,6 @@ void LLPrefsAscentVan::onCommitCheckBox(LLUICtrl* ctrl, void* user_data) self->childSetEnabled("custom_tag_color_text", showCustomOptions); self->childSetEnabled("custom_tag_color_swatch", showCustomOptions); } - - if (!gAgent.getID().isNull()) - { - gAgent.sendAgentSetAppearance(); - gAgent.resetClientTag(); - } } // Store current settings for cancel diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 2f878c450..b02fbf71c 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -535,14 +535,6 @@ BOOL LLAgent::getPhantom() return exlPhantom; } -void LLAgent::resetClientTag() -{ - if (gAgentAvatarp) - { - llinfos << "Resetting mClientTag." << llendl; - gAgentAvatarp->mClientTag = ""; - } -} // //----------------------------------------------------------------------------- @@ -3971,45 +3963,7 @@ void LLAgent::sendAgentSetAppearance() } } msg->nextBlockFast(_PREHASH_ObjectData); - - /*if (gSavedSettings.getBOOL("AscentUseCustomTag")) - { - LLColor4 color; - if (!gSavedSettings.getBOOL("AscentStoreSettingsPerAccount")) - { - color = gSavedSettings.setColor4("AscentCustomTagColor"); - } - else - { - color = gSavedPerAccountSettings.getColor4("AscentCustomTagColor"); - } - LLUUID old_teid; - U8 client_buffer[UUID_BYTES]; - memset(&client_buffer, 0, UUID_BYTES); - LLTextureEntry* entry = (LLTextureEntry*)gAgentAvatarp->getTE(0); - old_teid = entry->getID(); - //You edit this to change the tag in your client. Yes. - const char* tag_client = "Ascent"; - strncpy((char*)&client_buffer[0], tag_client, UUID_BYTES); - LLUUID part_a; - memcpy(&part_a.mData, &client_buffer[0], UUID_BYTES); - entry->setColor(color); - //This glow is used to tell if the tag color and name is set or not. - entry->setGlow(0.1f); - entry->setID(part_a); - gAgentAvatarp->packTEMessage( gMessageSystem, 1, gSavedSettings.getString("AscentReportClientUUID") ); - entry->setID(old_teid); - - } - else - {*/ - if (gSavedSettings.getBOOL("AscentUseTag")) - gAgentAvatarp->packTEMessage( gMessageSystem, 1, gSavedSettings.getString("AscentReportClientUUID")); - else - gAgentAvatarp->packTEMessage( gMessageSystem, 1, "c228d1cf-4b5d-4ba8-84f4-899a0796aa97"); - //} - resetClientTag(); - + gAgentAvatarp->sendAppearanceMessage( gMessageSystem ); } else { diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 2d4231ef1..bdb616695 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -169,12 +169,6 @@ public: void setGenderChosen(BOOL b) { mGenderChosen = b; } private: BOOL mGenderChosen; - - //-------------------------------------------------------------------- - // Client Tagging - //-------------------------------------------------------------------- -public: - void resetClientTag(); /** Identity ** ** diff --git a/indra/newview/llfloateravatarlist.cpp b/indra/newview/llfloateravatarlist.cpp index 6daabb383..882263e0e 100644 --- a/indra/newview/llfloateravatarlist.cpp +++ b/indra/newview/llfloateravatarlist.cpp @@ -350,12 +350,12 @@ BOOL LLFloaterAvatarList::postBuild() if(gHippoGridManager->getConnectedGrid()->isSecondLife()){ LLScrollListCtrl* list = getChild("avatar_list"); - list->getColumn(1)->setWidth(0); - list->getColumn(6)->setWidth(0); - list->getColumn(6)->mDynamicWidth = FALSE; - list->getColumn(6)->mRelWidth = 0; - list->getColumn(1)->mDynamicWidth = TRUE; - list->getColumn(1)->mRelWidth = -1; + list->getColumn(LIST_AVATAR_NAME)->setWidth(0); + list->getColumn(LIST_CLIENT)->setWidth(0); + list->getColumn(LIST_CLIENT)->mDynamicWidth = FALSE; + list->getColumn(LIST_CLIENT)->mRelWidth = 0; + list->getColumn(LIST_AVATAR_NAME)->mDynamicWidth = TRUE; + list->getColumn(LIST_AVATAR_NAME)->mRelWidth = -1; list->updateLayout(); } @@ -894,11 +894,11 @@ void LLFloaterAvatarList::refreshAvatarList() static const LLCachedControl avatar_name_color(gColors, "AvatarNameColor",LLColor4(LLColor4U(251, 175, 93, 255)) ); LLColor4 client_color(avatar_name_color); - std::string client; LLVOAvatar *avatarp = gObjectList.findAvatar(av_id); if(avatarp) { - avatarp->getClientInfo(client, client_color, TRUE); + std::string client = SHClientTagMgr::instance().getClientName(avatarp, false); + SHClientTagMgr::instance().getClientColor(avatarp, false, client_color); if(client == "") { client_color = unselected_color; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 0722bfb7b..1b190259b 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -586,25 +586,6 @@ bool handleCloudSettingsChanged(const LLSD& newvalue) return true; } -bool handleAscentSelfTag(const LLSD& newvalue) -{ - if(gAgentAvatarp) - gAgentAvatarp->mClientTag = ""; - return true; -} - -bool handleAscentGlobalTag(const LLSD& newvalue) -{ - S32 object_count = gObjectList.getNumObjects(); - for (S32 i = 0; i < object_count; i++) - { - LLViewerObject *objectp = gObjectList.getObject(i); - if (objectp && objectp->isAvatar()) - ((LLVOAvatar*)objectp)->mClientTag = ""; - } - return true; -} - bool handleAscentAvatarModifier(const LLSD& newvalue) { llinfos << "Calling gAgent.sendAgentSetAppearance() because AscentAvatar*Modifier changed." << llendl; @@ -791,13 +772,6 @@ void settings_setup_listeners() gSavedSettings.getControl("EmeraldBreastPhysicsToggle")->getSignal()->connect(boost::bind(&handleAvatarBoobToggleChanged, _2)); gSavedSettings.getControl("EmeraldBoobXYInfluence")->getSignal()->connect(boost::bind(&handleAvatarBoobXYInfluence, _2)); - gSavedSettings.getControl("AscentUseTag")->getSignal()->connect(boost::bind(&handleAscentSelfTag,_2)); - gSavedSettings.getControl("AscentUseCustomTag")->getSignal()->connect(boost::bind(&handleAscentSelfTag,_2)); - gSavedSettings.getControl("AscentCustomTagColor")->getSignal()->connect(boost::bind(&handleAscentSelfTag,_2)); - gSavedSettings.getControl("AscentCustomTagLabel")->getSignal()->connect(boost::bind(&handleAscentSelfTag,_2)); - gSavedSettings.getControl("AscentReportClientUUID")->getSignal()->connect(boost::bind(&handleAscentSelfTag,_2)); - gSavedSettings.getControl("AscentShowFriendsTag")->getSignal()->connect(boost::bind(&handleAscentGlobalTag,_2)); - gSavedSettings.getControl("AscentUseStatusColors")->getSignal()->connect(boost::bind(&handleAscentGlobalTag,_2)); gSavedSettings.getControl("AscentAvatarXModifier")->getSignal()->connect(boost::bind(&handleAscentAvatarModifier, _2)); gSavedSettings.getControl("AscentAvatarYModifier")->getSignal()->connect(boost::bind(&handleAscentAvatarModifier, _2)); gSavedSettings.getControl("AscentAvatarZModifier")->getSignal()->connect(boost::bind(&handleAscentAvatarModifier, _2)); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index dc4fb0b5a..e7867655c 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3192,11 +3192,8 @@ class LLAvatarClientUUID : public view_listener_t { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); if(!avatar) return true; - - std::string clientID; - LLColor4 color; - avatar->getClientInfo(clientID, color, false); - gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(clientID)); + const LLUUID clientID = SHClientTagMgr::instance().getClientID(avatar); + gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(clientID.asString())); return true; } }; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 63a71f5fb..c0e112c14 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3343,8 +3343,6 @@ class AuthHandler : public HippoRestHandlerRaw } }; -std::map gChatObjectAuth; - void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) { LLChat chat; @@ -3512,47 +3510,69 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) { msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, mesg); + static std::map sChatObjectAuth; + if ((source_temp == CHAT_SOURCE_OBJECT) && (type_temp == CHAT_TYPE_OWNER) && - (mesg.substr(0, 3) == "># ")) { - if (mesg.substr(mesg.size()-3, 3) == " #<") { + (mesg.substr(0, 3) == "># ")) + { + if (mesg.substr(mesg.size()-3, 3) == " #<"){ // hello from object if (from_id.isNull()) return; char buf[200]; snprintf(buf, 200, "%s v%d.%d.%d", gVersionChannel, gVersionMajor, gVersionMinor, gVersionPatch); send_chat_from_viewer(buf, CHAT_TYPE_WHISPER, 427169570); - gChatObjectAuth[from_id] = 1; - } else if (gChatObjectAuth.find(from_id) != gChatObjectAuth.end()) { + sChatObjectAuth[from_id] = 1; + return; + } + else if (sChatObjectAuth.find(from_id) != sChatObjectAuth.end()) + { LLUUID key; - if (LLUUID::parseUUID(mesg.substr(3, 36), &key)) { + if (key.set(mesg.substr(3, 36),false)) + { // object command found - if (key.isNull() && (mesg.size() == 39)) { + if (key.isNull() && (mesg.size() == 39)) + { // clear all nameplates - for (int i=0; i(obj)) + { avatar->clearNameFromChat(); + } } - } else { - if (key.isNull()) { + } + else + { + if (key.isNull()) + { llwarns << "Nameplate from chat on NULL avatar (ignored)" << llendl; return; } LLVOAvatar *avatar = gObjectList.findAvatar(key); - if (!avatar) { + if (!avatar) + { llwarns << "Nameplate from chat on invalid avatar (ignored)" << llendl; return; } - if (mesg.size() == 39) { + if (mesg.size() == 39) + { avatar->clearNameFromChat(); - } else if (mesg[39] == ' ') { + } + else if (mesg[39] == ' ') + { avatar->setNameFromChat(mesg.substr(40)); } } return; - } else if (mesg.substr(2, 9) == " floater ") { + } + else if (mesg.substr(2, 9) == " floater ") + { HippoFloaterXml::execute(mesg.substr(11)); return; - } else if (mesg.substr(2, 6) == " auth ") { + } + else if (mesg.substr(2, 6) == " auth ") + { std::string authUrl = mesg.substr(8); authUrl += (authUrl.find('?') != std::string::npos)? "&auth=": "?auth="; authUrl += gAuthString; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 7dcb9b01a..775250cf9 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -107,6 +107,7 @@ #include "llsdserialize.h" //For the client definitions #include "llcachename.h" #include "floaterao.h" +#include "llsdutil.h" // #include "llfloaterexploreanimations.h" @@ -115,6 +116,8 @@ #include "llavatarname.h" +#include "hippogridmanager.h" + // [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.2.0c) #include "rlvhandler.h" // [/RLVa:KB] @@ -600,6 +603,336 @@ private: LLCharacter* mCharacter; }; +SHClientTagMgr::SHClientTagMgr() +{ + //Status colors/friend tags are always relevant, regardless of grid. + gSavedSettings.getControl("AscentShowFriendsTag")->getSignal()->connect(boost::bind(&LLVOAvatar::invalidateNameTags)); + gSavedSettings.getControl("AscentUseStatusColors")->getSignal()->connect(boost::bind(&LLVOAvatar::invalidateNameTags)); + gSavedSettings.getControl("AscentShowSelfTagColor")->getSignal()->connect(boost::bind(&LLVOAvatar::invalidateNameTags)); + gSavedSettings.getControl("AscentShowOthersTagColor")->getSignal()->connect(boost::bind(&LLVOAvatar::invalidateNameTags)); + gSavedSettings.getControl("AscentLindenColor")->getSignal()->connect(boost::bind(&LLVOAvatar::invalidateNameTags)); + gSavedSettings.getControl("AscentEstateOwnerColor")->getSignal()->connect(boost::bind(&LLVOAvatar::invalidateNameTags)); + gSavedSettings.getControl("AscentFriendColor")->getSignal()->connect(boost::bind(&LLVOAvatar::invalidateNameTags)); + gSavedSettings.getControl("AscentMutedColor")->getSignal()->connect(boost::bind(&LLVOAvatar::invalidateNameTags)); + + if(!getIsEnabled()) + return; + + if (gSavedSettings.getBOOL("AscentUpdateTagsOnLoad")) + fetchDefinitions(); + parseDefinitions(); + + //These only matter to the agent avatar. Don't iterate over everything. + gSavedSettings.getControl("AscentUseTag")->getSignal()->connect(boost::bind(&SHClientTagMgr::updateAgentAvatarTag, this)); + gSavedSettings.getControl("AscentUseCustomTag")->getSignal()->connect(boost::bind(&SHClientTagMgr::updateAgentAvatarTag, this)); + gSavedSettings.getControl("AscentCustomTagColor")->getSignal()->connect(boost::bind(&SHClientTagMgr::updateAgentAvatarTag, this)); + gSavedSettings.getControl("AscentCustomTagLabel")->getSignal()->connect(boost::bind(&SHClientTagMgr::updateAgentAvatarTag, this)); + gSavedSettings.getControl("AscentReportClientUUID")->getSignal()->connect(boost::bind(&SHClientTagMgr::updateAgentAvatarTag, this)); + + //Fire off a AgentSetAppearance update if these change. + gSavedSettings.getControl("AscentUseTag")->getSignal()->connect(boost::bind(&LLAgent::sendAgentSetAppearance, &gAgent)); + gSavedSettings.getControl("AscentReportClientUUID")->getSignal()->connect(boost::bind(&LLAgent::sendAgentSetAppearance, &gAgent)); +} + +bool SHClientTagMgr::getIsEnabled() const +{ + //TE info is wiped out by the simulators on the MAIN grid. Disable client tagging when connected to it. + return !gHippoGridManager->getConnectedGrid()->isSecondLife(); +} + +bool SHClientTagMgr::fetchDefinitions() const +{ + std::string client_list_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "client_tags_sg1.xml"); + std::string client_list_url = gSavedSettings.getString("ClientDefinitionsURL"); + LLSD response = LLHTTPClient::blockingGet(client_list_url); + if(response.has("body")) + { + const LLSD &client_list = response["body"]; + + if(client_list.has("isComplete")) + { + llofstream export_file; + export_file.open(client_list_filename); + LLSDSerialize::toPrettyXML(client_list, export_file); + export_file.close(); + return true; + } + } + return false; +} +bool SHClientTagMgr::parseDefinitions() +{ + std::string client_list_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "client_tags_sg1.xml"); + + if(!LLFile::isfile(client_list_filename)) + { + client_list_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "client_tags_sg1.xml"); + } + + if(LLFile::isfile(client_list_filename)) + { + LLSD client_list; + llifstream importer(client_list_filename); + if(importer.is_open()) + { + LLSDSerialize::fromXMLDocument(client_list, importer); + importer.close(); + if(client_list.has("isComplete")) + { + mClientDefinitions.clear(); + for (LLSD::map_const_iterator it = client_list.beginMap(); it != client_list.endMap(); ++it) + { + llinfos << it->first << llendl; + LLUUID id; + if(id.set(it->first,false)) + { + LLSD info = it->second; + info["id"] = id; + F32 mult = info["multiple"].asReal(); + if(mult != 0.f) + { + static const LLCachedControl avatar_name_color(gColors,"AvatarNameColor",LLColor4(LLColor4U(251, 175, 93, 255)) ); + LLColor4 color(info["color"]); + color += avatar_name_color; + color *= 1.f/(mult+1.f); + info.insert("color", color.getValue()); + } + llinfos << info["name"] << " : " << info["id"] << llendl; + mClientDefinitions[id]=info; + llinfos << mClientDefinitions.size() << llendl; + } + } + if(getIsEnabled()) + { + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* pAvatar = dynamic_cast(*iter); + if(pAvatar) + updateAvatarTag(pAvatar); + } + } + return true; + } + } + } + return false; +} +void SHClientTagMgr::updateAgentAvatarTag() +{ + if(isAgentAvatarValid()) + updateAvatarTag(gAgentAvatarp); +} +const LLSD SHClientTagMgr::generateClientTag(const LLVOAvatar* pAvatar) const +{ + if(!getIsEnabled()) + return LLSD(); + + static const LLCachedControl avatar_name_color(gColors,"AvatarNameColor",LLColor4(LLColor4U(251, 175, 93, 255)) ); + LLUUID id; + + if (pAvatar->isSelf()) + { + static const LLCachedControl ascent_use_tag("AscentUseTag",true); + static const LLCachedControl ascent_use_custom_tag("AscentUseCustomTag", false); + static const LLCachedControl ascent_custom_tag_color("AscentCustomTagColor", LLColor4(.5f,1.f,.25f,1.f)); + static const LLCachedControl ascent_custom_tag_label("AscentCustomTagLabel","custom"); + static const LLCachedControl ascent_report_client_uuid("AscentReportClientUUID","f25263b7-6167-4f34-a4ef-af65213b2e39"); + + if (ascent_use_custom_tag) + { + LLSD info; + info.insert("name", ascent_custom_tag_label.get()); + info.insert("color", ascent_custom_tag_color.get().getValue()); + return info; + } + else if (ascent_use_tag) + { + id.set(ascent_report_client_uuid,false); + } + } + else + { + LLTextureEntry* pTextureEntry = pAvatar->getTE(TEX_HEAD_BODYPAINT); + if (!pTextureEntry) + return LLSD(); + + id = pTextureEntry->getID(); + + if(pAvatar->isFullyLoaded() && pTextureEntry->getGlow() > 0.0) + { + ///llinfos << "Using new client identifier." << llendl; + U8 tag_buffer[UUID_BYTES+1]; + memset(&tag_buffer, 0, UUID_BYTES); + memcpy(&tag_buffer[0], &id.mData, UUID_BYTES); + tag_buffer[UUID_BYTES] = 0; + U32 tag_len = llmin((S32)strlen((const char*)&tag_buffer[0]), UUID_BYTES); + std::string client((char*)&tag_buffer[0], tag_len); + LLStringFn::replace_ascii_controlchars(client, LL_UNKNOWN_CHAR); + LLSD info; + info.insert("name", std::string((char*)&tag_buffer[0], tag_len)); + info.insert("color", pTextureEntry->getColor().getValue()); + return info; + } + if(pAvatar->getTEImage(TEX_HEAD_BODYPAINT)->getID() == IMG_DEFAULT_AVATAR) + { + for(S32 te = TEX_UPPER_SHIRT; te <= TEX_SKIRT; ++te) //Don't iterate past skirt. The sim doesn't even send those TEs (Those TEs assume TEX_HAIR_BAKED's uuid) + { + LLWearableType::EType wearable = LLVOAvatarDictionary::getTEWearableType((LLVOAvatarDefines::ETextureIndex)te); + if( wearable != LLWearableType::WT_INVALID && + wearable != LLWearableType::WT_ALPHA && + wearable != LLWearableType::WT_TATTOO && + pAvatar->getTEImage(te)->getID() != IMG_DEFAULT_AVATAR) + { + static LLUUID grey_id("4934f1bf-3b1f-cf4f-dbdf-a72550d05bc6"); + + LLSD info; + + //Apparently this happens with broken clothing protection... + if( pAvatar->getTEImage(TEX_EYES_IRIS)->getID() == grey_id && + pAvatar->getTEImage(TEX_UPPER_BODYPAINT)->getID() == grey_id && + pAvatar->getTEImage(TEX_LOWER_BODYPAINT)->getID() == grey_id ) + { + info.insert("name", "?"); + info.insert("color", avatar_name_color.get().getValue()); + } + return info; + } + } + + //Verify if this actually ever happens on opensim with V3 clients. + LLSD info; + info.insert("name", "Viewer 2.0"); + info.insert("color", LLColor4::white.getValue()); + return info; + } + else if(pAvatar->getTEImage(TEX_HEAD_BODYPAINT)->isMissingAsset()) + { + LLSD info; + info.insert("name", "Unknown"); + info.insert("color", LLColor4(0.5f, 0.0f, 0.0f).getValue()); + return info; + } + } + + if(!mClientDefinitions.empty()) + { + std::map::const_iterator it = mClientDefinitions.find(id); + /*S32 idx = ll_rand(mClientDefinitions.size()-1); + for(;it!=mClientDefinitions.end();++it) + { + if(!idx--) + { + llinfos << "[" << idx << "] Returning " << it->second["name"] << " : " << it->second["id"] << llendl; + return it->second; + } + else + llinfos << "[" << idx << "] Skipping " << it->second["name"] << " : " << it->second["id"] << llendl; + }*/ + if(it != mClientDefinitions.end()) + { + return it->second; + } + } + //Unhandled. Just return blank. + return LLSD(); +} +void SHClientTagMgr::updateAvatarTag(LLVOAvatar* pAvatar) +{ + LLUUID id = pAvatar->getID(); + std::map::iterator it = mAvatarTags.find(id); + + LLSD new_tag = generateClientTag(pAvatar); + LLSD& old_tag = (it != mAvatarTags.end()) ? it->second : LLSD(); + + bool dirty = old_tag.size() != new_tag.size() || !llsd_equals(new_tag,old_tag); + if(dirty) + { + if(new_tag.isUndefined()) + mAvatarTags.erase(id); + else + mAvatarTags.insert(std::pair(id, new_tag)); + pAvatar->clearNameTag(); //LLVOAvatar::idleUpdateNameTag will pick up on mNameString being cleared. + } +} +const std::string SHClientTagMgr::getClientName(const LLVOAvatar* pAvatar, bool is_friend) const +{ + static LLCachedControl ascent_show_friends_tag("AscentShowFriendsTag", false); + if(is_friend && ascent_show_friends_tag) + return "Friend"; + else + { + LLSD tag; + std::map::const_iterator it = mAvatarTags.find(pAvatar->getID()); + if(it != mAvatarTags.end()) + { + tag = it->second.get("name"); + } + return tag.asString(); + } +} +const LLUUID SHClientTagMgr::getClientID(const LLVOAvatar* pAvatar) const +{ + LLSD tag; + std::map::const_iterator it = mAvatarTags.find(pAvatar->getID()); + if(it != mAvatarTags.end()) + { + tag = it->second.get("id"); + } + return tag.asUUID(); +} +bool SHClientTagMgr::getClientColor(const LLVOAvatar* pAvatar, bool check_status, LLColor4& color) const +{ + static const LLCachedControl ascent_use_status_colors("AscentUseStatusColors",true); + static const LLCachedControl ascent_show_self_tag_color("AscentShowSelfTagColor"); + static const LLCachedControl ascent_show_others_tag_color("AscentShowOthersTagColor"); + + if(check_status && ascent_use_status_colors && !pAvatar->isSelf()) + { + LLViewerRegion* parent_estate = LLWorld::getInstance()->getRegionFromPosGlobal(pAvatar->getPositionGlobal()); + if(LLMuteList::getInstance()->isLinden(pAvatar->getFullname())) + { + static const LLCachedControl ascent_linden_color( "AscentLindenColor" ); + color = ascent_linden_color.get(); + return true; + } + else if(pAvatar->getID().notNull() && parent_estate && parent_estate->isAlive() && pAvatar->getID() == parent_estate->getOwner()) + { + static const LLCachedControl ascent_estate_owner_color( "AscentEstateOwnerColor" ); + color = ascent_estate_owner_color.get(); + return true; + } + else if(LLAvatarTracker::instance().isBuddy(pAvatar->getID())) + { + static const LLCachedControl ascent_friend_color( "AscentFriendColor" ); + color = ascent_friend_color.get(); + return true; + } + else if(LLMuteList::getInstance()->isMuted(pAvatar->getID())) + { + static const LLCachedControl ascent_muted_color( "AscentMutedColor" ); + color = ascent_muted_color.get(); + return true; + } + } + std::map::const_iterator it; + LLSD tag; + if( + ((pAvatar->isSelf() && ascent_show_self_tag_color) || + (!pAvatar->isSelf() && ascent_show_others_tag_color)) && + (it = mAvatarTags.find(pAvatar->getID()))!=mAvatarTags.end() && + (tag = it->second.get("color")).isDefined()) + { + color.setValue(tag); + return true; + } + return false; +} +//Call on destruction of avatar. Removes entry in mAvatarTags map. +void SHClientTagMgr::clearAvatarTag(const LLVOAvatar* pAvatar) +{ + mAvatarTags.erase(pAvatar->getID()); +} + /** ** ** End LLVOAvatar Support classes @@ -658,7 +991,6 @@ F32 LLVOAvatar::sGreyUpdateTime = 0.f; BOOL LLVOAvatar::sDebugAvatarRotation = FALSE; //Custom stuff. -LLSD LLVOAvatar::sClientResolutionList; EmeraldGlobalBoobConfig LLVOAvatar::sBoobConfig; //----------------------------------------------------------------------------- @@ -698,13 +1030,10 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mNameBusy(false), mNameMute(false), mNameAppearance(false), - mRenderedName(), - mUsedNameSystem(), - mClientName(), + mNameFriend(false), + mNameAlpha(0.f), mRenderGroupTitles(sRenderGroupTitles), - mNameFromChatOverride(false), - mNameFromChatChanged(false), - mRenderTag(false), + mNameCloud(false), mFirstTEMessageReceived( FALSE ), mFirstAppearanceMessageReceived( FALSE ), mCulled( FALSE ), @@ -723,15 +1052,10 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mHasPelvisOffset( FALSE ), mRenderUnloadedAvatar(LLCachedControl(gSavedSettings, "RenderUnloadedAvatar")), mFirstSetActualBoobGravRan( false ), - mSupportsPhysics( false ) - //mFirstSetActualButtGravRan( false ), - //mFirstSetActualFatGravRan( false ) + mSupportsPhysics( false ), // -// mNametagSaysIdle(false), -// mIdleForever(true), -// mIdleMinutes(0), -// mFocusObject(LLUUID::null), -// mFocusVector(LLVector3d::zero) + mIdleMinute(0), + mCCSChatTextOverride(false) // { LLMemType mt(LLMemType::MTYPE_AVATAR); @@ -758,8 +1082,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mDirtyMesh = 2; // Dirty geometry, need to regenerate. mMeshTexturesDirty = FALSE; - mShadow0Facep = NULL; - mShadow1Facep = NULL; mHeadp = NULL; mIsBuilt = FALSE; @@ -795,10 +1117,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mRippleTimeLast = 0.f; - mShadowImagep = LLViewerTextureManager::getFetchedTextureFromFile("foot_shadow.j2c"); - gGL.getTexUnit(0)->bind(mShadowImagep.get()); - mShadowImagep->setAddressMode(LLTexUnit::TAM_CLAMP); - mInAir = FALSE; mStepOnLand = TRUE; @@ -892,12 +1210,11 @@ LLVOAvatar::~LLVOAvatar() mDead = TRUE; - // Clean up class data - LLVOAvatar::cullAvatarsByPixelArea(); - mAnimationSources.clear(); LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ; + SHClientTagMgr::instance().clearAvatarTag(this); + lldebugs << "LLVOAvatar Destructor end" << llendl; } @@ -965,11 +1282,6 @@ BOOL LLVOAvatar::areAllNearbyInstancesBaked(S32& grey_avatars) { continue; } -// else -// if( inst->getPixelArea() < MIN_PIXEL_AREA_FOR_COMPOSITE ) -// { -// return res; // Assumes sInstances is sorted by pixel area. -// } else if( !inst->isFullyBaked() ) { res = FALSE; @@ -1260,20 +1572,8 @@ void LLVOAvatar::initClass() { llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } - { - if (gSavedSettings.getBOOL("AscentUpdateTagsOnLoad")) - { - if (updateClientTags()) - { - LLChat chat; - chat.mSourceType = CHAT_SOURCE_SYSTEM; - chat.mText = llformat("Client definitions are up-to-date."); - LLFloaterChat::addChat(chat); - } - } - loadClientTags(); - } + SHClientTagMgr::instance(); //Instantiate. Parse. Will fetch a new tag file if AscentUpdateTagsOnLoad is true. } @@ -2162,7 +2462,7 @@ void LLVOAvatar::restoreMeshData() LLViewerJointAttachment* attachment = iter->second; if (!attachment->getIsHUDAttachment()) { - attachment->setAttachmentVisibility(TRUE); + attachment->setAttachmentVisibility(TRUE); } } @@ -2831,14 +3131,12 @@ void LLVOAvatar::idleUpdateAppearanceAnimation() } else { - F32 morph_amt = calcMorphAmount(); LLVisualParam *param; if (!isSelf()) { - - // animate only top level params + // animate only top level params for non-self avatars for (param = getFirstVisualParam(); param; param = getNextVisualParam()) @@ -3069,234 +3367,11 @@ void LLVOAvatar::idleUpdateWindEffect() } } -bool LLVOAvatar::updateClientTags() -{ - std::string client_list_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "client_tags_sg1.xml"); - std::string client_list_url = gSavedSettings.getString("ClientDefinitionsURL"); - LLSD response = LLHTTPClient::blockingGet(client_list_url); - if(response.has("body")) - { - const LLSD &client_list = response["body"]; - - if(client_list.has("isComplete")) - { - llofstream export_file; - export_file.open(client_list_filename); - LLSDSerialize::toPrettyXML(client_list, export_file); - export_file.close(); - return true; - } - } - return false; -} - -bool LLVOAvatar::loadClientTags() -{ - //Changed the file name to keep Emerald from overwriting it. Hokey stuff in there, and it's missing clients. -HGB - std::string client_list_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "client_tags_sg1.xml"); - - if(!LLFile::isfile(client_list_filename)) - { - client_list_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "client_tags_sg1.xml"); - } - - if(LLFile::isfile(client_list_filename)) - { - LLSD client_list; - - llifstream importer(client_list_filename); - LLSDSerialize::fromXMLDocument(client_list, importer); - if(client_list.has("isComplete")) - { - sClientResolutionList = client_list; - } - else - { - return false; - } - }else - { - return false; - } - - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - LLVOAvatar* avatarp = (LLVOAvatar*) *iter; - if(avatarp) - { - LLVector3 root_pos_last = avatarp->mRoot.getWorldPosition(); - avatarp->idleUpdateNameTag(root_pos_last); - } - } - return true; -} - -void LLVOAvatar::getClientInfo(std::string& client, LLColor4& color, BOOL useComment) -{ - if (!getTE(TEX_HEAD_BODYPAINT)) - return; - std::string uuid_str = getTE(TEX_HEAD_BODYPAINT)->getID().asString(); //UUID of the head texture - - if(isFullyLoaded()) - { - //Zwagoth's new client identification - HgB - // Overwrite the current tag/color settings if new method - // exists -- charbl. - const LLTextureEntry* texentry = getTE(0); - if(texentry->getGlow() > 0.0) - { - ///llinfos << "Using new client identifier." << llendl; - U8 tag_buffer[UUID_BYTES+1]; - memset(&tag_buffer, 0, UUID_BYTES); - memcpy(&tag_buffer[0], &texentry->getID().mData, UUID_BYTES); - tag_buffer[UUID_BYTES] = 0; - U32 tag_len = strlen((const char*)&tag_buffer[0]); - tag_len = (tag_len>UUID_BYTES) ? (UUID_BYTES) : tag_len; - client = std::string((char*)&tag_buffer[0], tag_len); - LLStringFn::replace_ascii_controlchars(mClientTag, LL_UNKNOWN_CHAR); - mNameString.clear(); - color = texentry->getColor(); - return; - } - } - - static const LLCachedControl avatar_name_color(gColors,"AvatarNameColor",LLColor4(LLColor4U(251, 175, 93, 255)) ); - if (isSelf()) - { - static const LLCachedControl ascent_use_custom_tag("AscentUseCustomTag", false); - static const LLCachedControl ascent_custom_tag_color("AscentCustomTagColor", LLColor4(.5f,1.f,.25f,1.f)); - static const LLCachedControl ascent_custom_tag_label("AscentCustomTagLabel","custom"); - static const LLCachedControl ascent_use_tag("AscentUseTag",true); - static const LLCachedControl ascent_report_client_uuid("AscentReportClientUUID","f25263b7-6167-4f34-a4ef-af65213b2e39"); - - if (ascent_use_custom_tag) - { - color = ascent_custom_tag_color; - client = ascent_custom_tag_label; - return; - } - else if (ascent_use_tag) - uuid_str = ascent_report_client_uuid; - } - if(getTEImage(TEX_HEAD_BODYPAINT)->getID() == IMG_DEFAULT_AVATAR) - { - BOOL res = FALSE; - for(int ti = TEX_UPPER_SHIRT; ti < TEX_NUM_INDICES; ti++) - { - switch((ETextureIndex)ti) - { - case TEX_HEAD_BODYPAINT: - case TEX_UPPER_SHIRT: - case TEX_LOWER_PANTS: - case TEX_EYES_IRIS: - case TEX_HAIR: - case TEX_UPPER_BODYPAINT: - case TEX_LOWER_BODYPAINT: - case TEX_LOWER_SHOES: - case TEX_LOWER_SOCKS: - case TEX_UPPER_JACKET: - case TEX_LOWER_JACKET: - case TEX_UPPER_GLOVES: - case TEX_UPPER_UNDERSHIRT: - case TEX_LOWER_UNDERPANTS: - case TEX_SKIRT: - if(getTEImage(ti)->getID() != IMG_DEFAULT_AVATAR) - res = TRUE; - break; - default: - break; - } - if(res) - break; - } - if(res) - { - //I found that someone failed at clothing protection - if(getTEImage(TEX_EYES_IRIS)->getID().asString() == "4934f1bf-3b1f-cf4f-dbdf-a72550d05bc6" - && getTEImage(TEX_UPPER_BODYPAINT)->getID().asString() == "4934f1bf-3b1f-cf4f-dbdf-a72550d05bc6" - && getTEImage(TEX_LOWER_BODYPAINT)->getID().asString() == "4934f1bf-3b1f-cf4f-dbdf-a72550d05bc6") - { - color = avatar_name_color; - client = "?"; - } - return; - } - else - { - color = LLColor4(1.0f, 1.0f, 1.0f); //White, since tags are white on their side. -HgB - client = "Viewer 2.0"; - return; - } - } - if(getTEImage(TEX_HEAD_BODYPAINT)->isMissingAsset()) - { - color = LLColor4(0.5f, 0.0f, 0.0f); - client = "Unknown"; - } - if (LLVOAvatar::sClientResolutionList.has("isComplete") && LLVOAvatar::sClientResolutionList.has(uuid_str)) - { - - LLSD cllsd = LLVOAvatar::sClientResolutionList[uuid_str]; - client = cllsd["name"].asString(); - LLColor4 colour; - colour.setValue(cllsd["color"]); - if(cllsd["multiple"].asReal() != 0) - { - color += colour; - color *= 1.0/(cllsd["multiple"].asReal()+1.0f); - } - else - color = colour; - } - else - { - color = avatar_name_color; - color.setAlpha(1.f); - client = "?"; - //llinfos << "Apparently this tag isn't registered: " << uuid_str << llendl; - } - - /*if (false) - //We'll remove this entirely eventually, but it's useful information if we're going to try for the new client tag idea. -HgB - //if(useComment) - { - LLUUID baked_head_id = getTE(9)->getID(); - LLPointer baked_head_image = LLViewerTextureManager::getFetchedTexture(baked_head_id); - if(baked_head_image && baked_head_image->decodedComment.length()) - { - if(client.length()) - client += ", "; - - if(baked_head_image->commentEncryptionType == ENC_EMKDU_V1 || baked_head_image->commentEncryptionType == ENC_ONYXKDU) - client += "(XOR) "; - else if(baked_head_image->commentEncryptionType == ENC_EMKDU_V2) - client += "(AES) "; - - client += baked_head_image->decodedComment; - } - - LLPointer baked_eye_image = gTextureList.getImage(getTE(11)->getID()); - - if(baked_eye_image && !baked_eye_image->decodedComment.empty() - && baked_eye_image->decodedComment != baked_head_image->decodedComment) - { - if(baked_eye_image->commentEncryptionType == ENC_EMKDU_V1 || baked_eye_image->commentEncryptionType == ENC_ONYXKDU) - extraMetadata = "(XOR) "; - else if(baked_eye_image->commentEncryptionType == ENC_EMKDU_V2) - extraMetadata = "(AES) "; - - extraMetadata += baked_eye_image->decodedComment; - } - }*/ -} - - void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) { // update chat bubble //-------------------------------------------------------------------- - // draw text label over characters head + // draw text label over character's head //-------------------------------------------------------------------- if (mChatTimer.getElapsedTimeF32() > BUBBLE_CHAT_TIME) { @@ -3308,6 +3383,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) static const LLCachedControl FADE_DURATION("RenderNameFadeDuration",1); // seconds static const LLCachedControl use_chat_bubbles("UseChatBubbles",false); static const LLCachedControl render_name_hide_self("RenderNameHideSelf",false); + static const LLCachedControl allow_nameplate_override ("CCSAllowNameplateOverride", true); // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b bool fRlvShowNames = gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES); // [/RLVa:KB] @@ -3319,8 +3395,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) ( (!fRlvShowNames) || (RlvSettings::getShowNameTags()) ) && // [/RLVa:KB] ((sRenderName == RENDER_NAME_ALWAYS) || - (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME) || - mNameFromChatOverride)); + (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME) || (allow_nameplate_override && mCCSChatTextOverride))); // If it's your own avatar, don't draw in mouselook, and don't // draw if we're specifically hiding our own name. if (isSelf()) @@ -3330,565 +3405,477 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) && (visible_chat || !render_name_hide_self); } - // check attachments for nameplate override - static const LLCachedControl allow_nameplate_override ("CCSAllowNameplateOverride", true); - std::string nameplate; - attachment_map_t::iterator it, end=mAttachmentPoints.end(); - if (allow_nameplate_override) for (it=mAttachmentPoints.begin(); it!=end; ++it) { - // get attached object - LLViewerJointAttachment *atm = it->second; - if (!atm) continue; - std::vector::const_iterator obj_it; - for(obj_it = atm->mAttachedObjects.begin(); obj_it != atm->mAttachedObjects.end(); ++obj_it) + if ( !render_name ) + { + if (mNameText) { - LLViewerObject* obj = (*obj_it); - if (!obj) continue; - // get default color - const LLTextureEntry *te = obj->getTE(0); - if (!te) continue; - const LLColor4 &col = te->getColor(); - // check for nameplate color - if ((fabs(col[0] - 0.012f) >= 0.001f) || - (fabs(col[1] - 0.036f) >= 0.001f) || - (fabs(col[2] - 0.008f) >= 0.001f) || - (fabs(col[3] - 0.000f) >= 0.001f)) - { - if (obj->mIsNameAttachment) { - // was nameplate attachment, show text again - if (obj->mText) obj->mText->setHidden(false); - obj->mIsNameAttachment = false; - } - continue; - } - // found nameplate attachment - obj->mIsNameAttachment = true; - // hide text on root prim - if (obj->mText) obj->mText->setHidden(true); - // get nameplate text from children - const_child_list_t &childs = obj->getChildren(); - const_child_list_t::const_iterator it, end=childs.end(); - for (it=childs.begin(); it!=end; ++it) { - LLViewerObject *obj = (*it); - if (!(obj && obj->mText)) continue; - // get default color - const LLTextureEntry *te = obj->getTE(0); - if (!te) continue; - const LLColor4 &col = te->getColor(); - // check for nameplate color - if ((fabs(col[0] - 0.012f) < 0.001f) || - (fabs(col[1] - 0.036f) < 0.001f) || - (fabs(col[2] - 0.012f) < 0.001f)) - { - // add text. getString appends to current content - if ((fabs(col[3] - 0.004f) < 0.001f) || - (render_name && (fabs(col[3] - 0.000f) < 0.001f))) - nameplate = obj->mText->getStringUTF8(); - } - } + // ...clean up old name tag + mNameText->markDead(); + mNameText = NULL; + sNumVisibleChatBubbles--; } + return; } - if ( render_name ) + BOOL new_name = FALSE; + if (visible_chat != mVisibleChat) { - BOOL new_name = FALSE; - if (visible_chat != mVisibleChat) + mVisibleChat = visible_chat; + new_name = TRUE; + } + + if (sRenderGroupTitles != (bool)mRenderGroupTitles) + { + mRenderGroupTitles = sRenderGroupTitles; + new_name = TRUE; + } + + // First Calculate Alpha + // If alpha > 0, create mNameText if necessary, otherwise delete it + F32 alpha = 0.f; + if (mAppAngle > 5.f) + { + const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; + if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) { - mVisibleChat = visible_chat; - new_name = TRUE; + alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; } - - static const LLCachedControl phoenix_name_system("PhoenixNameSystem", 0); - -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b - if (fRlvShowNames) + else { - if (mRenderGroupTitles) - { - mRenderGroupTitles = FALSE; - new_name = TRUE; - } + // ...not fading, full alpha + alpha = 1.f; } - else if (sRenderGroupTitles != mRenderGroupTitles) -// [/RLVa:KB] -// if (sRenderGroupTitles != mRenderGroupTitles) + } + else if (mAppAngle > 2.f) + { + // far away is faded out also + alpha = (mAppAngle-2.f)/3.f; + } + + if (alpha <= 0.f) + { + if (mNameText) { - mRenderGroupTitles = sRenderGroupTitles; - new_name = TRUE; + mNameText->markDead(); + mNameText = NULL; + sNumVisibleChatBubbles--; } - - std::string client; - - // First Calculate Alpha - // If alpha > 0, create mNameText if necessary, otherwise delete it - { - F32 alpha = 0.f; - if (mAppAngle > 5.f) - { - const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; - if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) - { - alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; - } - else - { - // ...not fading, full alpha - alpha = 1.f; - } - } - else if (mAppAngle > 2.f) - { - // far away is faded out also - alpha = (mAppAngle-2.f)/3.f; - } - - if (alpha > 0.f) - { - if (!mNameText) - { + return; + } + + if (!mNameText) + { mNameText = static_cast( LLHUDObject::addHUDObject( LLHUDObject::LL_HUD_NAME_TAG) ); //mNameText->setMass(10.f); - mNameText->setSourceObject(this); + mNameText->setSourceObject(this); mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP); - mNameText->setVisibleOffScreen(TRUE); - mNameText->setMaxLines(11); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - sNumVisibleChatBubbles++; - new_name = TRUE; - } + mNameText->setVisibleOffScreen(TRUE); + mNameText->setMaxLines(11); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + sNumVisibleChatBubbles++; + new_name = TRUE; + } - static const LLCachedControl avatar_name_color(gColors, "AvatarNameColor" ); + LLVector3 name_position = idleUpdateNameTagPosition(root_pos_last); + mNameText->setPositionAgent(name_position); + idleCCSUpdateAttachmentText(render_name); + idleUpdateNameTagText(new_name); + idleUpdateNameTagAlpha(new_name, alpha); +} +void LLVOAvatar::idleCCSUpdateAttachmentText(bool render_name) +{ + const F32 SECS_BETWEEN_UPDATES = 0.5f; + static const LLCachedControl allow_nameplate_override ("CCSAllowNameplateOverride", true); - //As pointed out by Zwagoth, we really shouldn't be doing this per-frame. Skip if we already have the data. -HgB - if (mClientTag == "") + std::string nameplate = ""; + + if(allow_nameplate_override) + { + if(!mCCSUpdateAttachmentTimer.checkExpirationAndReset(SECS_BETWEEN_UPDATES)) + return; + + for (attachment_map_t::iterator it=mAttachmentPoints.begin(); it!=mAttachmentPoints.end(); ++it) + { + // get attached object + LLViewerJointAttachment *joint = it->second; + if (!joint) + continue; + for(std::vector::const_iterator parent_it = joint->mAttachedObjects.begin(); + parent_it != joint->mAttachedObjects.end(); ++parent_it) + { + LLViewerObject* pObject = (*parent_it); + const LLTextureEntry *te = pObject ? pObject->getTE(0) : NULL; + if(!te) continue; + const LLColor4 &col = te->getColor(); + if( (fabs(col[0] - 0.012f) < 0.001f) && + (fabs(col[1] - 0.036f) < 0.001f) && + (fabs(col[2] - 0.008f) < 0.001f) && + (fabs(col[3] - 0.000f) < 0.001f) ) { - mClientColor = avatar_name_color; - getClientInfo(mClientTag,mClientColor); - if(mClientTag == "") - { - client = "?"; //prevent console spam.. - } + pObject->mIsNameAttachment = true; + if (pObject->mText) pObject->mText->setHidden(true); - // Overwrite the tag/color shit yet again if we want to see - // friends in a special color. -- charbl - if (LLAvatarTracker::instance().getBuddyInfo(this->getID()) != NULL) + //This extra loop seems really silly. + const_child_list_t &children = pObject->getChildren(); + for (const_child_list_t::const_iterator child_it=children.begin(); child_it!=children.end(); ++child_it) { - static const LLCachedControl ascent_show_friends_tag("AscentShowFriendsTag"); - if (ascent_show_friends_tag) + LLViewerObject* pChildObject = (*child_it); + const LLTextureEntry *te2 = pChildObject ? pChildObject->getTE(0) : NULL; + if(!te2 || !pChildObject->mText) continue; + const LLColor4 &col = te2->getColor(); + if ((fabs(col[0] - 0.012f) < 0.001f) || + (fabs(col[1] - 0.036f) < 0.001f) || + (fabs(col[2] - 0.012f) < 0.001f)) { - mClientTag = "Friend"; + if ((fabs(col[3] - 0.004f) < 0.001f) || + (render_name && (fabs(col[3] - 0.000f) < 0.001f))) + { + nameplate += pChildObject->mText->getStringUTF8(); + } } } } - - static const LLCachedControl ascent_use_status_colors("AscentUseStatusColors",true); - if (!isSelf() && ascent_use_status_colors) + else if(pObject->mIsNameAttachment) { - LLViewerRegion* parent_estate = LLWorld::getInstance()->getRegionFromPosGlobal(this->getPositionGlobal()); - LLUUID estate_owner = LLUUID::null; - if(parent_estate && parent_estate->isAlive()) - { - estate_owner = parent_estate->getOwner(); - } - - //Lindens are always more Linden than your friend, make that take precedence - if(LLMuteList::getInstance()->isLinden(getFullname())) - { - static const LLCachedControl ascent_linden_color( "AscentLindenColor" ); - mClientColor = ascent_linden_color; - } - //check if they are an estate owner at their current position - else if(estate_owner.notNull() && this->getID() == estate_owner) - { - static const LLCachedControl ascent_estate_owner_color( "AscentEstateOwnerColor" ); - mClientColor = ascent_estate_owner_color; - } - //without these dots, SL would suck. - else if (LLAvatarTracker::instance().getBuddyInfo(this->getID()) != NULL) - { - static const LLCachedControl ascent_friend_color( "AscentFriendColor" ); - mClientColor = ascent_friend_color; - } - //big fat jerkface who is probably a jerk, display them as such. - else if(LLMuteList::getInstance()->isMuted(this->getID())) - { - static const LLCachedControl ascent_muted_color( "AscentMutedColor" ); - mClientColor = ascent_muted_color; - } - } - - client = mClientTag; - - static const LLCachedControl ascent_show_self_tag_color("AscentShowSelfTagColor"); - static const LLCachedControl ascent_show_others_tag_color("AscentShowOthersTagColor"); - LLColor4 name_color = avatar_name_color; - if ((isSelf() && ascent_show_self_tag_color) - || (!isSelf() && ascent_show_others_tag_color)) - name_color = mClientColor; - - - name_color.setAlpha(alpha); - mNameText->setColor(name_color); - - 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; - - 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; - mNameText->setPositionAgent(name_position); + pObject->mIsNameAttachment = false; + if (pObject->mText) pObject->mText->setHidden(false); + } } - else if (mNameText) + } + } + if(mCCSAttachmentText != nameplate) + { + mCCSAttachmentText = nameplate; + clearNameTag(); + } +} + +void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) +{ + LLNameValue *title = getNVPair("Title"); + LLNameValue* firstname = getNVPair("FirstName"); + LLNameValue* lastname = getNVPair("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 + { + is_muted = LLMuteList::getInstance()->isMuted(getID()); + } + bool is_friend = LLAvatarTracker::instance().isBuddy(getID()); + bool is_cloud = getIsCloud(); + + if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + { + if (is_appearance != mNameAppearance) + { + if (is_appearance) { - mNameText->markDead(); - mNameText = NULL; - sNumVisibleChatBubbles--; + LLSD args; + args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); + args["NAME"] = getFullname(); + LLNotificationsUtil::add("AvatarRezEnteredAppearanceNotification",args); + llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' entered appearance mode." << llendl; } + else + { + LLSD args; + args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); + args["NAME"] = getFullname(); + LLNotificationsUtil::add("AvatarRezLeftAppearanceNotification",args); + llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left appearance mode." << llendl; + } + } + } + + std::string idle_string = getIdleTime(is_away, is_busy, is_appearance); + + // 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_friend != mNameFriend + || is_cloud != mNameCloud) + { + LLColor4 name_tag_color = getNameTagColor(is_friend); + + clearNameTag(); + + std::string groupText; + std::string firstnameText; + std::string lastnameText; + + if (is_away || is_muted || is_busy || is_appearance || !idle_string.empty()) + { + std::string line; + if (is_away) + { + line += LLTrans::getString("AvatarAway"); //"Away" + line += ", "; + } + if (is_busy) + { + line += LLTrans::getString("AvatarBusy"); //"Busy" + line += ", "; + } + if (is_muted) + { + line += LLTrans::getString("AvatarMuted"); //"Muted" + line += ", "; + } + if (is_appearance) + { + line += LLTrans::getString("AvatarEditingAppearance"); //"(Editing Appearance)" + line += ", "; + } + if (is_cloud) + { + line += LLTrans::getString("LoadingData"); //"Loading..." + line += ", "; + } + if (!idle_string.empty()) + { + line += idle_string; //"(Idle #min)" + line += ", "; + } + // trim last ", " + line.resize( line.length() - 2 ); + addNameTagLine(line, name_tag_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerifSmall()); + } + + if (sRenderGroupTitles + && title && title->getString() && title->getString()[0] != '\0') + { + std::string title_str = title->getString(); + LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR); + groupText=title_str; //Defer for later formatting + //addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL, + // LLFontGL::getFontSansSerifSmall()); + } + + // static LLICachedControl show_display_names("NameTagShowDisplayNames"); + // static LLUICachedControl show_usernames("NameTagShowUsernames"); + + static const LLCachedControl phoenix_name_system("PhoenixNameSystem", 0); + + bool show_display_names = phoenix_name_system > 0; + bool show_usernames = phoenix_name_system < 2; + if (show_display_names && 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)); + } + + // Might be blank if name not available yet, that's OK + if (show_display_names) + { + firstnameText=av_name.mDisplayName; //Defer for later formatting + //addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL, + // LLFontGL::getFontSansSerif()); + } + // Suppress SLID display if display name matches exactly (ugh) + if (show_usernames && !av_name.mIsDisplayNameDefault && !av_name.mUsername.empty()) + { + firstnameText.push_back('('); + firstnameText.append(av_name.mUsername); //Defer for later formatting + firstnameText.push_back(')'); + // *HACK: Desaturate the color + //LLColor4 username_color = name_tag_color * 0.83f; + //nameText=av_name.mUsername; + //addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL, + //LLFontGL::getFontSansSerifSmall()); + } + } + else + { + firstnameText=firstname->getString(); //Defer for later formatting + lastnameText=lastname->getString(); //Defer for later formatting + //const LLFontGL* font = LLFontGL::getFontSansSerif(); + //std::string full_name = + // LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); + //addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font); } - LLNameValue *title = getNVPair("Title"); - LLNameValue* firstname = getNVPair("FirstName"); - LLNameValue* lastname = getNVPair("LastName"); - - if (mNameText.notNull() && firstname && lastname) + static const LLCachedControl allow_nameplate_override ("CCSAllowNameplateOverride", true); + std::string client_name = SHClientTagMgr::instance().getClientName(this, is_friend); + if(!client_name.empty()) { - /* - Phoenix: Wolfspirit: - The following part replaces the username with the Displayname, if Displaynames are enabled + client_name.insert(0,1,'('); + client_name.push_back(')'); + } + std::string tag_format; + if(allow_nameplate_override && mCCSChatTextOverride) + tag_format=mCCSChatText; + else if(allow_nameplate_override && !mCCSAttachmentText.empty()) + tag_format=mCCSAttachmentText; + else + tag_format=sRenderGroupTitles ? "%g\n%f %l %t" : "%f\n%l %t"; - */ - LLAvatarName av_name; - bool dnhasloaded = false; - bool show_un = false; - if(LLAvatarNameCache::useDisplayNames() && LLAvatarNameCache::get(getID(), &av_name)) dnhasloaded=true; - - std::string usedname; - if(dnhasloaded && !av_name.mIsDisplayNameDefault && !av_name.mIsTemporaryName - && av_name.mDisplayName != av_name.getLegacyName()) - { - usedname = av_name.mDisplayName; - show_un = true; - } + // replace first name, last name and title + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("\r\n"); + tokenizer tokens(tag_format, sep); + for(tokenizer::iterator it=tokens.begin();it!=tokens.end();++it) + { + std::string line = *it; + LLStringUtil::trim(line); + if(line.empty()) + continue; + if(line == "%g") + addNameTagLine(groupText, name_tag_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerifSmall()); + else if(line == "%t") + addNameTagLine(client_name, name_tag_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerifSmall()); else { - usedname = firstname->getString(); - std::string ln = lastname->getString(); - if(ln != "Resident") - { - usedname += " "; - usedname += ln; - } - } - - bool is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end(); - if(mNameAway && ! is_away) mIdleTimer.reset(); - bool is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end(); - if(mNameBusy && ! is_busy) mIdleTimer.reset(); - bool is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end(); - if(mNameAppearance && ! is_appearance) mIdleTimer.reset(); - bool is_muted; - if (isSelf()) - { - is_muted = FALSE; - } - else - { - is_muted = LLMuteList::getInstance()->isMuted(getID()); - } - //idle text - std::string idle_string; - static LLCachedControl ascent_show_idle_time("AscentShowIdleTime"); - if(!isSelf() && mIdleTimer.getElapsedTimeF32() > 120.f && ascent_show_idle_time) - { - idle_string = getIdleTime(); - } - - if ((mNameString.empty() && !(mNameFromChatOverride && mNameFromChatText.empty())) || - new_name || - mRenderedName != usedname || - mUsedNameSystem != phoenix_name_system || - (!title && !mTitle.empty()) || - (title && mTitle != title->getString()) || - (is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute) || - is_appearance != mNameAppearance || client != mClientName || idle_string != mIdleString || - mNameFromAttachment != nameplate || - mNameFromChatChanged) - { - mRenderedName = usedname; - mNameFromAttachment = nameplate; - mNameAway = is_away; - mNameBusy = is_busy; - mNameMute = is_muted; - mClientName = client; - mIdleString = idle_string; - mUsedNameSystem = phoenix_name_system; - mNameAppearance = is_appearance; - mTitle = title? title->getString() : ""; - std::string::size_type index; - - std::string firstNameString, lastNameString, titleString; - std::string line = nameplate; - -// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b - if (!fRlvShowNames) - { - if (sRenderGroupTitles && title && title->getString() && title->getString()[0] != '\0') - { - titleString = title->getString(); - LLStringFn::replace_ascii_controlchars(titleString,LL_UNKNOWN_CHAR); - } - if (dnhasloaded) { - firstNameString = usedname; - } else { - firstNameString = firstname->getString(); - lastNameString = lastname->getString(); - } - } - else - { - show_un = false; - firstNameString = RlvStrings::getAnonym(firstname->getString() + std::string(" ") + lastname->getString()); - } -// [/RLVa:KB] - - // set name template - if (mNameFromChatOverride) { - //llinfos << "NEW NAME: '" << mNameFromChatText << "'" << llendl; - line = mNameFromChatText; - } else if (nameplate.empty()) { - if (sRenderGroupTitles) { - line = "%g\n%f %l"; - } else { - // If all group titles are turned off, stack first name - // on a line above last name - line = "%f\n%l"; - } - } - mNameFromChatChanged = false; - - // replace first name, last name and title while ((index = line.find("%f")) != std::string::npos) - line.replace(index, 2, firstNameString); + line.replace(index, 2, firstnameText); while ((index = line.find("%l")) != std::string::npos) - line.replace(index, 2, lastNameString); + line.replace(index, 2, lastnameText); while ((index = line.find("%g")) != std::string::npos) - line.replace(index, 2, titleString); - - // remove empty lines - while ((index = line.find("\r")) != std::string::npos) - line.erase(index, 1); - while (!line.empty() && (line[0] == ' ')) - line.erase(0, 1); - while (!line.empty() && (line[line.size()-1] == ' ')) - line.erase(line.size()-1, 1); - while ((index = line.find(" \n")) != std::string::npos) - line.erase(index, 1); - while ((index = line.find("\n ")) != std::string::npos) - line.erase(index+1, 1); - while (!line.empty() && (line[0] == '\n')) - line.erase(0, 1); - while (!line.empty() && (line[line.size()-1] == '\n')) - line.erase(line.size()-1, 1); - while ((index = line.find("\n\n")) != std::string::npos) - line.erase(index, 1); - - - BOOL need_comma = FALSE; - std::string additions; - - if (client.length() || is_away || is_muted || is_busy) - { - if ((client != "")&&(client != "?")) - { - if ((isSelf() && gSavedSettings.getBOOL("AscentShowSelfTag")) - || (!isSelf() && gSavedSettings.getBOOL("AscentShowOthersTag"))) - { - additions += client; - need_comma = TRUE; - } - } - if (is_away) - { - if (need_comma) - { - additions += ", "; - } - additions += "Away"; - need_comma = TRUE; - } - if (is_busy) - { - if (need_comma) - { - additions += ", "; - } - additions += "Busy"; - need_comma = TRUE; - } - if (is_muted) - { - if (need_comma) - { - additions += ", "; - } - additions += "Muted"; - need_comma = TRUE; - } - if (additions.length()) - line += " (" + additions + ")"; - - } - mSubNameString = ""; - if(show_un){ - if(phoenix_name_system != 2){ - mSubNameString = "("+av_name.mUsername+")"; - } - } - - if (is_appearance) - { - line += "\n"; - line += "(Editing Appearance)"; - } - if(!mIdleString.empty()) - { - line += "\n"; - line += mIdleString; - } - - mNameString = line; - new_name = TRUE; + line.replace(index, 2, groupText); + while ((index = line.find("%t")) != std::string::npos) + line.replace(index, 2, client_name); + LLStringUtil::trim(line); + if(!line.empty()) + addNameTagLine(line, name_tag_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerif()); } + } - if (visible_chat) - { - mIdleTimer.reset(); - //mNameText->setDropShadow(TRUE); - mNameText->setFont(LLFontGL::getFontSansSerif()); - mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); - if (new_name) - { - mNameText->setLabel(mNameString); - } + 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); + new_name = TRUE; + } + + if (mVisibleChat) + { + mNameText->setFont(LLFontGL::getFontSansSerif()); + mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); - char line[MAX_STRING]; /* Flawfinder: ignore */ - line[0] = '\0'; - std::deque::iterator chat_iter = mChats.begin(); - mNameText->clearString(); + char line[MAX_STRING]; /* Flawfinder: ignore */ + line[0] = '\0'; + std::deque::iterator chat_iter = mChats.begin(); + mNameText->clearString(); - LLColor4 new_chat = gColors.getColor( "AvatarNameColor" ); - 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) - { - ++chat_iter; - } + LLColor4 new_chat = gColors.getColor( "AvatarNameColor" ); + 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) + { + ++chat_iter; + } - for(; chat_iter != mChats.end(); ++chat_iter) - { - F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); - LLFontGL::StyleFlags style; - switch(chat_iter->mChatType) - { - case CHAT_TYPE_WHISPER: - style = LLFontGL::ITALIC; - break; - case CHAT_TYPE_SHOUT: - style = LLFontGL::BOLD; - break; - default: - style = LLFontGL::NORMAL; - break; - } - if (chat_fade_amt < 1.f) - { - F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); - 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(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(chat_iter->mText, old_chat, style); - } - } - mNameText->setVisibleOffScreen(TRUE); - - if (mTyping) - { - S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; - switch(dot_count) - { - case 1: - mNameText->addLine(".", new_chat); - break; - case 2: - mNameText->addLine("..", new_chat); - break; - case 3: - mNameText->addLine("...", new_chat); - break; - } - mIdleTimer.reset(); - } - } - else + for(; chat_iter != mChats.end(); ++chat_iter) + { + F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); + LLFontGL::StyleFlags style; + switch(chat_iter->mChatType) { - if (new_name) - { - if (gSavedSettings.getBOOL("SmallAvatarNames")) - { - mNameText->setFont(LLFontGL::getFontSansSerif()); - } - else - { - mNameText->setFont(LLFontGL::getFontSansSerifBig()); - } - mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - mNameText->setVisibleOffScreen(FALSE); - mNameText->setLabel(""); - mNameText->setString(mNameString); - mNameText->addLine(mSubNameString, mClientColor, LLFontGL::NORMAL, LLFontGL::getFontSansSerifSmall()); - } + case CHAT_TYPE_WHISPER: + style = LLFontGL::ITALIC; + break; + case CHAT_TYPE_SHOUT: + style = LLFontGL::BOLD; + break; + default: + style = LLFontGL::NORMAL; + break; + } + if (chat_fade_amt < 1.f) + { + F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); + 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(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(chat_iter->mText, old_chat, style); + } + } + mNameText->setVisibleOffScreen(TRUE); + + if (mTyping) + { + S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; + switch(dot_count) + { + case 1: + mNameText->addLine(".", new_chat); + break; + case 2: + mNameText->addLine("..", new_chat); + break; + case 3: + mNameText->addLine("...", new_chat); + break; } } } - else if (mNameText) + else { - mNameText->markDead(); - mNameText = NULL; - sNumVisibleChatBubbles--; + // ...not using chat bubbles, just names + mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + mNameText->setVisibleOffScreen(FALSE); } } +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->setLabel(""); + mNameText->setString( "" ); } } @@ -3915,9 +3902,81 @@ void LLVOAvatar::invalidateNameTags() 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(); + name_position[VZ] -= mPelvisToFoot; + name_position[VZ] += (mBodySize[VZ]* 0.55f); + name_position += (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) +{ + LLColor4 color; + if(SHClientTagMgr::instance().getClientColor(this,true,color)) + return color; + else + { + //Always fall back to this color, for now. + static const LLCachedControl avatar_name_color(gColors,"AvatarNameColor",LLColor4(LLColor4U(251, 175, 93, 255)) ); + return avatar_name_color; + } + /*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 + { + // ...not using display names + color_name = "NameTagLegacy"; + }*/ +} + void LLVOAvatar::idleUpdateBelowWater() { F32 avatar_height = (F32)(getPositionGlobal().mdV[VZ]); @@ -4943,7 +5002,7 @@ U32 LLVOAvatar::renderRigid() return num_indices; } -U32 LLVOAvatar::renderFootShadows() +/*U32 LLVOAvatar::renderFootShadows() { U32 num_indices = 0; @@ -4989,7 +5048,7 @@ U32 LLVOAvatar::renderFootShadows() mShadow1Facep->renderIndexed(foot_mask); return num_indices; -} +}*/ U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel) { @@ -5529,14 +5588,31 @@ void LLVOAvatar::resetAnimations() //----------------------------------------------------------------------------- // getIdleTime() //----------------------------------------------------------------------------- - -std::string LLVOAvatar::getIdleTime() +std::string LLVOAvatar::getIdleTime(bool is_away, bool is_busy, bool is_appearance) { - F32 elapsed_time = mIdleTimer.getElapsedTimeF32(); - U32 minutes = (U32)(elapsed_time/60); - - std::string output = llformat("(idle %dmin)", minutes); - return output; + if( (mNameAway && ! is_away) || + (mNameBusy && ! is_busy) || + (mNameAppearance && ! is_appearance) || + mTyping) + mIdleTimer.reset(); + + static LLCachedControl ascent_show_idle_time("AscentShowIdleTime", false); + U32 minutes = 0; + if(ascent_show_idle_time && !isSelf() && mIdleTimer.getElapsedTimeF32() > 120) + { + minutes = (U32)(mIdleTimer.getElapsedTimeF32()/60); + } + if(minutes != mIdleMinute) + clearNameTag(); + mIdleMinute = minutes; + if(mIdleMinute) + { + LLSD args; + args["[MINUTES]"]=(LLSD::Integer)minutes; + return LLTrans::getString("AvatarIdle", args); + } + else + return std::string(); } // Override selectively based on avatar sex and whether we're using new @@ -5649,6 +5725,7 @@ BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate) //----------------------------------------------------------------------------- // stopMotionFromSource() //----------------------------------------------------------------------------- +// virtual void LLVOAvatar::stopMotionFromSource(const LLUUID& source_id) { } @@ -5706,7 +5783,7 @@ S32 LLVOAvatar::getCollisionVolumeID(std::string &name) //----------------------------------------------------------------------------- // addDebugText() //----------------------------------------------------------------------------- - void LLVOAvatar::addDebugText(const std::string& text) +void LLVOAvatar::addDebugText(const std::string& text) { mDebugText.append(1, '\n'); mDebugText.append(text); @@ -5971,8 +6048,10 @@ LLJoint *LLVOAvatar::getCharacterJoint( U32 num ) //----------------------------------------------------------------------------- // requestStopMotion() //----------------------------------------------------------------------------- +// virtual void LLVOAvatar::requestStopMotion( LLMotion* motion ) { + // Only agent avatars should handle the stop motion notifications. } //----------------------------------------------------------------------------- @@ -6529,15 +6608,6 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline) mDrawable->setState(LLDrawable::ACTIVE); mDrawable->addFace(poolp, NULL); mDrawable->setRenderType(LLPipeline::RENDER_TYPE_AVATAR); - - LLFace *facep; - - // Add faces for the foot shadows - facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep); - mShadow0Facep = facep; - - facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep); - mShadow1Facep = facep; mNumInitFaces = mDrawable->getNumFaces() ; @@ -6580,107 +6650,6 @@ BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable) return TRUE; } -//----------------------------------------------------------------------------- -// updateShadowFaces() -//----------------------------------------------------------------------------- -void LLVOAvatar::updateShadowFaces() -{ - LLFace *face0p = mShadow0Facep; - LLFace *face1p = mShadow1Facep; - - // - // render avatar shadows - // - if (mInAir || mUpdatePeriod >= IMPOSTOR_PERIOD) - { - face0p->setSize(0, 0); - face1p->setSize(0, 0); - return; - } - - LLSprite sprite(mShadowImagep.notNull() ? mShadowImagep->getID() : LLUUID::null); - sprite.setFollow(FALSE); - const F32 cos_angle = gSky.getSunDirection().mV[2]; - F32 cos_elev = sqrt(1 - cos_angle * cos_angle); - if (cos_angle < 0) cos_elev = -cos_elev; - sprite.setSize(0.4f + cos_elev * 0.8f, 0.3f); - LLVector3 sun_vec = gSky.mVOSkyp ? gSky.mVOSkyp->getToSun() : LLVector3(0.f, 0.f, 0.f); - - if (mShadowImagep->hasGLTexture()) - { - LLVector3 normal; - LLVector3d shadow_pos; - LLVector3 shadow_pos_agent; - F32 foot_height; - - if (mFootLeftp) - { - LLVector3 joint_world_pos = mFootLeftp->getWorldPosition(); - // this only does a ray straight down from the foot, as our client-side ray-tracing is very limited now - // but we make an explicit ray trace call in expectation of future improvements - resolveRayCollisionAgent(gAgent.getPosGlobalFromAgent(joint_world_pos), - gAgent.getPosGlobalFromAgent(gSky.getSunDirection() + joint_world_pos), shadow_pos, normal); - shadow_pos_agent = gAgent.getPosAgentFromGlobal(shadow_pos); - foot_height = joint_world_pos.mV[VZ] - shadow_pos_agent.mV[VZ]; - - // Pull sprite in direction of surface normal - shadow_pos_agent += normal * SHADOW_OFFSET_AMT; - - // Render sprite - sprite.setNormal(normal); - if (isSelf() && gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) - { - sprite.setColor(0.f, 0.f, 0.f, 0.f); - } - else - { - sprite.setColor(0.f, 0.f, 0.f, clamp_rescale(foot_height, MIN_SHADOW_HEIGHT, MAX_SHADOW_HEIGHT, 0.5f, 0.f)); - } - sprite.setPosition(shadow_pos_agent); - - LLVector3 foot_to_knee = mKneeLeftp->getWorldPosition() - joint_world_pos; - //foot_to_knee.normalize(); - foot_to_knee -= projected_vec(foot_to_knee, sun_vec); - sprite.setYaw(azimuth(sun_vec - foot_to_knee)); - - sprite.updateFace(*face0p); - } - - if (mFootRightp) - { - LLVector3 joint_world_pos = mFootRightp->getWorldPosition(); - // this only does a ray straight down from the foot, as our client-side ray-tracing is very limited now - // but we make an explicit ray trace call in expectation of future improvements - resolveRayCollisionAgent(gAgent.getPosGlobalFromAgent(joint_world_pos), - gAgent.getPosGlobalFromAgent(gSky.getSunDirection() + joint_world_pos), shadow_pos, normal); - shadow_pos_agent = gAgent.getPosAgentFromGlobal(shadow_pos); - foot_height = joint_world_pos.mV[VZ] - shadow_pos_agent.mV[VZ]; - - // Pull sprite in direction of surface normal - shadow_pos_agent += normal * SHADOW_OFFSET_AMT; - - // Render sprite - sprite.setNormal(normal); - if (isSelf() && gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) - { - sprite.setColor(0.f, 0.f, 0.f, 0.f); - } - else - { - sprite.setColor(0.f, 0.f, 0.f, clamp_rescale(foot_height, MIN_SHADOW_HEIGHT, MAX_SHADOW_HEIGHT, 0.5f, 0.f)); - } - sprite.setPosition(shadow_pos_agent); - - LLVector3 foot_to_knee = mKneeRightp->getWorldPosition() - joint_world_pos; - //foot_to_knee.normalize(); - foot_to_knee -= projected_vec(foot_to_knee, sun_vec); - sprite.setYaw(azimuth(sun_vec - foot_to_knee)); - - sprite.updateFace(*face1p); - } - } -} - //----------------------------------------------------------------------------- // updateSexDependentLayerSets() //----------------------------------------------------------------------------- @@ -7098,7 +7067,7 @@ void LLVOAvatar::sitDown(BOOL bSitting) //----------------------------------------------------------------------------- void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) { - if (isSelf()) + if (isSelf()) { // Might be first sit LLFirstUse::useSit(); @@ -7502,13 +7471,10 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading) return changed; } - - BOOL LLVOAvatar::isFullyLoaded() const { // [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-22 (Catznip-2.2.0a) | Added: Catznip-2.2.0a // Changes to LLAppearanceMgr::updateAppearanceFromCOF() expect this function to actually return mFullyLoaded for gAgentAvatarp - static const LLCachedControl rener_unloaded_avatar("RenderUnloadedAvatar"); if ( (!isSelf()) && (mRenderUnloadedAvatar) ) return TRUE; else @@ -7516,10 +7482,11 @@ BOOL LLVOAvatar::isFullyLoaded() const // [/SL:KB] } + //----------------------------------------------------------------------------- // findMotion() //----------------------------------------------------------------------------- -LLMotion* LLVOAvatar::findMotion(const LLUUID& id) const +LLMotion* LLVOAvatar::findMotion(const LLUUID& id) const { return mMotionController.findMotion(id); } @@ -7532,7 +7499,6 @@ void LLVOAvatar::updateMeshTextures() { // llinfos << "updateMeshTextures" << llendl; if (gNoRender) return; - // if user has never specified a texture, assign the default for (U32 i=0; i < getNumTEs(); i++) { @@ -7699,23 +7665,22 @@ void LLVOAvatar::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked llassert(0); } - -void LLVOAvatar::setNameFromChat(const std::string &text) { - static const LLCachedControl allow_nameplate_override ("CCSAllowNameplateOverride", true); - if(allow_nameplate_override) { - mNameFromChatOverride = true; - mNameFromChatChanged = true; - mNameFromChatText = text; - } +void LLVOAvatar::setNameFromChat(const std::string &text) +{ + if(!mCCSChatTextOverride || mCCSChatText != text) + clearNameTag(); + mCCSChatTextOverride = true; + mCCSChatText = text; } -void LLVOAvatar::clearNameFromChat() { - mNameFromChatOverride = false; - mNameFromChatChanged = true; - mNameFromChatText = ""; +void LLVOAvatar::clearNameFromChat() +{ + if(mCCSChatTextOverride || mCCSChatText != "") + clearNameTag(); + mCCSChatTextOverride = false; + mCCSChatText = ""; } - void LLVOAvatar::addChat(const LLChat& chat) { std::deque::iterator chat_iter; @@ -7945,9 +7910,6 @@ LLColor4 LLVOAvatar::getDummyColor() void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const { - /* const char* te_name[] = { - "TEX_HEAD_BODYPAINT ", - "TEX_UPPER_SHIRT ", */ llinfos << (isSelf() ? "Self: " : "Other: ") << context << llendl; for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); @@ -7984,11 +7946,11 @@ void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const } // Unlike most wearable functions, this works for both self and other. -BOOL LLVOAvatar::isWearingWearableType( LLWearableType::EType type ) const +BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const { if (mIsDummy) return TRUE; - switch( type ) + switch(type) { case LLWearableType::WT_SHAPE: case LLWearableType::WT_SKIN: @@ -8220,21 +8182,9 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // llinfos << "LLVOAvatar::processAvatarAppearance()" << llendl; // dumpAvatarTEs( "PRE processAvatarAppearance()" ); unpackTEMessage(mesgsys, _PREHASH_ObjectData); + SHClientTagMgr::instance().updateAvatarTag(this); + // dumpAvatarTEs( "POST processAvatarAppearance()" ); - mClientTag = ""; - /*const LLTextureEntry* tex = getTE(0); - if(tex->getGlow() > 0.0) - { - U8 tag_buffer[UUID_BYTES+1]; - memset(&tag_buffer, 0, UUID_BYTES); - memcpy(&tag_buffer[0], &tex->getID().mData, UUID_BYTES); - tag_buffer[UUID_BYTES] = 0; - U32 tag_len = strlen((const char*)&tag_buffer[0]); - tag_len = (tag_len>UUID_BYTES) ? (UUID_BYTES) : tag_len; - mClientTag = std::string((char*)&tag_buffer[0], tag_len); - LLStringFn::replace_ascii_controlchars(mClientTag, LL_UNKNOWN_CHAR); - mNameString.clear(); - }*/ // prevent the overwriting of valid baked textures with invalid baked textures for (U8 baked_index = 0; baked_index < mBakedTextureDatas.size(); baked_index++) @@ -8270,7 +8220,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // Non-self avatars will no longer have component textures if (!isSelf()) { - //releaseUnnecessaryTextures(); Commented out to ensure that users get the right client data -HgB + releaseComponentTextures(); } mSupportsPhysics = false; @@ -8359,7 +8309,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) llinfos << getFullname() << " does not have avatar physics." << llendl; } } - + if (params_changed) { if (interp_params) @@ -8615,7 +8565,7 @@ void LLVOAvatar::dumpArchetypeXML( void* ) { LLAPRFile outfile(gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER, "new archetype.xml"), LL_APR_WB); apr_file_t* file = outfile.getFileHandle() ; - if( !file ) + if (!file) { return; } @@ -8625,25 +8575,25 @@ void LLVOAvatar::dumpArchetypeXML( void* ) apr_file_printf( file, "\n\t\n" ); // only body parts, not clothing. - for( S32 type = LLWearableType::WT_SHAPE; type <= LLWearableType::WT_EYES; type++ ) + for (S32 type = LLWearableType::WT_SHAPE; type <= LLWearableType::WT_EYES; type++) { - const std::string& wearable_name = LLWearableType::getTypeName( (LLWearableType::EType) type ); + const std::string& wearable_name = LLWearableType::getTypeName((LLWearableType::EType)type); apr_file_printf( file, "\n\t\t\n", wearable_name.c_str() ); - for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) + for (LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam()) { LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; if( (viewer_param->getWearableType() == type) && (viewer_param->isTweakable() ) ) { - apr_file_printf( file, "\t\t\n", - viewer_param->getID(), viewer_param->getName().c_str(), viewer_param->getWeight() ); + apr_file_printf(file, "\t\t\n", + viewer_param->getID(), viewer_param->getName().c_str(), viewer_param->getWeight()); } } - for(U8 te = 0; te < TEX_NUM_INDICES; te++) + for (U8 te = 0; te < TEX_NUM_INDICES; te++) { - if( LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te) == type ) + if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te) == type) { // MULTIPLE_WEARABLES: extend to multiple wearables? LLViewerTexture* te_image = ((LLVOAvatar *)(gAgentAvatarp))->getImage((ETextureIndex)te, 0); @@ -8660,6 +8610,7 @@ void LLVOAvatar::dumpArchetypeXML( void* ) apr_file_printf( file, "\n\n" ); } + void LLVOAvatar::setVisibilityRank(U32 rank) { if (mDrawable.isNull() || mDrawable->isDead()) @@ -8739,7 +8690,7 @@ void LLVOAvatar::cullAvatarsByPixelArea() } S32 grey_avatars = 0; - if ( LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars) ) + if (LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars)) { LLVOAvatar::deleteCachedImages(false); } @@ -8788,12 +8739,12 @@ LLVOAvatar::LLVOAvatarXmlInfo::LLVOAvatarXmlInfo() LLVOAvatar::LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo() { std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer()); - std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer()); + std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer()); std::for_each(mAttachmentInfoList.begin(), mAttachmentInfoList.end(), DeletePointer()); deleteAndClear(mTexSkinColorInfo); deleteAndClear(mTexHairColorInfo); deleteAndClear(mTexEyeColorInfo); - std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); + std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer()); std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer()); } @@ -9585,6 +9536,8 @@ const std::string LLVOAvatar::getBakedStatusForPrintout() const return line; } + + //virtual S32 LLVOAvatar::getTexImageSize() const { diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 10789219f..87e23906c 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -78,6 +78,45 @@ class LLTexGlobalColor; class LLVOAvatarBoneInfo; class LLVOAvatarSkeletonInfo; +class SHClientTagMgr : public LLSingleton, public boost::signals2::trackable +{ +public: + SHClientTagMgr(); + //Fetch updated client_tags_sg1.xml from server + bool fetchDefinitions() const; + //Parse definitions from client_tags_sg1.xml + bool parseDefinitions(); +private: + //Just refreshes the tag for the agent avatar. + //Used for boost::bind to verify agent avatar is valid before calling updateAvatarTag + void updateAgentAvatarTag(); + //Actually generate the tag information for the avatar + const LLSD generateClientTag(const LLVOAvatar* pAvatar) const; +public: + //Generates tag for particular avatar and sets dirty if the tag has changed. Call on received TE updates. + void updateAvatarTag(LLVOAvatar* pAvatar); + //Removes entry in mAvatarTags map. Call on destruction of avatar. + void clearAvatarTag(const LLVOAvatar* pAvatar); + + // Accessors + + //Returns true if tag system is enabled. + bool getIsEnabled() const; + //If a tag entry exists, returns the clientname if found. If is_friend is set, will return "Friend" if AscentShowFriendsTag is true. + const std::string getClientName(const LLVOAvatar* pAvatar, bool is_friend) const; + //Returns ID of tag entry if it exists, else returns a null LLUUID. + const LLUUID getClientID(const LLVOAvatar* pAvatar) const; + //Sets color to either 'status' color, or falls back to client color if status isn't relevant. + //If neither status or client color are found, returns false. + bool getClientColor(const LLVOAvatar* pAvatar, bool check_status, LLColor4& color) const; + +private: + //UUID map associating texture uuids to client info entries parsed from client_tags_sg1.xml + std::map mClientDefinitions; + //UUID map associating avatar uuids to their CURRENT client tag info. + std::map mAvatarTags; +}; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLVOAvatar // @@ -239,16 +278,20 @@ public: void idleUpdateLoadingEffect(); void idleUpdateWindEffect(); void idleUpdateNameTag(const LLVector3& root_pos_last); + void idleUpdateNameTagText(BOOL new_name); + LLVector3 idleUpdateNameTagPosition(const LLVector3& root_pos_last); + void idleUpdateNameTagAlpha(BOOL new_name, F32 alpha); + LLColor4 getNameTagColor(bool is_friend); void clearNameTag(); static void invalidateNameTag(const LLUUID& agent_id); // force all name tags to rebuild, useful when display names turned on/off static void invalidateNameTags(); + void addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font); void idleUpdateRenderCost(); void idleUpdateBelowWater(); void idleUpdateBoobEffect(); //Emerald - LLFrameTimer mIdleTimer; - std::string getIdleTime(); + //-------------------------------------------------------------------- // Static preferences (controlled by user settings/menus) @@ -387,8 +430,6 @@ private: **/ public: - // Graphical stuff for objects - maybe broken out into render class later? - U32 renderFootShadows(); U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); bool isVisuallyMuted() const; @@ -814,12 +855,10 @@ public: // Chat //-------------------------------------------------------------------- public: - void setNameFromChat(const std::string &text); - void clearNameFromChat(); void addChat(const LLChat& chat); void clearChat(); void startTyping() { mTyping = TRUE; mTypingTimer.reset(); mIdleTimer.reset();} - void stopTyping() { mTyping = FALSE; } + void stopTyping() { mTyping = FALSE; mIdleTimer.reset();} private: BOOL mVisibleChat; @@ -945,19 +984,16 @@ protected: static void getAnimLabels(LLDynamicArray* labels); static void getAnimNames(LLDynamicArray* names); private: - std::string mNameString; - std::string mSubNameString; + std::string mNameString; // UTF-8 title + name + status std::string mTitle; bool mNameAway; bool mNameBusy; bool mNameMute; bool mNameAppearance; - bool mRenderTag; - bool mRenderGroupTitles; - std::string mRenderedName; - std::string mClientName; - std::string mIdleString; - S32 mUsedNameSystem; + bool mNameFriend; + bool mNameCloud; + F32 mNameAlpha; + BOOL mRenderGroupTitles; //-------------------------------------------------------------------- // Display the name (then optionally fade it out) @@ -971,28 +1007,7 @@ private: BOOL mTyping; public: BOOL isTyping(){ return mTyping; } -private: LLFrameTimer mTypingTimer; - static void on_avatar_name_response(const LLUUID& agent_id, const LLAvatarName& av_name, void *userdata); - - //-------------------------------------------------------------------- - // Client tagging - //-------------------------------------------------------------------- -public: - // - void getClientInfo(std::string& clientTag, LLColor4& tagColor, BOOL useComment=FALSE); - std::string extraMetadata; - // - - static bool updateClientTags(); - static bool loadClientTags(); - std::string mClientTag; //Zwagoth's new client identification system. -HgB - LLColor4 mClientColor; //Zwagoth's new client identification system. -HgB - - bool mNameFromChatOverride; - bool mNameFromChatChanged; - std::string mNameFromChatText; - std::string mNameFromAttachment; /** Name ** ** @@ -1188,18 +1203,28 @@ protected: // Shared with LLVOAvatarSelf *******************************************************************************/ // +//Avatar idle timer +private: + std::string getIdleTime(bool is_away, bool is_busy, bool is_appearance); public: - //bool mNametagSaysIdle; - //bool mIdleForever; - //LLFrameTimer mIdleTimer; - //U32 mIdleMinutes; - LLUUID mFocusObject; - LLVector3d mFocusVector; - //void resetIdleTime(); + LLFrameTimer mIdleTimer; +private: + S32 mIdleMinute; + +//CCS Nametag +public: + void setNameFromChat(const std::string &text); + void clearNameFromChat(); +private: + void idleCCSUpdateAttachmentText(bool render_name); + LLFrameTimer mCCSUpdateAttachmentTimer; + std::string mCCSAttachmentText; + bool mCCSChatTextOverride; + std::string mCCSChatText; - static LLSD sClientResolutionList; // }; // LLVOAvatar + extern const F32 SELF_ADDITIONAL_PRI; extern const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL; diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index d9f22b24e..37921cabf 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -143,6 +143,8 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id, mMotionController.mIsSelf = TRUE; + SHClientTagMgr::instance().updateAvatarTag(this); //No TE update messages for self. Force update here. + lldebugs << "Marking avatar as self " << id << llendl; } @@ -2530,7 +2532,10 @@ bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const { LLTextureEntry* entry = getTE((U8) index); texture_id[index] = entry->getID(); - entry->setID(IMG_DEFAULT_AVATAR); + if (SHClientTagMgr::instance().getIsEnabled() && index == 0 && gSavedSettings.getBOOL("AscentUseTag")) + entry->setID(LLUUID(gSavedSettings.getString("AscentReportClientUUID"))); + else + entry->setID(IMG_DEFAULT_AVATAR); } } diff --git a/indra/newview/skins/default/xui/en-us/strings.xml b/indra/newview/skins/default/xui/en-us/strings.xml index a22532a99..b3130abb5 100644 --- a/indra/newview/skins/default/xui/en-us/strings.xml +++ b/indra/newview/skins/default/xui/en-us/strings.xml @@ -16,6 +16,9 @@ [NAME]'s teleport lure is to [DESTINATION] + + Idle [MINUTES]min + Second Life