diff options
| author | Callum Prentice <callum@gmail.com> | 2021-02-03 09:31:32 -0800 |
|---|---|---|
| committer | Callum Prentice <callum@gmail.com> | 2021-02-03 09:31:32 -0800 |
| commit | d26567915cd80999260edffc41df467a7cbbd80c (patch) | |
| tree | 84072d2a7a5e6afa7b57850ed4b325439cb2be16 /indra | |
| parent | 7528855442a100cee379b9e409280a69caa78bba (diff) | |
| parent | 21565a1f3fe1ae737e2f91c58be2c3cb0b5a2fec (diff) | |
Merge with Master after Viewer release
Diffstat (limited to 'indra')
116 files changed, 1865 insertions, 677 deletions
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index f7fbb6fda1..90dfa04f28 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -171,10 +171,9 @@ LLAvatarAppearance::LLAvatarXmlInfo::~LLAvatarXmlInfo() //----------------------------------------------------------------------------- // Static Data //----------------------------------------------------------------------------- -LLXmlTree LLAvatarAppearance::sXMLTree; -LLXmlTree LLAvatarAppearance::sSkeletonXMLTree; LLAvatarSkeletonInfo* LLAvatarAppearance::sAvatarSkeletonInfo = NULL; LLAvatarAppearance::LLAvatarXmlInfo* LLAvatarAppearance::sAvatarXmlInfo = NULL; +LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* LLAvatarAppearance::sAvatarDictionary = NULL; LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : @@ -202,7 +201,7 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : mBakedTextureDatas[i].mIsLoaded = false; mBakedTextureDatas[i].mIsUsed = false; mBakedTextureDatas[i].mMaskTexName = 0; - mBakedTextureDatas[i].mTextureIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((LLAvatarAppearanceDefines::EBakedTextureIndex)i); + mBakedTextureDatas[i].mTextureIndex = sAvatarDictionary->bakedToLocalTextureIndex((LLAvatarAppearanceDefines::EBakedTextureIndex)i); } } @@ -215,8 +214,8 @@ void LLAvatarAppearance::initInstance() mRoot = createAvatarJoint(); mRoot->setName( "mRoot" ); - for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end(); + for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = sAvatarDictionary->getMeshEntries().begin(); + iter != sAvatarDictionary->getMeshEntries().end(); ++iter) { const EMeshIndex mesh_index = iter->first; @@ -261,8 +260,8 @@ void LLAvatarAppearance::initInstance() //------------------------------------------------------------------------- // associate baked textures with meshes //------------------------------------------------------------------------- - for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end(); + for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = sAvatarDictionary->getMeshEntries().begin(); + iter != sAvatarDictionary->getMeshEntries().end(); ++iter) { const EMeshIndex mesh_index = iter->first; @@ -336,6 +335,12 @@ void LLAvatarAppearance::initClass() //static void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, const std::string& skeleton_file_name_arg) { + // init dictionary (don't repeat on second login attempt) + if (!sAvatarDictionary) + { + sAvatarDictionary = new LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary(); + } + std::string avatar_file_name; if (!avatar_file_name_arg.empty()) @@ -346,14 +351,15 @@ void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, cons { avatar_file_name = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR + "_lad.xml"); } - BOOL success = sXMLTree.parseFile( avatar_file_name, FALSE ); + LLXmlTree xml_tree; + BOOL success = xml_tree.parseFile( avatar_file_name, FALSE ); if (!success) { LL_ERRS() << "Problem reading avatar configuration file:" << avatar_file_name << LL_ENDL; } // now sanity check xml file - LLXmlTreeNode* root = sXMLTree.getRoot(); + LLXmlTreeNode* root = xml_tree.getRoot(); if (!root) { LL_ERRS() << "No root node found in avatar configuration file: " << avatar_file_name << LL_ENDL; @@ -400,8 +406,9 @@ void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, cons } std::string skeleton_path; + LLXmlTree skeleton_xml_tree; skeleton_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,skeleton_file_name); - if (!parseSkeletonFile(skeleton_path)) + if (!parseSkeletonFile(skeleton_path, skeleton_xml_tree)) { LL_ERRS() << "Error parsing skeleton file: " << skeleton_path << LL_ENDL; } @@ -414,7 +421,7 @@ void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, cons delete sAvatarSkeletonInfo; } sAvatarSkeletonInfo = new LLAvatarSkeletonInfo; - if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) + if (!sAvatarSkeletonInfo->parseXml(skeleton_xml_tree.getRoot())) { LL_ERRS() << "Error parsing skeleton XML file: " << skeleton_path << LL_ENDL; } @@ -453,9 +460,8 @@ void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, cons void LLAvatarAppearance::cleanupClass() { delete_and_clear(sAvatarXmlInfo); - // *TODO: What about sAvatarSkeletonInfo ??? - sSkeletonXMLTree.cleanup(); - sXMLTree.cleanup(); + delete_and_clear(sAvatarDictionary); + delete_and_clear(sAvatarSkeletonInfo); } using namespace LLAvatarAppearanceDefines; @@ -577,12 +583,12 @@ void LLAvatarAppearance::computeBodySize() //----------------------------------------------------------------------------- // parseSkeletonFile() //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename) +BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree) { //------------------------------------------------------------------------- // parse the file //------------------------------------------------------------------------- - BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE ); + BOOL parsesuccess = skeleton_xml_tree.parseFile( filename, FALSE ); if (!parsesuccess) { @@ -591,7 +597,7 @@ BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename) } // now sanity check xml file - LLXmlTreeNode* root = sSkeletonXMLTree.getRoot(); + LLXmlTreeNode* root = skeleton_xml_tree.getRoot(); if (!root) { LL_ERRS() << "No root node found in avatar skeleton file: " << filename << LL_ENDL; @@ -999,7 +1005,7 @@ BOOL LLAvatarAppearance::loadAvatar() { LLAvatarXmlInfo::LLAvatarMorphInfo *info = *iter; - EBakedTextureIndex baked = LLAvatarAppearanceDictionary::findBakedByRegionName(info->mRegion); + EBakedTextureIndex baked = sAvatarDictionary->findBakedByRegionName(info->mRegion); if (baked != BAKED_NUM_INDICES) { LLVisualParam* morph_param; @@ -1135,8 +1141,8 @@ BOOL LLAvatarAppearance::loadMeshNodes() switch(lod) case 0: mesh = &mHairMesh0; */ - for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator mesh_iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin(); - mesh_iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end(); + for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator mesh_iter = sAvatarDictionary->getMeshEntries().begin(); + mesh_iter != sAvatarDictionary->getMeshEntries().end(); ++mesh_iter) { const EMeshIndex mesh_index = mesh_iter->first; @@ -1264,8 +1270,8 @@ BOOL LLAvatarAppearance::loadLayersets() // scan baked textures and associate the layerset with the appropriate one EBakedTextureIndex baked_index = BAKED_NUM_INDICES; - for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = sAvatarDictionary->getBakedTextures().begin(); + baked_iter != sAvatarDictionary->getBakedTextures().end(); ++baked_iter) { const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index 6a4dbf3726..b1c70f9064 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -156,7 +156,7 @@ public: protected: - static BOOL parseSkeletonFile(const std::string& filename); + static BOOL parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree); virtual void buildCharacter(); virtual BOOL loadAvatar(); @@ -211,9 +211,6 @@ public: // XML parse tree //-------------------------------------------------------------------- protected: - static LLXmlTree sXMLTree; // avatar config file - static LLXmlTree sSkeletonXMLTree; // avatar skeleton file - static LLAvatarSkeletonInfo* sAvatarSkeletonInfo; static LLAvatarXmlInfo* sAvatarXmlInfo; @@ -255,6 +252,7 @@ public: public: virtual void updateMeshTextures() = 0; virtual void dirtyMesh() = 0; // Dirty the avatar mesh + static const LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary *getDictionary() { return sAvatarDictionary; } protected: virtual void dirtyMesh(S32 priority) = 0; // Dirty the avatar mesh, with priority @@ -263,6 +261,9 @@ protected: polymesh_map_t mPolyMeshes; avatar_joint_list_t mMeshLOD; + // mesh entries and backed textures + static LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* sAvatarDictionary; + /** Meshes ** ** *******************************************************************************/ diff --git a/indra/llappearance/llavatarappearancedefines.cpp b/indra/llappearance/llavatarappearancedefines.cpp index c72943bb82..9398ce3822 100644 --- a/indra/llappearance/llavatarappearancedefines.cpp +++ b/indra/llappearance/llavatarappearancedefines.cpp @@ -258,19 +258,17 @@ LLAvatarAppearanceDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index, } } -// static -ETextureIndex LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index) +ETextureIndex LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index) const { - return LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(index)->mTextureIndex; + return getBakedTexture(index)->mTextureIndex; } -// static EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(std::string name) { U8 index = 0; while (index < BAKED_NUM_INDICES) { - const BakedEntry *be = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index); + const BakedEntry *be = getBakedTexture((EBakedTextureIndex) index); if (be && be->mName.compare(name) == 0) { // baked texture found @@ -282,16 +280,15 @@ EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(std::stri return BAKED_NUM_INDICES; } -// static EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByImageName(std::string name) { U8 index = 0; while (index < BAKED_NUM_INDICES) { - const BakedEntry *be = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index); + const BakedEntry *be = getBakedTexture((EBakedTextureIndex) index); if (be) { - const TextureEntry *te = LLAvatarAppearanceDictionary::getInstance()->getTexture(be->mTextureIndex); + const TextureEntry *te = getTexture(be->mTextureIndex); if (te && te->mDefaultImageName.compare(name) == 0) { // baked texture found @@ -304,10 +301,9 @@ EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByImageName(std::strin return BAKED_NUM_INDICES; } -// static -LLWearableType::EType LLAvatarAppearanceDictionary::getTEWearableType(ETextureIndex index ) +LLWearableType::EType LLAvatarAppearanceDictionary::getTEWearableType(ETextureIndex index ) const { - return getInstance()->getTexture(index)->mWearableType; + return getTexture(index)->mWearableType; } // static diff --git a/indra/llappearance/llavatarappearancedefines.h b/indra/llappearance/llavatarappearancedefines.h index 5663d24293..8968187531 100644 --- a/indra/llappearance/llavatarappearancedefines.h +++ b/indra/llappearance/llavatarappearancedefines.h @@ -143,13 +143,14 @@ typedef std::vector<LLWearableType::EType> wearables_vec_t; // // This holds const data - it is initialized once and the contents never change after that. //------------------------------------------------------------------------ -class LLAvatarAppearanceDictionary : public LLSingleton<LLAvatarAppearanceDictionary> +class LLAvatarAppearanceDictionary { //-------------------------------------------------------------------- // Constructors and Destructors //-------------------------------------------------------------------- - LLSINGLETON(LLAvatarAppearanceDictionary); - virtual ~LLAvatarAppearanceDictionary(); +public: + LLAvatarAppearanceDictionary(); + ~LLAvatarAppearanceDictionary(); private: void createAssociations(); @@ -235,14 +236,14 @@ public: //-------------------------------------------------------------------- public: // Convert from baked texture to associated texture; e.g. BAKED_HEAD -> TEX_HEAD_BAKED - static ETextureIndex bakedToLocalTextureIndex(EBakedTextureIndex t); + ETextureIndex bakedToLocalTextureIndex(EBakedTextureIndex t) const; // find a baked texture index based on its name - static EBakedTextureIndex findBakedByRegionName(std::string name); - static EBakedTextureIndex findBakedByImageName(std::string name); + EBakedTextureIndex findBakedByRegionName(std::string name); + EBakedTextureIndex findBakedByImageName(std::string name); // Given a texture entry, determine which wearable type owns it. - static LLWearableType::EType getTEWearableType(ETextureIndex index); + LLWearableType::EType getTEWearableType(ETextureIndex index) const; static BOOL isBakedImageId(const LLUUID& id); static EBakedTextureIndex assetIdToBakedTextureIndex(const LLUUID& id); diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 1348fb0763..a4600069ce 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -726,8 +726,8 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) /* if ("upper_shirt" == local_texture_name) mLocalTexture = TEX_UPPER_SHIRT; */ mLocalTexture = TEX_NUM_INDICES; - for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); + iter != LLAvatarAppearance::getDictionary()->getTextures().end(); iter++) { const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; @@ -977,7 +977,7 @@ LLWearableType::EType LLTexLayerInterface::getWearableType() const return type; } - return LLAvatarAppearanceDictionary::getTEWearableType(te); + return LLAvatarAppearance::getDictionary()->getTEWearableType(te); } LLTexLayerInterface::ERenderPass LLTexLayerInterface::getRenderPass() const diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index 6079913a8e..28a36e6e41 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -183,7 +183,7 @@ void LLWearable::createVisualParams(LLAvatarAppearance *avatarp) void LLWearable::createLayers(S32 te, LLAvatarAppearance *avatarp) { LLTexLayerSet *layer_set = NULL; - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)te); if (texture_dict && texture_dict->mIsUsedByBakedTexture) { const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; @@ -606,7 +606,7 @@ void LLWearable::syncImages(te_map_t &src, te_map_t &dst) // Deep copy of src (copies only those tes that are current, filling in defaults where needed) for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) + if (LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex) te) == mType) { te_map_t::const_iterator iter = src.find(te); LLUUID image_id; diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp index 2bf3b9085b..66cc4f3766 100644 --- a/indra/llappearance/llwearabledata.cpp +++ b/indra/llappearance/llwearabledata.cpp @@ -339,7 +339,7 @@ U32 LLWearableData::getWearableCount(const LLWearableType::EType type) const U32 LLWearableData::getWearableCount(const U32 tex_index) const { - const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((LLAvatarAppearanceDefines::ETextureIndex)tex_index); + const LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((LLAvatarAppearanceDefines::ETextureIndex)tex_index); return getWearableCount(wearable_type); } @@ -349,7 +349,7 @@ LLUUID LLWearableData::computeBakedTextureHash(LLAvatarAppearanceDefines::EBaked LLUUID hash_id; bool hash_computed = false; LLMD5 hash; - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearance::getDictionary()->getBakedTexture(baked_index); for (U8 i=0; i < baked_dict->mWearables.size(); i++) { diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index 7bea8e9f9c..ba31290c24 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -567,16 +567,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) // Use the viewer-based thread-safe API which has a // fast/safe check for proxy enable. Would like to // encapsulate this someway... - if (LLProxy::instanceExists()) - { - // Make sure proxy won't be initialized from here, - // it might conflict with LLStartUp::startLLProxy() - LLProxy::getInstance()->applyProxySettings(mCurlHandle); - } - else - { - LL_WARNS() << "Proxy is not initialized!" << LL_ENDL; - } + // Make sure proxy won't be getInstance() from here, + // it is not thread safe + LLProxy::applyProxySettings(mCurlHandle); } else if (gpolicy.mHttpProxy.size()) @@ -817,6 +810,7 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void const size_t do_size((std::min)(req_size, body_size - op->mCurlBodyPos)); const size_t read_size(op->mReqBody->read(op->mCurlBodyPos, static_cast<char *>(data), do_size)); + // FIXME: singleton's instance() is Thread unsafe! Even if stats accumulators inside are. HTTPStats::instance().recordDataUp(read_size); op->mCurlBodyPos += read_size; return read_size; diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 3e7be26e59..350a8eb120 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -583,29 +583,39 @@ static void bilinear_scale(const U8 *src, U32 srcW, U32 srcH, U32 srcCh, U32 src // LLImage //--------------------------------------------------------------------------- -LLImage::LLImage(bool use_new_byte_range, S32 minimal_reverse_byte_range_percent) +//static +std::string LLImage::sLastErrorMessage; +LLMutex* LLImage::sMutex = NULL; +bool LLImage::sUseNewByteRange = false; +S32 LLImage::sMinimalReverseByteRangePercent = 75; + +//static +void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_percent) { - mMutex = new LLMutex(); - mUseNewByteRange = use_new_byte_range; - mMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent; + sUseNewByteRange = use_new_byte_range; + sMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent; + sMutex = new LLMutex(); } -LLImage::~LLImage() +//static +void LLImage::cleanupClass() { - delete mMutex; - mMutex = NULL; + delete sMutex; + sMutex = NULL; } -const std::string& LLImage::getLastErrorMessage() +//static +const std::string& LLImage::getLastError() { static const std::string noerr("No Error"); - return mLastErrorMessage.empty() ? noerr : mLastErrorMessage; + return sLastErrorMessage.empty() ? noerr : sLastErrorMessage; } -void LLImage::setLastErrorMessage(const std::string& message) +//static +void LLImage::setLastError(const std::string& message) { - LLMutexLock m(mMutex); - mLastErrorMessage = message; + LLMutexLock m(sMutex); + sLastErrorMessage = message; } //--------------------------------------------------------------------------- diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 9f8d061293..f66b1666d7 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -30,7 +30,6 @@ #include "lluuid.h" #include "llstring.h" #include "llpointer.h" -#include "llsingleton.h" #include "lltrace.h" const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2 @@ -88,26 +87,25 @@ typedef enum e_image_codec //============================================================================ // library initialization class +// LLImage is frequently used in threads so do not convert it to LLSingleton -class LLImage : public LLParamSingleton<LLImage> +class LLImage { - LLSINGLETON(LLImage, bool use_new_byte_range = false, S32 minimal_reverse_byte_range_percent = 75); - ~LLImage(); public: + static void initClass(bool use_new_byte_range = false, S32 minimal_reverse_byte_range_percent = 75); + static void cleanupClass(); - const std::string& getLastErrorMessage(); - static const std::string& getLastError() { return getInstance()->getLastErrorMessage(); }; - void setLastErrorMessage(const std::string& message); - static void setLastError(const std::string& message) { getInstance()->setLastErrorMessage(message); } - - bool useNewByteRange() { return mUseNewByteRange; } - S32 getReverseByteRangePercent() { return mMinimalReverseByteRangePercent; } - -private: - LLMutex* mMutex; - std::string mLastErrorMessage; - bool mUseNewByteRange; - S32 mMinimalReverseByteRangePercent; + static const std::string& getLastError(); + static void setLastError(const std::string& message); + + static bool useNewByteRange() { return sUseNewByteRange; } + static S32 getReverseByteRangePercent() { return sMinimalReverseByteRangePercent; } + +protected: + static LLMutex* sMutex; + static std::string sLastErrorMessage; + static bool sUseNewByteRange; + static S32 sMinimalReverseByteRangePercent; }; //============================================================================ diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 71cab0554d..4bff21610f 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -281,7 +281,7 @@ S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 r S32 bytes; S32 new_bytes = (S32) (sqrt((F32)(w*h))*(F32)(comp)*rate*1000.f/layer_factor); S32 old_bytes = (S32)((F32)(w*h*comp)*rate); - bytes = (LLImage::getInstance()->useNewByteRange() && (new_bytes < old_bytes) ? new_bytes : old_bytes); + bytes = (LLImage::useNewByteRange() && (new_bytes < old_bytes) ? new_bytes : old_bytes); bytes = llmax(bytes, calcHeaderSizeJ2C()); return bytes; } @@ -322,7 +322,7 @@ S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes) { S32 bytes_needed = calcDataSize(discard_level); // Use TextureReverseByteRange percent (see settings.xml) of the optimal size to qualify as correct rendering for the given discard level - if (bytes >= (bytes_needed*LLImage::getInstance()->getReverseByteRangePercent()/100)) + if (bytes >= (bytes_needed*LLImage::getReverseByteRangePercent()/100)) { break; } diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index 024afc109c..0f336a072f 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -244,7 +244,7 @@ public: LLInventoryCategory(const LLInventoryCategory* other); void copyCategory(const LLInventoryCategory* other); // LLRefCount requires custom copy protected: - ~LLInventoryCategory(); + virtual ~LLInventoryCategory(); //-------------------------------------------------------------------- // Accessors And Mutators diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 7da53bf8c8..e085fa6ada 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -5241,9 +5241,9 @@ public: LLVCacheTriangleData* tri = *iter; if (tri->mActive) { - tri->mScore = tri->mVertex[0]->mScore; - tri->mScore += tri->mVertex[1]->mScore; - tri->mScore += tri->mVertex[2]->mScore; + tri->mScore = tri->mVertex[0] ? tri->mVertex[0]->mScore : 0; + tri->mScore += tri->mVertex[1] ? tri->mVertex[1]->mScore : 0; + tri->mScore += tri->mVertex[2] ? tri->mVertex[2]->mScore : 0; if (!mBestTriangle || mBestTriangle->mScore < tri->mScore) { diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index fbd65cc67b..7380df041d 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -285,12 +285,27 @@ void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName& return; } + bool updated_account = true; // assume obsolete value for new arrivals by default + + std::map<LLUUID, LLAvatarName>::iterator it = mCache.find(agent_id); + if (it != mCache.end() + && (*it).second.getAccountName() == av_name.getAccountName()) + { + updated_account = false; + } + // Add to the cache mCache[agent_id] = av_name; // Suppress request from the queue mPendingQueue.erase(agent_id); + // notify mute list about changes + if (updated_account && mAccountNameChangedCallback) + { + mAccountNameChangedCallback(agent_id, av_name); + } + // Signal everyone waiting on this name signal_map_t::iterator sig_it = mSignalMap.find(agent_id); if (sig_it != mSignalMap.end()) @@ -303,6 +318,8 @@ void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName& delete signal; signal = NULL; } + + } void LLAvatarNameCache::requestNamesViaCapability() diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index ba89d569f3..549d1703fa 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -42,6 +42,7 @@ class LLAvatarNameCache : public LLSingleton<LLAvatarNameCache> ~LLAvatarNameCache(); public: typedef boost::signals2::signal<void (void)> use_display_name_signal_t; + typedef boost::function<void (const LLUUID id, const LLAvatarName& av_name)> account_name_changed_callback_t; // Import/export the name cache to file. bool importFile(std::istream& istr); @@ -103,6 +104,8 @@ public: void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb); + void setAccountNameChangedCallback(const account_name_changed_callback_t& cb) { mAccountNameChangedCallback = cb; } + private: // Handle name response off network. void processName(const LLUUID& agent_id, @@ -141,6 +144,7 @@ private: private: use_display_name_signal_t mUseDisplayNamesSignal; + account_name_changed_callback_t mAccountNameChangedCallback; // Cache starts in a paused state until we can determine if the // current region supports display names. diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 86bcfe6881..749e599c66 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -40,6 +40,7 @@ // incoming packet just to do a simple bool test. The getter for this // member is also static bool LLProxy::sUDPProxyEnabled = false; +LLProxy* LLProxy::sProxyInstance = NULL; // Some helpful TCP static functions. static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen); // Do a TCP data handshake @@ -60,11 +61,21 @@ LLProxy::LLProxy(): LLProxy::~LLProxy() { - if (ll_apr_is_initialized()) - { - stopSOCKSProxy(); - disableHTTPProxy(); - } + if (ll_apr_is_initialized()) + { + // locks mutex + stopSOCKSProxy(); + disableHTTPProxy(); + } + // The primary safety of sProxyInstance is the fact that by the + // point SUBSYSTEM_CLEANUP(LLProxy) gets called, nothing should + // be capable of using proxy + sProxyInstance = NULL; +} + +void LLProxy::initSingleton() +{ + sProxyInstance = this; } /** @@ -424,28 +435,28 @@ void LLProxy::cleanupClass() void LLProxy::applyProxySettings(CURL* handle) { // Do a faster unlocked check to see if we are supposed to proxy. - if (mHTTPProxyEnabled) + if (sProxyInstance && sProxyInstance->mHTTPProxyEnabled) { - // We think we should proxy, lock the proxy mutex. - LLMutexLock lock(&mProxyMutex); + // We think we should proxy, lock the proxy mutex. sProxyInstance is not protected by mutex + LLMutexLock lock(&sProxyInstance->mProxyMutex); // Now test again to verify that the proxy wasn't disabled between the first check and the lock. - if (mHTTPProxyEnabled) + if (sProxyInstance->mHTTPProxyEnabled) { - LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str()), CURLOPT_PROXY); - LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort()), CURLOPT_PROXYPORT); + LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, sProxyInstance->mHTTPProxy.getIPString().c_str()), CURLOPT_PROXY); + LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, sProxyInstance->mHTTPProxy.getPort()), CURLOPT_PROXYPORT); - if (mProxyType == LLPROXY_SOCKS) + if (sProxyInstance->mProxyType == LLPROXY_SOCKS) { - LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5), CURLOPT_PROXYTYPE); - if (mAuthMethodSelected == METHOD_PASSWORD) + LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5), CURLOPT_PROXYTYPE); + if (sProxyInstance->mAuthMethodSelected == METHOD_PASSWORD) { - std::string auth_string = mSocksUsername + ":" + mSocksPassword; - LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str()), CURLOPT_PROXYUSERPWD); + std::string auth_string = sProxyInstance->mSocksUsername + ":" + sProxyInstance->mSocksPassword; + LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str()), CURLOPT_PROXYUSERPWD); } } else { - LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP), CURLOPT_PROXYTYPE); + LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP), CURLOPT_PROXYTYPE); } } } diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h index a1ffa9e5d5..25f6977e14 100644 --- a/indra/llmessage/llproxy.h +++ b/indra/llmessage/llproxy.h @@ -226,6 +226,8 @@ class LLProxy: public LLSingleton<LLProxy> LLSINGLETON(LLProxy); LOG_CLASS(LLProxy); + /*virtual*/ void initSingleton(); + public: // Static check for enabled status for UDP packets. Call from main thread only. static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; } @@ -251,7 +253,7 @@ public: // Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false. // Safe to call from any thread. - void applyProxySettings(CURL* handle); + static void applyProxySettings(CURL* handle); // Start a connection to the SOCKS 5 proxy. Call from main thread only. S32 startSOCKSProxy(LLHost host); @@ -344,6 +346,10 @@ private: /*########################################################################################### END OF SHARED MEMBERS ###########################################################################################*/ + + // A hack to get arround getInstance() and capture_dependency() which are unsafe to use inside threads + // set/reset on init/cleanup, strictly for use in applyProxySettings + static LLProxy* sProxyInstance; }; #endif diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index eb6cb1b503..7d18bae947 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -152,8 +152,18 @@ void LLPluginProcessParent::shutdown() mapInstances_t::iterator it; for (it = sInstances.begin(); it != sInstances.end(); ++it) { - (*it).second->setState(STATE_GOODBYE); - (*it).second->idle(); + EState state = (*it).second->mState; + if (state != STATE_CLEANUP + || state != STATE_EXITING + || state != STATE_DONE + || state != STATE_ERROR) + { + (*it).second->setState(STATE_GOODBYE); + } + if (state != STATE_DONE) + { + (*it).second->idle(); + } } sInstances.clear(); } diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index d2aa3d8dc6..dfa29fb539 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -1472,7 +1472,8 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do std::string lookingForJoint = (*jointIt).c_str(); //Look for the joint xform that we extracted from the skeleton, using the jointIt as the key //and store it in the alternate bind matrix - if ( mJointMap.find( lookingForJoint ) != mJointMap.end() ) + if (mJointMap.find(lookingForJoint) != mJointMap.end() + && model->mSkinInfo.mInvBindMatrix.size() > i) { LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i]; newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() ); diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index dbe71e2882..33a33af160 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -45,6 +45,7 @@ bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc); bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node); const std::string MACOSX_FONT_PATH_LIBRARY = "/Library/Fonts/"; +const std::string MACOSX_FONT_SUPPLEMENTAL = "Supplemental/"; LLFontDescriptor::LLFontDescriptor(): mStyle(0) @@ -473,6 +474,8 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) font_paths.push_back(sys_path + *file_name_it); #if LL_DARWIN font_paths.push_back(MACOSX_FONT_PATH_LIBRARY + *file_name_it); + font_paths.push_back(MACOSX_FONT_PATH_LIBRARY + MACOSX_FONT_SUPPLEMENTAL + *file_name_it); + font_paths.push_back(sys_path + MACOSX_FONT_SUPPLEMENTAL + *file_name_it); #endif bool is_ft_collection = (std::find(ft_collection_list.begin(), ft_collection_list.end(), *file_name_it) != ft_collection_list.end()); diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 604fb4e946..ee02a90b54 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -965,6 +965,80 @@ std::string LLGLManager::getRawGLString() return gl_string; } +void LLGLManager::asLLSD(LLSD& info) +{ + // Currently these are duplicates of fields in "system". + info["gpu_vendor"] = mGLVendorShort; + info["gpu_version"] = mDriverVersionVendorString; + info["opengl_version"] = mGLVersionString; + + info["vram"] = mVRAM; + + // Extensions used by everyone + info["has_multitexture"] = mHasMultitexture; + info["has_ati_mem_info"] = mHasATIMemInfo; + info["has_nvx_mem_info"] = mHasNVXMemInfo; + info["num_texture_units"] = mNumTextureUnits; + info["has_mip_map_generation"] = mHasMipMapGeneration; + info["has_compressed_textures"] = mHasCompressedTextures; + info["has_framebuffer_object"] = mHasFramebufferObject; + info["max_samples"] = mMaxSamples; + info["has_blend_func_separate"] = mHasBlendFuncSeparate; + + // ARB Extensions + info["has_vertex_buffer_object"] = mHasVertexBufferObject; + info["has_vertex_array_object"] = mHasVertexArrayObject; + info["has_sync"] = mHasSync; + info["has_map_buffer_range"] = mHasMapBufferRange; + info["has_flush_buffer_range"] = mHasFlushBufferRange; + info["has_pbuffer"] = mHasPBuffer; + info["has_shader_objects"] = mHasShaderObjects; + info["has_vertex_shader"] = mHasVertexShader; + info["has_fragment_shader"] = mHasFragmentShader; + info["num_texture_image_units"] = mNumTextureImageUnits; + info["has_occlusion_query"] = mHasOcclusionQuery; + info["has_timer_query"] = mHasTimerQuery; + info["has_occlusion_query2"] = mHasOcclusionQuery2; + info["has_point_parameters"] = mHasPointParameters; + info["has_draw_buffers"] = mHasDrawBuffers; + info["has_depth_clamp"] = mHasDepthClamp; + info["has_texture_rectangle"] = mHasTextureRectangle; + info["has_texture_multisample"] = mHasTextureMultisample; + info["has_transform_feedback"] = mHasTransformFeedback; + info["max_sample_mask_words"] = mMaxSampleMaskWords; + info["max_color_texture_samples"] = mMaxColorTextureSamples; + info["max_depth_texture_samples"] = mMaxDepthTextureSamples; + info["max_integer_samples"] = mMaxIntegerSamples; + + // Other extensions. + info["has_anisotropic"] = mHasAnisotropic; + info["has_arb_env_combine"] = mHasARBEnvCombine; + info["has_cube_map"] = mHasCubeMap; + info["has_debug_output"] = mHasDebugOutput; + info["has_srgb_texture"] = mHassRGBTexture; + info["has_srgb_framebuffer"] = mHassRGBFramebuffer; + info["has_texture_srgb_decode"] = mHasTexturesRGBDecode; + + // Vendor-specific extensions + info["is_ati"] = mIsATI; + info["is_nvidia"] = mIsNVIDIA; + info["is_intel"] = mIsIntel; + info["is_gf2or4mx"] = mIsGF2or4MX; + info["is_gf3"] = mIsGF3; + info["is_gf_gfx"] = mIsGFFX; + info["ati_offset_vertical_lines"] = mATIOffsetVerticalLines; + info["ati_old_driver"] = mATIOldDriver; + + // Other fields + info["has_requirements"] = mHasRequirements; + info["has_separate_specular_color"] = mHasSeparateSpecularColor; + info["debug_gpu"] = mDebugGPU; + info["max_vertex_range"] = mGLMaxVertexRange; + info["max_index_range"] = mGLMaxIndexRange; + info["max_texture_size"] = mGLMaxTextureSize; + info["gl_renderer"] = mGLRenderer; +} + void LLGLManager::shutdownGL() { if (mInited) diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 91ef4e9102..966c4b3c77 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -165,6 +165,8 @@ public: void printGLInfoString(); void getGLInfo(LLSD& info); + void asLLSD(LLSD& info); + // In ALL CAPS std::string mGLVendor; std::string mGLVendorShort; diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 3b6a49735e..0151d20128 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1386,6 +1386,15 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S return FALSE; } + if (mHasExplicitFormat && + ((mFormatPrimary == GL_RGBA && mComponents < 4) || + (mFormatPrimary == GL_RGB && mComponents < 3))) + + { + LL_WARNS() << "Incorrect format: " << std::hex << mFormatPrimary << " components: " << (U32)mComponents << LL_ENDL; + mHasExplicitFormat = FALSE; + } + if( !mHasExplicitFormat ) { switch (mComponents) diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 4f3d7eed0a..61ddc8d59b 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -133,6 +133,7 @@ public: S32 getMipBytes(S32 discard_level = -1) const; BOOL getBoundRecently() const; BOOL isJustBound() const; + BOOL getHasExplicitFormat() const { return mHasExplicitFormat; } LLGLenum getPrimaryFormat() const { return mFormatPrimary; } LLGLenum getFormatType() const { return mFormatType; } @@ -197,7 +198,7 @@ private: U16 mPickMaskWidth; U16 mPickMaskHeight; S8 mUseMipMaps; - S8 mHasExplicitFormat; // If false (default), GL format is f(mComponents) + BOOL mHasExplicitFormat; // If false (default), GL format is f(mComponents) S8 mAutoGenMips; BOOL mIsMask; diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h index 70ab006fd6..8c01784071 100644 --- a/indra/llrender/llrender2dutils.h +++ b/indra/llrender/llrender2dutils.h @@ -32,6 +32,7 @@ #include "llpointer.h" // LLPointer<> #include "llrect.h" +#include "llsingleton.h" #include "llglslshader.h" class LLColor4; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index abb043f428..e9c980ad9a 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -303,12 +303,10 @@ void LLFloater::initFloater(const Params& p) mButtonsEnabled[BUTTON_CLOSE] = TRUE; } - // Help button: '?' - if ( !mHelpTopic.empty() ) - { - mButtonsEnabled[BUTTON_HELP] = TRUE; - } - + // Help button: '?' + //SL-14050 Disable all Help question marks + mButtonsEnabled[BUTTON_HELP] = FALSE; + // Minimize button only for top draggers if ( !mDragOnLeft && mCanMinimize ) { diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 84a1539094..f4ddfa8f18 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -285,7 +285,7 @@ public: typedef std::list<LLFolderViewModelItem*> child_list_t; virtual void addChild(LLFolderViewModelItem* child) - { + { mChildren.push_back(child); child->setParent(this); dirtyFilter(); diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 367c6c3c5b..a6e4f3a2af 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -763,14 +763,20 @@ void LLScrollListCtrl::updateColumns(bool force_update) } } + bool header_changed_width = false; // expand last column header we encountered to full list width if (last_header) { + S32 old_width = last_header->getColumn()->getWidth(); S32 new_width = llmax(0, mItemListRect.mRight - last_header->getRect().mLeft); last_header->reshape(new_width, last_header->getRect().getHeight()); last_header->setVisible(mDisplayColumnHeaders && new_width > 0); - last_header->getColumn()->setWidth(new_width); - } + if (old_width != new_width) + { + last_header->getColumn()->setWidth(new_width); + header_changed_width = true; + } + } // propagate column widths to individual cells if (columns_changed_width || force_update) @@ -789,6 +795,20 @@ void LLScrollListCtrl::updateColumns(bool force_update) } } } + else if (header_changed_width) + { + item_list::iterator iter; + S32 index = last_header->getColumn()->mIndex; // Not always identical to last column! + for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + { + LLScrollListItem *itemp = *iter; + LLScrollListCell* cell = itemp->getColumn(index); + if (cell) + { + cell->setWidth(last_header->getColumn()->getWidth()); + } + } + } } void LLScrollListCtrl::setHeadingHeight(S32 heading_height) @@ -1381,18 +1401,34 @@ BOOL LLScrollListCtrl::setSelectedByValue(const LLSD& value, BOOL selected) for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem* item = *iter; - if (item->getEnabled() && (item->getValue().asString() == value.asString())) - { - if (selected) - { - selectItem(item); - } - else - { - deselectItem(item); - } - found = TRUE; - break; + if (item->getEnabled()) + { + if (value.isBinary()) + { + if (item->getValue().isBinary()) + { + LLSD::Binary data1 = value.asBinary(); + LLSD::Binary data2 = item->getValue().asBinary(); + found = std::equal(data1.begin(), data1.end(), data2.begin()) ? TRUE : FALSE; + } + } + else + { + found = item->getValue().asString() == value.asString() ? TRUE : FALSE; + } + + if (found) + { + if (selected) + { + selectItem(item); + } + else + { + deselectItem(item); + } + break; + } } } diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index e6835f73fb..a69c0eb008 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -1481,4 +1481,43 @@ void LLUrlEntryExperienceProfile::onExperienceDetails( const LLSD& experience_de callObservers(experience_details[LLExperienceCache::EXPERIENCE_ID].asString(), name, LLStringUtil::null); } +// +// LLUrlEntryEmail Describes an IPv6 address +// +LLUrlEntryIPv6::LLUrlEntryIPv6() + : LLUrlEntryBase() +{ + mHostPath = "https?://\\[([a-f0-9:]+:+)+[a-f0-9]+]"; + mPattern = boost::regex(mHostPath + "(:\\d{1,5})?(/\\S*)?", + boost::regex::perl | boost::regex::icase); + mMenuName = "menu_url_http.xml"; + mTooltip = LLTrans::getString("TooltipHttpUrl"); +} +std::string LLUrlEntryIPv6::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ + boost::regex regex = boost::regex(mHostPath, boost::regex::perl | boost::regex::icase); + boost::match_results<std::string::const_iterator> matches; + + if (boost::regex_search(url, matches, regex)) + { + return url.substr(0, matches[0].length()); + } + else + { + return url; + } +} + +std::string LLUrlEntryIPv6::getQuery(const std::string &url) const +{ + boost::regex regex = boost::regex(mHostPath, boost::regex::perl | boost::regex::icase); + boost::match_results<std::string::const_iterator> matches; + + return boost::regex_replace(url, regex, ""); +} + +std::string LLUrlEntryIPv6::getUrl(const std::string &string) const +{ + return string; +} diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 78c149d9fd..0a0c247a6a 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -513,5 +513,18 @@ public: /*virtual*/ std::string getUrl(const std::string &string) const; }; +/// +/// LLUrlEntryEmail Describes an IPv6 address +/// +class LLUrlEntryIPv6 : public LLUrlEntryBase +{ +public: + LLUrlEntryIPv6(); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); + /*virtual*/ std::string getUrl(const std::string &string) const; + /*virtual*/ std::string getQuery(const std::string &url) const; + + std::string mHostPath; +}; #endif diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index ba6fa1e2e9..321a0ec5b9 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -79,6 +79,7 @@ LLUrlRegistry::LLUrlRegistry() mUrlEntrySLLabel = new LLUrlEntrySLLabel(); registerUrl(mUrlEntrySLLabel); registerUrl(new LLUrlEntryEmail()); + registerUrl(new LLUrlEntryIPv6()); } LLUrlRegistry::~LLUrlRegistry() diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index 3c34fd269e..4a4fdb72e3 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -903,4 +903,38 @@ namespace tut "and even no www something lindenlab.com", ""); } + + template<> template<> + void object::test<16>() + { + // + // test LLUrlEntryIPv6 + // + LLUrlEntryIPv6 url; + + // Regex tests. + testRegex("match urls with a protocol", url, + "this url should match http://[::1]", + "http://[::1]"); + + testRegex("match urls with a protocol and query", url, + "this url should match http://[::1]/file.mp3", + "http://[::1]/file.mp3"); + + testRegex("match urls with a protocol", url, + "this url should match http://[2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d]", + "http://[2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d]"); + + testRegex("match urls with port", url, + "let's specify some port http://[2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d]:8080", + "http://[2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d]:8080"); + + testRegex("don't match urls w/o protocol", url, + "looks like an url something [2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d] but no https prefix", + ""); + + testRegex("don't match incorrect urls", url, + "http://[ 2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d ]", + ""); + } } diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h |
