From c16591c046fa76fc5d13387efa3bcaec3422e593 Mon Sep 17 00:00:00 2001 From: James Cook Date: Fri, 12 Feb 2010 16:12:12 -0800 Subject: [PATCH] Per-avatar customizable icons next to name links in text Changed LLUrlEntryAgent callbacks to handle both link label and icon Eliminated legacy LLNameCache file loading Reviewed with Kelly --- indra/llcommon/llavatarname.cpp | 7 + indra/llcommon/llavatarname.h | 11 ++ indra/llmessage/llavatarnamecache.cpp | 147 +++++++++--------- indra/llmessage/llcachename.cpp | 83 +--------- indra/llmessage/llcachename.h | 5 +- indra/llui/lltextbase.cpp | 47 +++++- indra/llui/lltextbase.h | 5 +- indra/llui/llurlentry.cpp | 61 ++++++-- indra/llui/llurlentry.h | 9 +- indra/llui/llurlregistry.cpp | 4 +- indra/llui/llurlregistry.h | 4 +- indra/newview/llappviewer.cpp | 12 +- indra/newview/llstartup.cpp | 36 +++-- indra/newview/llstartup.h | 4 + .../default/textures/icons/Person_Check.png | Bin 0 -> 3824 bytes .../default/textures/icons/Person_Star.png | Bin 0 -> 3762 bytes .../skins/default/textures/textures.xml | 2 + 17 files changed, 231 insertions(+), 206 deletions(-) create mode 100644 indra/newview/skins/default/textures/icons/Person_Check.png create mode 100644 indra/newview/skins/default/textures/icons/Person_Star.png diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp index 0563374785..3b1ab4d267 100644 --- a/indra/llcommon/llavatarname.cpp +++ b/indra/llcommon/llavatarname.cpp @@ -35,6 +35,13 @@ #include "llavatarname.h" +LLAvatarName::LLAvatarName() +: mSLID(), + mDisplayName(), + mLastUpdate(0), + mBadge() +{ } + bool LLAvatarName::operator<(const LLAvatarName& rhs) const { if (mSLID == rhs.mSLID) diff --git a/indra/llcommon/llavatarname.h b/indra/llcommon/llavatarname.h index 4264a8e655..7205eb4523 100644 --- a/indra/llcommon/llavatarname.h +++ b/indra/llcommon/llavatarname.h @@ -39,6 +39,8 @@ class LL_COMMON_API LLAvatarName { public: + LLAvatarName(); + bool operator<(const LLAvatarName& rhs) const; // "bobsmith123" or "james.linden", US-ASCII only @@ -48,6 +50,15 @@ public: // Contains data whether or not user has explicitly set // a display name; may duplicate their SLID. std::string mDisplayName; + + // Names can change, so need to keep track of when name was + // last checked. + // Unix time-from-epoch seconds + U32 mLastUpdate; + + // Can be a viewer UI image name ("Person_Check") or a server-side + // image UUID, or empty string. + std::string mBadge; }; #endif diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 16bfa37b0e..610bc58057 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -38,6 +38,11 @@ #include // tolower() +namespace LLAvatarNameCache +{ + std::map sCache; +} + static std::string slid_from_full_name(const std::string& full_name) { std::string id = full_name; @@ -52,64 +57,67 @@ static std::string slid_from_full_name(const std::string& full_name) return id; } -static std::map sDisplayNames; - -// JAMESDEBUG HACK temporary IDEVO code -static std::string get_display_name(const LLUUID& id) -{ - if (sDisplayNames.empty()) - { - LLUUID id; - const unsigned char miyazaki_hayao_san[] - = { 0xE5, 0xAE, 0xAE, 0xE5, 0xB4, 0x8E, - 0xE9, 0xA7, 0xBF, - 0xE3, 0x81, 0x95, 0xE3, 0x82, 0x93, '\0' }; - id.set("27888d5f-4ddb-4df3-ad36-a1483ce0b3d9"); // miyazaki23 - sDisplayNames[id] = (const char*)miyazaki_hayao_san; - - id.set("3e5bf676-3577-c9ee-9fac-10df430015a1"); // Jim Linden - sDisplayNames[id] = "Jim Jenkins"; - - const unsigned char jose_sanchez[] = - { 'J','o','s',0xC3,0xA9,' ','S','a','n','c','h','e','z', '\0' }; - id.set("a2e76fcd-9360-4f6d-a924-938f923df11a"); // James Linden - sDisplayNames[id] = (const char*)jose_sanchez; - - id.set("a23fff6c-80ae-4997-9253-48272fd01d3c"); // bobsmith123 - sDisplayNames[id] = (const char*)jose_sanchez; - - id.set("3f7ced39-5e38-4fdd-90f2-423560b1e6e2"); // Hamilton Linden - sDisplayNames[id] = "Hamilton Hitchings"; - - id.set("537da1e1-a89f-4f9b-9056-b1f0757ccdd0"); // Rome Linden - sDisplayNames[id] = "Rome Portlock"; - - id.set("244195d6-c9b7-4fd6-9229-c3a8b2e60e81"); // M Linden - sDisplayNames[id] = "Mark Kingdon"; - - id.set("49856302-98d4-4e32-b5e9-035e5b4e83a4"); // T Linden - sDisplayNames[id] = "Tom Hale"; - - id.set("e6ed7825-708f-4c6b-b6a7-f3fe921a9176"); // Callen Linden - sDisplayNames[id] = "Christina Allen"; - - id.set("a7f0ac18-205f-41d2-b5b4-f75f096ae511"); // Crimp Linden - sDisplayNames[id] = "Chris Rimple"; - } - - std::map::iterator it = sDisplayNames.find(id); - if (it != sDisplayNames.end()) - { - return it->second; - } - else - { - return std::string(); - } -} - void LLAvatarNameCache::initClass() { + // HACK - prepopulate the cache + LLAvatarName name; + LLUUID id; + + name.mSLID = "miyazaki23"; + const unsigned char miyazaki_hayao_san[] + = { 0xE5, 0xAE, 0xAE, 0xE5, 0xB4, 0x8E, + 0xE9, 0xA7, 0xBF, + 0xE3, 0x81, 0x95, 0xE3, 0x82, 0x93, '\0' }; + name.mDisplayName = (const char*)miyazaki_hayao_san; + name.mBadge = "Person_Check"; + sCache[LLUUID("27888d5f-4ddb-4df3-ad36-a1483ce0b3d9")] = name; + + name.mSLID = "jim.linden"; + name.mDisplayName = "Jim Jenkins"; + name.mBadge = "Person_Star"; + sCache[LLUUID("3e5bf676-3577-c9ee-9fac-10df430015a1")] = name; + + name.mSLID = "james.linden"; + const unsigned char jose_sanchez[] = + { 'J','o','s',0xC3,0xA9,' ','S','a','n','c','h','e','z', '\0' }; + name.mDisplayName = (const char*)jose_sanchez; + name.mBadge = "35f217a3-f618-49cf-bbca-c86d486551a9"; // IMG_SHOT + sCache[LLUUID("a2e76fcd-9360-4f6d-a924-938f923df11a")] = name; + + name.mSLID = "bobsmith123"; + name.mDisplayName = (const char*)jose_sanchez; + name.mBadge = ""; + sCache[LLUUID("a23fff6c-80ae-4997-9253-48272fd01d3c")] = name; + + name.mSLID = "hamilton.linden"; + name.mDisplayName = "Hamilton Hitchings"; + name.mBadge = "Person_Star"; + sCache[LLUUID("3f7ced39-5e38-4fdd-90f2-423560b1e6e2")] = name; + + name.mSLID = "rome.linden"; + name.mDisplayName = "Rome Portlock"; + name.mBadge = "Person_Star"; + sCache[LLUUID("537da1e1-a89f-4f9b-9056-b1f0757ccdd0")] = name; + + name.mSLID = "m.linden"; + name.mDisplayName = "Mark Kingdon"; + name.mBadge = "Person_Star"; + sCache[LLUUID("244195d6-c9b7-4fd6-9229-c3a8b2e60e81")] = name; + + name.mSLID = "t.linden"; + name.mDisplayName = "Tom Hale"; + name.mBadge = "Person_Star"; + sCache[LLUUID("49856302-98d4-4e32-b5e9-035e5b4e83a4")] = name; + + name.mSLID = "callen.linden"; + name.mDisplayName = "Christina Allen"; + name.mBadge = "Person_Star"; + sCache[LLUUID("e6ed7825-708f-4c6b-b6a7-f3fe921a9176")] = name; + + name.mSLID = "crimp.linden"; + name.mDisplayName = "Chris Rimple"; + name.mBadge = "Person_Star"; + sCache[LLUUID("a7f0ac18-205f-41d2-b5b4-f75f096ae511")] = name; } void LLAvatarNameCache::cleanupClass() @@ -130,24 +138,23 @@ void LLAvatarNameCache::idle() bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) { + std::map::iterator it = sCache.find(agent_id); + if (it != sCache.end()) + { + *av_name = it->second; + return true; + } + std::string full_name; - bool found = gCacheName->getFullName(agent_id, full_name); - if (found) + if (gCacheName->getFullName(agent_id, full_name)) { av_name->mSLID = slid_from_full_name(full_name); - - std::string display_name = get_display_name(agent_id); - if (!display_name.empty()) - { - av_name->mDisplayName = display_name; - } - else - { - // ...no explicit display name, use legacy name - av_name->mDisplayName = full_name; - } + av_name->mDisplayName = full_name; + av_name->mBadge = "Generic_Person"; + return true; } - return found; + + return false; } void LLAvatarNameCache::get(const LLUUID& agent_id, name_cache_callback_t callback) diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 4e3c3630ab..b94788bd0c 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -308,89 +308,10 @@ boost::signals2::connection LLCacheName::addObserver(const LLCacheNameCallback& return impl.mSignal.connect(callback); } -void LLCacheName::importFile(LLFILE* fp) -{ - S32 count = 0; - - const S32 BUFFER_SIZE = 1024; - char buffer[BUFFER_SIZE]; /*Flawfinder: ignore*/ - - // *NOTE: These buffer sizes are hardcoded into sscanf() below - char id_string[MAX_STRING]; /*Flawfinder: ignore*/ - char firstname[MAX_STRING]; /*Flawfinder: ignore*/ - char lastname[MAX_STRING]; /*Flawfinder: ignore*/ - U32 create_time; - - // This is OK if the first line is actually a name. We just don't load it. - char* valid = fgets(buffer, BUFFER_SIZE, fp); - if (!valid) return; - - // *NOTE: This buffer size is hardcoded into sscanf() below - char version_string[BUFFER_SIZE]; /*Flawfinder: ignore*/ - S32 version = 0; - S32 match = sscanf( /* Flawfinder: ignore */ - buffer, - "%1023s %d", - version_string, &version); - if ( match != 2 - || strcmp(version_string, "version") - || version != CN_FILE_VERSION) - { - llwarns << "Ignoring old cache name file format" << llendl; - return; - } - - // We'll expire entries more than a week old - U32 now = (U32)time(NULL); - const U32 SECS_PER_DAY = 60 * 60 * 24; - U32 delete_before_time = now - (7 * SECS_PER_DAY); - - while(!feof(fp)) - { - valid = fgets(buffer, BUFFER_SIZE, fp); - if (!valid) break; - - match = sscanf( /* Flawfinder: ignore */ - buffer, - "%254s %u %254s %254s", - id_string, - &create_time, - firstname, - lastname); - if (4 != match) continue; - - LLUUID id(id_string); - if (id.isNull()) continue; - - // undo trivial XOR - S32 i; - for (i = 0; i < UUID_BYTES; i++) - { - id.mData[i] ^= 0x33; - } - - // Don't load entries that are more than a week old - if (create_time < delete_before_time) continue; - - LLCacheNameEntry* entry = new LLCacheNameEntry(); - entry->mIsGroup = false; - entry->mCreateTime = create_time; - entry->mFirstName = firstname; - entry->mLastName = lastname; - impl.mCache[id] = entry; - std::string fullname = entry->mFirstName + " " + entry->mLastName; - impl.mReverseCache[fullname] = id; - - count++; - } - - llinfos << "LLCacheName loaded " << count << " names" << llendl; -} - bool LLCacheName::importFile(std::istream& istr) { LLSD data; - if(LLSDSerialize::fromXML(data, istr) < 1) + if(LLSDSerialize::fromXMLDocument(data, istr) < 1) return false; // We'll expire entries more than a week old @@ -512,7 +433,7 @@ BOOL LLCacheName::Impl::getName(const LLUUID& id, std::string& first, std::strin } // static -void LLCacheName::LocalizeCacheName(std::string key, std::string value) +void LLCacheName::localizeCacheName(std::string key, std::string value) { if (key!="" && value!= "" ) sCacheName[key]=value; diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h index 322ca4aa1a..8d8e172c08 100644 --- a/indra/llmessage/llcachename.h +++ b/indra/llmessage/llcachename.h @@ -70,9 +70,6 @@ public: boost::signals2::connection addObserver(const LLCacheNameCallback& callback); - // janky old format. Remove after a while. Phoenix. 2008-01-30 - void importFile(LLFILE* fp); - // storing cache on disk; for viewer, in name.cache bool importFile(std::istream& istr); void exportFile(std::ostream& ostr); @@ -116,7 +113,7 @@ public: void dumpStats(); // Dumps the sizes of the cache and associated queues. static std::string getDefaultName(); - static void LocalizeCacheName(std::string key, std::string value); + static void localizeCacheName(std::string key, std::string value); static std::map sCacheName; private: diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index ef422dbdc5..075f54ed30 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1527,6 +1527,20 @@ std::string LLTextBase::getText() const return getViewModel()->getValue().asString(); } +// IDEVO - icons can be UI image names or UUID sent from +// server with avatar display name +static LLUIImagePtr image_from_icon_name(const std::string& icon_name) +{ + if (LLUUID::validate(icon_name)) + { + return LLUI::getUIImageByID( LLUUID(icon_name) ); + } + else + { + return LLUI::getUIImage(icon_name); + } +} + void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params) { LLStyle::Params style_params(input_params); @@ -1539,7 +1553,7 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c LLUrlMatch match; std::string text = new_text; while ( LLUrlRegistry::instance().findUrl(text, match, - boost::bind(&LLTextBase::replaceUrlLabel, this, _1, _2)) ) + boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3)) ) { start = match.getStart(); end = match.getEnd()+1; @@ -1570,15 +1584,18 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c // output an optional icon before the Url if (! match.getIcon().empty()) { - LLUIImagePtr image = LLUI::getUIImage(match.getIcon()); + LLUIImagePtr image = image_from_icon_name( match.getIcon() ); if (image) { - LLStyle::Params icon; - icon.image = image; + LLStyle::Params icon_params; + icon_params.image = image; + // must refer to our link so we can update the icon later + // after name/group data is looked up + icon_params.link_href = match.getUrl(); // Text will be replaced during rendering with the icon, // but string cannot be empty or the segment won't be // added (or drawn). - appendAndHighlightText(" ", prepend_newline, part, icon); + appendAndHighlightText(" ", prepend_newline, part, icon_params); prepend_newline = false; } } @@ -1728,8 +1745,9 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen } -void LLTextBase::replaceUrlLabel(const std::string &url, - const std::string &label) +void LLTextBase::replaceUrl(const std::string &url, + const std::string &label, + const std::string &icon) { // get the full (wide) text for the editor so we can change it LLWString text = getWText(); @@ -1759,6 +1777,21 @@ void LLTextBase::replaceUrlLabel(const std::string &url, modified = true; } + // Icon might be updated when more avatar or group info + // becomes available + if (style->isImage() && style->getLinkHREF() == url) + { + LLUIImagePtr image = image_from_icon_name( icon ); + if (image) + { + LLStyle::Params icon_params; + icon_params.image = image; + LLStyleConstSP new_style(new LLStyle(icon_params)); + seg->setStyle(new_style); + modified = true; + } + } + // work out the character offset for the next segment seg_start = seg->getEnd(); } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 3dda6f4cc8..dc8bc0dca0 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -309,7 +309,10 @@ protected: // misc void updateRects(); void needsScroll() { mScrollNeeded = TRUE; } - void replaceUrlLabel(const std::string &url, const std::string &label); + + // Replace a URL with a new icon and label, for example, when + // avatar names are looked up. + void replaceUrl(const std::string &url, const std::string &label, const std::string& icon); protected: // text segmentation and flow diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index dae2c44f08..dbfac63a72 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -55,6 +55,12 @@ std::string LLUrlEntryBase::getUrl(const std::string &string) const return escapeUrl(string); } +//virtual +std::string LLUrlEntryBase::getIcon(const std::string &url) const +{ + return mIcon; +} + std::string LLUrlEntryBase::getIDStringFromUrl(const std::string &url) const { // return the id from a SLURL in the format /app/{cmd}/{id}/about @@ -133,7 +139,9 @@ void LLUrlEntryBase::addObserver(const std::string &id, } } -void LLUrlEntryBase::callObservers(const std::string &id, const std::string &label) +void LLUrlEntryBase::callObservers(const std::string &id, + const std::string &label, + const std::string &icon) { // notify all callbacks waiting on the given uuid std::multimap::iterator it; @@ -141,7 +149,7 @@ void LLUrlEntryBase::callObservers(const std::string &id, const std::string &lab { // call the callback - give it the new label LLUrlEntryObserver &observer = it->second; - (*observer.signal)(it->second.url, label); + (*observer.signal)(it->second.url, label, icon); // then remove the signal - we only need to call it once delete observer.signal; mObservers.erase(it++); @@ -312,22 +320,18 @@ LLUrlEntryAgent::LLUrlEntryAgent() mColor = LLUIColorTable::instance().getColor("AgentLinkColor"); } -// IDEVO demo code -std::string LLUrlEntryAgent::buildName(const LLUUID& id) -{ - // JAMESDEBUG HACK: assume name is there - LLAvatarName av_name; - LLAvatarNameCache::get(id, &av_name); - return av_name.mDisplayName + " (" + av_name.mSLID + ")"; -} - void LLUrlEntryAgent::onNameCache(const LLUUID& id, const std::string& full_name, bool is_group) { - std::string final = buildName(id); + // IDEVO demo code + LLAvatarName av_name; + LLAvatarNameCache::get(id, &av_name); + std::string label = av_name.mDisplayName + " (" + av_name.mSLID + ")"; + // use custom icon if available + std::string icon = (!av_name.mBadge.empty() ? av_name.mBadge : mIcon); // received the agent name from the server - tell our observers - callObservers(id.asString(), final); + callObservers(id.asString(), label, icon); } std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb) @@ -353,7 +357,10 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa } else if (gCacheName->getFullName(agent_id, full_name)) { - return buildName(agent_id); + LLAvatarName av_name; + LLAvatarNameCache::get(agent_id, &av_name); + std::string label = av_name.mDisplayName + " (" + av_name.mSLID + ")"; + return label; } else { @@ -366,6 +373,30 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa } +std::string LLUrlEntryAgent::getIcon(const std::string &url) const +{ + std::string agent_id_string = getIDStringFromUrl(url); + if (agent_id_string.empty()) + { + return mIcon; + } + + LLUUID agent_id(agent_id_string); + if (agent_id.isNull()) + { + return mIcon; + } + + LLAvatarName av_name; + LLAvatarNameCache::get(agent_id, &av_name); + if (av_name.mBadge.empty()) + { + return mIcon; + } + + return av_name.mBadge; +} + // // LLUrlEntryGroup Describes a Second Life group Url, e.g., // secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about @@ -386,7 +417,7 @@ void LLUrlEntryGroup::onGroupNameReceived(const LLUUID& id, bool is_group) { // received the group name from the server - tell our observers - callObservers(id.asString(), name); + callObservers(id.asString(), name, mIcon); } std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCallback &cb) diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 2bc21eb989..1f0caeacf5 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -42,7 +42,8 @@ #include typedef boost::signals2::signal LLUrlLabelSignal; + const std::string& label, + const std::string& icon)> LLUrlLabelSignal; typedef LLUrlLabelSignal::slot_type LLUrlLabelCallback; /// @@ -77,7 +78,7 @@ public: virtual std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) { return url; } /// Return an icon that can be displayed next to Urls of this type - std::string getIcon() const { return mIcon; } + virtual std::string getIcon(const std::string &url) const; /// Return the color to render the displayed text LLUIColor getColor() const { return mColor; } @@ -101,7 +102,7 @@ protected: std::string getLabelFromWikiLink(const std::string &url) const; std::string getUrlFromWikiLink(const std::string &string) const; void addObserver(const std::string &id, const std::string &url, const LLUrlLabelCallback &cb); - void callObservers(const std::string &id, const std::string &label); + void callObservers(const std::string &id, const std::string &label, const std::string& icon); typedef struct { std::string url; @@ -168,10 +169,10 @@ class LLUrlEntryAgent : public LLUrlEntryBase public: LLUrlEntryAgent(); /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); + /*virtual*/ std::string getIcon(const std::string &url) const; private: void onNameCache(const LLUUID& id, const std::string& full_name, bool is_group); - std::string buildName(const LLUUID& id); }; /// diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index 5db1f46b8d..1ee87a01de 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -37,7 +37,7 @@ #include // default dummy callback that ignores any label updates from the server -void LLUrlRegistryNullCallback(const std::string &url, const std::string &label) +void LLUrlRegistryNullCallback(const std::string &url, const std::string &label, const std::string& icon) { } @@ -180,7 +180,7 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL match_entry->getUrl(url), match_entry->getLabel(url, cb), match_entry->getTooltip(), - match_entry->getIcon(), + match_entry->getIcon(url), match_entry->getColor(), match_entry->getMenuName(), match_entry->getLocation(url), diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index 6d47c2c2a2..dffbd9d4bf 100644 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -43,7 +43,9 @@ #include /// This default callback for findUrl() simply ignores any label updates -void LLUrlRegistryNullCallback(const std::string &url, const std::string &label); +void LLUrlRegistryNullCallback(const std::string &url, + const std::string &label, + const std::string &icon); /// /// LLUrlRegistry is a singleton that contains a set of Url types that diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 00a9e4d745..ba2e13da9d 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1298,8 +1298,7 @@ bool LLAppViewer::cleanup() LLPolyMesh::freeAllMeshes(); - delete gCacheName; - gCacheName = NULL; + LLStartUp::cleanupNameCache(); // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted. @@ -3337,15 +3336,6 @@ void LLAppViewer::loadNameCache() { if(gCacheName->importFile(cache_file)) return; } - - // Try to load from the legacy format. This should go away after a - // while. Phoenix 2008-01-30 - LLFILE* name_cache_fp = LLFile::fopen(name_cache, "r"); // Flawfinder: ignore - if (name_cache_fp) - { - gCacheName->importFile(name_cache_fp); - fclose(name_cache_fp); - } } void LLAppViewer::saveNameCache() diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index cfad29df89..97e47fb05e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -52,6 +52,7 @@ #endif #include "llares.h" +#include "llavatarnamecache.h" #include "lllandmark.h" #include "llcachename.h" #include "lldir.h" @@ -1280,16 +1281,7 @@ bool idle_startup() gXferManager->registerCallbacks(gMessageSystem); - if ( gCacheName == NULL ) - { - gCacheName = new LLCacheName(gMessageSystem); - gCacheName->addObserver(&callback_cache_name); - gCacheName->LocalizeCacheName("waiting", LLTrans::getString("AvatarNameWaiting")); - gCacheName->LocalizeCacheName("nobody", LLTrans::getString("AvatarNameNobody")); - gCacheName->LocalizeCacheName("none", LLTrans::getString("GroupNameNone")); - // Load stored cache if possible - LLAppViewer::instance()->loadNameCache(); - } + LLStartUp::initNameCache(); //gCacheName is required for nearby chat history loading //so I just moved nearby history loading a few states further @@ -2781,6 +2773,30 @@ void LLStartUp::fontInit() LLFontGL::loadDefaultFonts(); } +void LLStartUp::initNameCache() +{ + // Can be called multiple times + if ( gCacheName ) return; + + gCacheName = new LLCacheName(gMessageSystem); + gCacheName->addObserver(&callback_cache_name); + gCacheName->localizeCacheName("waiting", LLTrans::getString("AvatarNameWaiting")); + gCacheName->localizeCacheName("nobody", LLTrans::getString("AvatarNameNobody")); + gCacheName->localizeCacheName("none", LLTrans::getString("GroupNameNone")); + // Load stored cache if possible + LLAppViewer::instance()->loadNameCache(); + + LLAvatarNameCache::initClass(); +} + +void LLStartUp::cleanupNameCache() +{ + LLAvatarNameCache::cleanupClass(); + + delete gCacheName; + gCacheName = NULL; +} + bool LLStartUp::dispatchURL() { // ok, if we've gotten this far and have a startup URL diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index 92fe9521d3..14a7c71544 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -95,6 +95,10 @@ public: // Load default fonts not already loaded at start screen static void fontInit(); + static void initNameCache(); + + static void cleanupNameCache(); + // outfit_folder_name can be a folder anywhere in your inventory, // but the name must be a case-sensitive exact match. // gender_name is either "male" or "female" diff --git a/indra/newview/skins/default/textures/icons/Person_Check.png b/indra/newview/skins/default/textures/icons/Person_Check.png new file mode 100644 index 0000000000000000000000000000000000000000..f8638540d4eb8ecf17d3f19c3c943db35924b50e GIT binary patch literal 3824 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 literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/icons/Person_Star.png b/indra/newview/skins/default/textures/icons/Person_Star.png new file mode 100644 index 0000000000000000000000000000000000000000..ad10580ac45e7b6f4a9b92841feb21956b28a0e8 GIT binary patch literal 3762 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 literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 18d1779702..753f62dc8d 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -410,6 +410,8 @@ with the same filename but different name + +