diff options
Diffstat (limited to 'indra')
156 files changed, 3201 insertions, 1298 deletions
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 6d5b12d840..1c664e093b 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -45,12 +45,16 @@ struct AssetEntry : public LLDictionaryEntry AssetEntry(const char *desc_name, const char *type_name, // 8 character limit! const char *human_name, // for decoding to human readable form; put any and as many printable characters you want in each one - bool can_link) // can you create a link to this type? + bool can_link, // can you create a link to this type? + bool can_fetch, // can you fetch this asset by ID? + bool can_know) // can you see this asset's ID? : LLDictionaryEntry(desc_name), mTypeName(type_name), mHumanName(human_name), - mCanLink(can_link) + mCanLink(can_link), + mCanFetch(can_fetch), + mCanKnow(can_know) { llassert(strlen(mTypeName) <= 8); } @@ -58,6 +62,8 @@ struct AssetEntry : public LLDictionaryEntry const char *mTypeName; const char *mHumanName; bool mCanLink; + bool mCanFetch; + bool mCanKnow; }; class LLAssetDictionary : public LLSingleton<LLAssetDictionary>, @@ -69,32 +75,32 @@ public: LLAssetDictionary::LLAssetDictionary() { - // DESCRIPTION TYPE NAME HUMAN NAME CAN LINK? - // |--------------------|-----------|-------------------|-----------| - addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", FALSE)); - addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", FALSE)); - addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", FALSE)); - addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", FALSE)); - addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", FALSE)); - addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", TRUE)); - addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", TRUE)); - addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", FALSE)); - addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", TRUE)); - addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", FALSE)); - addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", FALSE)); - addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", FALSE)); - addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", TRUE)); - addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", FALSE)); - addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", FALSE)); - addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", FALSE)); - addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", FALSE)); - addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", TRUE)); - addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", FALSE)); - - addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "symbolic link", FALSE)); - addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "symbolic folder link", FALSE)); - - addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE)); + // DESCRIPTION TYPE NAME HUMAN NAME CAN LINK? CAN FETCH? CAN KNOW? + // |--------------------|-----------|-------------------|-----------|-----------|---------| + addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", false, false, true)); + addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", false, true, true)); + addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", false, false, false)); + addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", false, true, true)); + addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", false, false, false)); + addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", true, true, true)); + addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", true, false, false)); + addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", false, false, true)); + addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", true, false, false)); + addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", false, false, false)); + addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", false, false, false)); + addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", false, false, false)); + addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", true, true, true)); + addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", false, false, false)); + addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", false, false, false)); + addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", false, false, false)); + addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", false, true, true)); + addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", true, true, true)); + addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", false, false, false)); + + addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "sym link", false, false, true)); + addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "sym folder link", false, false, true)); + + addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, false, false, false)); }; // static @@ -225,3 +231,27 @@ const std::string &LLAssetType::badLookup() return sBadLookup; } + +// static +bool LLAssetType::lookupIsAssetFetchByIDAllowed(EType asset_type) +{ + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) + { + return entry->mCanFetch; + } + return false; +} + +// static +bool LLAssetType::lookupIsAssetIDKnowable(EType asset_type) +{ + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) + { + return entry->mCanKnow; + } + return false; +} diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index c7bbc2e74a..2c2dc27aaa 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -146,6 +146,9 @@ public: static bool lookupCanLink(EType asset_type); static bool lookupIsLinkType(EType asset_type); + static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download + static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer + static const std::string& badLookup(); // error string when a lookup fails protected: diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 5f3d9d6582..b5a73ec1d1 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -911,6 +911,20 @@ bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token return false; } +//static +template<> +void LLStringUtil::setLocale(std::string inLocale) +{ + sLocale = inLocale; +}; + +//static +template<> +std::string LLStringUtil::getLocale(void) +{ + return sLocale; +}; + // static template<> void LLStringUtil::formatNumber(std::string& numStr, std::string decimals) diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 62cedcde4e..96588b29b9 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -241,8 +241,8 @@ public: LL_COMMON_API static S32 format(std::basic_string<T>& s, const LLSD& substitutions); LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const format_map_t& substitutions); LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const LLSD& substitutions); - static void setLocale (std::string inLocale) {sLocale = inLocale;}; - static std::string getLocale (void) {return sLocale;}; + LL_COMMON_API static void setLocale (std::string inLocale); + LL_COMMON_API static std::string getLocale (void); static bool isValidIndex(const std::basic_string<T>& string, size_type i) { diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h index 0f1e59a18c..e3663544db 100644 --- a/indra/llcommon/llversionserver.h +++ b/indra/llcommon/llversionserver.h @@ -36,7 +36,7 @@ const S32 LL_VERSION_MAJOR = 1; const S32 LL_VERSION_MINOR = 31; const S32 LL_VERSION_PATCH = 0; -const S32 LL_VERSION_BUILD = 200030; +const S32 LL_VERSION_BUILD = 203110; const char * const LL_CHANNEL = "Second Life Server"; diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 540aea4252..3ab4257fab 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -36,7 +36,7 @@ const S32 LL_VERSION_MAJOR = 2; const S32 LL_VERSION_MINOR = 0; const S32 LL_VERSION_PATCH = 0; -const S32 LL_VERSION_BUILD = 200030; +const S32 LL_VERSION_BUILD = 203110; const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index 0ab1081200..02523467e8 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -408,6 +408,8 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, vo { lldebugs << "LLAssetStorage::getAssetData() - " << uuid << "," << LLAssetType::lookup(type) << llendl; + llinfos << "ASSET_TRACE requesting " << uuid << " type " << LLAssetType::lookup(type) << llendl; + if (mShutDown) { return; // don't get the asset or do any callbacks, we are shutting down @@ -471,6 +473,8 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, vo // we've already got the file // theoretically, partial files w/o a pending request shouldn't happen // unless there's a weird error + llinfos << "ASSET_TRACE asset " << uuid << " found in VFS" << llendl; + if (callback) { callback(mVFS, uuid, type, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED); @@ -528,6 +532,8 @@ void LLAssetStorage::downloadCompleteCallback( LLAssetType::EType file_type, void* user_data, LLExtStat ext_status) { + llinfos << "ASSET_TRACE asset " << file_id << " downloadCompleteCallback" << llendl; + lldebugs << "LLAssetStorage::downloadCompleteCallback() for " << file_id << "," << LLAssetType::lookup(file_type) << llendl; LLAssetRequest* req = (LLAssetRequest*)user_data; diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp index abfb432020..43f7c07e94 100644 --- a/indra/llmessage/lltransfersourceasset.cpp +++ b/indra/llmessage/lltransfersourceasset.cpp @@ -60,7 +60,7 @@ void LLTransferSourceAsset::initTransfer() // to the simulator. This is subset of assets we allow to be // simply pulled straight from the asset system. LLUUID* tidp; - if(is_asset_fetch_by_id_allowed(mParams.getAssetType())) + if(LLAssetType::lookupIsAssetFetchByIDAllowed(mParams.getAssetType())) { tidp = new LLUUID(getID()); gAssetStorage->getAssetData( @@ -257,50 +257,3 @@ BOOL LLTransferSourceParamsAsset::unpackParams(LLDataPacker &dp) return TRUE; } - -/** - * Helper functions - */ -bool is_asset_fetch_by_id_allowed(LLAssetType::EType type) -{ - // *FIX: Make this list smaller. - bool rv = false; - switch(type) - { - case LLAssetType::AT_SOUND: - case LLAssetType::AT_LANDMARK: - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - case LLAssetType::AT_ANIMATION: - case LLAssetType::AT_GESTURE: - rv = true; - break; - default: - break; - } - return rv; -} - -bool is_asset_id_knowable(LLAssetType::EType type) -{ - // *FIX: Make this list smaller. - bool rv = false; - switch(type) - { - case LLAssetType::AT_TEXTURE: - case LLAssetType::AT_SOUND: - case LLAssetType::AT_LANDMARK: - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_NOTECARD: - case LLAssetType::AT_BODYPART: - case LLAssetType::AT_ANIMATION: - case LLAssetType::AT_GESTURE: - case LLAssetType::AT_LINK: - case LLAssetType::AT_LINK_FOLDER: - rv = true; - break; - default: - break; - } - return rv; -} diff --git a/indra/llmessage/lltransfersourceasset.h b/indra/llmessage/lltransfersourceasset.h index 70b09b6aaf..8616595654 100644 --- a/indra/llmessage/lltransfersourceasset.h +++ b/indra/llmessage/lltransfersourceasset.h @@ -84,24 +84,4 @@ protected: S32 mCurPos; }; -/** - * @brief Quick check to see if the asset allows direct download. - * - * This might not be the right place for this function call, but it - * originally started life inside the LLTransferSourceAsset code. - * @param type The type of asset. - * @return Returns true if the asset can be fetched by id. - */ -bool is_asset_fetch_by_id_allowed(LLAssetType::EType type); - -/** - * @brief Quick check to see if all asset data can be known by the viewer. - * - * This might not be the right place for this function call, but it - * originally started life inside the LLTransferSourceAsset code. - * @param type The type of asset. - * @return Returns true if the asset id can be transmitted to the viewer. - */ -bool is_asset_id_knowable(LLAssetType::EType type); - #endif // LL_LLTRANSFERSOURCEASSET_H diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt index def9fcbeae..441becbae0 100644 --- a/indra/llplugin/CMakeLists.txt +++ b/indra/llplugin/CMakeLists.txt @@ -3,6 +3,7 @@ project(llplugin) include(00-Common) +include(CURL) include(LLCommon) include(LLImage) include(LLMath) @@ -55,3 +56,19 @@ list(APPEND llplugin_SOURCE_FILES ${llplugin_HEADER_FILES}) add_library (llplugin ${llplugin_SOURCE_FILES}) add_subdirectory(slplugin) + +# Add tests +include(LLAddBuildTest) +# UNIT TESTS +SET(llplugin_TEST_SOURCE_FILES + llplugincookiestore.cpp + ) + +# llplugincookiestore has a dependency on curl, so we need to link the curl library into the test. +set_source_files_properties( + llplugincookiestore.cpp + PROPERTIES + LL_TEST_ADDITIONAL_LIBRARIES "${CURL_LIBRARIES}" + ) + +LL_ADD_PROJECT_UNIT_TESTS(llplugin "${llplugin_TEST_SOURCE_FILES}") diff --git a/indra/llplugin/llplugincookiestore.cpp b/indra/llplugin/llplugincookiestore.cpp index 1964b8d789..85b1e70d78 100644 --- a/indra/llplugin/llplugincookiestore.cpp +++ b/indra/llplugin/llplugincookiestore.cpp @@ -53,7 +53,7 @@ LLPluginCookieStore::~LLPluginCookieStore() LLPluginCookieStore::Cookie::Cookie(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end): - mCookie(s, cookie_start, cookie_end), + mCookie(s, cookie_start, cookie_end - cookie_start), mNameStart(0), mNameEnd(0), mValueStart(0), mValueEnd(0), mDomainStart(0), mDomainEnd(0), @@ -62,11 +62,11 @@ LLPluginCookieStore::Cookie::Cookie(const std::string &s, std::string::size_type { } -LLPluginCookieStore::Cookie *LLPluginCookieStore::Cookie::createFromString(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end) +LLPluginCookieStore::Cookie *LLPluginCookieStore::Cookie::createFromString(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end, const std::string &host) { Cookie *result = new Cookie(s, cookie_start, cookie_end); - if(!result->parse()) + if(!result->parse(host)) { delete result; result = NULL; @@ -92,7 +92,7 @@ std::string LLPluginCookieStore::Cookie::getKey() const return result; } -bool LLPluginCookieStore::Cookie::parse() +bool LLPluginCookieStore::Cookie::parse(const std::string &host) { bool first_field = true; @@ -248,7 +248,50 @@ bool LLPluginCookieStore::Cookie::parse() // The cookie MUST have a name if(mNameEnd <= mNameStart) return false; + + // If the cookie doesn't have a domain, add the current host as the domain. + if(mDomainEnd <= mDomainStart) + { + if(host.empty()) + { + // no domain and no current host -- this is a parse failure. + return false; + } + + // Figure out whether this cookie ended with a ";" or not... + std::string::size_type last_char = mCookie.find_last_not_of(" "); + if((last_char != std::string::npos) && (mCookie[last_char] != ';')) + { + mCookie += ";"; + } + + mCookie += " domain="; + mDomainStart = mCookie.size(); + mCookie += host; + mDomainEnd = mCookie.size(); + + lldebugs << "added domain (" << mDomainStart << " to " << mDomainEnd << "), new cookie is: " << mCookie << llendl; + } + + // If the cookie doesn't have a path, add "/". + if(mPathEnd <= mPathStart) + { + // Figure out whether this cookie ended with a ";" or not... + std::string::size_type last_char = mCookie.find_last_not_of(" "); + if((last_char != std::string::npos) && (mCookie[last_char] != ';')) + { + mCookie += ";"; + } + + mCookie += " path="; + mPathStart = mCookie.size(); + mCookie += "/"; + mPathEnd = mCookie.size(); + lldebugs << "added path (" << mPathStart << " to " << mPathEnd << "), new cookie is: " << mCookie << llendl; + } + + return true; } @@ -409,13 +452,29 @@ void LLPluginCookieStore::setCookies(const std::string &cookies, bool mark_chang while(start != std::string::npos) { - std::string::size_type end = cookies.find('\n', start); + std::string::size_type end = cookies.find_first_of("\r\n", start); if(end > start) { // The line is non-empty. Try to create a cookie from it. setOneCookie(cookies, start, end, mark_changed); } - start = cookies.find_first_not_of("\n ", end); + start = cookies.find_first_not_of("\r\n ", end); + } +} + +void LLPluginCookieStore::setCookiesFromHost(const std::string &cookies, const std::string &host, bool mark_changed) +{ + std::string::size_type start = 0; + + while(start != std::string::npos) + { + std::string::size_type end = cookies.find_first_of("\r\n", start); + if(end > start) + { + // The line is non-empty. Try to create a cookie from it. + setOneCookie(cookies, start, end, mark_changed, host); + } + start = cookies.find_first_not_of("\r\n ", end); } } @@ -502,9 +561,9 @@ std::string LLPluginCookieStore::unquoteString(const std::string &s) // When deleting with mark_changed set to true, this replaces the existing cookie in the list with an entry that's marked both dead and changed. // Some time later when writeChangedCookies() is called with clear_changed set to true, the dead cookie is deleted from the list after being returned, so that the // delete operation (in the form of the expired cookie) is passed along. -void LLPluginCookieStore::setOneCookie(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end, bool mark_changed) +void LLPluginCookieStore::setOneCookie(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end, bool mark_changed, const std::string &host) { - Cookie *cookie = Cookie::createFromString(s, cookie_start, cookie_end); + Cookie *cookie = Cookie::createFromString(s, cookie_start, cookie_end, host); if(cookie) { lldebugs << "setting cookie: " << cookie->getCookie() << llendl; diff --git a/indra/llplugin/llplugincookiestore.h b/indra/llplugin/llplugincookiestore.h index 5250f008b6..a93f0c14f0 100644 --- a/indra/llplugin/llplugincookiestore.h +++ b/indra/llplugin/llplugincookiestore.h @@ -66,18 +66,21 @@ public: void setCookies(const std::string &cookies, bool mark_changed = true); void readCookies(std::istream& s, bool mark_changed = true); + // sets one or more cookies (without reinitializing anything), supplying a hostname the cookies came from -- use when setting a cookie manually + void setCookiesFromHost(const std::string &cookies, const std::string &host, bool mark_changed = true); + // quote or unquote a string as per the definition of 'quoted-string' in rfc2616 static std::string quoteString(const std::string &s); static std::string unquoteString(const std::string &s); private: - void setOneCookie(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end, bool mark_changed); + void setOneCookie(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end, bool mark_changed, const std::string &host = LLStringUtil::null); class Cookie { public: - static Cookie *createFromString(const std::string &s, std::string::size_type cookie_start = 0, std::string::size_type cookie_end = std::string::npos); + static Cookie *createFromString(const std::string &s, std::string::size_type cookie_start = 0, std::string::size_type cookie_end = std::string::npos, const std::string &host = LLStringUtil::null); // Construct a string from the cookie that uniquely represents it, to be used as a key in a std::map. std::string getKey() const; @@ -95,7 +98,7 @@ private: private: Cookie(const std::string &s, std::string::size_type cookie_start = 0, std::string::size_type cookie_end = std::string::npos); - bool parse(); + bool parse(const std::string &host); std::string::size_type findFieldEnd(std::string::size_type start = 0, std::string::size_type end = std::string::npos); bool matchName(std::string::size_type start, std::string::size_type end, const char *name); diff --git a/indra/llplugin/tests/llplugincookiestore_test.cpp b/indra/llplugin/tests/llplugincookiestore_test.cpp new file mode 100644 index 0000000000..020d9c1977 --- /dev/null +++ b/indra/llplugin/tests/llplugincookiestore_test.cpp @@ -0,0 +1,211 @@ +/** + * @file llplugincookiestore_test.cpp + * @brief Unit tests for LLPluginCookieStore. + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * @endcond + */ + +#include "linden_common.h" +#include "../test/lltut.h" + +#include "../llplugincookiestore.h" + + +namespace tut +{ + // Main Setup + struct LLPluginCookieStoreFixture + { + LLPluginCookieStoreFixture() + { + // We need dates definitively in the past and the future to properly test cookie expiration. + LLDate now = LLDate::now(); + LLDate past(now.secondsSinceEpoch() - (60.0 * 60.0 * 24.0)); // 1 day in the past + LLDate future(now.secondsSinceEpoch() + (60.0 * 60.0 * 24.0)); // 1 day in the future + + mPastString = past.asRFC1123(); + mFutureString = future.asRFC1123(); + } + + std::string mPastString; + std::string mFutureString; + LLPluginCookieStore mCookieStore; + + // List of cookies used for validation + std::list<std::string> mCookies; + + // This sets up mCookies from a string returned by one of the functions in LLPluginCookieStore + void setCookies(const std::string &cookies) + { + mCookies.clear(); + std::string::size_type start = 0; + + while(start != std::string::npos) + { + std::string::size_type end = cookies.find_first_of("\r\n", start); + if(end > start) + { + std::string line(cookies, start, end - start); + if(line.find_first_not_of("\r\n\t ") != std::string::npos) + { + // The line has some non-whitespace characters. Save it to the list. + mCookies.push_back(std::string(cookies, start, end - start)); + } + } + start = cookies.find_first_not_of("\r\n ", end); + } + } + + // This ensures that a cookie matching the one passed is in the list. + void ensureCookie(const std::string &cookie) + { + std::list<std::string>::iterator iter; + for(iter = mCookies.begin(); iter != mCookies.end(); iter++) + { + if(*iter == cookie) + { + // Found the cookie + // TODO: this should do a smarter equality comparison on the two cookies, instead of just a string compare. + return; + } + } + + // Didn't find this cookie + std::string message = "cookie not found: "; + message += cookie; + ensure(message, false); + } + + // This ensures that the number of cookies in the list matches what's expected. + void ensureSize(const std::string &message, size_t size) + { + if(mCookies.size() != size) + { + std::stringstream full_message; + + full_message << message << " (expected " << size << ", actual " << mCookies.size() << ")"; + ensure(full_message.str(), false); + } + } + }; + + typedef test_group<LLPluginCookieStoreFixture> factory; + typedef factory::object object; + factory tf("LLPluginCookieStore test"); + + // Tests + template<> template<> + void object::test<1>() + { + // Test 1: cookie uniqueness and update lists. + // Valid, distinct cookies: + + std::string cookie01 = "cookieA=value; domain=example.com; path=/"; + std::string cookie02 = "cookieB=value; domain=example.com; path=/"; // different name + std::string cookie03 = "cookieA=value; domain=foo.example.com; path=/"; // different domain + std::string cookie04 = "cookieA=value; domain=example.com; path=/bar/"; // different path + std::string cookie05 = "cookieC; domain=example.com; path=/"; // empty value + std::string cookie06 = "cookieD=value; domain=example.com; path=/; expires="; // different name, persistent cookie + cookie06 += mFutureString; + + mCookieStore.setCookies(cookie01); + mCookieStore.setCookies(cookie02); + mCookieStore.setCookies(cookie03); + mCookieStore.setCookies(cookie04); + mCookieStore.setCookies(cookie05); + mCookieStore.setCookies(cookie06); + + // Invalid cookies (these will get parse errors and not be added to the store) + + std::string badcookie01 = "cookieD=value; domain=example.com; path=/; foo=bar"; // invalid field name + std::string badcookie02 = "cookieE=value; path=/"; // no domain + + mCookieStore.setCookies(badcookie01); + mCookieStore.setCookies(badcookie02); + + // All cookies added so far should have been marked as "changed" + setCookies(mCookieStore.getChangedCookies()); + ensureSize("count of changed cookies", 6); + ensureCookie(cookie01); + ensureCookie(cookie02); + ensureCookie(cookie03); + ensureCookie(cookie04); + ensureCookie(cookie05); + ensureCookie(cookie06); + + // Save off the current state of the cookie store (we'll restore it later) + std::string savedCookies = mCookieStore.getAllCookies(); + + // Test replacing cookies + std::string cookie01a = "cookieA=newvalue; domain=example.com; path=/"; // updated value + std::string cookie02a = "cookieB=newvalue; domain=example.com; path=/; expires="; // remove cookie (by setting an expire date in the past) + cookie02a += mPastString; + + mCookieStore.setCookies(cookie01a); + mCookieStore.setCookies(cookie02a); + + // test for getting changed cookies + setCookies(mCookieStore.getChangedCookies()); + ensureSize("count of updated cookies", 2); + ensureCookie(cookie01a); + ensureCookie(cookie02a); + + // and for the state of the store after getting changed cookies + setCookies(mCookieStore.getAllCookies()); + ensureSize("count of valid cookies", 5); + ensureCookie(cookie01a); + ensureCookie(cookie03); + ensureCookie(cookie04); + ensureCookie(cookie05); + ensureCookie(cookie06); + + // Check that only the persistent cookie is returned here + setCookies(mCookieStore.getPersistentCookies()); + ensureSize("count of persistent cookies", 1); + ensureCookie(cookie06); + + // Restore the cookie store to a previous state and verify + mCookieStore.setAllCookies(savedCookies); + + // Since setAllCookies defaults to not marking cookies as changed, this list should be empty. + setCookies(mCookieStore.getChangedCookies()); + ensureSize("count of changed cookies after restore", 0); + + // Verify that the restore worked as it should have. + setCookies(mCookieStore.getAllCookies()); + ensureSize("count of restored cookies", 6); + ensureCookie(cookie01); + ensureCookie(cookie02); + ensureCookie(cookie03); + ensureCookie(cookie04); + ensureCookie(cookie05); + ensureCookie(cookie06); + } + +} diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index e12776f83a..0959722aa6 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -465,10 +465,11 @@ void LLAccordionCtrlTab::setHeaderVisible(bool value) reshape(getRect().getWidth(), getRect().getHeight(), FALSE); }; -//vurtual +//virtual BOOL LLAccordionCtrlTab::postBuild() { - mHeader->setVisible(mHeaderVisible); + if(mHeader) + mHeader->setVisible(mHeaderVisible); static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); @@ -504,7 +505,8 @@ BOOL LLAccordionCtrlTab::postBuild() mScrollbar->setVisible(false); } - mContainerPanel->setVisible(mDisplayChildren); + if(mContainerPanel) + mContainerPanel->setVisible(mDisplayChildren); return LLUICtrl::postBuild(); } diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index 832f148902..9d4e2fa495 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -248,15 +248,14 @@ void LLDragHandleTop::reshapeTitleBox() return; } const LLFontGL* font = LLFontGL::getFontSansSerif(); - S32 title_width = font->getWidth( mTitleBox->getText() ) + TITLE_HPAD; - if (getMaxTitleWidth() > 0) - title_width = llmin(title_width, getMaxTitleWidth()); + S32 title_width = getRect().getWidth(); + title_width -= 2 * LEFT_PAD + 2 * BORDER_PAD + getButtonsRect().getWidth(); S32 title_height = llround(font->getLineHeight()); LLRect title_rect; title_rect.setLeftTopAndSize( LEFT_PAD, getRect().getHeight() - title_vpad, - getRect().getWidth() - LEFT_PAD - RIGHT_PAD, + title_width, title_height); // calls reshape on mTitleBox diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h index dc5410787b..825bc9303e 100644 --- a/indra/llui/lldraghandle.h +++ b/indra/llui/lldraghandle.h @@ -71,6 +71,8 @@ public: BOOL getForeground() const { return mForeground; } void setMaxTitleWidth(S32 max_width) {mMaxTitleWidth = llmin(max_width, mMaxTitleWidth); } S32 getMaxTitleWidth() const { return mMaxTitleWidth; } + void setButtonsRect(const LLRect& rect){ mButtonsRect = rect; } + LLRect getButtonsRect() { return mButtonsRect; } void setTitleVisible(BOOL visible); virtual void setTitle( const std::string& title ) = 0; @@ -88,6 +90,7 @@ protected: LLTextBox* mTitleBox; private: + LLRect mButtonsRect; S32 mDragLastScreenX; S32 mDragLastScreenY; S32 mLastMouseScreenX; diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index d499e08ecb..0fd7e7ed55 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -53,17 +53,6 @@ LLFlatListView::Params::Params() no_items_text("no_items_text") {}; -LLFlatListView::~LLFlatListView() -{ - clear(); - // Route menu back to the default - if( gEditMenuHandler == this ) - { - gEditMenuHandler = NULL; - } -}; - - void LLFlatListView::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) { LLScrollContainer::reshape(width, height, called_from_parent); @@ -795,13 +784,13 @@ bool LLFlatListView::selectNextItemPair(bool is_up_direction, bool reset_selecti BOOL LLFlatListView::canSelectAll() const { - return !mItemPairs.empty() && mAllowSelection; + return !mItemPairs.empty() && mAllowSelection && mMultipleSelection; } void LLFlatListView::selectAll() { - if (!mAllowSelection) - return; + if (!mAllowSelection || !mMultipleSelection) + return false; mSelectedItemPairs.clear(); diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index 3a2ab54658..e2f01964de 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -380,11 +380,14 @@ private: void setNoItemsCommentVisible(bool visible) const; -private: +protected: /** Comparator to use when sorting the list. */ const ItemComparator* mItemComparator; + +private: + LLPanel* mItemsPanel; S32 mItemsNoScrollWidth; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index a9accc0ba6..e672252a50 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -346,7 +346,7 @@ void LLFloater::layoutDragHandle() rect = getLocalRect(); } mDragHandle->setRect(rect); - updateButtons(); + updateTitleButtons(); applyTitle(); } @@ -1061,11 +1061,10 @@ void LLFloater::setMinimized(BOOL minimize) // Reshape *after* setting mMinimized reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE ); } - - applyTitle (); make_ui_sound("UISndWindowClose"); - updateButtons(); + updateTitleButtons(); + applyTitle (); } void LLFloater::setFocus( BOOL b ) @@ -1121,6 +1120,7 @@ void LLFloater::setIsChrome(BOOL is_chrome) setFocus(FALSE); // can't Ctrl-Tab to "chrome" floaters setFocusRoot(FALSE); + mButtons[BUTTON_CLOSE]->setToolTip(LLStringExplicit(getButtonTooltip(Params(), BUTTON_CLOSE, is_chrome))); } // no titles displayed on "chrome" floaters @@ -1190,7 +1190,7 @@ void LLFloater::setHost(LLMultiFloater* host) mButtonScale = 1.f; //mButtonsEnabled[BUTTON_TEAR_OFF] = FALSE; } - updateButtons(); + updateTitleButtons(); if (host) { mHostHandle = host->getHandle(); @@ -1389,7 +1389,7 @@ void LLFloater::setCanDock(bool b) mButtonsEnabled[BUTTON_DOCK] = FALSE; } } - updateButtons(); + updateTitleButtons(); } void LLFloater::setDocked(bool docked, bool pop_on_undock) @@ -1398,7 +1398,7 @@ void LLFloater::setDocked(bool docked, bool pop_on_undock) { mDocked = docked; mButtonsEnabled[BUTTON_DOCK] = !mDocked; - updateButtons(); + updateTitleButtons(); storeDockStateControl(); } @@ -1451,7 +1451,7 @@ void LLFloater::onClickTearOff(LLFloater* self) } self->setTornOff(false); } - self->updateButtons(); + self->updateTitleButtons(); } // static @@ -1691,7 +1691,7 @@ void LLFloater::setCanMinimize(BOOL can_minimize) mButtonsEnabled[BUTTON_MINIMIZE] = can_minimize && !isMinimized(); mButtonsEnabled[BUTTON_RESTORE] = can_minimize && isMinimized(); - updateButtons(); + updateTitleButtons(); } void LLFloater::setCanClose(BOOL can_close) @@ -1699,7 +1699,7 @@ void LLFloater::setCanClose(BOOL can_close) mCanClose = can_close; mButtonsEnabled[BUTTON_CLOSE] = can_close; - updateButtons(); + updateTitleButtons(); } void LLFloater::setCanTearOff(BOOL can_tear_off) @@ -1707,7 +1707,7 @@ void LLFloater::setCanTearOff(BOOL can_tear_off) mCanTearOff = can_tear_off; mButtonsEnabled[BUTTON_TEAR_OFF] = mCanTearOff && !mHostHandle.isDead(); - updateButtons(); + updateTitleButtons(); } @@ -1731,10 +1731,11 @@ void LLFloater::setCanDrag(BOOL can_drag) } } -void LLFloater::updateButtons() +void LLFloater::updateTitleButtons() { static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0); static LLUICachedControl<S32> close_box_from_top ("UICloseBoxFromTop", 0); + LLRect buttons_rect; S32 button_count = 0; for (S32 i = 0; i < BUTTON_COUNT; i++) { @@ -1785,6 +1786,15 @@ void LLFloater::updateButtons() llround((F32)floater_close_box_size * mButtonScale)); } + if(!buttons_rect.isValid()) + { + buttons_rect = btn_rect; + } + else + { + mDragOnLeft ? buttons_rect.mRight + btn_rect.mRight : + buttons_rect.mLeft = btn_rect.mLeft; + } mButtons[i]->setRect(btn_rect); mButtons[i]->setVisible(TRUE); // the restore button should have a tab stop so that it takes action when you Ctrl-Tab to a minimized floater @@ -1796,7 +1806,10 @@ void LLFloater::updateButtons() } } if (mDragHandle) - mDragHandle->setMaxTitleWidth(getRect().getWidth() - (button_count * (floater_close_box_size + 1))); + { + localRectToOtherView(buttons_rect, &buttons_rect, mDragHandle); + mDragHandle->setButtonsRect(buttons_rect); + } } void LLFloater::buildButtons(const Params& floater_params) @@ -1844,7 +1857,7 @@ void LLFloater::buildButtons(const Params& floater_params) p.click_callback.function(boost::bind(sButtonCallbacks[i], this)); p.tab_stop(false); p.follows.flags(FOLLOWS_TOP|FOLLOWS_RIGHT); - p.tool_tip = getButtonTooltip(floater_params, (EFloaterButton)i); + p.tool_tip = getButtonTooltip(floater_params, (EFloaterButton)i, getIsChrome()); p.scale_image(true); p.chrome(true); @@ -1853,7 +1866,7 @@ void LLFloater::buildButtons(const Params& floater_params) mButtons[i] = buttonp; } - updateButtons(); + updateTitleButtons(); } // static @@ -1899,8 +1912,15 @@ LLUIImage* LLFloater::getButtonPressedImage(const Params& p, EFloaterButton e) } // static -std::string LLFloater::getButtonTooltip(const Params& p, EFloaterButton e) +std::string LLFloater::getButtonTooltip(const Params& p, EFloaterButton e, bool is_chrome) { + // EXT-4081 (Lag Meter: Ctrl+W does not close floater) + // If floater is chrome set 'Close' text for close button's tooltip + if(is_chrome && BUTTON_CLOSE == e) + { + static std::string close_tooltip_chrome = LLTrans::getString("BUTTON_CLOSE_CHROME"); + return close_tooltip_chrome; + } // TODO: per-floater localizable tooltips set in XML return sButtonToolTips[e]; } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 97d2bda594..403723d9d8 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -311,19 +311,26 @@ protected: virtual void onClickCloseBtn(); + virtual void updateTitleButtons(); + private: void setForeground(BOOL b); // called only by floaterview void cleanupHandles(); // remove handles to dead floaters void createMinimizeButton(); - void updateButtons(); void buildButtons(const Params& p); // Images and tooltips are named in the XML, but we want to look them // up by index. static LLUIImage* getButtonImage(const Params& p, EFloaterButton e); static LLUIImage* getButtonPressedImage(const Params& p, EFloaterButton e); - static std::string getButtonTooltip(const Params& p, EFloaterButton e); + /** + * @params is_chrome - if floater is Chrome it means that floater will never get focus. + * Therefore it can't be closed with 'Ctrl+W'. So the tooltip text of close button( X ) + * should be 'Close' not 'Close(Ctrl+W)' as for usual floaters. + */ + static std::string getButtonTooltip(const Params& p, EFloaterButton e, bool is_chrome); + BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButton index); void addResizeCtrls(); void layoutResizeCtrls(); diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index d7424cf05a..65ef53443b 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1552,3 +1552,11 @@ std::ostream& operator<<(std::ostream& s, const LLNotification& notification) return s; } +void LLPostponedNotification::onCachedNameReceived(const LLUUID& id, const std::string& first, + const std::string& last, bool is_group) +{ + gCacheName->getFullName(id, mName); + modifyNotificationParams(); + LLNotifications::instance().add(mParams); + cleanup(); +} diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 400491a154..1799ca65b7 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -104,6 +104,7 @@ #include "llinitparam.h" #include "llnotificationslistener.h" #include "llnotificationptr.h" +#include "llcachename.h" typedef enum e_notification_priority @@ -949,6 +950,62 @@ private: boost::scoped_ptr<LLNotificationsListener> mListener; }; +/** + * Abstract class for postponed notifications. + * Provides possibility to add notification after specified by id avatar or group will be + * received from cache name. The object of this type automatically well be deleted + * by cleanup method after respond will be received from cache name. + * + * To add custom postponed notification to the notification system client should: + * 1 create class derived from LLPostponedNotification; + * 2 call LLPostponedNotification::add method; + */ +class LLPostponedNotification +{ +public: + /** + * Performs hooking cache name callback which will add notification to notifications system. + * Type of added notification should be specified by template parameter T + * and non-private derived from LLPostponedNotification class, + * otherwise compilation error will occur. + */ + template<class T> + static void add(const LLNotification::Params& params, + const LLUUID& id, bool is_group) + { + // upcast T to the base type to restrict T derivation from LLPostponedNotification + LLPostponedNotification* thiz = new T(); + + thiz->mParams = params; + + gCacheName->get(id, is_group, boost::bind( + &LLPostponedNotification::onCachedNameReceived, thiz, _1, _2, + _3, _4)); + } + +private: + void onCachedNameReceived(const LLUUID& id, const std::string& first, + const std::string& last, bool is_group); + + void cleanup() + { + delete this; + } + +protected: + LLPostponedNotification() {} + virtual ~LLPostponedNotification() {} + + /** + * Abstract method provides possibility to modify notification parameters and + * will be called after cache name retrieve information about avatar or group + * and before notification will be added to the notification system. + */ + virtual void modifyNotificationParams() = 0; + + LLNotification::Params mParams; + std::string mName; +}; #endif//LL_LLNOTIFICATIONS_H diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index fb8cb1c93b..e08026eaf4 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -962,7 +962,18 @@ void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent) { if (width != getRect().getWidth() || height != getRect().getHeight()) { + //EXT-4288 + //to keep consistance scrolling behaviour + //when scrolling from top and from bottom... + bool is_scrolled_to_end = (mScroller!=NULL) && scrolledToEnd(); + LLUICtrl::reshape( width, height, called_from_parent ); + + if (is_scrolled_to_end) + { + deselect(); + endOfDoc(); + } // do this first after reshape, because other things depend on // up-to-date mVisibleTextRect diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 4d25b4134e..399d284402 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -2074,6 +2074,9 @@ void LLWindowSDL::initCursors() mSDLCursors[UI_CURSOR_TOOLPAUSE] = makeSDLCursorFromBMP("toolpause.BMP",0,0); mSDLCursors[UI_CURSOR_TOOLMEDIAOPEN] = makeSDLCursorFromBMP("toolmediaopen.BMP",0,0); mSDLCursors[UI_CURSOR_PIPETTE] = makeSDLCursorFromBMP("lltoolpipette.BMP",2,28); + mSDLCursors[UI_CURSOR_TOOLSIT] = makeSDLCursorFromBMP("toolsit.BMP",20,15); + mSDLCursors[UI_CURSOR_TOOLBUY] = makeSDLCursorFromBMP("toolbuy.BMP",20,15); + mSDLCursors[UI_CURSOR_TOOLOPEN] = makeSDLCursorFromBMP("toolopen.BMP",20,15); if (getenv("LL_ATI_MOUSE_CURSOR_BUG") != NULL) { llinfos << "Disabling cursor updating due to LL_ATI_MOUSE_CURSOR_BUG" << llendl; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 5c7e9c8db2..47fde08a9d 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -74,6 +74,7 @@ set(viewer_SOURCE_FILES llagentpilot.cpp llagentui.cpp llagentwearables.cpp + llagentwearablesfetch.cpp llanimstatelabels.cpp llappearancemgr.cpp llappviewer.cpp @@ -318,7 +319,6 @@ set(viewer_SOURCE_FILES llpanellandmedia.cpp llpanellogin.cpp llpanelloginlistener.cpp - llpanellookinfo.cpp llpanelmaininventory.cpp llpanelmediasettingsgeneral.cpp llpanelmediasettingspermissions.cpp @@ -327,6 +327,7 @@ set(viewer_SOURCE_FILES llpanelnearbymedia.cpp llpanelobject.cpp llpanelobjectinventory.cpp + llpaneloutfitedit.cpp llpaneloutfitsinventory.cpp llpanelpeople.cpp llpanelpeoplemenus.cpp @@ -574,6 +575,7 @@ set(viewer_HEADER_FILES llagentpilot.h llagentui.h llagentwearables.h + llagentwearablesfetch.h llanimstatelabels.h llappearance.h llappearancemgr.h @@ -816,7 +818,6 @@ set(viewer_HEADER_FILES llpanellandmedia.h llpanellogin.h llpanelloginlistener.h - llpanellookinfo.h llpanelmaininventory.h llpanelmediasettingsgeneral.h llpanelmediasettingspermissions.h @@ -825,6 +826,7 @@ set(viewer_HEADER_FILES llpanelnearbymedia.h llpanelobject.h llpanelobjectinventory.h + llpaneloutfitedit.h llpaneloutfitsinventory.h llpanelpeople.h llpanelpeoplemenus.h diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index 879408d6e4..02c3dfc6e0 100644 --- a/indra/newview/English.lproj/InfoPlist.strings +++ b/indra/newview/English.lproj/InfoPlist.strings @@ -2,6 +2,6 @@ CFBundleName = "Second Life"; -CFBundleShortVersionString = "Second Life version 2.0.0.200030"; -CFBundleGetInfoString = "Second Life version 2.0.0.200030, Copyright 2004-2009 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version 2.0.0.203110"; +CFBundleGetInfoString = "Second Life version 2.0.0.203110, Copyright 2004-2009 Linden Research, Inc."; diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index 38ebb22b84..4cb01a0f33 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -32,7 +32,7 @@ </dict> </array> <key>CFBundleVersion</key> - <string>2.0.0.200030</string> + <string>2.0.0.203110</string> <key>CSResourcesFileMapped</key> <true/> </dict> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e62c4fbfc1..9cb25e2b42 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4620,7 +4620,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>1</integer> + <integer>0</integer> </map> <key>MediaShowOutsideParcel</key> <map> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 69d4bba16d..f434782977 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -3203,9 +3203,9 @@ bool LLAgent::teleportCore(bool is_local) // yet if the teleport will succeed. Look in // process_teleport_location_reply - // close the map and find panels so we can see our destination + // close the map panel so we can see our destination. + // we don't close search floater, see EXT-5840. LLFloaterReg::hideInstance("world_map"); - LLFloaterReg::hideInstance("search"); // hide land floater too - it'll be out of date LLFloaterReg::hideInstance("about_land"); diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 66f9e1117b..9638d0e94f 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -107,6 +107,8 @@ LLAgentCamera gAgentCamera; // LLAgentCamera() //----------------------------------------------------------------------------- LLAgentCamera::LLAgentCamera() : + mInitialized(false), + mDrawDistance( DEFAULT_FAR_PLANE ), mLookAt(NULL), @@ -142,7 +144,7 @@ LLAgentCamera::LLAgentCamera() : mSitCameraEnabled(FALSE), mCameraSmoothingLastPositionGlobal(), mCameraSmoothingLastPositionAgent(), - mCameraSmoothingStop(FALSE), + mCameraSmoothingStop(false), mCameraUpVector(LLVector3::z_axis), // default is straight up @@ -219,7 +221,7 @@ void LLAgentCamera::init() mCameraZoomFraction = 1.f; mTrackFocusObject = gSavedSettings.getBOOL("TrackFocusObject"); - mInitialized = TRUE; + mInitialized = true; } //----------------------------------------------------------------------------- @@ -1042,7 +1044,7 @@ void LLAgentCamera::cameraPanLeft(F32 meters) mFocusGlobal = mFocusTargetGlobal; // disable smoothing for camera pan, which causes some residents unhappiness - mCameraSmoothingStop = TRUE; + mCameraSmoothingStop = true; cameraZoomIn(1.f); updateFocusOffset(); @@ -1062,7 +1064,7 @@ void LLAgentCamera::cameraPanUp(F32 meters) mFocusGlobal = mFocusTargetGlobal; // disable smoothing for camera pan, which causes some residents unhappiness - mCameraSmoothingStop = TRUE; + mCameraSmoothingStop = true; cameraZoomIn(1.f); updateFocusOffset(); @@ -1364,7 +1366,8 @@ void LLAgentCamera::updateCamera() LLVector3d camera_pos_agent = camera_pos_global - agent_pos; // Sitting on what you're manipulating can cause camera jitter with smoothing. // This turns off smoothing while editing. -MG - mCameraSmoothingStop |= (BOOL)LLToolMgr::getInstance()->inBuildMode(); + bool in_build_mode = LLToolMgr::getInstance()->inBuildMode(); + mCameraSmoothingStop = mCameraSmoothingStop || in_build_mode; if (cameraThirdPerson() && !mCameraSmoothingStop) { @@ -1396,7 +1399,7 @@ void LLAgentCamera::updateCamera() mCameraSmoothingLastPositionGlobal = camera_pos_global; mCameraSmoothingLastPositionAgent = camera_pos_agent; - mCameraSmoothingStop = FALSE; + mCameraSmoothingStop = false; } diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h index 3ba24ef32b..5cbb1de6f4 100644 --- a/indra/newview/llagentcamera.h +++ b/indra/newview/llagentcamera.h @@ -82,7 +82,7 @@ public: void cleanup(); void setAvatarObject(LLVOAvatarSelf* avatar); private: - BOOL mInitialized; + bool mInitialized; //-------------------------------------------------------------------- @@ -151,7 +151,7 @@ private: LLVector3 mCameraVirtualPositionAgent; // Camera virtual position (target) before performing FOV zoom LLVector3d mCameraSmoothingLastPositionGlobal; LLVector3d mCameraSmoothingLastPositionAgent; - BOOL mCameraSmoothingStop; + bool mCameraSmoothingStop; LLVector3 mCameraLag; // Third person camera lag LLVector3 mCameraUpVector; // Camera's up direction in world coordinates (determines the 'roll' of the view) diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index dad7c7e705..0542e73bfd 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -36,6 +36,7 @@ #include "llaccordionctrltab.h" #include "llagent.h" #include "llagentcamera.h" +#include "llagentwearablesfetch.h" #include "llappearancemgr.h" #include "llcallbacklist.h" #include "llfloatercustomize.h" @@ -57,77 +58,6 @@ #include <boost/scoped_ptr.hpp> -//-------------------------------------------------------------------- -// Classes for fetching initial wearables data -//-------------------------------------------------------------------- -// Outfit folder fetching callback structure. -class LLInitialWearablesFetch : public LLInventoryFetchDescendentsObserver -{ -public: - LLInitialWearablesFetch() {} - ~LLInitialWearablesFetch(); - virtual void done(); - - struct InitialWearableData - { - EWearableType mType; - LLUUID mItemID; - LLUUID mAssetID; - InitialWearableData(EWearableType type, LLUUID& itemID, LLUUID& assetID) : - mType(type), - mItemID(itemID), - mAssetID(assetID) - {} - }; - - typedef std::vector<InitialWearableData> initial_wearable_data_vec_t; - initial_wearable_data_vec_t mCOFInitialWearables; // Wearables from the Current Outfit Folder - initial_wearable_data_vec_t mAgentInitialWearables; // Wearables from the old agent wearables msg - -protected: - void processWearablesMessage(); - void processContents(); -}; - -class LLLibraryOutfitsFetch : public LLInventoryFetchDescendentsObserver -{ -public: - enum ELibraryOutfitFetchStep { - LOFS_FOLDER = 0, - LOFS_OUTFITS, - LOFS_LIBRARY, - LOFS_IMPORTED, - LOFS_CONTENTS - }; - LLLibraryOutfitsFetch() : mCurrFetchStep(LOFS_FOLDER), mOutfitsPopulated(false) - { - mMyOutfitsID = LLUUID::null; - mClothingID = LLUUID::null; - mLibraryClothingID = LLUUID::null; - mImportedClothingID = LLUUID::null; - mImportedClothingName = "Imported Library Clothing"; - } - ~LLLibraryOutfitsFetch() {} - virtual void done(); - void doneIdle(); - LLUUID mMyOutfitsID; - void importedFolderFetch(); -protected: - void folderDone(void); - void outfitsDone(void); - void libraryDone(void); - void importedFolderDone(void); - void contentsDone(void); - enum ELibraryOutfitFetchStep mCurrFetchStep; - uuid_vec_t mLibraryClothingFolders; - uuid_vec_t mImportedClothingFolders; - bool mOutfitsPopulated; - LLUUID mClothingID; - LLUUID mLibraryClothingID; - LLUUID mImportedClothingID; - std::string mImportedClothingName; -}; - LLAgentWearables gAgentWearables; BOOL LLAgentWearables::mInitialWearablesUpdateReceived = FALSE; @@ -1014,8 +944,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs // Store initial wearables data until we know whether we have the current outfit folder or need to use the data. LLInitialWearablesFetch::InitialWearableData wearable_data(type, item_id, asset_id); // MULTI-WEARABLE: update - outfit->mAgentInitialWearables.push_back(wearable_data); - + outfit->add(wearable_data); } lldebugs << " " << LLWearableDictionary::getTypeLabel(type) << llendl; @@ -1595,7 +1524,6 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem } // Assumes existing wearables are not dirty. -// MULTI_WEARABLE: assumes one wearable per type. void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLWearable* >& wearables, BOOL remove) @@ -1853,16 +1781,24 @@ void LLAgentWearables::queryWearableCache() gAgentQueryManager.mWearablesCacheQueryID++; } -// MULTI_WEARABLE: need a way to specify by wearable rather than by type. // User has picked "remove from avatar" from a menu. // static -void LLAgentWearables::userRemoveWearable(EWearableType& type) +void LLAgentWearables::userRemoveWearable(const EWearableType &type, const U32 &index) +{ + if (!(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES)) //&& + //!((!gAgent.isTeen()) && (type==WT_UNDERPANTS || type==WT_UNDERSHIRT))) + { + gAgentWearables.removeWearable(type,false,index); + } +} + +//static +void LLAgentWearables::userRemoveWearablesOfType(const EWearableType &type) { - if (!(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR)) //&& + if (!(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES)) //&& //!((!gAgent.isTeen()) && (type==WT_UNDERPANTS || type==WT_UNDERSHIRT))) { - // MULTI_WEARABLE: fixed to 0th for now. - gAgentWearables.removeWearable(type,false,0); + gAgentWearables.removeWearable(type,true,0); } } @@ -2140,463 +2076,3 @@ void LLAgentWearables::populateMyOutfitsFolder(void) outfits->done(); } } - -void LLLibraryOutfitsFetch::done() -{ - // Delay this until idle() routine, since it's a heavy operation and - // we also can't have it run within notifyObservers. - doOnIdle(boost::bind(&LLLibraryOutfitsFetch::doneIdle,this)); - gInventory.removeObserver(this); // Prevent doOnIdle from being added twice. -} - -void LLLibraryOutfitsFetch::doneIdle() -{ - gInventory.addObserver(this); // Add this back in since it was taken out during ::done() - - switch (mCurrFetchStep) - { - case LOFS_FOLDER: - folderDone(); - mCurrFetchStep = LOFS_OUTFITS; - break; - case LOFS_OUTFITS: - outfitsDone(); - mCurrFetchStep = LOFS_LIBRARY; - break; - case LOFS_LIBRARY: - libraryDone(); - mCurrFetchStep = LOFS_IMPORTED; - break; - case LOFS_IMPORTED: - importedFolderDone(); - mCurrFetchStep = LOFS_CONTENTS; - break; - case LOFS_CONTENTS: - contentsDone(); - break; - default: - llwarns << "Got invalid state for outfit fetch: " << mCurrFetchStep << llendl; - mOutfitsPopulated = TRUE; - break; - } - - // We're completely done. Cleanup. - if (mOutfitsPopulated) - { - gInventory.removeObserver(this); - delete this; - return; - } -} - -void LLLibraryOutfitsFetch::folderDone(void) -{ - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t wearable_array; - gInventory.collectDescendents(mMyOutfitsID, cat_array, wearable_array, - LLInventoryModel::EXCLUDE_TRASH); - // Early out if we already have items in My Outfits. - if (cat_array.count() > 0 || wearable_array.count() > 0) - { - mOutfitsPopulated = true; - return; - } - - mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); - mLibraryClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); - - // If Library->Clothing->Initial Outfits exists, use that. - LLNameCategoryCollector matchFolderFunctor("Initial Outfits"); - gInventory.collectDescendentsIf(mLibraryClothingID, - cat_array, wearable_array, - LLInventoryModel::EXCLUDE_TRASH, - matchFolderFunctor); - if (cat_array.count() > 0) - { - const LLViewerInventoryCategory *cat = cat_array.get(0); - mLibraryClothingID = cat->getUUID(); - } - - mCompleteFolders.clear(); - - // Get the complete information on the items in the inventory. - uuid_vec_t folders; - folders.push_back(mClothingID); - folders.push_back(mLibraryClothingID); - fetchDescendents(folders); - if (isEverythingComplete()) - { - done(); - } -} - -void LLLibraryOutfitsFetch::outfitsDone(void) -{ - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t wearable_array; - uuid_vec_t folders; - - // Collect the contents of the Library's Clothing folder - gInventory.collectDescendents(mLibraryClothingID, cat_array, wearable_array, - LLInventoryModel::EXCLUDE_TRASH); - - llassert(cat_array.count() > 0); - for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); - iter != cat_array.end(); - ++iter) - { - const LLViewerInventoryCategory *cat = iter->get(); - - // Get the names and id's of every outfit in the library, skip "Ruth" - // because it's a low quality legacy outfit - if (cat->getName() != "Ruth") - { - // Get the name of every outfit in the library - folders.push_back(cat->getUUID()); - mLibraryClothingFolders.push_back(cat->getUUID()); - } - } - cat_array.clear(); - wearable_array.clear(); - - // Check if you already have an "Imported Library Clothing" folder - LLNameCategoryCollector matchFolderFunctor(mImportedClothingName); - gInventory.collectDescendentsIf(mClothingID, - cat_array, wearable_array, - LLInventoryModel::EXCLUDE_TRASH, - matchFolderFunctor); - if (cat_array.size() > 0) - { - const LLViewerInventoryCategory *cat = cat_array.get(0); - mImportedClothingID = cat->getUUID(); - } - - mCompleteFolders.clear(); - - fetchDescendents(folders); - if (isEverythingComplete()) - { - done(); - } -} - -class LLLibraryOutfitsCopyDone: public LLInventoryCallback -{ -public: - LLLibraryOutfitsCopyDone(LLLibraryOutfitsFetch * fetcher): - mFireCount(0), mLibraryOutfitsFetcher(fetcher) - { - } - - virtual ~LLLibraryOutfitsCopyDone() - { - if (!LLApp::isExiting() && mLibraryOutfitsFetcher) - { - gInventory.addObserver(mLibraryOutfitsFetcher); - mLibraryOutfitsFetcher->done(); - } - } - - /* virtual */ void fire(const LLUUID& inv_item) - { - mFireCount++; - } -private: - U32 mFireCount; - LLLibraryOutfitsFetch * mLibraryOutfitsFetcher; -}; - -// Copy the clothing folders from the library into the imported clothing folder -void LLLibraryOutfitsFetch::libraryDone(void) -{ - if (mImportedClothingID != LLUUID::null) - { - // Skip straight to fetching the contents of the imported folder - importedFolderFetch(); - return; - } - - // Remove observer; next autopopulation step will be triggered externally by LLLibraryOutfitsCopyDone. - gInventory.removeObserver(this); - - LLPointer<LLInventoryCallback> copy_waiter = new LLLibraryOutfitsCopyDone(this); - mImportedClothingID = gInventory.createNewCategory(mClothingID, - LLFolderType::FT_NONE, - mImportedClothingName); - // Copy each folder from library into clothing unless it already exists. - for (uuid_vec_t::const_iterator iter = mLibraryClothingFolders.begin(); - iter != mLibraryClothingFolders.end(); - ++iter) - { - const LLUUID& src_folder_id = (*iter); // Library clothing folder ID - const LLViewerInventoryCategory *cat = gInventory.getCategory(src_folder_id); - if (!cat) - { - llwarns << "Library folder import for uuid:" << src_folder_id << " failed to find folder." << llendl; - continue; - } - - if (!LLAppearanceMgr::getInstance()->getCanMakeFolderIntoOutfit(src_folder_id)) - { - llinfos << "Skipping non-outfit folder name:" << cat->getName() << llendl; - continue; - } - - // Don't copy the category if it already exists. - LLNameCategoryCollector matchFolderFunctor(cat->getName()); - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t wearable_array; - gInventory.collectDescendentsIf(mImportedClothingID, - cat_array, wearable_array, - LLInventoryModel::EXCLUDE_TRASH, - matchFolderFunctor); - if (cat_array.size() > 0) - { - continue; - } - - LLUUID dst_folder_id = gInventory.createNewCategory(mImportedClothingID, - LLFolderType::FT_NONE, - cat->getName()); - LLAppearanceMgr::getInstance()->shallowCopyCategoryContents(src_folder_id, dst_folder_id, copy_waiter); - } -} - -void LLLibraryOutfitsFetch::importedFolderFetch(void) -{ - // Fetch the contents of the Imported Clothing Folder - uuid_vec_t folders; - folders.push_back(mImportedClothingID); - - mCompleteFolders.clear(); - - fetchDescendents(folders); - if (isEverythingComplete()) - { - done(); - } -} - -void LLLibraryOutfitsFetch::importedFolderDone(void) -{ - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t wearable_array; - uuid_vec_t folders; - - // Collect the contents of the Imported Clothing folder - gInventory.collectDescendents(mImportedClothingID, cat_array, wearable_array, - LLInventoryModel::EXCLUDE_TRASH); - - for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); - iter != cat_array.end(); - ++iter) - { - const LLViewerInventoryCategory *cat = iter->get(); - - // Get the name of every imported outfit - folders.push_back(cat->getUUID()); - mImportedClothingFolders.push_back(cat->getUUID()); - } - - mCompleteFolders.clear(); - fetchDescendents(folders); - if (isEverythingComplete()) - { - done(); - } -} - -void LLLibraryOutfitsFetch::contentsDone(void) -{ - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t wearable_array; - - for (uuid_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin(); - folder_iter != mImportedClothingFolders.end(); - ++folder_iter) - { - const LLUUID &folder_id = (*folder_iter); - const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id); - if (!cat) - { - llwarns << "Library folder import for uuid:" << folder_id << " failed to find folder." << llendl; - continue; - } - - // First, make a folder in the My Outfits directory. - LLUUID new_outfit_folder_id = gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, cat->getName()); - - cat_array.clear(); - wearable_array.clear(); - // Collect the contents of each imported clothing folder, so we can create new outfit links for it - gInventory.collectDescendents(folder_id, cat_array, wearable_array, - LLInventoryModel::EXCLUDE_TRASH); - - for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin(); - wearable_iter != wearable_array.end(); - ++wearable_iter) - { - const LLViewerInventoryItem *item = wearable_iter->get(); - link_inventory_item(gAgent.getID(), - item->getLinkedUUID(), - new_outfit_folder_id, - item->getName(), - LLAssetType::AT_LINK, - NULL); - } - } - - mOutfitsPopulated = true; -} - -//-------------------------------------------------------------------- -// InitialWearablesFetch -// -// This grabs contents from the COF and processes them. -// The processing is handled in idle(), i.e. outside of done(), -// to avoid gInventory.notifyObservers recursion. -//-------------------------------------------------------------------- - -LLInitialWearablesFetch::~LLInitialWearablesFetch() -{ -} - -// virtual -void LLInitialWearablesFetch::done() -{ - // Delay processing the actual results of this so it's not handled within - // gInventory.notifyObservers. The results will be handled in the next - // idle tick instead. - gInventory.removeObserver(this); - doOnIdle(boost::bind(&LLInitialWearablesFetch::processContents,this)); -} - -void LLInitialWearablesFetch::processContents() -{ - // Fetch the wearable items from the Current Outfit Folder - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t wearable_array; - LLFindWearables is_wearable; - gInventory.collectDescendentsIf(mCompleteFolders.front(), cat_array, wearable_array, - LLInventoryModel::EXCLUDE_TRASH, is_wearable); - - LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); - if (wearable_array.count() > 0) - { - LLAppearanceMgr::instance().updateAppearanceFromCOF(); - } - else - { - // if we're constructing the COF from the wearables message, we don't have a proper outfit link - LLAppearanceMgr::instance().setOutfitDirty(true); - processWearablesMessage(); - } - delete this; -} - -class LLFetchAndLinkObserver: public LLInventoryFetchObserver -{ -public: - LLFetchAndLinkObserver(LLInventoryFetchObserver::item_ref_t& ids): - m_ids(ids), - LLInventoryFetchObserver(true) // retry for missing items - { - } - ~LLFetchAndLinkObserver() - { - } - virtual void done() - { - gInventory.removeObserver(this); - - // Link to all fetched items in COF. - LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy; - for (LLInventoryFetchObserver::item_ref_t::iterator it = m_ids.begin(); - it != m_ids.end(); - ++it) - { - LLUUID id = *it; - LLViewerInventoryItem *item = gInventory.getItem(*it); - if (!item) - { - llwarns << "fetch failed!" << llendl; - continue; - } - - link_inventory_item(gAgent.getID(), - item->getLinkedUUID(), - LLAppearanceMgr::instance().getCOF(), - item->getName(), - LLAssetType::AT_LINK, - link_waiter); - } - } -private: - LLInventoryFetchObserver::item_ref_t m_ids; -}; - -void LLInitialWearablesFetch::processWearablesMessage() -{ - if (!mAgentInitialWearables.empty()) // We have an empty current outfit folder, use the message data instead. - { - const LLUUID current_outfit_id = LLAppearanceMgr::instance().getCOF(); - LLInventoryFetchObserver::item_ref_t ids; - for (U8 i = 0; i < mAgentInitialWearables.size(); ++i) - { - // Populate the current outfit folder with links to the wearables passed in the message - InitialWearableData *wearable_data = new InitialWearableData(mAgentInitialWearables[i]); // This will be deleted in the callback. - - if (wearable_data->mAssetID.notNull()) - { - ids.push_back(wearable_data->mItemID); - } - else - { - llinfos << "Invalid wearable, type " << wearable_data->mType << " itemID " - << wearable_data->mItemID << " assetID " << wearable_data->mAssetID << llendl; - delete wearable_data; - } - } - - // Add all current attachments to the requested items as well. - if (isAgentAvatarValid()) - { - for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); - iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (!attachment) continue; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - LLViewerObject* attached_object = (*attachment_iter); - if (!attached_object) continue; - const LLUUID& item_id = attached_object->getItemID(); - if (item_id.isNull()) continue; - ids.push_back(item_id); - } - } - } - - // Need to fetch the inventory items for ids, then create links to them after they arrive. - LLFetchAndLinkObserver *fetcher = new LLFetchAndLinkObserver(ids); - fetcher->fetchItems(ids); - // If no items to be fetched, done will never be triggered. - // TODO: Change LLInventoryFetchObserver::fetchItems to trigger done() on this condition. - if (fetcher->isEverythingComplete()) - { - fetcher->done(); - } - else - { - gInventory.addObserver(fetcher); - } - } - else - { - LL_WARNS("Wearables") << "No current outfit folder items found and no initial wearables fallback message received." << LL_ENDL; - } -} - - diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 652ffd4587..9f8aadeae7 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -193,8 +193,8 @@ public: // Static UI hooks //-------------------------------------------------------------------- public: - // MULTI-WEARABLE: assuming one wearable per type. Need upstream changes. - static void userRemoveWearable(EWearableType& type); + static void userRemoveWearable(const EWearableType &type, const U32 &index); + static void userRemoveWearablesOfType(const EWearableType &type); static void userRemoveAllClothes(); typedef std::vector<LLViewerObject*> llvo_vec_t; diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp new file mode 100644 index 0000000000..45274a8e2c --- /dev/null +++ b/indra/newview/llagentwearablesfetch.cpp @@ -0,0 +1,516 @@ +/** + * @file llagentwearablesfetch.cpp + * @brief LLAgentWearblesFetch class implementation + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llagentwearablesfetch.h" + +#include "llagent.h" +#include "llagentwearables.h" +#include "llappearancemgr.h" +#include "llinventoryfunctions.h" +#include "llvoavatarself.h" + +LLInitialWearablesFetch::LLInitialWearablesFetch() +{ +} + +LLInitialWearablesFetch::~LLInitialWearablesFetch() +{ +} + +// virtual +void LLInitialWearablesFetch::done() +{ + // Delay processing the actual results of this so it's not handled within + // gInventory.notifyObservers. The results will be handled in the next + // idle tick instead. + gInventory.removeObserver(this); + doOnIdle(boost::bind(&LLInitialWearablesFetch::processContents,this)); +} + +void LLInitialWearablesFetch::add(InitialWearableData &data) + +{ + mAgentInitialWearables.push_back(data); +} + +void LLInitialWearablesFetch::processContents() +{ + // Fetch the wearable items from the Current Outfit Folder + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + LLFindWearables is_wearable; + gInventory.collectDescendentsIf(mCompleteFolders.front(), cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH, is_wearable); + + LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); + if (wearable_array.count() > 0) + { + LLAppearanceMgr::instance().updateAppearanceFromCOF(); + } + else + { + // if we're constructing the COF from the wearables message, we don't have a proper outfit link + LLAppearanceMgr::instance().setOutfitDirty(true); + processWearablesMessage(); + } + delete this; +} + +class LLFetchAndLinkObserver: public LLInventoryFetchObserver +{ +public: + LLFetchAndLinkObserver(LLInventoryFetchObserver::item_ref_t& ids): + m_ids(ids), + LLInventoryFetchObserver(true) // retry for missing items + { + } + ~LLFetchAndLinkObserver() + { + } + virtual void done() + { + gInventory.removeObserver(this); + + // Link to all fetched items in COF. + LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy; + for (LLInventoryFetchObserver::item_ref_t::iterator it = m_ids.begin(); + it != m_ids.end(); + ++it) + { + LLUUID id = *it; + LLViewerInventoryItem *item = gInventory.getItem(*it); + if (!item) + { + llwarns << "fetch failed!" << llendl; + continue; + } + + link_inventory_item(gAgent.getID(), + item->getLinkedUUID(), + LLAppearanceMgr::instance().getCOF(), + item->getName(), + LLAssetType::AT_LINK, + link_waiter); + } + } +private: + LLInventoryFetchObserver::item_ref_t m_ids; +}; + +void LLInitialWearablesFetch::processWearablesMessage() +{ + if (!mAgentInitialWearables.empty()) // We have an empty current outfit folder, use the message data instead. + { + const LLUUID current_outfit_id = LLAppearanceMgr::instance().getCOF(); + LLInventoryFetchObserver::item_ref_t ids; + for (U8 i = 0; i < mAgentInitialWearables.size(); ++i) + { + // Populate the current outfit folder with links to the wearables passed in the message + InitialWearableData *wearable_data = new InitialWearableData(mAgentInitialWearables[i]); // This will be deleted in the callback. + + if (wearable_data->mAssetID.notNull()) + { + ids.push_back(wearable_data->mItemID); + } + else + { + llinfos << "Invalid wearable, type " << wearable_data->mType << " itemID " + << wearable_data->mItemID << " assetID " << wearable_data->mAssetID << llendl; + delete wearable_data; + } + } + + // Add all current attachments to the requested items as well. + if (isAgentAvatarValid()) + { + for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); + iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (!attachment) continue; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject* attached_object = (*attachment_iter); + if (!attached_object) continue; + const LLUUID& item_id = attached_object->getItemID(); + if (item_id.isNull()) continue; + ids.push_back(item_id); + } + } + } + + // Need to fetch the inventory items for ids, then create links to them after they arrive. + LLFetchAndLinkObserver *fetcher = new LLFetchAndLinkObserver(ids); + fetcher->fetchItems(ids); + // If no items to be fetched, done will never be triggered. + // TODO: Change LLInventoryFetchObserver::fetchItems to trigger done() on this condition. + if (fetcher->isEverythingComplete()) + { + fetcher->done(); + } + else + { + gInventory.addObserver(fetcher); + } + } + else + { + LL_WARNS("Wearables") << "No current outfit folder items found and no initial wearables fallback message received." << LL_ENDL; + } +} + +LLLibraryOutfitsFetch::LLLibraryOutfitsFetch() : + mCurrFetchStep(LOFS_FOLDER), + mOutfitsPopulated(false) +{ + mMyOutfitsID = LLUUID::null; + mClothingID = LLUUID::null; + mLibraryClothingID = LLUUID::null; + mImportedClothingID = LLUUID::null; + mImportedClothingName = "Imported Library Clothing"; +} + +LLLibraryOutfitsFetch::~LLLibraryOutfitsFetch() +{ +} + +void LLLibraryOutfitsFetch::done() +{ + // Delay this until idle() routine, since it's a heavy operation and + // we also can't have it run within notifyObservers. + doOnIdle(boost::bind(&LLLibraryOutfitsFetch::doneIdle,this)); + gInventory.removeObserver(this); // Prevent doOnIdle from being added twice. +} + +void LLLibraryOutfitsFetch::doneIdle() +{ + gInventory.addObserver(this); // Add this back in since it was taken out during ::done() + + switch (mCurrFetchStep) + { + case LOFS_FOLDER: + folderDone(); + mCurrFetchStep = LOFS_OUTFITS; + break; + case LOFS_OUTFITS: + outfitsDone(); + mCurrFetchStep = LOFS_LIBRARY; + break; + case LOFS_LIBRARY: + libraryDone(); + mCurrFetchStep = LOFS_IMPORTED; + break; + case LOFS_IMPORTED: + importedFolderDone(); + mCurrFetchStep = LOFS_CONTENTS; + break; + case LOFS_CONTENTS: + contentsDone(); + break; + default: + llwarns << "Got invalid state for outfit fetch: " << mCurrFetchStep << llendl; + mOutfitsPopulated = TRUE; + break; + } + + // We're completely done. Cleanup. + if (mOutfitsPopulated) + { + gInventory.removeObserver(this); + delete this; + return; + } +} + +void LLLibraryOutfitsFetch::folderDone(void) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + gInventory.collectDescendents(mMyOutfitsID, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + // Early out if we already have items in My Outfits. + if (cat_array.count() > 0 || wearable_array.count() > 0) + { + mOutfitsPopulated = true; + return; + } + + mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); + mLibraryClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); + + // If Library->Clothing->Initial Outfits exists, use that. + LLNameCategoryCollector matchFolderFunctor("Initial Outfits"); + gInventory.collectDescendentsIf(mLibraryClothingID, + cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH, + matchFolderFunctor); + if (cat_array.count() > 0) + { + const LLViewerInventoryCategory *cat = cat_array.get(0); + mLibraryClothingID = cat->getUUID(); + } + + mCompleteFolders.clear(); + + // Get the complete information on the items in the inventory. + uuid_vec_t folders; + folders.push_back(mClothingID); + folders.push_back(mLibraryClothingID); + fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } +} + +void LLLibraryOutfitsFetch::outfitsDone(void) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + uuid_vec_t folders; + + // Collect the contents of the Library's Clothing folder + gInventory.collectDescendents(mLibraryClothingID, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + + llassert(cat_array.count() > 0); + for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); + iter != cat_array.end(); + ++iter) + { + const LLViewerInventoryCategory *cat = iter->get(); + + // Get the names and id's of every outfit in the library, skip "Ruth" + // because it's a low quality legacy outfit + if (cat->getName() != "Ruth") + { + // Get the name of every outfit in the library + folders.push_back(cat->getUUID()); + mLibraryClothingFolders.push_back(cat->getUUID()); + } + } + cat_array.clear(); + wearable_array.clear(); + + // Check if you already have an "Imported Library Clothing" folder + LLNameCategoryCollector matchFolderFunctor(mImportedClothingName); + gInventory.collectDescendentsIf(mClothingID, + cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH, + matchFolderFunctor); + if (cat_array.size() > 0) + { + const LLViewerInventoryCategory *cat = cat_array.get(0); + mImportedClothingID = cat->getUUID(); + } + + mCompleteFolders.clear(); + + fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } +} + +class LLLibraryOutfitsCopyDone: public LLInventoryCallback +{ +public: + LLLibraryOutfitsCopyDone(LLLibraryOutfitsFetch * fetcher): + mFireCount(0), mLibraryOutfitsFetcher(fetcher) + { + } + + virtual ~LLLibraryOutfitsCopyDone() + { + if (!LLApp::isExiting() && mLibraryOutfitsFetcher) + { + gInventory.addObserver(mLibraryOutfitsFetcher); + mLibraryOutfitsFetcher->done(); + } + } + + /* virtual */ void fire(const LLUUID& inv_item) + { + mFireCount++; + } +private: + U32 mFireCount; + LLLibraryOutfitsFetch * mLibraryOutfitsFetcher; +}; + +// Copy the clothing folders from the library into the imported clothing folder +void LLLibraryOutfitsFetch::libraryDone(void) +{ + if (mImportedClothingID != LLUUID::null) + { + // Skip straight to fetching the contents of the imported folder + importedFolderFetch(); + return; + } + + // Remove observer; next autopopulation step will be triggered externally by LLLibraryOutfitsCopyDone. + gInventory.removeObserver(this); + + LLPointer<LLInventoryCallback> copy_waiter = new LLLibraryOutfitsCopyDone(this); + mImportedClothingID = gInventory.createNewCategory(mClothingID, + LLFolderType::FT_NONE, + mImportedClothingName); + // Copy each folder from library into clothing unless it already exists. + for (uuid_vec_t::const_iterator iter = mLibraryClothingFolders.begin(); + iter != mLibraryClothingFolders.end(); + ++iter) + { + const LLUUID& src_folder_id = (*iter); // Library clothing folder ID + const LLViewerInventoryCategory *cat = gInventory.getCategory(src_folder_id); + if (!cat) + { + llwarns << "Library folder import for uuid:" << src_folder_id << " failed to find folder." << llendl; + continue; + } + + if (!LLAppearanceMgr::getInstance()->getCanMakeFolderIntoOutfit(src_folder_id)) + { + llinfos << "Skipping non-outfit folder name:" << cat->getName() << llendl; + continue; + } + + // Don't copy the category if it already exists. + LLNameCategoryCollector matchFolderFunctor(cat->getName()); + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + gInventory.collectDescendentsIf(mImportedClothingID, + cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH, + matchFolderFunctor); + if (cat_array.size() > 0) + { + continue; + } + + LLUUID dst_folder_id = gInventory.createNewCategory(mImportedClothingID, + LLFolderType::FT_NONE, + cat->getName()); + LLAppearanceMgr::getInstance()->shallowCopyCategoryContents(src_folder_id, dst_folder_id, copy_waiter); + } +} + +void LLLibraryOutfitsFetch::importedFolderFetch(void) +{ + // Fetch the contents of the Imported Clothing Folder + uuid_vec_t folders; + folders.push_back(mImportedClothingID); + + mCompleteFolders.clear(); + + fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } +} + +void LLLibraryOutfitsFetch::importedFolderDone(void) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + uuid_vec_t folders; + + // Collect the contents of the Imported Clothing folder + gInventory.collectDescendents(mImportedClothingID, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + + for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); + iter != cat_array.end(); + ++iter) + { + const LLViewerInventoryCategory *cat = iter->get(); + + // Get the name of every imported outfit + folders.push_back(cat->getUUID()); + mImportedClothingFolders.push_back(cat->getUUID()); + } + + mCompleteFolders.clear(); + fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } +} + +void LLLibraryOutfitsFetch::contentsDone(void) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + + for (uuid_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin(); + folder_iter != mImportedClothingFolders.end(); + ++folder_iter) + { + const LLUUID &folder_id = (*folder_iter); + const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id); + if (!cat) + { + llwarns << "Library folder import for uuid:" << folder_id << " failed to find folder." << llendl; + continue; + } + + // First, make a folder in the My Outfits directory. + LLUUID new_outfit_folder_id = gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, cat->getName()); + + cat_array.clear(); + wearable_array.clear(); + // Collect the contents of each imported clothing folder, so we can create new outfit links for it + gInventory.collectDescendents(folder_id, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + + for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin(); + wearable_iter != wearable_array.end(); + ++wearable_iter) + { + const LLViewerInventoryItem *item = wearable_iter->get(); + link_inventory_item(gAgent.getID(), + item->getLinkedUUID(), + new_outfit_folder_id, + item->getName(), + LLAssetType::AT_LINK, + NULL); + } + } + + mOutfitsPopulated = true; +} + diff --git a/indra/newview/llagentwearablesfetch.h b/indra/newview/llagentwearablesfetch.h new file mode 100644 index 0000000000..72063114b8 --- /dev/null +++ b/indra/newview/llagentwearablesfetch.h @@ -0,0 +1,118 @@ +/** + * @file llagentwearablesinitialfetch.h + * @brief LLAgentWearablesInitialFetch class header file + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLAGENTWEARABLESINITIALFETCH_H +#define LL_LLAGENTWEARABLESINITIALFETCH_H + +#include "llinventoryobserver.h" +#include "llwearabledictionary.h" +#include "lluuid.h" + +//-------------------------------------------------------------------- +// InitialWearablesFetch +// +// This grabs contents from the COF and processes them. +// The processing is handled in idle(), i.e. outside of done(), +// to avoid gInventory.notifyObservers recursion. +//-------------------------------------------------------------------- +class LLInitialWearablesFetch : public LLInventoryFetchDescendentsObserver +{ +public: + LLInitialWearablesFetch(); + ~LLInitialWearablesFetch(); + virtual void done(); + + struct InitialWearableData + { + EWearableType mType; + LLUUID mItemID; + LLUUID mAssetID; + InitialWearableData(EWearableType type, LLUUID& itemID, LLUUID& assetID) : + mType(type), + mItemID(itemID), + mAssetID(assetID) + {} + }; + + void add(InitialWearableData &data); + +protected: + void processWearablesMessage(); + void processContents(); + +private: + typedef std::vector<InitialWearableData> initial_wearable_data_vec_t; + initial_wearable_data_vec_t mAgentInitialWearables; // Wearables from the old agent wearables msg +}; + +//-------------------------------------------------------------------- +// InitialWearablesFetch +// +// This grabs outfits from the Library and copies those over to the user's +// outfits folder, typically during first-ever login. +//-------------------------------------------------------------------- +class LLLibraryOutfitsFetch : public LLInventoryFetchDescendentsObserver +{ +public: + enum ELibraryOutfitFetchStep + { + LOFS_FOLDER = 0, + LOFS_OUTFITS, + LOFS_LIBRARY, + LOFS_IMPORTED, + LOFS_CONTENTS + }; + + LLLibraryOutfitsFetch(); + ~LLLibraryOutfitsFetch(); + + virtual void done(); + void doneIdle(); + LLUUID mMyOutfitsID; + void importedFolderFetch(); +protected: + void folderDone(void); + void outfitsDone(void); + void libraryDone(void); + void importedFolderDone(void); + void contentsDone(void); + enum ELibraryOutfitFetchStep mCurrFetchStep; + uuid_vec_t mLibraryClothingFolders; + uuid_vec_t mImportedClothingFolders; + bool mOutfitsPopulated; + LLUUID mClothingID; + LLUUID mLibraryClothingID; + LLUUID mImportedClothingID; + std::string mImportedClothingName; +}; + +#endif // LL_AGENTWEARABLESINITIALFETCH_H diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 4075ad8ee2..c85c72837c 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -161,6 +161,14 @@ void LLAvatarActions::offerTeleport(const LLUUID& invitee) if (invitee.isNull()) return; + //waiting until Name Cache gets updated with corresponding avatar name + std::string just_to_request_name; + if (!gCacheName->getFullName(invitee, just_to_request_name)) + { + gCacheName->get(invitee, FALSE, boost::bind((void (*)(const LLUUID&)) &LLAvatarActions::offerTeleport, invitee)); + return; + } + LLDynamicArray<LLUUID> ids; ids.push_back(invitee); offerTeleport(ids); @@ -434,6 +442,20 @@ void LLAvatarActions::toggleBlock(const LLUUID& id) LLMuteList::getInstance()->add(mute); } } +// static +bool LLAvatarActions::canOfferTeleport(const LLUUID& id) +{ + // First use LLAvatarTracker::isBuddy() + // If LLAvatarTracker::instance().isBuddyOnline function only is used + // then for avatars that are online and not a friend it will return false. + // But we should give an ability to offer a teleport for such avatars. + if(LLAvatarTracker::instance().isBuddy(id)) + { + return LLAvatarTracker::instance().isBuddyOnline(id); + } + + return true; +} void LLAvatarActions::inviteToGroup(const LLUUID& id) { diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index c573144a33..9d8b4b4e23 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -171,6 +171,12 @@ public: */ static void csr(const LLUUID& id, std::string name); + /** + * Checks whether can offer teleport to the avatar + * Can't offer only for offline friends + */ + static bool canOfferTeleport(const LLUUID& id); + private: static bool callbackAddFriend(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index e8abdd32ec..6ec62a61a0 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -334,6 +334,17 @@ boost::signals2::connection LLAvatarList::setItemDoubleClickCallback(const mouse return mItemDoubleClickSignal.connect(cb); } +//virtual +S32 LLAvatarList::notifyParent(const LLSD& info) +{ + if (info.has("sort") && &NAME_COMPARATOR == mItemComparator) + { + sort(); + return 1; + } + return LLFlatListView::notifyParent(info); +} + void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos) { LLAvatarListItem* item = new LLAvatarListItem(); diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index c3f79dcb3a..5a55975413 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -96,6 +96,8 @@ public: boost::signals2::connection setItemDoubleClickCallback(const mouse_signal_t::slot_type& cb); + virtual S32 notifyParent(const LLSD& info); + protected: void refresh(); diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 9645e75e60..44f88cce29 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -119,8 +119,9 @@ S32 LLAvatarListItem::notifyParent(const LLSD& info) if (info.has("visibility_changed")) { updateChildren(); + return 1; } - return 0; + return LLPanel::notifyParent(info); } void LLAvatarListItem::onMouseEnter(S32 x, S32 y, MASK mask) @@ -334,6 +335,9 @@ void LLAvatarListItem::onNameCache(const std::string& first_name, const std::str { std::string name = first_name + " " + last_name; setName(name); + + //requesting the list to resort + notifyParent(LLSD().with("sort", LLSD())); } // Convert given number of seconds to a string like "23 minutes", "15 hours" or "3 years", diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 34cb6fd2eb..41bee540fc 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -160,10 +160,6 @@ LLBottomTray::LLBottomTray(const LLSD&) LLUICtrlFactory::getInstance()->buildPanel(this,"panel_bottomtray.xml"); - mChicletPanel = getChild<LLChicletPanel>("chiclet_list"); - - mChicletPanel->setChicletClickedCallback(boost::bind(&LLBottomTray::onChicletClick,this,_1)); - LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraPresets, _2)); //this is to fix a crash that occurs because LLBottomTray is a singleton @@ -171,8 +167,6 @@ LLBottomTray::LLBottomTray(const LLSD&) //destroyed LLBottomTray requires some subsystems that are long gone //LLUI::getRootView()->addChild(this); - initStateProcessedObjectMap(); - // Necessary for focus movement among child controls setFocusRoot(TRUE); @@ -371,6 +365,23 @@ void LLBottomTray::setVisible(BOOL visible) gFloaterView->setSnapOffsetBottom(0); } +S32 LLBottomTray::notifyParent(const LLSD& info) +{ + if(info.has("well_empty")) // implementation of EXT-3397 + { + const std::string chiclet_name = info["well_name"]; + + // only "im_well" or "notification_well" names are expected. + // They are set in panel_bottomtray.xml in <chiclet_im_well> & <chiclet_notification> + llassert("im_well" == chiclet_name || "notification_well" == chiclet_name); + + BOOL should_be_visible = !info["well_empty"]; + showWellButton("im_well" == chiclet_name ? RS_IM_WELL : RS_NOTIFICATION_WELL, should_be_visible); + return 1; + } + return LLPanel::notifyParent(info); +} + void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask) { // We should show BottomTrayContextMenu in last turn @@ -487,6 +498,15 @@ BOOL LLBottomTray::postBuild() mNearbyChatBar->getChatBox()->setContextMenu(NULL); + mChicletPanel = getChild<LLChicletPanel>("chiclet_list"); + mChicletPanel->setChicletClickedCallback(boost::bind(&LLBottomTray::onChicletClick,this,_1)); + + initStateProcessedObjectMap(); + + // update wells visibility: + showWellButton(RS_IM_WELL, !LLIMWellWindow::getInstance()->isWindowEmpty()); + showWellButton(RS_NOTIFICATION_WELL, !LLNotificationWellWindow::getInstance()->isWindowEmpty()); + return TRUE; } @@ -855,6 +875,7 @@ void LLBottomTray::processWidthIncreased(S32 delta_width) bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* available_width) { lldebugs << "Trying to show object type: " << shown_object_type << llendl; + llassert(mStateProcessedObjectMap[shown_object_type] != NULL); LLPanel* panel = mStateProcessedObjectMap[shown_object_type]; if (NULL == panel) @@ -886,6 +907,7 @@ bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* availa void LLBottomTray::processHideButton(EResizeState processed_object_type, S32* required_width, S32* buttons_freed_width) { lldebugs << "Trying to hide object type: " << processed_object_type << llendl; + llassert(mStateProcessedObjectMap[processed_object_type] != NULL); LLPanel* panel = mStateProcessedObjectMap[processed_object_type]; if (NULL == panel) @@ -963,6 +985,7 @@ void LLBottomTray::processShrinkButtons(S32* required_width, S32* buttons_freed_ void LLBottomTray::processShrinkButton(EResizeState processed_object_type, S32* required_width) { + llassert(mStateProcessedObjectMap[processed_object_type] != NULL); LLPanel* panel = mStateProcessedObjectMap[processed_object_type]; if (NULL == panel) { @@ -1046,6 +1069,7 @@ void LLBottomTray::processExtendButtons(S32* available_width) void LLBottomTray::processExtendButton(EResizeState processed_object_type, S32* available_width) { + llassert(mStateProcessedObjectMap[processed_object_type] != NULL); LLPanel* panel = mStateProcessedObjectMap[processed_object_type]; if (NULL == panel) { @@ -1126,6 +1150,7 @@ void LLBottomTray::initStateProcessedObjectMap() void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool visible) { + llassert(mStateProcessedObjectMap[shown_object_type] != NULL); LLPanel* panel = mStateProcessedObjectMap[shown_object_type]; if (NULL == panel) { @@ -1264,4 +1289,29 @@ bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible return is_set; } +void LLBottomTray::showWellButton(EResizeState object_type, bool visible) +{ + llassert( ((RS_NOTIFICATION_WELL | RS_IM_WELL) & object_type) == object_type ); + + const std::string panel_name = RS_IM_WELL == object_type ? "im_well_panel" : "notification_well_panel"; + + LLView * panel = getChild<LLView>(panel_name); + + // if necessary visibility is set nothing to do here + if (panel->getVisible() == (BOOL)visible) return; + + S32 panel_width = panel->getRect().getWidth(); + panel->setVisible(visible); + + if (visible) + { + // method assumes that input param is a negative value + processWidthDecreased(-panel_width); + } + else + { + processWidthIncreased(panel_width); + } +} + //EOF diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 18c14e5e19..3c45777645 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -83,6 +83,8 @@ public: virtual void setVisible(BOOL visible); + /*virtual*/ S32 notifyParent(const LLSD& info); + // Implements LLVoiceClientStatusObserver::onChange() to enable the speak // button when voice is available /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); @@ -116,6 +118,8 @@ private: , RS_BUTTON_MOVEMENT = 0x0010 , RS_BUTTON_GESTURES = 0x0020 , RS_BUTTON_SPEAK = 0x0040 + , RS_IM_WELL = 0x0080 + , RS_NOTIFICATION_WELL = 0x0100 /** * Specifies buttons which can be hidden when bottom tray is shrunk. @@ -184,6 +188,15 @@ private: */ bool setVisibleAndFitWidths(EResizeState object_type, bool visible); + /** + * Shows/hides panel with specified well button (IM or Notification) + * + * @param[in] object_type - type of well button to be processed. + * Must be one of RS_IM_WELL or RS_NOTIFICATION_WELL. + * @param[in] visible - flag specified whether button should be shown or hidden. + */ + void showWellButton(EResizeState object_type, bool visible); + MASK mResizeState; typedef std::map<EResizeState, LLPanel*> state_object_map_t; diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index f5faeca126..71e7ae7061 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -447,7 +447,6 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) : LLUICtrl(p), mMessageHeaderFilename(p.message_header), mMessageSeparatorFilename(p.message_separator), - mMessagePlaintextSeparatorFilename(p.message_plaintext_separator), mLeftTextPad(p.left_text_pad), mRightTextPad(p.right_text_pad), mLeftWidgetPad(p.left_widget_pad), @@ -535,12 +534,6 @@ LLView* LLChatHistory::getSeparator() return separator; } -LLView* LLChatHistory::getPlaintextSeparator() -{ - LLPanel* separator = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>(mMessagePlaintextSeparatorFilename, NULL, LLPanel::child_registry_t::instance()); - return separator; -} - LLView* LLChatHistory::getHeader(const LLChat& chat,const LLStyle::Params& style_params) { LLChatHistoryHeader* header = LLChatHistoryHeader::createInstance(mMessageHeaderFilename); @@ -639,16 +632,6 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (use_plain_text_chat_history) { - // append plaintext separator - LLView* separator = getPlaintextSeparator(); - LLInlineViewSegment::Params p; - p.force_newline = true; - p.left_pad = mLeftWidgetPad; - p.right_pad = mRightWidgetPad; - p.view = separator; - //mEditor->appendWidget(p, "\n", false); // TODO: this is absolute minimal fix for EXT-3818 because it's late for 2.0 - mEditor->appendWidget(p, "", false); // This should be properly fixed in 2.1 - mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, style_params); if (utf8str_trim(chat.mFromName).size() != 0) @@ -752,7 +735,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (notification != NULL) { LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel( - notification); + notification, chat.mSessionID); //we can't set follows in xml since it broke toasts behavior notify_box->setFollowsLeft(); notify_box->setFollowsRight(); diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index dfe5ea98e6..950b32861b 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -47,8 +47,6 @@ class LLChatHistory : public LLUICtrl Optional<std::string> message_header; //Message separator filename Optional<std::string> message_separator; - //Message plaintext separator filename - Optional<std::string> message_plaintext_separator; //Text left padding from the scroll rect Optional<S32> left_text_pad; //Text right padding from the scroll rect @@ -71,7 +69,6 @@ class LLChatHistory : public LLUICtrl Params() : message_header("message_header"), message_separator("message_separator"), - message_plaintext_separator("message_plaintext_separator"), left_text_pad("left_text_pad"), right_text_pad("right_text_pad"), left_widget_pad("left_widget_pad"), @@ -100,11 +97,6 @@ class LLChatHistory : public LLUICtrl */ LLView* getSeparator(); /** - * Builds a message plaintext separator. - * @return pointer to LLView separator object. - */ - LLView* getPlaintextSeparator(); - /** * Builds a message header. * @return pointer to LLView header object. */ @@ -141,7 +133,6 @@ class LLChatHistory : public LLUICtrl std::string mMessageHeaderFilename; std::string mMessageSeparatorFilename; - std::string mMessagePlaintextSeparatorFilename; S32 mLeftTextPad; S32 mRightTextPad; diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 1f92686a43..e39384b7b2 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -229,6 +229,11 @@ void LLSysWellChiclet::setNewMessagesState(bool new_messages) void LLSysWellChiclet::updateWidget(bool is_window_empty) { mButton->setEnabled(!is_window_empty); + + LLSD params; + params["well_empty"] = is_window_empty; + params["well_name"] = getName(); + notifyParent(params); } // virtual BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index 362010d65a..149ba2478d 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -112,13 +112,12 @@ private: }; LLExpandableTextBox::LLTextBoxEx::Params::Params() -: more_label("more_label") { } LLExpandableTextBox::LLTextBoxEx::LLTextBoxEx(const Params& p) : LLTextEditor(p), - mExpanderLabel(p.more_label), + mExpanderLabel(p.label), mExpanderVisible(false) { setIsChrome(TRUE); diff --git a/indra/newview/llexpandabletextbox.h b/indra/newview/llexpandabletextbox.h index 9d4a8aef76..5872592fae 100644 --- a/indra/newview/llexpandabletextbox.h +++ b/indra/newview/llexpandabletextbox.h @@ -54,7 +54,6 @@ protected: public: struct Params : public LLInitParam::Block<Params, LLTextEditor::Params> { - Mandatory<std::string> more_label; Params(); }; diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp index 8c7899af3e..18db60705b 100644 --- a/indra/newview/llfloateravatartextures.cpp +++ b/indra/newview/llfloateravatartextures.cpp @@ -31,15 +31,14 @@ */ #include "llviewerprecompiledheaders.h" - #include "llfloateravatartextures.h" +#include "llagent.h" +#include "llagentwearables.h" #include "lltexturectrl.h" - #include "lluictrlfactory.h" #include "llviewerobjectlist.h" #include "llvoavatar.h" -#include "llagentwearables.h" using namespace LLVOAvatarDefines; @@ -75,7 +74,6 @@ void LLFloaterAvatarTextures::draw() LLFloater::draw(); } -#if !LL_RELEASE_FOR_DOWNLOAD static void update_texture_ctrl(LLVOAvatar* avatarp, LLTextureCtrl* ctrl, ETextureIndex te) @@ -132,72 +130,68 @@ static LLVOAvatar* find_avatar(const LLUUID& id) void LLFloaterAvatarTextures::refresh() { - LLVOAvatar *avatarp = find_avatar(mID); - if (avatarp) + if (gAgent.isGodlike()) { - std::string fullname; - if (gCacheName->getFullName(avatarp->getID(), fullname)) + LLVOAvatar *avatarp = find_avatar(mID); + if (avatarp) { - setTitle(mTitle + ": " + fullname); + std::string fullname; + if (gCacheName->getFullName(avatarp->getID(), fullname)) + { + setTitle(mTitle + ": " + fullname); + } + for (U32 i=0; i < TEX_NUM_INDICES; i++) + { + update_texture_ctrl(avatarp, mTextures[i], ETextureIndex(i)); + } } - for (U32 i=0; i < TEX_NUM_INDICES; i++) + else { - update_texture_ctrl(avatarp, mTextures[i], ETextureIndex(i)); + setTitle(mTitle + ": " + getString("InvalidAvatar") + " (" + mID.asString() + ")"); } } - else - { - setTitle(mTitle + ": " + getString("InvalidAvatar") + " (" + mID.asString() + ")"); - } } -#else - -void LLFloaterAvatarTextures::refresh() -{ -} - -#endif - // static void LLFloaterAvatarTextures::onClickDump(void* data) { -#if !LL_RELEASE_FOR_DOWNLOAD - LLFloaterAvatarTextures* self = (LLFloaterAvatarTextures*)data; - LLVOAvatar* avatarp = find_avatar(self->mID); - if (!avatarp) return; - - for (S32 i = 0; i < avatarp->getNumTEs(); i++) + if (gAgent.isGodlike()) { - const LLTextureEntry* te = avatarp->getTE(i); - if (!te) continue; + LLFloaterAvatarTextures* self = (LLFloaterAvatarTextures*)data; + LLVOAvatar* avatarp = find_avatar(self->mID); + if (!avatarp) return; - if (LLVOAvatar::isIndexLocalTexture((ETextureIndex)i)) + for (S32 i = 0; i < avatarp->getNumTEs(); i++) { - LLUUID id = IMG_DEFAULT_AVATAR; - EWearableType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType((ETextureIndex)i); - LLWearable *wearable = gAgentWearables.getWearable(wearable_type, 0); - if (wearable) + const LLTextureEntry* te = avatarp->getTE(i); + if (!te) continue; + + if (LLVOAvatar::isIndexLocalTexture((ETextureIndex)i)) { - LLLocalTextureObject *lto = wearable->getLocalTextureObject(i); - if (lto) + LLUUID id = IMG_DEFAULT_AVATAR; + EWearableType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType((ETextureIndex)i); + LLWearable *wearable = gAgentWearables.getWearable(wearable_type, 0); + if (wearable) { - id = lto->getID(); + LLLocalTextureObject *lto = wearable->getLocalTextureObject(i); + if (lto) + { + id = lto->getID(); + } + } + if (id != IMG_DEFAULT_AVATAR) + { + llinfos << "Avatar TE " << i << " id " << id << llendl; + } + else + { + llinfos << "Avatar TE " << i << " id " << "<DEFAULT>" << llendl; } - } - if (id != IMG_DEFAULT_AVATAR) - { - llinfos << "Avatar TE " << i << " id " << id << llendl; } else { - llinfos << "Avatar TE " << i << " id " << "<DEFAULT>" << llendl; + llinfos << "Avatar TE " << i << " id " << te->getID() << llendl; } } - else - { - llinfos << "Avatar TE " << i << " id " << te->getID() << llendl; - } } -#endif } diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index 5a332726b2..0aca12bc5e 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -355,10 +355,10 @@ void LLFloaterGesture::addGesture(const LLUUID& item_id , LLMultiGesture* gestur element["columns"][0]["value"] = ""; element["columns"][0]["font"]["name"] = "SANSSERIF"; element["columns"][0]["font"]["style"] = font_style; - element["columns"][0]["column"] = "trigger"; - element["columns"][0]["value"] = "---"; - element["columns"][0]["font"]["name"] = "SANSSERIF"; - element["columns"][0]["font"]["style"] = font_style; + element["columns"][1]["column"] = "shortcut"; + element["columns"][1]["value"] = "---"; + element["columns"][1]["font"]["name"] = "SANSSERIF"; + element["columns"][1]["font"]["style"] = font_style; element["columns"][2]["column"] = "key"; element["columns"][2]["value"] = "~~~"; element["columns"][2]["font"]["name"] = "SANSSERIF"; diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index fbd516ba7a..e7b2da043f 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -828,7 +828,6 @@ const F32 HOURS_TO_RADIANS = (2.f*F_PI)/24.f; LLPanelGridTools::LLPanelGridTools() : LLPanel() { - mCommitCallbackRegistrar.add("GridTools.KickAll", boost::bind(&LLPanelGridTools::onClickKickAll, this)); mCommitCallbackRegistrar.add("GridTools.FlushMapVisibilityCaches", boost::bind(&LLPanelGridTools::onClickFlushMapVisibilityCaches, this)); } @@ -846,46 +845,6 @@ void LLPanelGridTools::refresh() { } -void LLPanelGridTools::onClickKickAll() -{ - LLNotificationsUtil::add("KickAllUsers", LLSD(), LLSD(), LLPanelGridTools::confirmKick); -} - - -bool LLPanelGridTools::confirmKick(const LLSD& notification, const LLSD& response) -{ - if (LLNotificationsUtil::getSelectedOption(notification, response) == 0) - { - LLSD payload; - payload["kick_message"] = response["message"].asString(); - LLNotificationsUtil::add("ConfirmKick", LLSD(), payload, LLPanelGridTools::finishKick); - } - return false; -} - - -// static -bool LLPanelGridTools::finishKick(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - - - if (option == 0) - { - LLMessageSystem* msg = gMessageSystem; - - msg->newMessageFast(_PREHASH_GodKickUser); - msg->nextBlockFast(_PREHASH_UserInfo); - msg->addUUIDFast(_PREHASH_GodID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_AgentID, LL_UUID_ALL_AGENTS ); - msg->addU32("KickFlags", KICK_FLAGS_DEFAULT ); - msg->addStringFast(_PREHASH_Reason, notification["payload"]["kick_message"].asString()); - gAgent.sendReliableMessage(); - } - return false; -} - void LLPanelGridTools::onClickFlushMapVisibilityCaches() { LLNotificationsUtil::add("FlushMapVisibilityCaches", LLSD(), LLSD(), flushMapVisibilityCachesConfirm); diff --git a/indra/newview/llfloatergodtools.h b/indra/newview/llfloatergodtools.h index 4e97a1058e..aee9db78a3 100644 --- a/indra/newview/llfloatergodtools.h +++ b/indra/newview/llfloatergodtools.h @@ -198,9 +198,6 @@ public: void refresh(); - void onClickKickAll(); - static bool confirmKick(const LLSD& notification, const LLSD& response); - static bool finishKick(const LLSD& notification, const LLSD& response); static void onDragSunPhase(LLUICtrl *ctrl, void *userdata); void onClickFlushMapVisibilityCaches(); static bool flushMapVisibilityCachesConfirm(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 6467ee13b0..02c83dcd09 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -1612,7 +1612,7 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo item_params.columns.add().value(object_count_str).font(FONT).column("count"); item_params.columns.add().value(LLDate((time_t)most_recent_time)).font(FONT).column("mostrecent").type("date"); - self->mOwnerList->addRow(item_params); + self->mOwnerList->addNameItemRow(item_params); lldebugs << "object owner " << owner_id << " (" << (is_group_owned ? "group" : "agent") << ") owns " << object_count << " objects." << llendl; diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp index 8894628788..5677899dd9 100644 --- a/indra/newview/llfloatermap.cpp +++ b/indra/newview/llfloatermap.cpp @@ -215,6 +215,20 @@ void LLFloaterMap::draw() LLFloater::draw(); } +// virtual +void LLFloaterMap::onFocusReceived() +{ + setBackgroundOpaque(true); + LLPanel::onFocusReceived(); +} + +// virtual +void LLFloaterMap::onFocusLost() +{ + setBackgroundOpaque(false); + LLPanel::onFocusLost(); +} + void LLFloaterMap::reshape(S32 width, S32 height, BOOL called_from_parent) { LLFloater::reshape(width, height, called_from_parent); diff --git a/indra/newview/llfloatermap.h b/indra/newview/llfloatermap.h index 6c9138c6a7..9ff2f03180 100644 --- a/indra/newview/llfloatermap.h +++ b/indra/newview/llfloatermap.h @@ -53,6 +53,8 @@ public: /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); /*virtual*/ void draw(); + /*virtual*/ void onFocusLost(); + /*virtual*/ void onFocusReceived(); private: void handleZoom(const LLSD& userdata); diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 4fbd1efbef..43743ec37a 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -980,7 +980,6 @@ void LLFolderView::finishRenamingItem( void ) if( mRenameItem ) { setSelectionFromRoot( mRenameItem, TRUE ); - mRenameItem = NULL; } // List is re-sorted alphabeticly, so scroll to make sure the selected item is visible. diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index ecbaac5743..c916e4b98c 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -437,11 +437,8 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) S32 LLFolderViewItem::getItemHeight() { - if (mHidden) return 0; + if (getHidden()) return 0; - //S32 icon_height = mIcon->getHeight(); - //S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight()); - //return llmax( icon_height, label_height ) + ICON_PAD; return mItemHeight; } @@ -824,32 +821,34 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, return handled; } - void LLFolderViewItem::draw() { - if (mHidden) return; + if (getHidden()) + { + return; + } static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); - static LLUIColor sFocusOutlineColor = - LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); + static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemSuffixColor", DEFAULT_WHITE); static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); - const Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); const S32 TOP_PAD = default_params.item_top_pad; + const S32 FOCUS_LEFT = 1; + const LLFontGL* font = getLabelFontForStyle(mLabelStyle); - bool possibly_has_children = false; - bool up_to_date = mListener && mListener->isUpToDate(); - if((up_to_date && hasVisibleChildren() ) || // we fetched our children and some of them have passed the filter... - (!up_to_date && mListener && mListener->hasChildren())) // ...or we know we have children but haven't fetched them (doesn't obey filter) - { - possibly_has_children = true; - } - if(/*mControlLabel[0] != '\0' && */possibly_has_children) + + //--------------------------------------------------------------------------------// + // Draw open folder arrow + // + const bool up_to_date = mListener && mListener->isUpToDate(); + const bool possibly_has_children = ((up_to_date && hasVisibleChildren()) || // we fetched our children and some of them have passed the filter... + (!up_to_date && mListener && mListener->hasChildren())); // ...or we know we have children but haven't fetched them (doesn't obey filter) + if (possibly_has_children) { LLUIImage* arrow_image = default_params.folder_arrow_image; gl_draw_scaled_rotated_image( @@ -857,22 +856,16 @@ void LLFolderViewItem::draw() ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, arrow_image->getImage(), sFgColor); } - // See also LLFolderView::updateRenamerPosition() - F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); - - LLFontGL* font = getLabelFontForStyle(mLabelStyle); - - // If we have keyboard focus, draw selection filled - BOOL show_context = getRoot()->getShowSelectionContext(); - BOOL filled = show_context || (getRoot()->getParentPanel()->hasFocus()); - const S32 FOCUS_LEFT = 1; - S32 focus_top = getRect().getHeight(); - S32 focus_bottom = getRect().getHeight() - mItemHeight; - bool folder_open = (getRect().getHeight() > mItemHeight + 4); - // always render "current" item, only render other selected items if - // mShowSingleSelection is FALSE - if( mIsSelected ) + //--------------------------------------------------------------------------------// + // Draw highlight for selected items + // + const BOOL show_context = getRoot()->getShowSelectionContext(); + const BOOL filled = show_context || (getRoot()->getParentPanel()->hasFocus()); // If we have keyboard focus, draw selection filled + const S32 focus_top = getRect().getHeight(); + const S32 focus_bottom = getRect().getHeight() - mItemHeight; + const bool folder_open = (getRect().getHeight() > mItemHeight + 4); + if (mIsSelected) // always render "current" item. Only render other selected items if mShowSingleSelection is FALSE { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLColor4 bg_color = sHighlightBgColor; @@ -891,152 +884,169 @@ void LLFolderViewItem::draw() bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); } } - - gl_rect_2d( - FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - bg_color, filled); + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + bg_color, filled); if (mIsCurSelection) { - gl_rect_2d( - FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - sFocusOutlineColor, FALSE); + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + sFocusOutlineColor, FALSE); } if (folder_open) { - gl_rect_2d( - FOCUS_LEFT, - focus_bottom + 1, // overlap with bottom edge of above rect - getRect().getWidth() - 2, - 0, - sFocusOutlineColor, FALSE); + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, // overlap with bottom edge of above rect + getRect().getWidth() - 2, + 0, + sFocusOutlineColor, FALSE); if (show_context) { - gl_rect_2d( - FOCUS_LEFT, - focus_bottom + 1, - getRect().getWidth() - 2, - 0, - sHighlightBgColor, TRUE); + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, + getRect().getWidth() - 2, + 0, + sHighlightBgColor, TRUE); } } } + + //--------------------------------------------------------------------------------// + // Draw DragNDrop highlight + // if (mDragAndDropTarget) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gl_rect_2d( - FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - sHighlightBgColor, FALSE); + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + sHighlightBgColor, FALSE); if (folder_open) { - gl_rect_2d( - FOCUS_LEFT, - focus_bottom + 1, // overlap with bottom edge of above rect - getRect().getWidth() - 2, - 0, - sHighlightBgColor, FALSE); + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, // overlap with bottom edge of above rect + getRect().getWidth() - 2, + 0, + sHighlightBgColor, FALSE); } mDragAndDropTarget = FALSE; } - S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; - // First case is used for open folders - if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) + + //--------------------------------------------------------------------------------// + // Draw open icon + // + const S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; + if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders { mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); } - else if(mIcon) + else if (mIcon) { mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); } - if (!mLabel.empty()) + + //--------------------------------------------------------------------------------// + // Exit if no label to draw + // + if (mLabel.empty()) { - // highlight filtered text - BOOL debug_filters = getRoot()->getDebugFilters(); - LLColor4 color = ( (mIsSelected && filled) ? sHighlightFgColor : sFgColor ); - F32 right_x; - F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + return; + } - if (debug_filters) - { - if (!getFiltered() && !possibly_has_children) - { - color.mV[VALPHA] *= 0.5f; - } + LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; + F32 right_x = 0; + F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); - LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? LLColor4(0.5f, 0.8f, 0.5f, 1.f) : LLColor4(0.8f, 0.5f, 0.5f, 1.f); - LLFontGL::getFontMonospace()->renderUTF8( - mStatusText, 0, text_left, y, filter_color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, &right_x, FALSE ); - text_left = right_x; + //--------------------------------------------------------------------------------// + // Highlight filtered text + // + if (getRoot()->getDebugFilters()) + { + if (!getFiltered() && !possibly_has_children) + { + color.mV[VALPHA] *= 0.5f; } + LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? + LLColor4(0.5f, 0.8f, 0.5f, 1.f) : + LLColor4(0.8f, 0.5f, 0.5f, 1.f); + LLFontGL::getFontMonospace()->renderUTF8(mStatusText, 0, text_left, y, filter_color, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + S32_MAX, S32_MAX, &right_x, FALSE ); + text_left = right_x; + } - font->renderUTF8( mLabel, 0, text_left, y, color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE); + //--------------------------------------------------------------------------------// + // Draw the actual label text + // + font->renderUTF8(mLabel, 0, text_left, y, color, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE); -// LLViewerInventoryCategory *item = 0; -// if (getListener()) -// item = gInventory.getCategory(getListener()->getUUID()); - bool root_is_loading = false; - if (getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(),gInventory.getRootFolderID())) - { - // Descendent of my inventory. - root_is_loading = LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress(); - } - if (getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(),gInventory.getLibraryRootFolderID())) - { - // Descendent of library - root_is_loading = LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress(); - } - - if ( (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) - || (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() && root_is_loading && mShowLoadStatus) ) - { - std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) "; - font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE); - } + //--------------------------------------------------------------------------------// + // Draw "Loading..." text + // + bool root_is_loading = false; + if (getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(), + gInventory.getRootFolderID())) // Descendent of my inventory + { + root_is_loading = LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress(); + } + if (getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(), + gInventory.getLibraryRootFolderID())) // Descendent of library + { + root_is_loading = LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress(); + } + if ((mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) || + (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() && root_is_loading && (mShowLoadStatus || mHidden))) + { + std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) "; + font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + S32_MAX, S32_MAX, &right_x, FALSE); + } - if (!mLabelSuffix.empty()) - { - font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, &right_x, FALSE ); - } + //--------------------------------------------------------------------------------// + // Draw label suffix + // + if (!mLabelSuffix.empty()) + { + font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + S32_MAX, S32_MAX, &right_x, FALSE ); + } - if (mStringMatchOffset != std::string::npos) + //--------------------------------------------------------------------------------// + // Highlight string match + // + if (mStringMatchOffset != std::string::npos) + { + // don't draw backgrounds for zero-length strings + S32 filter_string_length = getRoot()->getFilterSubString().size(); + if (filter_string_length > 0) { - // don't draw backgrounds for zero-length strings - S32 filter_string_length = getRoot()->getFilterSubString().size(); - if (filter_string_length > 0) - { - std::string combined_string = mLabel + mLabelSuffix; - S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; - S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; - S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); - S32 top = getRect().getHeight() - TOP_PAD; + std::string combined_string = mLabel + mLabelSuffix; + S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; + S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; + S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); + S32 top = getRect().getHeight() - TOP_PAD; - LLUIImage* box_image = default_params.selection_image; - LLRect box_rect(left, top, right, bottom); - box_image->draw(box_rect, sFilterBGColor); - F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); - F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; - font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, - sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - filter_string_length, S32_MAX, &right_x, FALSE ); - } + LLUIImage* box_image = default_params.selection_image; + LLRect box_rect(left, top, right, bottom); + box_image->draw(box_rect, sFilterBGColor); + F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); + F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, + sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + filter_string_length, S32_MAX, &right_x, FALSE ); } } } diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index 00e2365ffd..d4eecc8c48 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -105,7 +105,7 @@ public: { if (group_id.isNull()) return true; - LLGroupActions::show(group_id); + LLGroupActions::inspect(group_id); return true; } return false; @@ -246,6 +246,12 @@ static bool isGroupUIVisible() return panel->isInVisibleChain(); } +// static +void LLGroupActions::inspect(const LLUUID& group_id) +{ + LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", group_id)); +} + // static void LLGroupActions::show(const LLUUID& group_id) { diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h index e99df86cd9..55cae4db0b 100644 --- a/indra/newview/llgroupactions.h +++ b/indra/newview/llgroupactions.h @@ -66,6 +66,11 @@ public: static void show(const LLUUID& group_id); /** + * Show group inspector floater. + */ + static void inspect(const LLUUID& group_id); + + /** * Refresh group information panel. */ static void refresh(const LLUUID& group_id); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 0099cd114f..e0f155a6a9 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -81,6 +81,9 @@ const static std::string ADHOC_NAME_SUFFIX(" Conference"); const static std::string NEARBY_P2P_BY_OTHER("nearby_P2P_by_other"); const static std::string NEARBY_P2P_BY_AGENT("nearby_P2P_by_agent"); +/** Timeout of outgoing session initialization (in seconds) */ +const static U32 SESSION_INITIALIZATION_TIMEOUT = 30; + std::string LLCallDialogManager::sPreviousSessionlName = ""; LLIMModel::LLIMSession::SType LLCallDialogManager::sPreviousSessionType = LLIMModel::LLIMSession::P2P_SESSION; std::string LLCallDialogManager::sCurrentSessionlName = ""; @@ -92,6 +95,19 @@ const LLUUID LLOutgoingCallDialog::OCD_KEY = LLUUID("7CF78E11-0CFE-498D-ADB9-141 // LLIMMgr* gIMMgr = NULL; + +BOOL LLSessionTimeoutTimer::tick() +{ + if (mSessionId.isNull()) return TRUE; + + LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId); + if (session && !session->mSessionInitialized) + { + gIMMgr->showSessionStartError("session_initialization_timed_out_error", mSessionId); + } + return TRUE; +} + void toast_callback(const LLSD& msg){ // do not show toast in busy mode or it goes from agent if (gAgent.getBusy() || gAgent.getID() == msg["from_id"]) @@ -215,6 +231,11 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& //so we're already initialized mSessionInitialized = true; } + else + { + //tick returns TRUE - timer will be deleted after the tick + new LLSessionTimeoutTimer(mSessionID, SESSION_INITIALIZATION_TIMEOUT); + } if (IM_NOTHING_SPECIAL == type) { @@ -1539,6 +1560,11 @@ LLCallDialog::LLCallDialog(const LLSD& payload) setDocked(true); } +LLCallDialog::~LLCallDialog() +{ + LLUI::removePopup(this); +} + void LLCallDialog::getAllowedRect(LLRect& rect) { rect = gViewerWindow->getWorldViewRectScaled(); @@ -1592,7 +1618,7 @@ void LLCallDialog::onOpen(const LLSD& key) LLDockableFloater::onOpen(key); // it should be over the all floaters. EXT-5116 - gFloaterView->bringToFront(this, FALSE); + LLUI::addPopup(this); } void LLCallDialog::setIcon(const LLSD& session_id, const LLSD& participant_id) diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 0a23fda9d8..ffa8a16797 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -34,6 +34,7 @@ #define LL_LLIMVIEW_H #include "lldockablefloater.h" +#include "lleventtimer.h" #include "llinstantmessage.h" #include "lllogchat.h" @@ -45,7 +46,24 @@ class LLFriendObserver; class LLCallDialogManager; class LLIMSpeakerMgr; +/** + * Timeout Timer for outgoing Ad-Hoc/Group IM sessions which being initialized by the server + */ +class LLSessionTimeoutTimer : public LLEventTimer +{ +public: + LLSessionTimeoutTimer(const LLUUID& session_id, F32 period) : LLEventTimer(period), mSessionId(session_id) {} + virtual ~LLSessionTimeoutTimer() {}; + /* virtual */ BOOL tick(); + +private: + LLUUID mSessionId; +}; + +/** + * Model (MVC) for IM Sessions + */ class LLIMModel : public LLSingleton<LLIMModel> { public: @@ -477,7 +495,7 @@ class LLCallDialog : public LLDockableFloater { public: LLCallDialog(const LLSD& payload); - ~LLCallDialog() {} + ~LLCallDialog(); virtual BOOL postBuild(); diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 35cb9b3468..94ea236757 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -137,6 +137,7 @@ private: void onVolumeChange(const LLSD& data); bool enableMute(); bool enableUnmute(); + bool enableTeleportOffer(); // Is used to determine if "Add friend" option should be enabled in gear menu bool isNotFriend(); @@ -235,6 +236,7 @@ LLInspectAvatar::LLInspectAvatar(const LLSD& sd) boost::bind(&LLInspectAvatar::onVisibleZoomIn, this)); mEnableCallbackRegistrar.add("InspectAvatar.Gear.Enable", boost::bind(&LLInspectAvatar::isNotFriend, this)); mEnableCallbackRegistrar.add("InspectAvatar.Gear.EnableCall", boost::bind(&LLAvatarActions::canCall)); + mEnableCallbackRegistrar.add("InspectAvatar.Gear.EnableTeleportOffer", boost::bind(&LLInspectAvatar::enableTeleportOffer, this)); mEnableCallbackRegistrar.add("InspectAvatar.EnableMute", boost::bind(&LLInspectAvatar::enableMute, this)); mEnableCallbackRegistrar.add("InspectAvatar.EnableUnmute", boost::bind(&LLInspectAvatar::enableUnmute, this)); @@ -764,6 +766,11 @@ bool LLInspectAvatar::enableUnmute() } } +bool LLInspectAvatar::enableTeleportOffer() +{ + return LLAvatarActions::canOfferTeleport(mAvatarID); +} + ////////////////////////////////////////////////////////////////////////////// // LLInspectAvatarUtil ////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 604af3d074..0fbf3148ac 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -31,10 +31,12 @@ */ #include "llviewerprecompiledheaders.h" +#include "llinventorybridge.h" + // external projects #include "lltransfersourceasset.h" -#include "llinventorybridge.h" + #include "llagent.h" #include "llagentcamera.h" @@ -594,7 +596,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, LLViewerInventoryItem* inv_item = gInventory.getItem(mUUID); if (inv_item) { - is_asset_knowable = is_asset_id_knowable(inv_item->getType()); + is_asset_knowable = LLAssetType::lookupIsAssetIDKnowable(inv_item->getType()); } if ( !is_asset_knowable // disable menu item for Inventory items with unknown asset. EXT-5308 || (! ( isItemPermissive() || gAgent.isGodlike() ) ) @@ -1923,50 +1925,6 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, return accept; } -bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat, - LLInventoryItem* item) -{ - // Valid COF items are: - // - links to wearables (body parts or clothing) - // - links to attachments - // - links to gestures - // - links to ensemble folders - LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); - if (linked_item) - { - LLAssetType::EType type = linked_item->getType(); - return (type == LLAssetType::AT_CLOTHING || - type == LLAssetType::AT_BODYPART || - type == LLAssetType::AT_GESTURE || - type == LLAssetType::AT_OBJECT); - } - else - { - LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); - // BAP remove AT_NONE support after ensembles are fully working? - return (linked_category && - ((linked_category->getPreferredType() == LLFolderType::FT_NONE) || - (LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType())))); - } -} - - -bool LLFindWearables::operator()(LLInventoryCategory* cat, - LLInventoryItem* item) -{ - if(item) - { - if((item->getType() == LLAssetType::AT_CLOTHING) - || (item->getType() == LLAssetType::AT_BODYPART)) - { - return TRUE; - } - } - return FALSE; -} - - - //Used by LLFolderBridge as callback for directory recursion. class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver { diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index ab2133d779..3e16dfea5f 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -239,6 +239,47 @@ bool LLNameCategoryCollector::operator()( return false; } +bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat, + LLInventoryItem* item) +{ + // Valid COF items are: + // - links to wearables (body parts or clothing) + // - links to attachments + // - links to gestures + // - links to ensemble folders + LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); + if (linked_item) + { + LLAssetType::EType type = linked_item->getType(); + return (type == LLAssetType::AT_CLOTHING || + type == LLAssetType::AT_BODYPART || + type == LLAssetType::AT_GESTURE || + type == LLAssetType::AT_OBJECT); + } + else + { + LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); + // BAP remove AT_NONE support after ensembles are fully working? + return (linked_category && + ((linked_category->getPreferredType() == LLFolderType::FT_NONE) || + (LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType())))); + } +} + +bool LLFindWearables::operator()(LLInventoryCategory* cat, + LLInventoryItem* item) +{ + if(item) + { + if((item->getType() == LLAssetType::AT_CLOTHING) + || (item->getType() == LLAssetType::AT_BODYPART)) + { + return TRUE; + } + } + return FALSE; +} + ///---------------------------------------------------------------------------- /// LLAssetIDMatches ///---------------------------------------------------------------------------- diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 7a538e372b..9611c286eb 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -148,16 +148,30 @@ void LLNameListCtrl::mouseOverHighlightNthItem( S32 target_index ) if(0 <= cur_index && cur_index < (S32)getItemList().size()) { LLScrollListItem* item = getItemList()[cur_index]; - LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(mNameColumnIndex)); - if(cell) - cell->setTextWidth(cell->getTextWidth() + info_icon_size); + if (item) + { + LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(mNameColumnIndex)); + if (cell) + cell->setTextWidth(cell->getTextWidth() + info_icon_size); + } + else + { + llwarns << "highlighted name list item is NULL" << llendl; + } } if(target_index != -1) { LLScrollListItem* item = getItemList()[target_index]; LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(mNameColumnIndex)); - if(cell) - cell->setTextWidth(cell->getTextWidth() - info_icon_size); + if (item) + { + if (cell) + cell->setTextWidth(cell->getTextWidth() - info_icon_size); + } + else + { + llwarns << "target name item is NULL" << llendl; + } } } diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 424b8c9a66..1507b7d324 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -807,8 +807,11 @@ public: { if (tokens.size() < 2) return false; S32 channel = tokens[0].asInteger(); - std::string mesg = tokens[1].asString(); - send_chat_from_viewer(mesg, CHAT_TYPE_NORMAL, channel); + + // Send unescaped message, see EXT-6353. + std::string unescaped_mesg (LLURI::unescape(tokens[1].asString())); + + send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel); return true; } }; diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 1dc0e414a2..99a1fedcf3 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -42,6 +42,8 @@ #include "llinstantmessage.h" #include "llnotificationptr.h" +class LLIMFloater; + namespace LLNotificationsUI { // ENotificationType enumerates all possible types of notifications that could be met @@ -304,8 +306,6 @@ public: /** * Checks if passed notification can create toast. - * - * It returns false only for inventory accepted/declined notifications if respective IM window is open (EXT-5909) */ static bool canSpawnToast(const LLNotificationPtr& notification); @@ -315,6 +315,11 @@ public: static bool isIMFloaterOpened(const LLNotificationPtr& notification); /** + * Determines whether IM floater is focused. + */ + static bool isIMFloaterFocused(const LLNotificationPtr& notification); + + /** * Writes notification message to IM session. */ static void logToIM(const EInstantMessage& session_type, @@ -375,6 +380,14 @@ public: * Decrements counter of IM messages. */ static void decIMMesageCounter(const LLNotificationPtr& notification); + +private: + + /** + * Find IM floater based on "from_id" + */ + static LLIMFloater* findIMFloater(const LLNotificationPtr& notification); + }; } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index d3ad61128d..3f551f6b32 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -128,7 +128,8 @@ const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"), FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"), SERVER_OBJECT_MESSAGE("ServerObjectMessage"), TELEPORT_OFFERED("TeleportOffered"), - TELEPORT_OFFER_SENT("TeleportOfferSent"); + TELEPORT_OFFER_SENT("TeleportOfferSent"), + IM_SYSTEM_MESSAGE_TIP("IMSystemMessageTip"); // static @@ -147,7 +148,8 @@ bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) || INVENTORY_DECLINED == notification->getName() || USER_GIVE_ITEM == notification->getName() || TELEPORT_OFFERED == notification->getName() - || TELEPORT_OFFER_SENT == notification->getName(); + || TELEPORT_OFFER_SENT == notification->getName() + || IM_SYSTEM_MESSAGE_TIP == notification->getName(); } // static @@ -157,7 +159,8 @@ bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification) && FRIEND_ONLINE != notification->getName() && FRIEND_OFFLINE != notification->getName() && INVENTORY_ACCEPTED != notification->getName() - && INVENTORY_DECLINED != notification->getName(); + && INVENTORY_DECLINED != notification->getName() + && IM_SYSTEM_MESSAGE_TIP != notification->getName(); } // static @@ -193,10 +196,36 @@ bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notificat // static bool LLHandlerUtil::canSpawnToast(const LLNotificationPtr& notification) { - bool cannot_spawn = isIMFloaterOpened(notification) && (INVENTORY_DECLINED == notification->getName() - || INVENTORY_ACCEPTED == notification->getName()); - - return !cannot_spawn; + if(INVENTORY_DECLINED == notification->getName() + || INVENTORY_ACCEPTED == notification->getName()) + { + // return false for inventory accepted/declined notifications if respective IM window is open (EXT-5909) + return ! isIMFloaterOpened(notification); + } + + if(FRIENDSHIP_ACCEPTED == notification->getName()) + { + // don't show FRIENDSHIP_ACCEPTED if IM window is opened and focused - EXT-6441 + return ! isIMFloaterFocused(notification); + } + + if(OFFER_FRIENDSHIP == notification->getName() + || USER_GIVE_ITEM == notification->getName() + || TELEPORT_OFFERED == notification->getName()) + { + // When ANY offer arrives, show toast, unless IM window is already open - EXT-5904 + return ! isIMFloaterOpened(notification); + } + + return true; +} + +// static +LLIMFloater* LLHandlerUtil::findIMFloater(const LLNotificationPtr& notification) +{ + LLUUID from_id = notification->getPayload()["from_id"]; + LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); + return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); } // static @@ -204,12 +233,7 @@ bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) { bool res = false; - LLUUID from_id = notification->getPayload()["from_id"]; - LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, - from_id); - - LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>( - "impanel", session_id); + LLIMFloater* im_floater = findIMFloater(notification); if (im_floater != NULL) { res = im_floater->getVisible() == TRUE; @@ -218,6 +242,19 @@ bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) return res; } +bool LLHandlerUtil::isIMFloaterFocused(const LLNotificationPtr& notification) +{ + bool res = false; + + LLIMFloater* im_floater = findIMFloater(notification); + if (im_floater != NULL) + { + res = im_floater->hasFocus() == TRUE; + } + + return res; +} + // static void LLHandlerUtil::logToIM(const EInstantMessage& session_type, const std::string& session_name, const std::string& from_name, @@ -286,7 +323,7 @@ void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_fi { const std::string name = LLHandlerUtil::getSubstitutionName(notification); - std::string session_name = notification->getPayload().has( + const std::string& session_name = notification->getPayload().has( "SESSION_NAME") ? notification->getPayload()["SESSION_NAME"].asString() : name; // don't create IM p2p session with objects, it's necessary condition to log @@ -295,12 +332,6 @@ void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_fi { LLUUID from_id = notification->getPayload()["from_id"]; - //*HACK for ServerObjectMessage the sesson name is really weird, see EXT-4779 - if (SERVER_OBJECT_MESSAGE == notification->getName()) - { - session_name = "chat"; - } - //there still appears a log history file with weird name " .txt" if (" " == session_name || "{waiting}" == session_name || "{nobody}" == session_name) { @@ -355,6 +386,7 @@ void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChat LLChat chat_msg(notification->getMessage()); chat_msg.mSourceType = type; chat_msg.mFromName = SYSTEM_FROM; + chat_msg.mFromID = LLUUID::null; nearby_chat->addMessage(chat_msg); } } diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index e93aec9d01..c5960a9040 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -115,15 +115,11 @@ bool LLOfferHandler::processNotification(const LLSD& notify) session_id = LLHandlerUtil::spawnIMSession(name, from_id); } - bool show_toast = true; + bool show_toast = LLHandlerUtil::canSpawnToast(notification); bool add_notid_to_im = LLHandlerUtil::canAddNotifPanelToIM(notification); if (add_notid_to_im) { LLHandlerUtil::addNotifPanelToIM(notification); - if (LLHandlerUtil::isIMFloaterOpened(notification)) - { - show_toast = false; - } } if (notification->getPayload().has("SUPPRESS_TOAST") diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index 706787e824..c00b6a4147 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -59,6 +59,8 @@ #include "llaccordionctrltab.h" #include "llaccordionctrl.h" +#include "lltrans.h" + static LLRegisterPanelClassWrapper<LLPanelGroup> t_panel_group("panel_group_info_sidetray"); @@ -333,8 +335,9 @@ void LLPanelGroup::update(LLGroupChange gc) LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID); if(gdatap) { - childSetValue("group_name", gdatap->mName); - childSetToolTip("group_name",gdatap->mName); + std::string group_name = gdatap->mName.empty() ? LLTrans::getString("LoadingData") : gdatap->mName; + childSetValue("group_name", group_name); + childSetToolTip("group_name",group_name); LLGroupData agent_gdatap; bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlike(); @@ -379,8 +382,9 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID); if(gdatap) { - childSetValue("group_name", gdatap->mName); - childSetToolTip("group_name",gdatap->mName); + std::string group_name = gdatap->mName.empty() ? LLTrans::getString("LoadingData") : gdatap->mName; + childSetValue("group_name", group_name); + childSetToolTip("group_name",group_name); } LLButton* button_apply = findChild<LLButton>("btn_apply"); diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp index 9023afc602..f276df8573 100644 --- a/indra/newview/llpanelgrouplandmoney.cpp +++ b/indra/newview/llpanelgrouplandmoney.cpp @@ -1600,6 +1600,8 @@ void LLPanelGroupLandMoney::setGroupID(const LLUUID& id) mImplementationp->mMoneySalesTabEHp->setGroupID(mGroupID); } + mImplementationp->mBeenActivated = true; + activate(); } diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index 3dbe9a7f59..4ffd43cb0f 100644 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -397,17 +397,20 @@ std::string LLPanelLandmarkInfo::getFullFolderName(const LLViewerInventoryCatego if (is_under_root_category || cat->getParentUUID() == gInventory.getRootFolderID()) { std::string localized_name; + + // Looking for translation only for protected type categories + // to avoid warnings about non existent string in strings.xml. + bool is_protected_type = LLFolderType::lookupIsProtectedType(cat->getPreferredType()); + if (is_under_root_category) { // translate category name, if it's right below the root - // FIXME: it can throw notification about non existent string in strings.xml - bool is_found = LLTrans::findString(localized_name, "InvFolder " + name); + bool is_found = is_protected_type && LLTrans::findString(localized_name, "InvFolder " + name); name = is_found ? localized_name : name; } else { - // FIXME: it can throw notification about non existent string in strings.xml - bool is_found = LLTrans::findString(localized_name, "InvFolder " + cat->getName()); + bool is_found = is_protected_type && LLTrans::findString(localized_name, "InvFolder " + cat->getName()); // add translated category name to folder's full name name = (is_found ? localized_name : cat->getName()) + "/" + name; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 4cde02c1ce..c7793bbc43 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -924,12 +924,7 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const return false; } } - else if (!root_folder_view && "category" != command_name) - { - return false; - } else if ( "paste" == command_name - || "rename" == command_name || "cut" == command_name || "copy" == command_name || "delete" == command_name @@ -941,17 +936,16 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const } else if ( "teleport" == command_name || "more_info" == command_name - || "rename" == command_name || "show_on_map" == command_name || "copy_slurl" == command_name ) { // disable some commands for multi-selection. EXT-1757 - if (root_folder_view && - root_folder_view->getSelectedCount() > 1) - { - return false; - } + return root_folder_view && root_folder_view->getSelectedCount() == 1; + } + else if ("rename" == command_name) + { + return root_folder_view && root_folder_view->getSelectedCount() == 1 && canSelectedBeModified(command_name); } else if("category" == command_name) { @@ -1080,7 +1074,7 @@ bool LLLandmarksPanel::canSelectedBeModified(const std::string& command_name) co } else if ("delete" == command_name) { - can_be_modified = listenerp ? listenerp->isItemRemovable() : false; + can_be_modified = listenerp ? listenerp->isItemRemovable() && !listenerp->isItemInTrash() : false; } else if("paste" == command_name) { diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp new file mode 100644 index 0000000000..ba22adc01c --- /dev/null +++ b/indra/newview/llpaneloutfitedit.cpp @@ -0,0 +1,519 @@ +/** + * @file llpaneloutfitedit.cpp + * @brief Displays outfit edit information in Side Tray. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpaneloutfitedit.h" + +// *TODO: reorder includes to match the coding standard +#include "llagent.h" +#include "llagentwearables.h" +#include "llappearancemgr.h" +#include "llinventory.h" +#include "llviewercontrol.h" +#include "llui.h" +#include "llfloater.h" +#include "llfloaterreg.h" +#include "llinventoryfunctions.h" +#include "llinventorypanel.h" +#include "llviewerwindow.h" +#include "llviewerinventory.h" +#include "llbutton.h" +#include "llcombobox.h" +#include "llfiltereditor.h" +#include "llfloaterinventory.h" +#include "llinventorybridge.h" +#include "llinventorymodel.h" +#include "llinventorymodelbackgroundfetch.h" +#include "lluiconstants.h" +#include "llscrolllistctrl.h" +#include "lltextbox.h" +#include "lluictrlfactory.h" +#include "llsdutil.h" +#include "llsidepanelappearance.h" +#include "llwearablelist.h" + +static LLRegisterPanelClassWrapper<LLPanelOutfitEdit> t_outfit_edit("panel_outfit_edit"); + +const U64 WEARABLE_MASK = (1LL << LLInventoryType::IT_WEARABLE); +const U64 ATTACHMENT_MASK = (1LL << LLInventoryType::IT_ATTACHMENT) | (1LL << LLInventoryType::IT_OBJECT); +const U64 ALL_ITEMS_MASK = WEARABLE_MASK | ATTACHMENT_MASK; + +class LLInventoryLookObserver : public LLInventoryObserver +{ +public: + LLInventoryLookObserver(LLPanelOutfitEdit *panel) : mPanel(panel) {} + virtual ~LLInventoryLookObserver() + { + if (gInventory.containsObserver(this)) + { + gInventory.removeObserver(this); + } + } + + virtual void changed(U32 mask) + { + if (mask & (LLInventoryObserver::ADD | LLInventoryObserver::REMOVE)) + { + mPanel->updateLookInfo(); + } + } +protected: + LLPanelOutfitEdit *mPanel; +}; + +class LLLookFetchObserver : public LLInventoryFetchDescendentsObserver +{ +public: + LLLookFetchObserver(LLPanelOutfitEdit *panel) : + mPanel(panel) + {} + LLLookFetchObserver() {} + virtual void done() + { + mPanel->lookFetched(); + if(gInventory.containsObserver(this)) + { + gInventory.removeObserver(this); + } + } +private: + LLPanelOutfitEdit *mPanel; +}; + + + +LLPanelOutfitEdit::LLPanelOutfitEdit() +: LLPanel(), mLookID(), mFetchLook(NULL), mSearchFilter(NULL), +mLookContents(NULL), mInventoryItemsPanel(NULL), mAddToLookBtn(NULL), +mRemoveFromLookBtn(NULL), mLookObserver(NULL), mNumItemsInLook(0) +{ + mSavedFolderState = new LLSaveFolderState(); + mSavedFolderState->setApply(FALSE); + + mFetchLook = new LLLookFetchObserver(this); + mLookObserver = new LLInventoryLookObserver(this); + gInventory.addObserver(mLookObserver); + + mLookItemTypes.reserve(NUM_LOOK_ITEM_TYPES); + for (U32 i = 0; i < NUM_LOOK_ITEM_TYPES; i++) + { + mLookItemTypes.push_back(LLLookItemType()); + } + + // TODO: make these strings translatable + mLookItemTypes[LIT_ALL] = LLLookItemType("All Items", ALL_ITEMS_MASK); + mLookItemTypes[LIT_WEARABLE] = LLLookItemType("Shape & Clothing", WEARABLE_MASK); + mLookItemTypes[LIT_ATTACHMENT] = LLLookItemType("Attachments", ATTACHMENT_MASK); + +} + +LLPanelOutfitEdit::~LLPanelOutfitEdit() +{ + delete mSavedFolderState; + if (gInventory.containsObserver(mFetchLook)) + { + gInventory.removeObserver(mFetchLook); + } + delete mFetchLook; + + if (gInventory.containsObserver(mLookObserver)) + { + gInventory.removeObserver(mLookObserver); + } + delete mLookObserver; +} + +BOOL LLPanelOutfitEdit::postBuild() +{ + // gInventory.isInventoryUsable() no longer needs to be tested per Richard's fix for race conditions between inventory and panels + + mLookName = getChild<LLTextBox>("curr_look_name"); + + childSetCommitCallback("add_btn", boost::bind(&LLPanelOutfitEdit::showAddWearablesPanel, this), NULL); + + /* + mLookContents->setDoubleClickCallback(onDoubleClickSpeaker, this); + mLookContents->setCommitOnSelectionChange(TRUE); + mLookContents->setCommitCallback(boost::bind(&LLPanelActiveSpeakers::handleSpeakerSelect, this, _2)); + mLookContents->setSortChangedCallback(boost::bind(&LLPanelActiveSpeakers::onSortChanged, this)); + mLookContents->setContextMenu(LLScrollListCtrl::MENU_AVATAR); + */ + + mInventoryItemsPanel = getChild<LLInventoryPanel>("inventory_items"); + mInventoryItemsPanel->setFilterTypes(ALL_ITEMS_MASK); + mInventoryItemsPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + // mInventoryItemsPanel->setSelectCallback(boost::bind(&LLPanelOutfitEdit::onInventorySelectionChange, this, _1, _2)); + // mInventoryItemsPanel->getRootFolder()->setReshapeCallback(boost::bind(&LLPanelOutfitEdit::onInventorySelectionChange, this, _1, _2)); + + LLComboBox* type_filter = getChild<LLComboBox>("inventory_filter"); + type_filter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onTypeFilterChanged, this, _1)); + type_filter->removeall(); + for (U32 i = 0; i < mLookItemTypes.size(); ++i) + { + type_filter->add(mLookItemTypes[i].displayName); + } + type_filter->setCurrentByIndex(LIT_ALL); + + mSearchFilter = getChild<LLFilterEditor>("look_item_filter"); + mSearchFilter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onSearchEdit, this, _2)); + + /* Removing add to look inline button (not part of mvp for viewer 2) + LLButton::Params add_params; + add_params.name("add_to_look"); + add_params.click_callback.function(boost::bind(&LLPanelOutfitEdit::onAddToLookClicked, this)); + add_params.label("+"); + + mAddToLookBtn = LLUICtrlFactory::create<LLButton>(add_params); + mAddToLookBtn->setEnabled(FALSE); + mAddToLookBtn->setVisible(FALSE); */ + + childSetAction("add_item_btn", boost::bind(&LLPanelOutfitEdit::onAddToLookClicked, this), this); + + mUpBtn = getChild<LLButton>("up_btn"); + mUpBtn->setEnabled(TRUE); + mUpBtn->setClickedCallback(boost::bind(&LLPanelOutfitEdit::onUpClicked, this)); + + mLookContents = getChild<LLScrollListCtrl>("look_items_list"); + mLookContents->sortByColumn("look_item_sort", TRUE); + mLookContents->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onLookItemSelectionChange, this)); + + /* + LLButton::Params remove_params; + remove_params.name("remove_from_look"); + remove_params.click_callback.function(boost::bind(&LLPanelOutfitEdit::onRemoveFromLookClicked, this)); + remove_params.label("-"); */ + + //mRemoveFromLookBtn = LLUICtrlFactory::create<LLButton>(remove_params); + mRemoveFromLookBtn = getChild<LLButton>("remove_from_look_btn"); + mRemoveFromLookBtn->setEnabled(FALSE); + mRemoveFromLookBtn->setVisible(FALSE); + //childSetAction("remove_from_look_btn", boost::bind(&LLPanelOutfitEdit::onRemoveFromLookClicked, this), this); + mRemoveFromLookBtn->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onRemoveFromLookClicked, this)); + //getChild<LLPanel>("look_info_group_bar")->addChild(mRemoveFromLookBtn); remove_item_btn + + mEditWearableBtn = getChild<LLButton>("edit_wearable_btn"); + mEditWearableBtn->setEnabled(FALSE); + mEditWearableBtn->setVisible(FALSE); + mEditWearableBtn->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onEditWearableClicked, this)); + + childSetAction("remove_item_btn", boost::bind(&LLPanelOutfitEdit::onRemoveFromLookClicked, this), this); + + return TRUE; +} + +void LLPanelOutfitEdit::showAddWearablesPanel() +{ + childSetVisible("add_wearables_panel", childGetValue("add_btn")); +} + +void LLPanelOutfitEdit::onTypeFilterChanged(LLUICtrl* ctrl) +{ + LLComboBox* type_filter = dynamic_cast<LLComboBox*>(ctrl); + llassert(type_filter); + if (type_filter) + { + U32 curr_filter_type = type_filter->getCurrentIndex(); + mInventoryItemsPanel->setFilterTypes(mLookItemTypes[curr_filter_type].inventoryMask); + } + + mSavedFolderState->setApply(TRUE); + mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); + + LLOpenFoldersWithSelection opener; + mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(opener); + mInventoryItemsPanel->getRootFolder()->scrollToShowSelection(); + + LLInventoryModelBackgroundFetch::instance().start(); +} + +void LLPanelOutfitEdit::onSearchEdit(const std::string& string) +{ + if (mSearchString != string) + { + mSearchString = string; + + // Searches are case-insensitive + LLStringUtil::toUpper(mSearchString); + LLStringUtil::trimHead(mSearchString); + } + + if (mSearchString == "") + { + mInventoryItemsPanel->setFilterSubString(LLStringUtil::null); + + // re-open folders that were initially open + mSavedFolderState->setApply(TRUE); + mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); + LLOpenFoldersWithSelection opener; + mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(opener); + mInventoryItemsPanel->getRootFolder()->scrollToShowSelection(); + } + + LLInventoryModelBackgroundFetch::instance().start(); + + if (mInventoryItemsPanel->getFilterSubString().empty() && mSearchString.empty()) + { + // current filter and new filter empty, do nothing + return; + } + + // save current folder open state if no filter currently applied + if (mInventoryItemsPanel->getRootFolder()->getFilterSubString().empty()) + { + mSavedFolderState->setApply(FALSE); + mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); + } + + // set new filter string + mInventoryItemsPanel->setFilterSubString(mSearchString); +} + +void LLPanelOutfitEdit::onAddToLookClicked(void) +{ + LLFolderViewItem* curr_item = mInventoryItemsPanel->getRootFolder()->getCurSelectedItem(); + LLFolderViewEventListener* listenerp = curr_item->getListener(); + link_inventory_item(gAgent.getID(), listenerp->getUUID(), mLookID, listenerp->getName(), + LLAssetType::AT_LINK, LLPointer<LLInventoryCallback>(NULL)); + updateLookInfo(); +} + + +void LLPanelOutfitEdit::onRemoveFromLookClicked(void) +{ + LLUUID id_to_remove = mLookContents->getSelectionInterface()->getCurrentID(); + + LLViewerInventoryItem * item_to_remove = gInventory.getItem(id_to_remove); + + if (item_to_remove) + { + // returns null if not a wearable (attachment, etc). + const LLWearable* wearable_to_remove = gAgentWearables.getWearableFromAssetID(item_to_remove->getAssetUUID()); + if (!wearable_to_remove || gAgentWearables.canWearableBeRemoved( wearable_to_remove )) + { + gInventory.purgeObject( id_to_remove ); + updateLookInfo(); + mRemoveFromLookBtn->setEnabled(FALSE); + if (mRemoveFromLookBtn->getVisible()) + { + mRemoveFromLookBtn->setVisible(FALSE); + } + } + } +} + + +void LLPanelOutfitEdit::onUpClicked(void) +{ + LLUUID inv_id = mLookContents->getSelectionInterface()->getCurrentID(); + if (inv_id.isNull()) + { + //nothing selected, do nothing + return; + } + + LLViewerInventoryItem *link_item = gInventory.getItem(inv_id); + if (!link_item) + { + llwarns << "could not find inventory item based on currently worn link." << llendl; + return; + } + + + LLUUID asset_id = link_item->getAssetUUID(); + if (asset_id.isNull()) + { + llwarns << "inventory link has null Asset ID. could not get object reference" << llendl; + } + + static const std::string empty = ""; + LLWearableList::instance().getAsset(asset_id, + empty, // don't care about wearable name + link_item->getActualType(), + LLSidepanelAppearance::editWearable, + (void*)getParentUICtrl()); +} + + +void LLPanelOutfitEdit::onEditWearableClicked(void) +{ + LLUUID id_to_edit = mLookContents->getSelectionInterface()->getCurrentID(); + + LLViewerInventoryItem * item_to_edit = gInventory.getItem(id_to_edit); + + if (item_to_edit) + { + // returns null if not a wearable (attachment, etc). + LLWearable* wearable_to_edit = gAgentWearables.getWearableFromAssetID(item_to_edit->getAssetUUID()); + if (!wearable_to_edit || !wearable_to_edit->getPermissions().allowModifyBy(gAgent.getID()) ) + { + LLSidepanelAppearance::editWearable(wearable_to_edit, getParent()); + if (mEditWearableBtn->getVisible()) + { + mEditWearableBtn->setVisible(FALSE); + } + } + } +} + +void LLPanelOutfitEdit::onInventorySelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action) +{ + LLFolderViewItem* current_item = mInventoryItemsPanel->getRootFolder()->getCurSelectedItem(); + if (!current_item) + { + return; + } + + /* Removing add to look inline button (not part of mvp for viewer 2) + LLRect btn_rect(current_item->getLocalRect().mRight - 50, + current_item->getLocalRect().mTop, + current_item->getLocalRect().mRight - 30, + current_item->getLocalRect().mBottom); + + mAddToLookBtn->setRect(btn_rect); + mAddToLookBtn->setEnabled(TRUE); + if (!mAddToLookBtn->getVisible()) + { + mAddToLookBtn->setVisible(TRUE); + } + + current_item->addChild(mAddToLookBtn); */ +} + +void LLPanelOutfitEdit::onLookItemSelectionChange(void) +{ + S32 left_offset = -4; + S32 top_offset = -10; + LLRect rect = mLookContents->getLastSelectedItem()->getRect(); + LLRect btn_rect( + left_offset + rect.mRight - 50, + top_offset + rect.mTop, + left_offset + rect.mRight - 30, + top_offset + rect.mBottom); + + mEditWearableBtn->setRect(btn_rect); + + mEditWearableBtn->setEnabled(TRUE); + if (!mEditWearableBtn->getVisible()) + { + mEditWearableBtn->setVisible(TRUE); + } + //mLookContents->addChild(mRemoveFromLookBtn); +} + +void LLPanelOutfitEdit::changed(U32 mask) +{ +} + +void LLPanelOutfitEdit::lookFetched(void) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + + // collectDescendentsIf takes non-const reference: + LLFindCOFValidItems is_cof_valid; + gInventory.collectDescendentsIf(mLookID, + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_cof_valid); + for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); + iter != item_array.end(); + iter++) + { + const LLViewerInventoryItem *item = (*iter); + + LLSD row; + row["id"] = item->getUUID(); + LLSD& columns = row["columns"]; + columns[0]["column"] = "look_item"; + columns[0]["type"] = "text"; + columns[0]["value"] = item->getName(); + columns[1]["column"] = "look_item_sort"; + columns[1]["type"] = "text"; // TODO: multi-wearable sort "type" should go here. + columns[1]["value"] = "BAR"; // TODO: Multi-wearable sort index should go here + + mLookContents->addElement(row); + } + + if (mLookContents->getItemCount() != mNumItemsInLook) + { + mNumItemsInLook = mLookContents->getItemCount(); + LLAppearanceMgr::instance().updateCOF(mLookID); + } +} + +void LLPanelOutfitEdit::updateLookInfo() +{ + if (getVisible()) + { + mLookContents->clearRows(); + + uuid_vec_t folders; + folders.push_back(mLookID); + mFetchLook->fetchDescendents(folders); + if (mFetchLook->isEverythingComplete()) + { + mFetchLook->done(); + } + else + { + gInventory.addObserver(mFetchLook); + } + } +} + +void LLPanelOutfitEdit::displayLookInfo(const LLInventoryCategory* pLook) +{ + if (!pLook) + { + return; + } + + if (!getVisible()) + { + setVisible(TRUE); + } + + if (mLookID != pLook->getUUID()) + { + mLookID = pLook->getUUID(); + mLookName->setText(pLook->getName()); + updateLookInfo(); + } +} + +void LLPanelOutfitEdit::reset() +{ + mLookID.setNull(); +} + diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h new file mode 100644 index 0000000000..5c00f84e0e --- /dev/null +++ b/indra/newview/llpaneloutfitedit.h @@ -0,0 +1,129 @@ +/** + * @file llpaneloutfitedit.h + * @brief Displays outfit edit information in Side Tray. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELOUTFITEDIT_H +#define LL_LLPANELOUTFITEDIT_H + +#include "llpanel.h" + +#include "v3dmath.h" +#include "lluuid.h" + +#include "lliconctrl.h" + +#include "llremoteparcelrequest.h" +#include "llinventory.h" +#include "llinventorymodel.h" + +class LLButton; +class LLTextBox; +class LLInventoryCategory; +class LLInventoryLookObserver; +class LLInventoryPanel; +class LLSaveFolderState; +class LLFolderViewItem; +class LLScrollListCtrl; +class LLLookFetchObserver; +class LLFilterEditor; + +class LLPanelOutfitEdit : public LLPanel +{ +public: + + // NOTE: initialize mLookItemTypes at the index of any new enum you add in the LLPanelOutfitEdit() constructor + typedef enum e_look_item_type + { + LIT_ALL = 0, + LIT_WEARABLE, // clothing or shape + LIT_ATTACHMENT, + NUM_LOOK_ITEM_TYPES + } ELookItemType; + + struct LLLookItemType { + std::string displayName; + U64 inventoryMask; + LLLookItemType() : displayName("NONE"), inventoryMask(0) {} + LLLookItemType(std::string name, U64 mask) : displayName(name), inventoryMask(mask) {} + }; + + LLPanelOutfitEdit(); + /*virtual*/ ~LLPanelOutfitEdit(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void changed(U32 mask); + + void reset(); + // Ignore all old information, useful if you are + // recycling an existing dialog and need to clear it. + + /*virtual*/ void setParcelID(const LLUUID& parcel_id); + // Sends a request for data about the given parcel, which will + // only update the location if there is none already available. + + void showAddWearablesPanel(); + + void onTypeFilterChanged(LLUICtrl* ctrl); + void onSearchEdit(const std::string& string); + void onInventorySelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); + void onAddToLookClicked(void); + void onLookItemSelectionChange(void); + void onRemoveFromLookClicked(void); + void onEditWearableClicked(void); + void onUpClicked(void); + + void displayLookInfo(const LLInventoryCategory* pLook); + + void lookFetched(void); + + void updateLookInfo(void); + +private: + + LLUUID mLookID; + LLTextBox* mLookName; + LLScrollListCtrl* mLookContents; + LLInventoryPanel* mInventoryItemsPanel; + LLFilterEditor* mSearchFilter; + LLSaveFolderState* mSavedFolderState; + std::string mSearchString; + LLButton* mAddToLookBtn; + LLButton* mRemoveFromLookBtn; + LLButton* mUpBtn; + LLButton* mEditWearableBtn; + S32 mNumItemsInLook; + + LLLookFetchObserver* mFetchLook; + LLInventoryLookObserver* mLookObserver; + std::vector<LLLookItemType> mLookItemTypes; +}; + +#endif // LL_LLPANELOUTFITEDIT_H diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 8a1be2706c..288edeb031 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -178,8 +178,8 @@ public: protected: virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const { - LLPointer<LLSpeaker> lhs = LLLocalSpeakerMgr::instance().findSpeaker(item1->getAvatarId()); - LLPointer<LLSpeaker> rhs = LLLocalSpeakerMgr::instance().findSpeaker(item2->getAvatarId()); + LLPointer<LLSpeaker> lhs = LLActiveSpeakerMgr::instance().findSpeaker(item1->getAvatarId()); + LLPointer<LLSpeaker> rhs = LLActiveSpeakerMgr::instance().findSpeaker(item2->getAvatarId()); if ( lhs.notNull() && rhs.notNull() ) { // Compare by last speaking time @@ -672,11 +672,6 @@ void LLPanelPeople::updateFriendList() lldebugs << "Friends Cards were not found" << llendl; } - // show special help text for just created account to help found friends. EXT-4836 - static LLTextBox* no_friends_text = getChild<LLTextBox>("no_friends_msg"); - no_friends_text->setVisible(all_friendsp.size() == 0); - - LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin(); for (; buddy_it != all_buddies.end(); ++buddy_it) { @@ -685,6 +680,14 @@ void LLPanelPeople::updateFriendList() online_friendsp.push_back(buddy_id); } + // show special help text for just created account to help found friends. EXT-4836 + static LLTextBox* no_friends_text = getChild<LLTextBox>("no_friends_msg"); + + // Seems sometimes all_friends can be empty because of issue with Inventory loading (clear cache, slow connection...) + // So, lets check all lists to avoid overlapping the text with online list. See EXT-6448. + bool any_friend_exists = (all_friendsp.size() > 0) || (online_friendsp.size() > 0); + no_friends_text->setVisible(!any_friend_exists); + /* * Avatarlists will be hidden by showFriendsAccordionsIfNeeded(), if they do not have items. * But avatarlist can be updated only if it is visible @see LLAvatarList::draw(); @@ -708,7 +711,7 @@ void LLPanelPeople::updateNearbyList() mNearbyList->setDirty(); DISTANCE_COMPARATOR.updateAvatarsPositions(positions, mNearbyList->getIDs()); - LLLocalSpeakerMgr::instance().update(TRUE); + LLActiveSpeakerMgr::instance().update(TRUE); } void LLPanelPeople::updateRecentList() diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index 8b365c6433..862e32cca8 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -226,6 +226,11 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) return (LLAvatarTracker::instance().isBuddyOnline(id) && is_agent_mappable(id)) || gAgent.isGodlike(); } + else if(item == std::string("can_offer_teleport")) + { + const LLUUID& id = mUUIDs.front(); + return LLAvatarActions::canOfferTeleport(id); + } return false; } diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index 01b6e8ffad..71d16a08b4 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -195,8 +195,8 @@ void LLPanelPermissions::disableAll() childSetEnabled("Owner Name", FALSE); childSetEnabled("Group:", FALSE); - childSetText("Group Name", LLStringUtil::null); - childSetEnabled("Group Name", FALSE); + childSetText("Group Name Proxy", LLStringUtil::null); + childSetEnabled("Group Name Proxy", FALSE); childSetEnabled("button set group", FALSE); childSetText("Object Name", LLStringUtil::null); diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 6f920cf4b9..bde8d02885 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -288,7 +288,8 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data); if(c_info && getAvatarId() == c_info->target_id) { - mClassifiedsList->clear(); + // do not clear classified list in case we will receive two or more data packets. + // list has been cleared in updateData(). (fix for EXT-6436) LLAvatarClassifieds::classifieds_list_t::const_iterator it = c_info->classifieds_list.begin(); for(; c_info->classifieds_list.end() != it; ++it) diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 90c8f2551f..0a34531eee 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -348,7 +348,7 @@ LLContextMenu* LLTeleportHistoryPanel::ContextMenu::createMenu() void LLTeleportHistoryPanel::ContextMenu::onTeleport() { - LLTeleportHistoryStorage::getInstance()->goToItem(mIndex); + confirmTeleport(mIndex); } void LLTeleportHistoryPanel::ContextMenu::onInfo() @@ -507,7 +507,7 @@ void LLTeleportHistoryPanel::onTeleport() return; // teleport to existing item in history, so we don't add it again - mTeleportHistory->goToItem(itemp->getIndex()); + confirmTeleport(itemp->getIndex()); } /* @@ -1058,3 +1058,27 @@ void LLTeleportHistoryPanel::onAccordionExpand(LLUICtrl* ctrl, const LLSD& param mLastSelectedFlatlList->resetSelection(); } } + +// static +void LLTeleportHistoryPanel::confirmTeleport(S32 hist_idx) +{ + LLSD args; + args["HISTORY_ENTRY"] = LLTeleportHistoryStorage::getInstance()->getItems()[hist_idx].mTitle; + LLNotificationsUtil::add("TeleportToHistoryEntry", args, LLSD(), + boost::bind(&LLTeleportHistoryPanel::onTeleportConfirmation, _1, _2, hist_idx)); +} + +// Called when user reacts upon teleport confirmation dialog. +// static +bool LLTeleportHistoryPanel::onTeleportConfirmation(const LLSD& notification, const LLSD& response, S32 hist_idx) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + + if (0 == option) + { + // Teleport to given history item. + LLTeleportHistoryStorage::getInstance()->goToItem(hist_idx); + } + + return false; +} diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h index 4eeaec7705..5e2ccc0c93 100644 --- a/indra/newview/llpanelteleporthistory.h +++ b/indra/newview/llpanelteleporthistory.h @@ -103,6 +103,9 @@ private: bool isAccordionCollapsedByUser(LLUICtrl* acc_tab); void onAccordionExpand(LLUICtrl* ctrl, const LLSD& param); + static void confirmTeleport(S32 hist_idx); + static bool onTeleportConfirmation(const LLSD& notification, const LLSD& response, S32 hist_idx); + LLTeleportHistoryStorage* mTeleportHistory; LLAccordionCtrl* mHistoryAccordion; diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index ee8e3f1db6..bfd9a840f2 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -38,6 +38,7 @@ #include "llagent.h" #include "llassetuploadresponders.h" +#include "lldraghandle.h" #include "llviewerwindow.h" #include "llbutton.h" #include "llfloaterreg.h" @@ -188,6 +189,20 @@ void LLPreviewNotecard::refreshFromInventory(const LLUUID& new_item_id) loadAsset(); } +void LLPreviewNotecard::updateTitleButtons() +{ + LLPreview::updateTitleButtons(); + + LLUICtrl* lock_btn = getChild<LLUICtrl>("lock"); + if(lock_btn->getVisible() && !isMinimized()) // lock button stays visible if floater is minimized. + { + LLRect lock_rc = lock_btn->getRect(); + LLRect buttons_rect = getDragHandle()->getButtonsRect(); + buttons_rect.mLeft = lock_rc.mLeft; + getDragHandle()->setButtonsRect(buttons_rect); + } +} + void LLPreviewNotecard::loadAsset() { // request the asset. diff --git a/indra/newview/llpreviewnotecard.h b/indra/newview/llpreviewnotecard.h index 5b8cf1c2f6..e0363eef54 100644 --- a/indra/newview/llpreviewnotecard.h +++ b/indra/newview/llpreviewnotecard.h @@ -79,6 +79,7 @@ public: protected: + void updateTitleButtons(); virtual void loadAsset(); bool saveIfNeeded(LLInventoryItem* copyitem = NULL); diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index c9e9b2815c..b951434010 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -93,7 +93,7 @@ LLSidepanelAppearance::LLSidepanelAppearance() : LLPanel(), mFilterSubString(LLStringUtil::null), mFilterEditor(NULL), - mLookInfo(NULL), + mOutfitEdit(NULL), mCurrOutfitPanel(NULL) { } @@ -129,10 +129,10 @@ BOOL LLSidepanelAppearance::postBuild() mPanelOutfitsInventory = dynamic_cast<LLPanelOutfitsInventory *>(getChild<LLPanel>("panel_outfits_inventory")); mPanelOutfitsInventory->setParent(this); - mLookInfo = dynamic_cast<LLPanelLookInfo*>(getChild<LLPanel>("panel_look_info")); - if (mLookInfo) + mOutfitEdit = dynamic_cast<LLPanelOutfitEdit*>(getChild<LLPanel>("panel_outfit_edit")); + if (mOutfitEdit) { - LLButton* back_btn = mLookInfo->getChild<LLButton>("back_btn"); + LLButton* back_btn = mOutfitEdit->getChild<LLButton>("back_btn"); if (back_btn) { back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onBackButtonClicked, this)); @@ -177,7 +177,7 @@ void LLSidepanelAppearance::onOpen(const LLSD& key) if(key.size() == 0) return; - toggleLookInfoPanel(TRUE); + toggleOutfitEditPanel(TRUE); updateVerbs(); mLookInfoType = key["type"].asString(); @@ -186,7 +186,7 @@ void LLSidepanelAppearance::onOpen(const LLSD& key) { LLInventoryCategory *pLook = gInventory.getCategory(key["id"].asUUID()); if (pLook) - mLookInfo->displayLookInfo(pLook); + mOutfitEdit->displayLookInfo(pLook); } } @@ -241,9 +241,9 @@ void LLSidepanelAppearance::onEditAppearanceButtonClicked() void LLSidepanelAppearance::onEditButtonClicked() { - toggleLookInfoPanel(FALSE); + toggleOutfitEditPanel(FALSE); toggleWearableEditPanel(TRUE, NULL); - /*if (mLookInfo->getVisible()) + /*if (mOutfitEdit->getVisible()) { } else @@ -254,7 +254,7 @@ void LLSidepanelAppearance::onEditButtonClicked() void LLSidepanelAppearance::onNewOutfitButtonClicked() { - if (!mLookInfo->getVisible()) + if (!mOutfitEdit->getVisible()) { mPanelOutfitsInventory->onSave(); } @@ -263,22 +263,22 @@ void LLSidepanelAppearance::onNewOutfitButtonClicked() void LLSidepanelAppearance::onBackButtonClicked() { - toggleLookInfoPanel(FALSE); + toggleOutfitEditPanel(FALSE); } void LLSidepanelAppearance::onEditWearBackClicked() { mEditWearable->saveChanges(); toggleWearableEditPanel(FALSE, NULL); - toggleLookInfoPanel(TRUE); + toggleOutfitEditPanel(TRUE); } -void LLSidepanelAppearance::toggleLookInfoPanel(BOOL visible) +void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible) { - if (!mLookInfo) + if (!mOutfitEdit) return; - mLookInfo->setVisible(visible); + mOutfitEdit->setVisible(visible); if (mPanelOutfitsInventory) mPanelOutfitsInventory->setVisible(!visible); mFilterEditor->setVisible(!visible); mEditBtn->setVisible(!visible); @@ -305,7 +305,7 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *we void LLSidepanelAppearance::updateVerbs() { - bool is_look_info_visible = mLookInfo->getVisible(); + bool is_look_info_visible = mOutfitEdit->getVisible(); if (mPanelOutfitsInventory && !is_look_info_visible) { @@ -344,7 +344,7 @@ void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name) void LLSidepanelAppearance::editWearable(LLWearable *wearable, void *data) { LLSidepanelAppearance *panel = (LLSidepanelAppearance*) data; - panel->toggleLookInfoPanel(FALSE); + panel->toggleOutfitEditPanel(FALSE); panel->toggleWearableEditPanel(TRUE, wearable); } diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index aa2e67fd16..1d78e92a84 100644 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -36,7 +36,7 @@ #include "llinventoryobserver.h" #include "llinventory.h" -#include "llpanellookinfo.h" +#include "llpaneloutfitedit.h" class LLFilterEditor; class LLCurrentlyWornFetchObserver; @@ -71,12 +71,12 @@ private: void onEditButtonClicked(); void onBackButtonClicked(); void onEditWearBackClicked(); - void toggleLookInfoPanel(BOOL visible); + void toggleOutfitEditPanel(BOOL visible); void toggleWearableEditPanel(BOOL visible, LLWearable* wearable); LLFilterEditor* mFilterEditor; LLPanelOutfitsInventory* mPanelOutfitsInventory; - LLPanelLookInfo* mLookInfo; + LLPanelOutfitEdit* mOutfitEdit; LLPanelEditWearable* mEditWearable; LLButton* mOpenOutfitBtn; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 1a1dffe85c..b5a73a3143 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -3087,6 +3087,13 @@ bool process_login_success_response() } } + // Start the process of fetching the OpenID session cookie for this user login + std::string openid_url = response["openid_url"]; + if(!openid_url.empty()) + { + std::string openid_token = response["openid_token"]; + LLViewerMedia::openIDSetup(openid_url, openid_token); + } bool success = false; // JC: gesture loading done below, when we have an asset system diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 58f64ff1f3..b660a2b8ea 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -372,6 +372,8 @@ void LLStatusBar::setVisibleForMouselook(bool visible) mTextTime->setVisible(visible); getChild<LLUICtrl>("buycurrency")->setVisible(visible); getChild<LLUICtrl>("buyL")->setVisible(visible); + mBtnVolume->setVisible(visible); + mMediaToggle->setVisible(visible); mSGBandwidth->setVisible(visible); mSGPacketLoss->setVisible(visible); setBackgroundVisible(visible); diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 66373feb93..cbb030836e 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -58,7 +58,8 @@ LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLTransientDockableFloater(N mSysWellChiclet(NULL), mSeparator(NULL), NOTIFICATION_WELL_ANCHOR_NAME("notification_well_panel"), - IM_WELL_ANCHOR_NAME("im_well_panel") + IM_WELL_ANCHOR_NAME("im_well_panel"), + mIsReshapedByUser(false) { mTypedItemsCount[IT_NOTIFICATION] = 0; @@ -100,6 +101,13 @@ void LLSysWellWindow::setMinimized(BOOL minimize) } //--------------------------------------------------------------------------------- +void LLSysWellWindow::handleReshape(const LLRect& rect, bool by_user) +{ + mIsReshapedByUser |= by_user; // mark floater that it is reshaped by user + LLTransientDockableFloater::handleReshape(rect, by_user); +} + +//--------------------------------------------------------------------------------- void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask) { // just set floater visible. Screen channels will be cleared. @@ -211,7 +219,7 @@ void LLSysWellWindow::reshapeWindow() // it includes height from floater top to list top and from floater bottom and list bottom static S32 parent_list_delta_height = getRect().getHeight() - mMessageList->getRect().getHeight(); - if (isDocked()) // Don't reshape undocked Well window. See EXT-5715. + if (!mIsReshapedByUser) // Don't reshape Well window, if it ever was reshaped by user. See EXT-5715. { S32 notif_list_height = mMessageList->getItemsRect().getHeight() + 2 * mMessageList->getBorderWidth(); diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 3790aa3ea9..296bdf7482 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -70,6 +70,7 @@ public: /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); // override LLFloater's minimization according to EXT-1216 /*virtual*/ void setMinimized(BOOL minimize); + /*virtual*/ void handleReshape(const LLRect& rect, bool by_user); void onStartUpToastClick(S32 x, S32 y, MASK mask); @@ -121,7 +122,7 @@ protected: typedef std::map<EItemType, S32> typed_items_count_t; typed_items_count_t mTypedItemsCount; - + bool mIsReshapedByUser; }; /** diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 907740a88e..c9d2d404c0 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -45,6 +45,7 @@ #include "lltrans.h" #include "llnotificationsutil.h" #include "llviewermessage.h" +#include "llimfloater.h" const S32 BOTTOM_PAD = VPAD * 3; const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding @@ -531,12 +532,26 @@ void LLToastNotifyPanel::disableRespondedOptions(LLNotificationPtr& notification ////////////////////////////////////////////////////////////////////////// -LLIMToastNotifyPanel::LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLRect& rect /* = LLRect::null */) - : LLToastNotifyPanel(pNotification, rect) +LLIMToastNotifyPanel::LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect /* = LLRect::null */) + : mSessionID(session_id), LLToastNotifyPanel(pNotification, rect) { mTextBox->setFollowsAll(); } +LLIMToastNotifyPanel::~LLIMToastNotifyPanel() +{ + // We shouldn't delete notification when IM floater exists + // since that notification will be reused by IM floater. + // This may happened when IM floater reloads messages, exactly when user + // changes layout of IM chat log(disable/enable plaintext mode). + // See EXT-6500 + LLIMFloater* im_floater = LLIMFloater::findInstance(mSessionID); + if (im_floater != NULL && !im_floater->isDead()) + { + mCloseNotificationOnDestroy = false; + } +} + void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) { S32 text_height = mTextBox->getTextBoundingRect().getHeight(); diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index a8d2d03236..1c68e4c6b3 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -138,9 +138,14 @@ class LLIMToastNotifyPanel : public LLToastNotifyPanel { public: - LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null); + LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect = LLRect::null); + + ~LLIMToastNotifyPanel(); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + +protected: + LLUUID mSessionID; }; #endif /* LLTOASTNOTIFYPANEL_H_ */ diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 6f0d9cdd95..d3eed40f25 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -257,7 +257,43 @@ public: LLViewerMediaImpl *mMediaImpl; bool mInitialized; }; + +class LLViewerMediaOpenIDResponder : public LLHTTPClient::Responder +{ +LOG_CLASS(LLViewerMediaOpenIDResponder); +public: + LLViewerMediaOpenIDResponder( ) + { + } + + ~LLViewerMediaOpenIDResponder() + { + } + + /* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content) + { + LL_DEBUGS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL; + LL_DEBUGS("MediaAuth") << content << LL_ENDL; + std::string cookie = content["set-cookie"].asString(); + + LLViewerMedia::openIDCookieResponse(cookie); + } + + /* virtual */ void completedRaw( + U32 status, + const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + // This is just here to disable the default behavior (attempting to parse the response as llsd). + // We don't care about the content of the response, only the set-cookie header. + } + +}; + LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL; +LLURL LLViewerMedia::sOpenIDURL; +std::string LLViewerMedia::sOpenIDCookie; static LLViewerMedia::impl_list sViewerMediaImplList; static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap; static LLTimer sMediaCreateTimer; @@ -1067,7 +1103,8 @@ void LLViewerMedia::clearAllCookies() } } - + // If we have an OpenID cookie, re-add it to the cookie store. + setOpenIDCookie(); } ///////////////////////////////////////////////////////////////////////////////////////// @@ -1168,7 +1205,9 @@ void LLViewerMedia::loadCookieFile() pimpl->mMediaSource->clear_cookies(); } } - + + // If we have an OpenID cookie, re-add it to the cookie store. + setOpenIDCookie(); } @@ -1241,6 +1280,62 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom } +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::setOpenIDCookie() +{ + if(!sOpenIDCookie.empty()) + { + getCookieStore()->setCookiesFromHost(sOpenIDCookie, sOpenIDURL.mAuthority); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string &openid_token) +{ + LL_DEBUGS("MediaAuth") << "url = \"" << openid_url << "\", token = \"" << openid_token << "\"" << LL_ENDL; + + // post the token to the url + // the responder will need to extract the cookie(s). + + // Save the OpenID URL for later -- we may need the host when adding the cookie. + sOpenIDURL.init(openid_url.c_str()); + + // We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies. + sOpenIDCookie.clear(); + + LLSD headers = LLSD::emptyMap(); + // Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header + headers["Accept"] = "*/*"; + // and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream" + headers["Content-Type"] = "application/x-www-form-urlencoded"; + + // postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here. + size_t size = openid_token.size(); + U8 *data = new U8[size]; + memcpy(data, openid_token.data(), size); + + LLHTTPClient::postRaw( + openid_url, + data, + size, + new LLViewerMediaOpenIDResponder(), + headers); + +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::openIDCookieResponse(const std::string &cookie) +{ + LL_DEBUGS("MediaAuth") << "Cookie received: \"" << cookie << "\"" << LL_ENDL; + + sOpenIDCookie += cookie; + + setOpenIDCookie(); +} + bool LLViewerMedia::hasInWorldMedia() { if (sInWorldMediaDisabled) return false; @@ -1442,7 +1537,10 @@ void LLViewerMediaImpl::createMediaSource() } else if(! mMimeType.empty()) { - initializeMedia(mMimeType); + if (!initializeMedia(mMimeType)) + { + LL_WARNS("Media") << "Failed to initialize media for mime type " << mMimeType << LL_ENDL; + } } } diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 10dacf9532..e829d7a5b4 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -44,6 +44,8 @@ #include "llpluginclassmedia.h" #include "v4color.h" +#include "llurl.h" + class LLViewerMediaImpl; class LLUUID; class LLViewerMediaTexture; @@ -152,11 +154,17 @@ public: static void addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path = std::string("/"), bool secure = false ); static void addSessionCookie(const std::string &name, const std::string &value, const std::string &domain, const std::string &path = std::string("/"), bool secure = false ); static void removeCookie(const std::string &name, const std::string &domain, const std::string &path = std::string("/") ); + + static void openIDSetup(const std::string &openid_url, const std::string &openid_token); + static void openIDCookieResponse(const std::string &cookie); private: + static void setOpenIDCookie(); static void onTeleportFinished(); static LLPluginCookieStore *sCookieStore; + static LLURL sOpenIDURL; + static std::string sOpenIDCookie; }; // Implementation functions not exported into header file diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index eae60b4d85..7d87f06794 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1805,9 +1805,10 @@ class LLAdvancedDebugAvatarTextures : public view_listener_t { bool handleEvent(const LLSD& userdata) { -#ifndef LL_RELEASE_FOR_DOWNLOAD - handle_debug_avatar_textures(NULL); -#endif + if (gAgent.isGodlike()) + { + handle_debug_avatar_textures(NULL); + } return true; } }; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 6dc0983f10..1426c0b9e2 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1685,6 +1685,18 @@ bool inspect_remote_object_callback(const LLSD& notification, const LLSD& respon } static LLNotificationFunctorRegistration inspect_remote_object_callback_reg("ServerObjectMessage", inspect_remote_object_callback); +class LLPostponedServerObjectNotification: public LLPostponedNotification +{ +protected: + /* virtual */ + void modifyNotificationParams() + { + LLSD payload = mParams.payload; + payload["SESSION_NAME"] = mName; + mParams.payload = payload; + } +}; + void process_improved_im(LLMessageSystem *msg, void **user_data) { if (gNoRender) @@ -1754,17 +1766,15 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) std::string separator_string(": "); LLSD args; + LLSD payload; switch(dialog) { case IM_CONSOLE_AND_CHAT_HISTORY: - // These are used for system messages, hence don't need the name, - // as it is always "Second Life". // *TODO: Translate args["MESSAGE"] = message; - - // Note: don't put the message in the IM history, even though was sent - // via the IM mechanism. - LLNotificationsUtil::add("SystemMessageTip",args); + payload["SESSION_NAME"] = name; + payload["from_id"] = from_id; + LLNotificationsUtil::add("IMSystemMessageTip",args, payload); break; case IM_NOTHING_SPECIAL: @@ -1987,7 +1997,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // For requested notices, we don't want to send the popups. if (dialog != IM_GROUP_NOTICE_REQUESTED) { - LLSD payload; payload["subject"] = subj; payload["message"] = mes; payload["sender_name"] = name; @@ -2223,7 +2232,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) if(SYSTEM_FROM == name) { // System's UUID is NULL (fixes EXT-4766) - chat.mFromID = from_id = LLUUID::null; + chat.mFromID = LLUUID::null; } LLSD query_string; @@ -2269,13 +2278,16 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) payload["slurl"] = location; payload["name"] = name; std::string session_name; - gCacheName->getFullName(from_id, session_name); - payload["SESSION_NAME"] = session_name; if (from_group) { payload["group_owned"] = "true"; } - LLNotificationsUtil::add("ServerObjectMessage", substitutions, payload); + + LLNotification::Params params("ServerObjectMessage"); + params.substitutions = substitutions; + params.payload = payload; + + LLPostponedNotification::add<LLPostponedServerObjectNotification>(params, from_id, false); } break; case IM_FROM_TASK_AS_ALERT: @@ -2318,7 +2330,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) { LLSD args; // *TODO: Translate -> [FIRST] [LAST] (maybe) - args["NAME"] = name; + args["NAME_SLURL"] = LLSLURL::buildCommand("agent", from_id, "about"); args["MESSAGE"] = message; LLSD payload; payload["from_id"] = from_id; @@ -2384,7 +2396,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } else { - args["[NAME]"] = name; + args["NAME_SLURL"] = LLSLURL::buildCommand("agent", from_id, "about"); if(message.empty()) { //support for frienship offers from clients before July 2008 @@ -4031,7 +4043,7 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data) //clear animation flags avatarp = (LLVOAvatar *)gObjectList.findObject(uuid); - if (!isAgentAvatarValid()) + if (!avatarp) { // no agent by this ID...error? LL_WARNS("Messaging") << "Received animation state for unknown avatar" << uuid << LL_ENDL; @@ -5590,6 +5602,10 @@ void handle_lure(const LLUUID& invitee) // Prompt for a message to the invited user. void handle_lure(const uuid_vec_t& ids) { + if (ids.empty()) return; + + if (!gAgent.getRegion()) return; + LLSD edit_args; edit_args["REGION"] = gAgent.getRegion()->getName(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 6fb1a054ed..ae3f680cbf 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2090,7 +2090,7 @@ void LLViewerWindow::draw() // Draw tool specific overlay on world LLToolMgr::getInstance()->getCurrentTool()->draw(); - if( gAgentCamera.cameraMouselook() ) + if( gAgentCamera.cameraMouselook() || LLFloaterCamera::inFreeCameraMode() ) { drawMouselookInstructions(); stop_glerror(); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index fe6990eae9..c15dbeb8c6 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -87,14 +87,14 @@ using namespace LLVOAvatarDefines; struct LocalTextureData { LocalTextureData() : - mIsBakedReady(FALSE), + mIsBakedReady(false), mDiscard(MAX_DISCARD_LEVEL+1), mImage(NULL), mWearableID(IMG_DEFAULT_AVATAR), mTexEntry(NULL) {} LLPointer<LLViewerFetchedTexture> mImage; - BOOL mIsBakedReady; + bool mIsBakedReady; S32 mDiscard; LLUUID mWearableID; // UUID of the wearable that this texture belongs to, not of the image itself LLTextureEntry *mTexEntry; diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 4960d4d103..4856e82275 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -124,12 +124,10 @@ public: public: /*virtual*/ BOOL updateIsFullyLoaded(); private: - BOOL mIsBaked; // are the stored baked textures up to date? //-------------------------------------------------------------------- // Region state //-------------------------------------------------------------------- -private: U64 mLastRegionHandle; LLFrameTimer mRegionCrossingTimer; S32 mRegionCrossingCount; diff --git a/indra/newview/res-sdl/toolbuy.BMP b/indra/newview/res-sdl/toolbuy.BMP Binary files differnew file mode 100644 index 0000000000..07e9273721 --- /dev/null +++ b/indra/newview/res-sdl/toolbuy.BMP diff --git a/indra/newview/res-sdl/toolopen.BMP b/indra/newview/res-sdl/toolopen.BMP Binary files differnew file mode 100644 index 0000000000..5b87979304 --- /dev/null +++ b/indra/newview/res-sdl/toolopen.BMP diff --git a/indra/newview/res-sdl/toolsit.BMP b/indra/newview/res-sdl/toolsit.BMP Binary files differnew file mode 100644 index 0000000000..8ce59ae97a --- /dev/null +++ b/indra/newview/res-sdl/toolsit.BMP diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index 7a965cf57e..ecdcacec46 100644 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -129,8 +129,8 @@ TOOLBUY CURSOR "toolbuy.cur" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,0,0,3422 - PRODUCTVERSION 2,0,0,3422 + FILEVERSION 2,0,0,203110 + PRODUCTVERSION 2,0,0,203110 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -147,12 +147,12 @@ BEGIN BEGIN VALUE "CompanyName", "Linden Lab" VALUE "FileDescription", "Second Life" - VALUE "FileVersion", "2.0.0.200030" + VALUE "FileVersion", "2.0.0.203110" VALUE "InternalName", "Second Life" VALUE "LegalCopyright", "Copyright © 2001-2008, Linden Research, Inc." VALUE "OriginalFilename", "SecondLife.exe" VALUE "ProductName", "Second Life" - VALUE "ProductVersion", "2.0.0.200030" + VALUE "ProductVersion", "2.0.0.203110" END END BLOCK "VarFileInfo" diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index fcf5cfadb2..777d671e81 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -524,7 +524,7 @@ reference="Unused?" /> <color name="NetMapBackgroundColor" - value="0 0 0 0.3" /> + value="0 0 0 0" /> <color name="NetMapGroupOwnAboveWater" reference="Purple" /> diff --git a/indra/newview/skins/default/textures/windows/Icon_Gear_Background.png b/indra/newview/skins/default/textures/windows/Icon_Gear_Background.png Binary files differindex db74b93afd..93d62a8d4f 100644 --- a/indra/newview/skins/default/textures/windows/Icon_Gear_Background.png +++ b/indra/newview/skins/default/textures/windows/Icon_Gear_Background.png diff --git a/indra/newview/skins/default/textures/windows/Icon_Gear_Foreground.png b/indra/newview/skins/default/textures/windows/Icon_Gear_Foreground.png Binary files differindex 1032e45f7e..b2b2a77a88 100644 --- a/indra/newview/skins/default/textures/windows/Icon_Gear_Foreground.png +++ b/indra/newview/skins/default/textures/windows/Icon_Gear_Foreground.png diff --git a/indra/newview/skins/default/textures/windows/Icon_Gear_Over.png b/indra/newview/skins/default/textures/windows/Icon_Gear_Over.png Binary files differindex 01dbde102b..67bd399358 100644 --- a/indra/newview/skins/default/textures/windows/Icon_Gear_Over.png +++ b/indra/newview/skins/default/textures/windows/Icon_Gear_Over.png diff --git a/indra/newview/skins/default/textures/windows/Icon_Gear_Press.png b/indra/newview/skins/default/textures/windows/Icon_Gear_Press.png Binary files differindex 6614bdd165..6fc3744d6b 100644 --- a/indra/newview/skins/default/textures/windows/Icon_Gear_Press.png +++ b/indra/newview/skins/default/textures/windows/Icon_Gear_Press.png diff --git a/indra/newview/skins/default/xui/da/language_settings.xml b/indra/newview/skins/default/xui/da/language_settings.xml index 71418d446a..fa8a788605 100644 --- a/indra/newview/skins/default/xui/da/language_settings.xml +++ b/indra/newview/skins/default/xui/da/language_settings.xml @@ -3,9 +3,9 @@ <strings> <!-- Locale Information --> - <string name="MicrosoftLocale">english</string> - <string name="DarwinLocale">C</string> - <string name="LinuxLocale">C</string> + <string name="MicrosoftLocale">danish</string> + <string name="DarwinLocale">da_DK.UTF-8</string> + <string name="LinuxLocale">da_DK.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu diff --git a/indra/newview/skins/default/xui/de/language_settings.xml b/indra/newview/skins/default/xui/de/language_settings.xml index 71418d446a..3e357007ff 100644 --- a/indra/newview/skins/default/xui/de/language_settings.xml +++ b/indra/newview/skins/default/xui/de/language_settings.xml @@ -3,9 +3,9 @@ <strings> <!-- Locale Information --> - <string name="MicrosoftLocale">english</string> - <string name="DarwinLocale">C</string> - <string name="LinuxLocale">C</string> + <string name="MicrosoftLocale">german</string> + <string name="DarwinLocale">de_DE.UTF-8</string> + <string name="LinuxLocale">de_DE.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu diff --git a/indra/newview/skins/default/xui/de/panel_status_bar.xml b/indra/newview/skins/default/xui/de/panel_status_bar.xml index 0e182fa417..803bd1b5ab 100644 --- a/indra/newview/skins/default/xui/de/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/de/panel_status_bar.xml @@ -22,7 +22,7 @@ [AMT] L$ </panel.string> <button label="" label_selected="" name="buycurrency" tool_tip="Mein Kontostand"/> - <button label="Kaufen" name="buyL" tool_tip="Hier klicken, um mehr L$ zu kaufen"/> + <button label=" " name="buyL" tool_tip="Hier klicken, um mehr L$ zu kaufen"/> <text name="TimeText" tool_tip="Aktuelle Zeit (Pazifik)"> 24:00 H PST </text> diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index bc67621dfd..d03231a3fa 100644 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -76,7 +76,7 @@ Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number allow_html="true" follows="top|left" font="SansSerif" - height="350" + height="343" bg_readonly_color="Transparent" left="5" max_length="65536" diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml index e02d32596a..637f9f55d4 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml @@ -24,13 +24,13 @@ <text type="string" length="1" - follows="top|left" + follows="top|left|right" font="SansSerifHuge" layout="topleft" left="20" height="30" top="25" - width="300" + width="340" name="info_need_more"> You need more L$ </text> @@ -55,7 +55,7 @@ left="20" height="30" top="25" - width="200" + width="300" name="info_buying"> Buy L$ </text> @@ -178,8 +178,8 @@ follows="top|left" height="16" halign="right" - left="140" - width="180" + left="20" + width="300" layout="topleft" name="buy_action"> [ACTION] diff --git a/indra/newview/skins/default/xui/en/floater_event.xml b/indra/newview/skins/default/xui/en/floater_event.xml index 0255e202fb..d9c9d63c72 100644 --- a/indra/newview/skins/default/xui/en/floater_event.xml +++ b/indra/newview/skins/default/xui/en/floater_event.xml @@ -244,6 +244,7 @@ layout="topleft" left="6" name="event_desc" + textbox.label="More" width="322"> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</expandable_text> </layout_panel> diff --git a/indra/newview/skins/default/xui/en/floater_god_tools.xml b/indra/newview/skins/default/xui/en/floater_god_tools.xml index 36ef6beb59..240871ec25 100644 --- a/indra/newview/skins/default/xui/en/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_god_tools.xml @@ -31,19 +31,6 @@ <button follows="left|top" height="20" - label="Kick all Residents" - label_selected="Kick all Residents" - layout="topleft" - left="10" - name="Kick all users" - top="30" - width="120"> - <button.commit_callback - function="GridTools.KickAll" /> - </button> - <button - follows="left|top" - height="20" label="Flush This Region's Map Visibility Caches" label_selected="Flush This Region's Map Visibility Caches" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_map.xml b/indra/newview/skins/default/xui/en/floater_map.xml index 5d35275e17..e21e44204d 100644 --- a/indra/newview/skins/default/xui/en/floater_map.xml +++ b/indra/newview/skins/default/xui/en/floater_map.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + bg_alpha_image_overlay="DkGray_66" legacy_header_height="18" can_minimize="true" can_resize="true" diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index fd046c3695..4c67698943 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2701,15 +2701,15 @@ even though the user gets a free copy. <button follows="top|left" tool_tip="Edit this Media" - height="18" - image_disabled="OptionsMenu_Disabled" - image_selected="OptionsMenu_Press" - image_unselected="OptionsMenu_Off" + height="12" + image_disabled="Icon_Gear_Foreground" + image_selected="Icon_Gear_Background" + image_unselected="Icon_Gear_Press" layout="topleft" left_pad="10" name="edit_media" - top_delta="0" - width="18"> + top_delta="3" + width="12"> <button.commit_callback function="BuildTool.EditMedia"/> </button> @@ -2842,7 +2842,7 @@ even though the user gets a free copy. left_delta="0" name="button about land" top_pad="4" - width="112" /> + width="125" /> <check_box control_name="ShowParcelOwners" height="19" @@ -2863,7 +2863,7 @@ even though the user gets a free copy. left="20" name="label_parcel_modify" top="152" - width="150"> + width="240"> Modify Parcel </text> <button @@ -2875,7 +2875,7 @@ even though the user gets a free copy. left="30" name="button subdivide land" top="172" - width="112" /> + width="125" /> <button follows="left|top" height="23" @@ -2885,7 +2885,7 @@ even though the user gets a free copy. left_delta="0" name="button join land" top_pad="4" - width="112" /> + width="125" /> <text type="string" length="1" @@ -2896,7 +2896,7 @@ even though the user gets a free copy. left="20" name="label_parcel_trans" top="256" - width="150"> + width="240"> Land Transactions </text> <button @@ -2908,7 +2908,7 @@ even though the user gets a free copy. left="30" name="button buy land" top="276" - width="112" /> + width="125" /> <button follows="left|top" height="23" @@ -2918,6 +2918,6 @@ even though the user gets a free copy. left_delta="0" name="button abandon land" top_pad="4" - width="112" /> + width="125" /> </panel> </floater> diff --git a/indra/newview/skins/default/xui/en/inspect_object.xml b/indra/newview/skins/default/xui/en/inspect_object.xml index 00e00b9694..b8a7222e8e 100644 --- a/indra/newview/skins/default/xui/en/inspect_object.xml +++ b/indra/newview/skins/default/xui/en/inspect_object.xml @@ -26,6 +26,7 @@ owner [OWNER] <string name="Touch">Touch</string> <string name="Sit">Sit</string> <text + allow_html="false" follows="all" font="SansSerifLarge" height="16" diff --git a/indra/newview/skins/default/xui/en/main_view.xml b/indra/newview/skins/default/xui/en/main_view.xml index e8f9d65be5..b2e4a7ad95 100644 --- a/indra/newview/skins/default/xui/en/main_view.xml +++ b/indra/newview/skins/default/xui/en/main_view.xml @@ -164,15 +164,6 @@ tab_group="-2" width="1024"/> <panel top="0" - follows="all" - height="768" - mouse_opaque="true" - name="progress_view" - filename="panel_progress.xml" - class="progress_view" - width="1024" - visible="false"/> - <panel top="0" follows="all" mouse_opaque="false" left="0" @@ -193,6 +184,15 @@ <panel top="0" follows="all" height="768" + mouse_opaque="true" + name="progress_view" + filename="panel_progress.xml" + class="progress_view" + width="1024" + visible="false"/> + <panel top="0" + follows="all" + height="768" mouse_opaque="false" name="popup_holder" class="popup_holder" diff --git a/indra/newview/skins/default/xui/en/menu_group_plus.xml b/indra/newview/skins/default/xui/en/menu_group_plus.xml index e83d07baec..fce7414d80 100644 --- a/indra/newview/skins/default/xui/en/menu_group_plus.xml +++ b/indra/newview/skins/default/xui/en/menu_group_plus.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <menu name="menu_group_plus" left="0" bottom="0" visible="false" - mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false"> + mouse_opaque="false"> <menu_item_call name="item_join" label="Join Group..."> <menu_item_call.on_click function="People.Group.Plus.Action" userdata="join_group" /> </menu_item_call> diff --git a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml index 1b002b1c32..a5ac5f76e1 100644 --- a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml @@ -40,6 +40,8 @@ name="teleport"> <menu_item_call.on_click function="InspectAvatar.Teleport"/> + <menu_item_call.on_enable + function="InspectAvatar.Gear.EnableTeleportOffer"/> </menu_item_call> <menu_item_call label="Invite to Group" diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml index f1117d1419..92752a0fee 100644 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <menu name="menu_group_plus" left="0" bottom="0" visible="false" - mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false"> + mouse_opaque="false"> <menu_item_check label="Sort by Name" name="sort_name"> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml index df3cb26b04..2efb204ffb 100644 --- a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <menu name="menu_group_plus" left="0" bottom="0" visible="false" - mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false"> + mouse_opaque="false"> <menu_item_check label="Display Group Icons" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index 014a52bb4f..d2e35e4cc0 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -88,5 +88,8 @@ name="teleport"> <menu_item_call.on_click function="Avatar.OfferTeleport"/> + <menu_item_call.on_enable + function="Avatar.EnableItem" + parameter="can_offer_teleport"/> </menu_item_call> </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml index 39f9e48609..69b3831738 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <menu name="menu_group_plus" left="0" bottom="0" visible="false" - mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false"> + mouse_opaque="false"> <menu_item_check label="Sort by Recent Speakers" name="sort_by_recent_speakers"> diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml index cfd6dc78b6..5c9555db92 100644 --- a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <menu name="menu_group_plus" left="0" bottom="0" visible="false" - mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false"> + mouse_opaque="false"> <menu_item_check label="Sort by Most Recent" name="sort_most"> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 43f594ca5a..8b4554502a 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -137,7 +137,8 @@ </menu_item_call> <menu_item_call label="My Groups" - name="My Groups"> + name="My Groups" + shortcut="control|shift|G"> <menu_item_call.on_click function="SideTray.PanelPeopleTab" parameter="groups_panel" /> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index c39a91281e..3d41989e54 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3111,6 +3111,18 @@ Teleport to [PICK]? </notification> <notification + icon="alertmodal.tga" + name="TeleportToHistoryEntry" + type="alertmodal"> +Teleport to [HISTORY_ENTRY]? + <usetemplate + ignoretext="Confirm that I want to teleport to a history location" + name="okcancelignore" + notext="Cancel" + yestext="Teleport"/> + </notification> + + <notification icon="alert.tga" label="Message everyone in your Estate" name="MessageEstate" @@ -4269,6 +4281,13 @@ The string [STRING_NAME] is missing from strings.xml type="notifytip"> [MESSAGE] </notification> + + <notification + icon="notifytip.tga" + name="IMSystemMessageTip" + type="notifytip"> +[MESSAGE] + </notification> <notification icon="notifytip.tga" @@ -5103,7 +5122,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you th icon="notify.tga" name="TeleportOffered" type="offer"> -[NAME] has offered to teleport you to their location: +[NAME_SLURL] has offered to teleport you to their location: [MESSAGE] <form name="form"> @@ -5148,7 +5167,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you th icon="notify.tga" name="OfferFriendship" type="offer"> -[NAME] is offering friendship. +[NAME_SLURL] is offering friendship. [MESSAGE] diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 58c5c11e51..c34a367c32 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -263,7 +263,7 @@ top="0" name="chiclet_list_panel" width="189" - min_width="60" + min_width="95" user_resize="false" auto_resize="true"> <!--*NOTE: min_width of the chiclet_panel (chiclet_list) must be the same @@ -274,7 +274,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. height="24" layout="topleft" left="1" - min_width="60" + min_width="95" name="chiclet_list" top="7" chiclet_padding="4" @@ -330,7 +330,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. min_width="4" name="DUMMY" top="0" - width="5"/> + width="4"/> <layout_panel auto_resize="false" follows="right" @@ -339,8 +339,8 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. min_height="28" top="0" name="im_well_panel" - width="35" - min_width="35" + width="37" + min_width="37" user_resize="false"> <chiclet_im_well max_displayed_count="99" @@ -388,22 +388,10 @@ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well layout="topleft" min_height="28" top="0" - left_pad="3" name="notification_well_panel" - width="40" - min_width="40" + width="37" + min_width="37" user_resize="false"> - <icon - auto_resize="false" - color="0 0 0 0" - follows="left|right" - height="10" - image_name="spacer24.tga" - layout="topleft" - left="0" - min_width="4" - top="0" - width="5" /> <chiclet_notification flash_period="0.25" follows="right" @@ -434,17 +422,6 @@ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well function="Button.SetDockableFloaterToggle" parameter="notification_well_window" /> </button> - <icon - auto_resize="false" - color="0 0 0 0" - follows="left|right" - height="10" - image_name="spacer24.tga" - layout="topleft" - left="0" - min_width="4" - top="0" - width="5" /> </chiclet_notification> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml index 250dadd390..9124ad528d 100644 --- a/indra/newview/skins/default/xui/en/panel_chat_header.xml +++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml @@ -21,6 +21,7 @@ top="3" width="18" /> <text + allow_html="false" allow_scroll="false" v_pad = "7" read_only = "true" diff --git a/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml b/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml index 996e28c575..af3315ebfe 100644 --- a/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml @@ -65,6 +65,7 @@ left="103" name="description" textbox.max_length="1024" + textbox.label="More" textbox.show_context_menu="false" top_pad="0" width="178" diff --git a/indra/newview/skins/default/xui/en/panel_group_notices.xml b/indra/newview/skins/default/xui/en/panel_group_notices.xml index 731b3c119c..479629f6ea 100644 --- a/indra/newview/skins/default/xui/en/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml @@ -131,6 +131,7 @@ Maximum 200 per group daily Subject: </text> <line_editor + follows="left|top|right" border_style="line" border_thickness="1" height="16" @@ -153,6 +154,7 @@ Maximum 200 per group daily Message: </text> <text_editor + follows="left|top|right" height="90" layout="topleft" left_pad="3" @@ -173,6 +175,7 @@ Maximum 200 per group daily Attach: </text> <line_editor + follows="left|top|right" enabled="false" height="19" layout="topleft" @@ -222,7 +225,7 @@ Maximum 200 per group daily label="Send" label_selected="Send" layout="topleft" - right="-10" + right="-25" top_pad="10" name="send_notice" width="100" /> diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml index 88566ea037..7d7e21d4b0 100644 --- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml +++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml @@ -16,7 +16,7 @@ border_size="0" clip="false" follows="all" - height="168" + height="183" layout="topleft" left="5" name="button_stack" diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml index befeb182f9..31ba539c44 100644 --- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml +++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml @@ -133,6 +133,7 @@ layout="topleft" left="10" name="description" + textbox.label="More" top_pad="10" value="Du waltz die spritz" width="280" /> diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index 639e5d30ef..a7e87f2a1e 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -16,7 +16,7 @@ bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" follows="all" - height="369" + height="373" layout="topleft" left="3" name="landmarks_accordion" diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index bef62f48e0..6c81107dde 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -411,13 +411,13 @@ top="+31" width="303" /> <tab_container - bg_opaque_color="DkGray2" - bg_alpha_color="DkGray2" + bg_alpha_color="DkGray" + bg_opaque_color="DkGray" background_visible="true" background_opaque="true" follows="all" halign="center" - height="306" + height="311" layout="topleft" left="7" name="inventory filter tabs" @@ -434,7 +434,7 @@ border="false" bevel_style="none" follows="all" - height="295" + height="310" label="MY INVENTORY" help_topic="my_inventory_tab" layout="topleft" @@ -451,7 +451,7 @@ border="false" bevel_style="none" follows="all" - height="293" + height="310" label="RECENT" help_topic="recent_inventory_tab" layout="topleft" @@ -466,7 +466,7 @@ follows="left|right|bottom" height="27" layout="topleft" - top_pad="4" + top_pad="-1" left="10" name="bottom_panel" width="310"> diff --git a/indra/newview/skins/default/xui/en/panel_my_profile.xml b/indra/newview/skins/default/xui/en/panel_my_profile.xml index 4112b65635..5e41d65720 100644 --- a/indra/newview/skins/default/xui/en/panel_my_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_my_profile.xml @@ -117,6 +117,8 @@ layout="topleft" left="107" textbox.max_length="512" + textbox.label="More" + textbox.show_context_menu="true" name="sl_description_edit" top_pad="-3" translate="false" @@ -171,6 +173,8 @@ layout="topleft" left="107" textbox.max_length="512" + textbox.label="More" + textbox.show_context_menu="true" name="fl_description_edit" top_pad="-3" translate="false" @@ -311,6 +315,8 @@ name="sl_groups" top_pad="0" translate="false" + textbox.label="More" + textbox.show_context_menu="true" width="298" expanded_bg_visible="true" expanded_bg_color="DkGray"> diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml new file mode 100644 index 0000000000..4d3ee07195 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -0,0 +1,346 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- Side tray Outfit Edit panel --> +<panel + background_visible="true" + border="false" + height="600" + follows="all" + label="Outfit Edit" + layout="topleft" + left="0" + min_height="350" + name="outfit_edit" + top="0" + width="320"> + + <panel.string + name="not_available"> + (N\A) + </panel.string> + <panel.string + name="unknown"> + (unknown) + </panel.string> + + + <button + follows="top|left" + height="23" + image_overlay="BackArrow_Off" + layout="topleft" + name="back_btn" + left="5" + tab_stop="false" + top="2" + width="23" /> + <text + follows="top|right" + font="SansSerifHugeBold" + height="26" + layout="topleft" + left_pad="20" + name="title" + text_color="LtGray" + top="0" + value="Edit Outfit" + use_ellipses="true" + width="275" /> + +<!-- "HEADER WITH ICON, STATUS TEXT AND OUTFIT NAME" --> + <panel + bevel_style="none" + follows="top|left|right" + height="45" + label="bottom_panel" + layout="topleft" + left="5" + name="header_panel" + top_pad="5" + width="300"> + <icon + follows="left|top" + height="40" + image_name="t-shirt-image" + left="2" + mouse_opaque="false" + name="outfit_icon" + top="1" + scale_image="true" + visible="true" + width="35" /> + <panel + bevel_style="none" + follows="top|right" + height="40" + label="bottom_panel" + layout="topleft" + left_pad="10" + name="outfit_name_and_status" + top="2" + width="200"> + <text + follows="top|left|right" + font="SansSerif" + height="13" + layout="topleft" + name="status" + text_color="Green" + top="0" + value="Editing..." + use_ellipses="true" + width="275" /> + <text + follows="bottom|left|right" + font="SansSerifHugeBold" + height="26" + layout="topleft" + name="curr_look_name" + text_color="LtGray" + top_pad="0" + value="[Current Outfit]" + use_ellipses="true" + width="275" /> + </panel> + </panel> + + +<!-- LIST OF WEARABLES (CURRENT OUTFIT/ WEARABLES TO ADD) --> + <layout_stack + animate="false" + default_tab_group="2" + follows="all" + height="470" + width="300" + layout="topleft" + orientation="vertical" + name="im_panels" + tab_group="1" + top_pad="10" + left="5"> + <layout_panel + layout="topleft" + follows="left|top|right" + height="220" + label="IM Control Panel" + min_height="100" + name="outfit_wearables_panel" + width="300" + auto_resize="true" + user_resize="true"> + + <scroll_list + width="300" + column_padding="0" + draw_heading="false" + draw_stripes="false" + follows="left|top|right|bottom" + layout="topleft" + name="look_items_list" + search_column="1" + sort_column="2" + left="0" + height="193" + top="0"> + <scroll_list.columns + label="Look Item" + name="look_item" + width="285" /> + <scroll_list.columns + label="Outfit Item Sort" + width="0" + sort_column="look_item_sort" + name="look_item_sort" /> + </scroll_list> + + <panel + background_visible="true" + bevel_style="none" + follows="bottom|left|right" + height="27" + label="bottom_panel" + layout="topleft" + left="0" + name="edit_panel" + top_pad="0" + width="300"> + <button + follows="bottom|left" + height="25" + image_hover_unselected="Toolbar_Left_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Left_Selected" + image_unselected="Toolbar_Left_Off" + layout="topleft" + left="0" + name="gear_menu_btn" + top="1" + width="31" /> + <button + is_toggle="true" + follows="bottom|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="1" + name="add_btn" + top="1" + width="31" /> + <button + follows="bottom|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="1" + name="new_btn" + top="1" + width="31" /> + <button + follows="bottom|right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TrashItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + name="trash_btn" + right="-1" + top="1" + width="31" /> + </panel> + </layout_panel> + + + <layout_panel + auto_resize="true" + default_tab_group="3" + height="250" + min_height="120" + name="add_wearables_panel" + width="300" + tab_group="2" + user_resize="true" + visible="false"> + + <text + follows="top|left|right" + font="SansSerifBold" + height="13" + layout="topleft" + left="5" + name="status" + text_color="LtGray" + top="5" + value="Add Wearables" + use_ellipses="true" + width="275" /> + + <filter_editor + background_image="TextField_Search_Off" + follows="left|top|right" + font="SansSerif" + label="Filter" + layout="topleft" + left="5" + width="290" + height="20" + name="look_item_filter" + text_color="black" + text_pad_left="25" /> + + <inventory_panel + allow_multi_select="true" + border="false" + follows="left|top|right|bottom" + height="176" + layout="topleft" + left="0" + mouse_opaque="false" + name="inventory_items" + top_pad="5" + width="300"/> + + <panel + background_visible="true" + bevel_style="none" + follows="left|right|bottom" + height="27" + label="add_wearables_button_bar" + layout="topleft" + left="0" + name="add_wearables_button_bar" + top_pad="0" + width="300"> + <button + follows="bottom|left" + height="25" + image_hover_unselected="Toolbar_Left_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Left_Selected" + image_unselected="Toolbar_Left_Off" + layout="topleft" + left="0" + name="wearables_gear_menu_btn" + top="1" + width="31" /> + <button + follows="bottom|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + label="F" + layout="topleft" + left_pad="1" + name="folder_view_btn" + top="1" + width="31" /> + <button + follows="bottom|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + label="L" + layout="topleft" + left_pad="1" + name="list_view_btn" + top="1" + width="31" /> + </panel> + </layout_panel> + </layout_stack> + + <panel + follows="left|right|bottom" + height="30" + layout="topleft" + left="5" + top_pad="10" + name="save_revert_button_bar" + width="300"> + <button + follows="bottom|left|right" + height="23" + label="Save" + left="0" + layout="topleft" + name="save_btn" + width="145" /> + <button + follows="bottom|left|right" + height="23" + left_pad="15" + label="Revert" + layout="topleft" + name="revert_btn" + width="145" /> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml index 66ef373168..f9ad525642 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -14,7 +14,7 @@ border="false"> <tab_container follows="all" - height="497" + height="501" layout="topleft" left="7" name="appearance_tabs" @@ -58,7 +58,7 @@ height="73" layout="topleft" left="9" - top_pad="3" + top_pad="-1" visible="true" name="bottom_panel" width="310"> @@ -119,13 +119,13 @@ <button follows="bottom|left" height="23" - label="M" + label="Edit Outfit" layout="topleft" right="-140" name="look_edit_btn" top="26" visible="false" - width="20" /> + width="50" /> </panel> </panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 85841da48f..6152dd1587 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -81,7 +81,7 @@ bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" follows="all" - height="352" + height="356" ignore_online_status="true" layout="topleft" left="3" @@ -97,6 +97,7 @@ layout="topleft" left="3" name="bottom_panel" + top_pad="0" width="313"> <button follows="bottom|left" @@ -156,7 +157,7 @@ bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" follows="all" - height="352" + height="356" layout="topleft" left="3" name="friends_accordion" @@ -204,6 +205,7 @@ layout="topleft" left="3" name="bottom_panel" + top_pad="0" width="313"> <button follows="bottom|left" @@ -237,7 +239,7 @@ layout="topleft" left_pad="1" name="dummy_icon" - width="210" + width="209" /> <button follows="bottom|left" @@ -287,7 +289,7 @@ If you're looking for people to hang out with, [secondlife:///app/worldmap try t bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" follows="all" - height="352" + height="356" layout="topleft" left="3" name="group_list" @@ -303,6 +305,7 @@ If you're looking for people to hang out with, [secondlife:///app/worldmap try t layout="topleft" left="0" name="bottom_panel" + top_pad="0" width="313"> <button follows="bottom|left" @@ -372,7 +375,7 @@ If you're looking for people to hang out with, [secondlife:///app/worldmap try t bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" follows="all" - height="352" + height="356" layout="topleft" left="3" multi_select="true" @@ -388,6 +391,7 @@ If you're looking for people to hang out with, [secondlife:///app/worldmap try t layout="topleft" left="0" name="bottom_panel" + top_pad="0" width="313"> <button follows="bottom|left" diff --git a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml index 715dc5f23c..41651edaa0 100644 --- a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml @@ -65,6 +65,7 @@ left="103" name="picture_descr" textbox.max_length="1024" + textbox.label="More" textbox.show_context_menu="false" top_pad="0" width="178" diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml index 2efcfa5772..a43b244fa0 100644 --- a/indra/newview/skins/default/xui/en/panel_place_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml @@ -275,6 +275,7 @@ layout="topleft" left="5" name="description" + textbox.label="More" top_pad="10" value="Du waltz die spritz" width="300" /> diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index 30191aecb6..a666608103 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -107,6 +107,8 @@ layout="topleft" left="107" textbox.max_length="512" + textbox.label="More" + textbox.show_context_menu="true" name="sl_description_edit" top_pad="-3" translate="false" @@ -151,6 +153,8 @@ layout="topleft" left="107" textbox.max_length="512" + textbox.label="More" + textbox.show_context_menu="true" name="fl_description_edit" top_pad="-3" translate="false" @@ -289,6 +293,8 @@ left="7" name="sl_groups" textbox.max_length="512" + textbox.label="More" + textbox.show_context_menu="true" top_pad="0" translate="false" width="290" diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history.xml b/indra/newview/skins/default/xui/en/panel_teleport_history.xml index cbcaf1a58c..21addb8e6f 100644 --- a/indra/newview/skins/default/xui/en/panel_teleport_history.xml +++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml @@ -6,7 +6,7 @@ bg_alpha_color="DkGray"> <accordion follows="left|top|right|bottom" - height="369" + height="373" layout="topleft" left="3" top="0" diff --git a/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml index cd66c56ca1..7b22b2cce1 100644 --- a/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml +++ b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml @@ -32,9 +32,9 @@ parameter="MuteAudio" /> </slider> <button - left="7" + left="10" top_pad="9" - width="18" + width="12" height="12" follows="top|left" name="prefs_btn" diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml index b3d55fec65..20a1de59fc 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml @@ -102,14 +102,17 @@ width="333"> name="newlook_btn" width="100" />--> <panel - class="panel_look_info" - filename="panel_look_info.xml" + class="panel_outfit_edit" + filename="panel_outfit_edit.xml" + height="550" follows="all" layout="topleft" - left="0" - name="panel_look_info" - top="35" - visible="false" /> + left="5" + min_height="410" + name="panel_outfit_edit" + top="5" + visible="false" + width="320"/> <panel class="panel_edit_wearable" filename="panel_edit_wearable.xml" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 00bbbd65d0..0c73b8d769 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -114,6 +114,7 @@ <!-- ButtonToolTips, llfloater.cpp --> <string name="BUTTON_CLOSE_DARWIN">Close (⌘W)</string> <string name="BUTTON_CLOSE_WIN">Close (Ctrl+W)</string> + <string name="BUTTON_CLOSE_CHROME">Close</string>> <string name="BUTTON_RESTORE">Restore</string> <string name="BUTTON_MINIMIZE">Minimize</string> <string name="BUTTON_TEAR_OFF">Tear Off</string> @@ -3048,6 +3049,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="unread_chat_multiple"> [SOURCES] have said something new </string>" + <string name="session_initialization_timed_out_error"> + The session initialization is timed out + </string> <!-- Financial operations strings --> <string name="paid_you_ldollars">[NAME] paid you L$[AMOUNT]</string> diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml index aa3ea736b8..ef885e8045 100644 --- a/indra/newview/skins/default/xui/en/widgets/chat_history.xml +++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml @@ -2,7 +2,6 @@ <chat_history message_header="panel_chat_header.xml" message_separator="panel_chat_separator.xml" - message_plaintext_separator="panel_chat_plaintext_separator.xml" left_text_pad="10" right_text_pad="15" left_widget_pad="0" diff --git a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml index d9b6387f0d..6190ea7872 100644 --- a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml +++ b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml @@ -5,7 +5,7 @@ allow_html="true" allow_scroll="true" bg_visible="false" - more_label="More" + label="More" follows="left|top|right" name="text" read_only="true" diff --git a/indra/newview/skins/default/xui/en/widgets/text.xml b/indra/newview/skins/default/xui/en/widgets/text.xml index 855584a0db..998ec5b170 100644 --- a/indra/newview/skins/default/xui/en/widgets/text.xml +++ b/indra/newview/skins/default/xui/en/widgets/text.xml @@ -15,6 +15,7 @@ bg_visible="false" border_visible="false" hover="false" + sound_flags="0" text_color="LabelTextColor" v_pad="0" max_length="4096"/> diff --git a/indra/newview/skins/default/xui/es/floater_tools.xml b/indra/newview/skins/default/xui/es/floater_tools.xml index ac3a949821..9c5fea9267 100644 --- a/indra/newview/skins/default/xui/es/floater_tools.xml +++ b/indra/newview/skins/default/xui/es/floater_tools.xml @@ -399,7 +399,7 @@ máximo" name="checkbox fullbright"/> <text name="tex gen"> Detallado </text> - <combo_box name="combobox texgen" width="86"> + <combo_box name="combobox texgen"> <combo_box.item label="Por defecto" name="Default"/> <combo_box.item label="Plano" name="Planar"/> </combo_box> @@ -442,9 +442,9 @@ máximo" name="checkbox fullbright"/> <check_box label="Voltear" name="checkbox flip s"/> <spinner label="Vertical (V)" name="TexScaleV"/> <check_box label="Voltear" name="checkbox flip t"/> - <spinner label="Rotación" left="118" name="TexRot" width="62"/> - <spinner label="Repeticiones / Metro" left="118" name="rptctrl" width="62"/> - <button label="Aplicar" label_selected="Aplicar" left_delta="72" name="button apply"/> + <spinner label="Rotación" name="TexRot"/> + <spinner label="Repeticiones / Metro" name="rptctrl"/> + <button label="Aplicar" label_selected="Aplicar" name="button apply"/> <text name="tex offset"> Desplazar </text> @@ -487,8 +487,8 @@ Gris = Público"/> <text name="label_parcel_modify"> Modificar la parcela </text> - <button label="Dividir" label_selected="Dividir" name="button subdivide land" width="140"/> - <button label="Inscribirse" label_selected="Inscribirse" name="button join land" width="140"/> + <button label="Dividir" label_selected="Dividir" name="button subdivide land"/> + <button label="Inscribirse" label_selected="Inscribirse" name="button join land"/> <text name="label_parcel_trans"> Transacciones de terreno </text> diff --git a/indra/newview/skins/default/xui/es/language_settings.xml b/indra/newview/skins/default/xui/es/language_settings.xml index 71418d446a..1ade4ba300 100644 --- a/indra/newview/skins/default/xui/es/language_settings.xml +++ b/indra/newview/skins/default/xui/es/language_settings.xml @@ -3,9 +3,9 @@ <strings> <!-- Locale Information --> - <string name="MicrosoftLocale">english</string> - <string name="DarwinLocale">C</string> - <string name="LinuxLocale">C</string> + <string name="MicrosoftLocale">spanish</string> + <string name="DarwinLocale">es_ES.UTF-8</string> + <string name="LinuxLocale">es_ES.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu diff --git a/indra/newview/skins/default/xui/fr/language_settings.xml b/indra/newview/skins/default/xui/fr/language_settings.xml index 71418d446a..117ae16ee8 100644 --- a/indra/newview/skins/default/xui/fr/language_settings.xml +++ b/indra/newview/skins/default/xui/fr/language_settings.xml @@ -3,9 +3,9 @@ <strings> <!-- Locale Information --> - <string name="MicrosoftLocale">english</string> - <string name="DarwinLocale">C</string> - <string name="LinuxLocale">C</string> + <string name="MicrosoftLocale">french</string> + <string name="DarwinLocale">fr_FR.UTF-8</string> + <string name="LinuxLocale">fr_FR.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu diff --git a/indra/newview/skins/default/xui/it/language_settings.xml b/indra/newview/skins/default/xui/it/language_settings.xml index 71418d446a..82cf789a6b 100644 --- a/indra/newview/skins/default/xui/it/language_settings.xml +++ b/indra/newview/skins/default/xui/it/language_settings.xml @@ -3,9 +3,9 @@ <strings> <!-- Locale Information --> - <string name="MicrosoftLocale">english</string> - <string name="DarwinLocale">C</string> - <string name="LinuxLocale">C</string> + <string name="MicrosoftLocale">italian</string> + <string name="DarwinLocale">it_IT.UTF-8</string> + <string name="LinuxLocale">it_IT.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu diff --git a/indra/newview/skins/default/xui/ja/language_settings.xml b/indra/newview/skins/default/xui/ja/language_settings.xml index 71418d446a..72382417d9 100644 --- a/indra/newview/skins/default/xui/ja/language_settings.xml +++ b/indra/newview/skins/default/xui/ja/language_settings.xml @@ -3,9 +3,9 @@ <strings> <!-- Locale Information --> - <string name="MicrosoftLocale">english</string> - <string name="DarwinLocale">C</string> - <string name="LinuxLocale">C</string> + <string name="MicrosoftLocale">japanese</string> + <string name="DarwinLocale">ja_JP.UTF-8</string> + <string name="LinuxLocale">ja_JP.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu diff --git a/indra/newview/skins/default/xui/nl/language_settings.xml b/indra/newview/skins/default/xui/nl/language_settings.xml index 71418d446a..dc4663705f 100644 --- a/indra/newview/skins/default/xui/nl/language_settings.xml +++ b/indra/newview/skins/default/xui/nl/language_settings.xml @@ -3,9 +3,9 @@ <strings> <!-- Locale Information --> - <string name="MicrosoftLocale">english</string> - <string name="DarwinLocale">C</string> - <string name="LinuxLocale">C</string> + <string name="MicrosoftLocale">dutch</string> + <string name="DarwinLocale">nl_NL.UTF-8</string> + <string name="LinuxLocale">nl_NL.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu diff --git a/indra/newview/skins/default/xui/pl/language_settings.xml b/indra/newview/skins/default/xui/pl/language_settings.xml index 71418d446a..debc451a33 100644 --- a/indra/newview/skins/default/xui/pl/language_settings.xml +++ b/indra/newview/skins/default/xui/pl/language_settings.xml @@ -3,9 +3,9 @@ <strings> <!-- Locale Information --> - <string name="MicrosoftLocale">english</string> - <string name="DarwinLocale">C</string> - <string name="LinuxLocale">C</string> + <string name="MicrosoftLocale">polish</string> + <string name="DarwinLocale">pl_PL.UTF-8</string> + <string name="LinuxLocale">pl_PL.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu diff --git a/indra/newview/skins/default/xui/pt/language_settings.xml b/indra/newview/skins/default/xui/pt/language_settings.xml index 71418d446a..f25e77574d 100644 --- a/indra/newview/skins/default/xui/pt/language_settings.xml +++ b/indra/newview/skins/default/xui/pt/language_settings.xml @@ -3,9 +3,9 @@ <strings> <!-- Locale Information --> - <string name="MicrosoftLocale">english</string> - <string name="DarwinLocale">C</string> - <string name="LinuxLocale">C</string> + <string name="MicrosoftLocale">portuguese</string> + <string name="DarwinLocale">pt_PT.UTF-8</string> + <string name="LinuxLocale">pt_PT.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu |