diff --git a/.gitignore b/.gitignore index a8c150ae66..f94d376ae5 100755 --- a/.gitignore +++ b/.gitignore @@ -106,3 +106,5 @@ my_autobuild.xml *.srctrlprj compile_commands.json +# ignore tracy for now +indra/tracy \ No newline at end of file diff --git a/FIRESTORM-SOURCE_LICENSE_HEADER.txt b/FIRESTORM-SOURCE_LICENSE_HEADER.txt index 733719b436..25d6ff11ea 100644 --- a/FIRESTORM-SOURCE_LICENSE_HEADER.txt +++ b/FIRESTORM-SOURCE_LICENSE_HEADER.txt @@ -2,7 +2,7 @@ * @file * @brief * - * $LicenseInfo:firstyear=2020&license=fsviewerlgpl$ + * $LicenseInfo:firstyear=2021&license=fsviewerlgpl$ * Phoenix Firestorm Viewer Source Code * Copyright (C) 2020, The Phoenix Firestorm Project, Inc. * diff --git a/autobuild.xml b/autobuild.xml index 4d9638e3f1..ac5174405d 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -448,9 +448,9 @@ archive hash - 322dd6c45c384d454ae14ef127984a4e + ae90d19cdcddf539f6d0b41cab12f918 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65457/612879/bugsplat-1.0.7.546418-darwin64-546418.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72773/702861/bugsplat-1.0.7.552580-darwin64-552580.tar.bz2 name darwin64 @@ -460,9 +460,9 @@ archive hash - 010a0e73c0fddaa2316411803fad8e69 + f5936eceb6a33ff0f1cc31996a40f29c url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65456/612876/bugsplat-3.6.0.8.546418-windows-546418.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72774/702905/bugsplat-3.6.0.8.552580-windows-552580.tar.bz2 name windows @@ -472,16 +472,16 @@ archive hash - 7e8530762e7b50663708a888c23b8780 + 9cd940754e53e0670030b3da5ba8f373 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65455/612874/bugsplat-3.6.0.8.546418-windows64-546418.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72775/702906/bugsplat-3.6.0.8.552580-windows64-552580.tar.bz2 name windows64 version - 3.6.0.8.546418 + 3.6.0.8.552580 colladadom @@ -964,11 +964,11 @@ archive hash - fc2d285da5298b666fc3c54015a8669a + 87c4984c2bddcdaf6ca403a06f22ce4e hash_algorithm md5 url - file:///opt/firestorm/fmodstudio-2.01.05-darwin-202981448.tar.bz2 + file:///opt/firestorm/fmodstudio-2.01.07-darwin-210010951.tar.bz2 name darwin @@ -978,11 +978,11 @@ archive hash - ee3c5e3449e06bc3dbb1c9dc29aca53d + d33d848660ca7e4c2de789e325706d24 hash_algorithm md5 url - file:///opt/firestorm/fmodstudio-2.01.05-linux64-202931144.tar.bz2 + file:///opt/firestorm/fmodstudio-2.01.07-linux64-203630250.tar.bz2 name linux64 @@ -992,11 +992,11 @@ archive hash - b88e70667efc230a00d6a2d982af8fc5 + 9e9f303912776014519c18a0205250ee hash_algorithm md5 url - file:///c:/cygwin/opt/firestorm/fmodstudio-2.01.05-windows-202860859.tar.bz2 + file:///c:/cygwin/opt/firestorm/fmodstudio-2.01.07-windows-203561745.tar.bz2 name windows @@ -1006,18 +1006,18 @@ archive hash - 401829b65cac61a2f96179fadf7eb015 + ae336fe814a6867f6449d0401ea7a9e4 hash_algorithm md5 url - file:///c:/cygwin/opt/firestorm/fmodstudio-2.01.05-windows64-202860900.tar.bz2 + file:///c:/cygwin/opt/firestorm/fmodstudio-2.01.07-windows64-203561747.tar.bz2 name windows64 version - 2.01.05 + 2.01.07 fontconfig @@ -2375,18 +2375,18 @@ archive hash - 9f4687d7d328b0c13a9e651e805e880a + c541838a933e0714a954e9ef6c89345d hash_algorithm md5 url - https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/71501/691487/llca-202011010215.551526-common-551526.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/73387/708088/llca-202012011600.553112-common-553112.tar.bz2 name common version - 202011010215.551526 + 202012011600.553112 llphysicsextensions_source @@ -3709,7 +3709,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors canonical_repo https://bitbucket.org/lindenlab/viewer copyright - Copyright (c) 2020, The Phoenix Firestorm Project, Inc. + Copyright (c) 2021, The Phoenix Firestorm Project, Inc. description Firestorm Viewer license diff --git a/build.sh b/build.sh index 4dff58971f..b790f655a9 100755 --- a/build.sh +++ b/build.sh @@ -477,10 +477,12 @@ then fi # Run upload extensions + # Ex: bugsplat if [ -d ${build_dir}/packages/upload-extensions ]; then for extension in ${build_dir}/packages/upload-extensions/*.sh; do begin_section "Upload Extension $extension" . $extension + [ $? -eq 0 ] || fatal "Upload of extension $extension failed" end_section "Upload Extension $extension" done fi diff --git a/doc/contributions.txt b/doc/contributions.txt index 22bd4ae794..6a47b53121 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -1358,7 +1358,8 @@ Sovereign Engineer MAINT-7343 SL-11079 OPEN-343 - SL-11625 + SL-11625 + BUG-229030 SpacedOut Frye VWR-34 VWR-45 diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 2475b88538..d1fd54c7b6 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; @@ -346,6 +345,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()) @@ -356,14 +361,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; @@ -410,8 +416,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; } @@ -424,7 +431,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; } @@ -463,9 +470,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; @@ -598,12 +604,12 @@ F32 LLAvatarAppearance::getAvatarOffset() /*const*/ //----------------------------------------------------------------------------- // 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) { @@ -612,7 +618,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; @@ -1021,7 +1027,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; @@ -1157,8 +1163,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; @@ -1286,8 +1292,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 820fe21d39..f395b78605 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -162,7 +162,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(); // [RLVa:KB] - Checked: 2013-03-03 (RLVa-1.4.8) @@ -222,9 +222,6 @@ public: // XML parse tree //-------------------------------------------------------------------- protected: - static LLXmlTree sXMLTree; // avatar config file - static LLXmlTree sSkeletonXMLTree; // avatar skeleton file - static LLAvatarSkeletonInfo* sAvatarSkeletonInfo; static LLAvatarXmlInfo* sAvatarXmlInfo; @@ -272,6 +269,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 @@ -280,6 +278,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 440e43320c..b3cbdf307b 100644 --- a/indra/llappearance/llavatarappearancedefines.cpp +++ b/indra/llappearance/llavatarappearancedefines.cpp @@ -260,19 +260,17 @@ LLAvatarAppearanceDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index, va_end( argp ); // Needs to be freed when done. } -// 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 @@ -284,16 +282,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 @@ -306,10 +303,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 wearables_vec_t; // // This holds const data - it is initialized once and the contents never change after that. //------------------------------------------------------------------------ -class LLAvatarAppearanceDictionary : public LLSingleton +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 9cb53d6a54..2db9ac9fc0 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -735,8 +735,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; @@ -986,7 +986,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 750dcb5b63..1a45cc29c3 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -186,7 +186,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; @@ -613,7 +613,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 764481cc7e..0bbae88203 100644 --- a/indra/llappearance/llwearabledata.cpp +++ b/indra/llappearance/llwearabledata.cpp @@ -350,7 +350,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); } @@ -360,7 +360,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/llaudio/llstreamingaudio_fmodstudio.cpp b/indra/llaudio/llstreamingaudio_fmodstudio.cpp index 5fef19d6d2..0d3e58b3e5 100644 --- a/indra/llaudio/llstreamingaudio_fmodstudio.cpp +++ b/indra/llaudio/llstreamingaudio_fmodstudio.cpp @@ -392,6 +392,7 @@ void LLStreamingAudio_FMODSTUDIO::setGain(F32 vol) Check_FMOD_Error(mFMODInternetStreamChannelp->setVolume(vol), "FMOD::Channel::setVolume"); } } + // Streamtitle display // virtual bool LLStreamingAudio_FMODSTUDIO::getNewMetadata(LLSD& metadata) @@ -404,14 +405,17 @@ bool LLStreamingAudio_FMODSTUDIO::getNewMetadata(LLSD& metadata) mNewMetadata = false; return true; } - - return mNewMetadata; + else + { + return false; + } } metadata = LLSD(); return false; } // + /////////////////////////////////////////////////////// // manager of possibly-multiple internet audio streams diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 58d90d46df..59f27c20bf 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -1208,7 +1208,9 @@ namespace { LLError::RecorderPtr r = *i; - if (!r->enabled()) + // Crash fix + //if (!r->enabled()) + if (!r || !r->enabled()) { continue; } diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index 83a4b64e8f..ad933154c2 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -388,7 +388,7 @@ LLSingletonBase::vec_t LLSingletonBase::dep_sort() // extracts just the first (key) element from each sorted_iterator, then // uses vec_t's range constructor... but frankly this is more // straightforward, as long as we remember the above reserve() call! - for (const SingletonDeps::sorted_iterator::value_type& pair : sdeps.sort()) + for (const SingletonDeps::sorted_iterator::value_type pair : sdeps.sort()) { ret.push_back(pair.first); } diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 0b9dec969c..8fbbc36162 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -359,10 +359,11 @@ void LLThread::setQuitting() } // static -LLThread::id_t LLThread::currentID() -{ - return std::this_thread::get_id(); -} +// give this a better chance to inline +// LLThread::id_t LLThread::currentID() +// { +// return std::this_thread::get_id(); +// } // static void LLThread::yield() diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index 5cd0731f6c..118c60d7a6 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -60,8 +60,8 @@ public: bool isQuitting() const { return (QUITTING == mStatus); } bool isStopped() const { return (STOPPED == mStatus) || (CRASHED == mStatus); } bool isCrashed() const { return (CRASHED == mStatus); } - - static id_t currentID(); // Return ID of current thread + // Try to encourage the inlining + static LL_FORCE_INLINE id_t currentID(){return std::this_thread::get_id();}; // Return ID of current thread static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure. public: diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index ae2d067bc2..8eccae00c7 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -577,16 +577,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()) @@ -827,6 +820,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(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 246f3058b1..9055202121 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 4739606bc1..5a850d62cf 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 +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 d57479ed3d..06d2788c75 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/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 7ab5f914a5..a8e9a6bd64 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -306,12 +306,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::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()) @@ -324,6 +339,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 c8f1dc3fde..9663981faf 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -42,6 +42,7 @@ class LLAvatarNameCache : public LLSingleton ~LLAvatarNameCache(); public: typedef boost::signals2::signal use_display_name_signal_t; + typedef boost::function account_name_changed_callback_t; // Import/export the name cache to file. bool importFile(std::istream& istr); @@ -113,6 +114,8 @@ public: void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb); + void setAccountNameChangedCallback(const account_name_changed_callback_t& cb) { mAccountNameChangedCallback = cb; } + // FIRE-6659: Legacy "Resident" name toggle void clearCache(); @@ -154,6 +157,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/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp index f3f87d15f6..25c1c015f8 100644 --- a/indra/llmessage/llcoproceduremanager.cpp +++ b/indra/llmessage/llcoproceduremanager.cpp @@ -196,6 +196,7 @@ void LLCoprocedureManager::setPropertyMethods(SettingQuery_t queryfn, SettingUpd // workaround until we get mutex into initializePool initializePool("VAssetStorage"); initializePool("Upload"); + initializePool("ExpCache"); // FIRE-30731: ExpCache coroutine pool crash } //------------------------------------------------------------------------- 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 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 bf7c7ddba2..1d4c10eab2 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -154,8 +154,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(); } @@ -895,16 +905,24 @@ void LLPluginProcessParent::poll(F64 timeout) { // timed out with no incoming data. Just return. } - else if(status == EBADF) + // better logging of poll issues + // else if(status == EBADF) + else if(APR_STATUS_IS_EBADF(status)) { // This happens when one of the file descriptors in the pollset is destroyed, which happens whenever a plugin's socket is closed. // The pollset has been or will be recreated, so just return. LL_DEBUGS("PluginPoll") << "apr_pollset_poll returned EBADF" << LL_ENDL; } - else if(status != APR_SUCCESS) + // better logging of poll issues + // else if(status != APR_SUCCESS) + // { + // LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << LL_ENDL; + // } + else { - LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << LL_ENDL; + LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << " (" << APR_TO_OS_ERROR(status) << ")" << LL_ENDL; } + // } // Remove instances in the done state from the sInstances map. diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index 1617c4ed6a..bc133d3692 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -1535,7 +1535,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 08405df8b0..a8cdce95e9 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) @@ -512,6 +513,8 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) font_paths.push_back(usr_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 7acf904a77..45a11f1b85 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -970,6 +970,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 dc8c1f2e32..f1b63b9f28 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -175,6 +175,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/llrender.cpp b/indra/llrender/llrender.cpp index beed5a2c51..975160ee72 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -874,10 +874,11 @@ void LLTexUnit::setTextureColorSpace(eTextureColorSpace space) } } else -#endif +// #endif // Colour space and shader fixes for BUG-228586 (Rye) { glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); } +#endif // Colour space and shader fixes for BUG-228586 (Rye) } LLLightState::LLLightState(S32 index) 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 b5185a3871..c54e6e57c0 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -329,12 +329,11 @@ 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 + // Nope! + mButtonsEnabled[BUTTON_HELP] = !mHelpTopic.empty();// FALSE; + // Minimize button only for top draggers if ( !mDragOnLeft && mCanMinimize ) { diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 082eb91368..a907786e99 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -295,7 +295,7 @@ public: typedef std::list child_list_t; virtual void addChild(LLFolderViewModelItem* child) - { + { mChildren.push_back(child); child->setParent(this); dirtyFilter(); diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index a4069fc287..ffd45026aa 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -4202,6 +4202,9 @@ void LLContextMenu::show(S32 x, S32 y, LLView* spawning_view) { y += height; } + + // FIRE-10883: Prevent context menu from going off screen + y = llmin(y, menu_region_rect.mTop); } // Open out to the left if menu extends past right edge @@ -4215,6 +4218,9 @@ void LLContextMenu::show(S32 x, S32 y, LLView* spawning_view) { x -= width; } + + // FIRE-10883: Prevent context menu from going off screen + x = llmax(x, menu_region_rect.mLeft); } S32 local_x, local_y; diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 0c3fff25a5..fba3e98411 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -851,16 +851,22 @@ void LLScrollListCtrl::updateColumns(bool force_update) } } + bool header_changed_width = false; // expand last column header we encountered to full list width // Fixed last column on LLScrollListCtrl expanding on control resize when column width should be fixed or dynamic //if (last_header) if (last_header && last_header->canResize()) { + 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) @@ -879,6 +885,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) @@ -932,6 +952,8 @@ BOOL LLScrollListCtrl::selectFirstItem() // virtual BOOL LLScrollListCtrl::selectNthItem( S32 target_index ) { + // FIRE-30571: Comboboxes select all items then pressing Page-Up + target_index = llclamp(target_index, 0, (S32)mItemList.size() - 1); return selectItemRange(target_index, target_index); } @@ -1524,18 +1546,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 (item->getEnabled()) { - if (selected) - { - selectItem(item); - } - else - { - deselectItem(item); - } - found = TRUE; - break; + 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; + } } } @@ -2915,8 +2953,16 @@ void LLScrollListCtrl::sortByColumnIndex(U32 column, BOOL ascending) void LLScrollListCtrl::updateSort() const { - if (hasSortOrder() && !isSorted()) + // FIRE-30667 et al. Group hang issues + // if (hasSortOrder() && !isSorted()) + // { + static LLUICachedControl sortDeferFrameCount("FSSortDeferalFrames"); + if ( hasSortOrder() && !isSorted() && ( mLastUpdateFrame > 1 && ( LLFrameTimer::getFrameCount() - mLastUpdateFrame ) >= sortDeferFrameCount ) ) + // encoding two (unlikely) special values into mLastUpdateFrame 1 means we've sorted and 0 means we've nothing new to do. + // 0 is set after sorting, 1 can be set by a parent for any post sorting action. { + mLastUpdateFrame=0; + // // do stable sort to preserve any previous sorts std::stable_sort( mItemList.begin(), diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 0b36bc204d..b6cc6590ed 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -412,7 +412,9 @@ public: void sortOnce(S32 column, BOOL ascending); // manually call this whenever editing list items in place to flag need for resorting - void setNeedsSort(bool val = true) { mSorted = !val; } + // FIRE-30667 et al. Avoid hangs on large list updates + // void setNeedsSort(bool val = true) { mSorted = !val; } + void setNeedsSort(bool val = true) { mSorted = !val; mLastUpdateFrame = LLFrameTimer::getFrameCount(); } void dirtyColumns(); // some operation has potentially affected column layout or ordering boost::signals2::connection setSortCallback(sort_signal_t::slot_type cb ) @@ -452,6 +454,8 @@ protected: public: void updateLineHeight(); + // FIRE-30667 et al. Avoid hangs on large list updates + mutable U32 mLastUpdateFrame; private: void selectPrevItem(BOOL extend_selection); @@ -478,6 +482,7 @@ private: static void copyNameToClipboard(std::string id, bool is_group); static void copySLURLToClipboard(std::string id, bool is_group); + S32 mLineHeight; // the max height of a single line S32 mScrollLines; // how many lines we've scrolled down S32 mPageLines; // max number of lines is it possible to see on the screen given mRect and mLineHeight diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 1b158bbead..118cc318c2 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -953,6 +953,30 @@ std::string LLUrlEntryAgentRLVAnonymizedName::getName(const LLAvatarName& avatar } // [/RLVa:KB] +// FIRE-30611: "You" in transcript is underlined +/// +/// FSUrlEntryAgentSelf Describes the agent's Second Life agent Url, e.g., +/// secondlife:///app/agentself/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about +FSUrlEntryAgentSelf::FSUrlEntryAgentSelf() : LLUrlEntryAgent() +// +{ + mPattern = boost::regex(APP_HEADER_REGEX "/agentself/[\\da-f-]+/\\w+", + boost::regex::perl|boost::regex::icase); +} + +std::string FSUrlEntryAgentSelf::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ + if (LLUI::getInstance()->mSettingGroups["config"]->getBOOL("FSChatHistoryShowYou")) + { + return LLTrans::getString("AgentNameSubst"); + } + else + { + return LLUrlEntryAgent::getLabel(url, cb); + } +} +// + // // LLUrlEntryGroup Describes a Second Life group Url, e.g., // secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about @@ -1696,4 +1720,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 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 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 4e9b7cb066..8390b8462e 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -362,6 +362,20 @@ private: }; // [/RLVa:KB] +// FIRE-30611: "You" in transcript is underlined +/// +/// FSUrlEntryAgentSelf Describes the agent's Second Life agent Url, e.g., +/// secondlife:///app/agentself/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about +class FSUrlEntryAgentSelf : public LLUrlEntryAgent +{ +public: + FSUrlEntryAgentSelf(); +private: + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); +}; +// + + /// /// LLUrlEntryExperienceProfile Describes a Second Life experience profile Url, e.g., /// secondlife:///app/experience/0e346d8b-4433-4d66-a6b0-fd37083abc4c/profile @@ -598,6 +612,20 @@ 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; +}; + /// /// LLUrlEntryJira Describes Jira issue names -KC /// diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index 568ac92a4c..a66c099a81 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -41,7 +41,7 @@ LLUrlRegistry::LLUrlRegistry() { // mUrlEntry.reserve(20); // [RLVa:KB] - Checked: 2010-11-01 (RLVa-1.2.2a) | Added: RLVa-1.2.2a - mUrlEntry.reserve(28); + mUrlEntry.reserve(29); // [/RLVa:KB] // Urls are matched in the order that they were registered @@ -71,6 +71,7 @@ LLUrlRegistry::LLUrlRegistry() // [RLVa:KB] - Checked: 2010-11-01 (RLVa-1.2.2a) | Added: RLVa-1.2.2a registerUrl(new LLUrlEntryAgentRLVAnonymizedName()); // [/RLVa:KB] + registerUrl(new FSUrlEntryAgentSelf());// FIRE-30611: "You" in transcript is underlined // LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since // LLUrlEntryAgent is a less specific (catchall for agent urls) registerUrl(new LLUrlEntryAgent()); @@ -95,6 +96,7 @@ LLUrlRegistry::LLUrlRegistry() // Allow URLs with no protocol again registerUrl(new LLUrlEntryHTTPNoProtocol()); registerUrl(new LLUrlEntryEmail()); + registerUrl(new LLUrlEntryIPv6()); // parse jira issue names to links -KC registerUrl(new LLUrlEntryJira()); } 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 index fd4efe5346..48194252a5 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -175,6 +175,10 @@ public: virtual void setTitle(const std::string& win_title) {}; // + + // windows only DirectInput8 for joysticks + virtual void* getDirectInput8() { return NULL; }; + virtual bool getInputDevices(U32 device_type_filter, void * devices_callback, void* userdata) { return false; }; protected: LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags); virtual ~LLWindow(); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index f1ad9fed5f..7d26eee5af 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -59,6 +59,9 @@ #include #include +#include // needed for llurlentry test to build on some systems +#pragma comment(lib, "dxguid.lib") // needed for llurlentry test to build on some systems +#pragma comment(lib, "dinput8") const S32 MAX_MESSAGE_PER_UPDATE = 20; const S32 BITS_PER_PIXEL = 32; @@ -76,6 +79,7 @@ const F32 ICON_FLASH_TIME = 0.5f; extern BOOL gDebugWindowProc; LPWSTR gIconResource = IDI_APPLICATION; +LPDIRECTINPUT8 gDirectInput8; LLW32MsgCallback gAsyncMsgCallback = NULL; @@ -485,6 +489,21 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, mhInstance = GetModuleHandle(NULL); mWndProc = NULL; + // Init Direct Input - needed for joystick / Spacemouse + + LPDIRECTINPUT8 di8_interface; + HRESULT status = DirectInput8Create( + mhInstance, // HINSTANCE hinst, + DIRECTINPUT_VERSION, // DWORD dwVersion, + IID_IDirectInput8, // REFIID riidltf, + (LPVOID*)&di8_interface, // LPVOID * ppvOut, + NULL // LPUNKNOWN punkOuter + ); + if (status == DI_OK) + { + gDirectInput8 = di8_interface; + } + mSwapMethod = SWAP_METHOD_UNDEFINED; // No WPARAM yet. @@ -1435,24 +1454,29 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO LL_INFOS("Window") << "pixel formats done." << LL_ENDL ; - S32 swap_method = 0; - S32 cur_format = num_formats-1; - GLint swap_query = WGL_SWAP_METHOD_ARB; + S32 swap_method = 0; + S32 cur_format = 0; + GLint swap_query = WGL_SWAP_METHOD_ARB; - BOOL found_format = FALSE; - - while (!found_format && wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method)) + // SL-14705 Fix name tags showing in front of objects with AMD GPUs. + // On AMD hardware we need to iterate from the first pixel format to the end. + // Spec: + // https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_pixel_format.txt + while (wglGetPixelFormatAttribivARB(mhDC, pixel_formats[cur_format], 0, 1, &swap_query, &swap_method)) { - if (swap_method == WGL_SWAP_UNDEFINED_ARB || cur_format <= 0) + if (swap_method == WGL_SWAP_UNDEFINED_ARB) { - found_format = TRUE; + break; } - else + else if (cur_format >= (S32)(num_formats - 1)) { - --cur_format; + cur_format = 0; + break; } + + ++cur_format; } - + pixel_format = pixel_formats[cur_format]; if (mhDC != 0) // Does The Window Have A Device Context? @@ -4256,6 +4280,28 @@ void LLWindowWin32::setDPIAwareness() } } +void* LLWindowWin32::getDirectInput8() +{ + return &gDirectInput8; +} + +bool LLWindowWin32::getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata) +{ + if (gDirectInput8 != NULL) + { + // Enumerate devices + HRESULT status = gDirectInput8->EnumDevices( + (DWORD) device_type_filter, // DWORD dwDevType, + (LPDIENUMDEVICESCALLBACK)di8_devices_callback, // LPDIENUMDEVICESCALLBACK lpCallback, // BOOL DIEnumDevicesCallback( LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef ) // BOOL CALLBACK DinputDevice::DevicesCallback + (LPVOID*)userdata, // LPVOID pvRef + DIEDFL_ATTACHEDONLY // DWORD dwFlags + ); + + return status == DI_OK; + } + return false; +} + F32 LLWindowWin32::getSystemUISize() { F32 scale_value = 1.f; diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 5c3a260d51..3d76ab76f3 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -121,6 +121,9 @@ public: static std::vector getDynamicFallbackFontList(); static void setDPIAwareness(); + + /*virtual*/ void* getDirectInput8(); + /*virtual*/ bool getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata); protected: LLWindowWin32(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags, diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 325e345316..7ed85a815d 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -743,6 +743,24 @@ LLSD LLControlGroup::getLLSD(const std::string& name) return get(name); } +LLSD LLControlGroup::asLLSD(bool diffs_only) +{ + // Dump all stored values as LLSD + LLSD result = LLSD::emptyArray(); + for (ctrl_name_table_t::iterator iter = mNameTable.begin(); + iter != mNameTable.end(); iter++) + { + LLControlVariable *control = iter->second; + if (!control || control->isType(TYPE_STRING) || (diffs_only && control->isDefault())) + { + continue; + } + const std::string& name = iter->first; + result[name] = getLLSD(name); + } + return result; +} + BOOL LLControlGroup::controlExists(const std::string& name) { ctrl_name_table_t::iterator iter = mNameTable.find(name); diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 07e4ffc0dd..7347152bb1 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -286,6 +286,8 @@ public: LLColor4 getColor4(const std::string& name); LLColor3 getColor3(const std::string& name); + LLSD asLLSD(bool diffs_only); + // generic getter template T get(const std::string& name) { diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 3f0bbbe888..c3dda5ea92 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2642,7 +2642,7 @@ if (DARWIN) set(MACOSX_BUNDLE_BUNDLE_NAME "Firestorm") set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}") set(MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_MACOSX_PHASE}${VIEWER_REVISION}") - set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2010-2020 The Phoenix Firestorm Project, Inc.") + set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2010-2021 The Phoenix Firestorm Project, Inc.") set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "Firestorm.nib") set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "LLApplication") diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index 4e0275a728..0be5b92c3c 100644 --- a/indra/newview/English.lproj/InfoPlist.strings +++ b/indra/newview/English.lproj/InfoPlist.strings @@ -3,4 +3,4 @@ CFBundleName = "Firestorm"; CFBundleShortVersionString = "Firestorm version %%VERSION%%"; -CFBundleGetInfoString = "Firestorm version %%VERSION%%, Copyright 2010-2020 The Phoenix Firestorm Project, Inc."; +CFBundleGetInfoString = "Firestorm version %%VERSION%%, Copyright 2010-2021 The Phoenix Firestorm Project, Inc."; diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index ec4458ee66..8b3e8996e5 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -278,10 +278,8 @@ icon="Command_View_Icon" label_ref="Command_View_Label" tooltip_ref="Command_View_Tooltip" - execute_function="Floater.Toggle" - execute_parameters="camera" - is_running_function="Floater.IsOpen" - is_running_parameters="camera" + execute_function="View.ToggleCameraFloater" + is_running_function="View.CheckCameraFloater" /> Value 0 + FSSortDeferalFrames + + Comment + How many frames after an update should we wait before sorting + Persist + 1 + Type + U32 + Value + 2 + FSGroupNotifyNoTransparency Comment @@ -7444,6 +7455,17 @@ Backup 0 + JoystickDeviceUUID + + Comment + Preffered device ID. + Persist + 1 + Type + String + Value + + JoystickMouselookYaw Comment @@ -25590,5 +25612,16 @@ Change of this parameter will affect the layout of buttons in notification toast Value 1 + FSUseSmallCameraFloater + + Comment + If enabled, the camera floater will be smaller and not contain the camera preset controls. + Persist + 1 + Type + Boolean + Value + 0 + diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl index d29e8a9423..28eea92691 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -40,6 +40,7 @@ uniform sampler2D specularMap; VARYING vec2 vary_texcoord0; +vec3 linear_to_srgb(vec3 cl);// Colour space and shader fixes for BUG-228586 (Rye) void main() { vec4 col = texture2D(diffuseMap, vary_texcoord0.xy); @@ -52,6 +53,7 @@ void main() vec4 norm = texture2D(normalMap, vary_texcoord0.xy); vec4 spec = texture2D(specularMap, vary_texcoord0.xy); + col.rgb = linear_to_srgb(col.rgb);// Colour space and shader fixes for BUG-228586 (Rye) frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = spec; frag_data[2] = vec4(norm.xy,0,0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl index 80d19102b6..a18f6e7ac0 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl @@ -405,6 +405,7 @@ void main() vec3 npos = normalize(-pos.xyz); vec3 light = vec3(0, 0, 0); + final_specular.rgb = srgb_to_linear(final_specular.rgb);// Colour space and shader fixes for BUG-228586 (Rye) #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w ); diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl index 093da8d26d..854e3712bf 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl @@ -111,7 +111,10 @@ void main() vec3 n = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz); #ifdef HAS_NORMAL_MAP vec3 t = normalize((mat*vec4(tangent.xyz+position.xyz,1.0)).xyz-pos.xyz); - vec3 b = cross(n, t)*tangent.w; +// normalize the bitangent (cross product of two normalised vectors is not itself normalised) + // vec3 b = cross(n, t)*tangent.w; + vec3 b = normalize(cross(n, t)*tangent.w); +// vary_mat0 = vec3(t.x, b.x, n.x); vary_mat1 = vec3(t.y, b.y, n.y); @@ -122,11 +125,11 @@ vary_normal = n; #else //HAS_SKIN vec3 n = normalize(normal_matrix * normal); #ifdef HAS_NORMAL_MAP -// tangents should not use the inv_transpose matrix - // vec3 t = normalize(normal_matrix * tangent.xyz); - vec3 t = normalize((modelview_projection_matrix * vec4(tangent.xyz,0)).xyz); + vec3 t = normalize(normal_matrix * tangent.xyz); +// normalize the bitangent (cross product of two normalised vectors is not itself normalised) + // vec3 b = cross(n,t)*tangent.w; + vec3 b = normalize(cross(n,t)*tangent.w); // - vec3 b = cross(n,t)*tangent.w; //vec3 t = cross(b,n) * binormal.w; vary_mat0 = vec3(t.x, b.x, n.x); diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index 8c402fcb54..70e19267ab 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -33,10 +33,10 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect depthMap; +// uniform sampler2DRect depthMap; // Colour space and shader fixes for BUG-228586 (Rye) uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; -uniform samplerCube environmentMap; +// uniform samplerCube environmentMap;// Colour space and shader fixes for BUG-228586 (Rye) uniform sampler2D noiseMap; uniform sampler2D lightFunc; @@ -73,10 +73,10 @@ void main() vec3 norm = getNorm(frag.xy); vec4 spec = texture2DRect(specularRect, frag.xy); - spec.rgb = srgb_to_linear(spec.rgb); + // spec.rgb = srgb_to_linear(spec.rgb);// Colour space and shader fixes for BUG-228586 (Rye) vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb; - diff.rgb = srgb_to_linear(diff.rgb); - + // diff.rgb = srgb_to_linear(diff.rgb);// Colour space and shader fixes for BUG-228586 (Rye) + float noise = texture2D(noiseMap, frag.xy / 128.0).b; vec3 npos = normalize(-pos); diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index 9bba45bc4e..7e14565eea 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -40,9 +40,14 @@ out vec4 frag_color; uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; -uniform sampler2DRect depthMap; +// Colour space and shader fixes for BUG-228586 (Rye) +// uniform sampler2DRect depthMap; +// uniform sampler2DRect normalMap; -uniform samplerCube environmentMap; +// Colour space and shader fixes for BUG-228586 (Rye) +// uniform samplerCube environmentMap; +// + uniform sampler2D noiseMap; uniform sampler2D projectionMap; uniform sampler2D lightFunc; @@ -182,11 +187,12 @@ void main() vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; - // SL-12005 Projector light pops as we get closer, more objectionable than being in wrong color space. - // We can't switch to linear here unless we do it everywhere* - // *gbuffer is sRGB, convert to linear whenever sampling from it - diff_tex.rgb = srgb_to_linear(diff_tex.rgb); - +// Colour space and shader fixes for BUG-228586 (Rye) + // // SL-12005 Projector light pops as we get closer, more objectionable than being in wrong color space. + // // We can't switch to linear here unless we do it everywhere* + // // *gbuffer is sRGB, convert to linear whenever sampling from it + // diff_tex.rgb = srgb_to_linear(diff_tex.rgb); +// vec3 dlit = vec3(0, 0, 0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index d805c9ea48..f062bf8fcd 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -35,11 +35,13 @@ out vec4 frag_color; uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; -uniform sampler2DRect normalMap; -uniform samplerCube environmentMap; +// Colour space and shader fixes for BUG-228586 (Rye) +//uniform sampler2DRect normalMap; +//uniform samplerCube environmentMap; +// uniform sampler2D noiseMap; uniform sampler2D lightFunc; -uniform sampler2DRect depthMap; +//uniform sampler2DRect depthMap;// Colour space and shader fixes for BUG-228586 (Rye) uniform vec3 env_mat[3]; uniform float sun_wash; @@ -90,7 +92,7 @@ void main() float noise = texture2D(noiseMap, frag.xy/128.0).b; vec3 col = texture2DRect(diffuseRect, frag.xy).rgb; - col.rgb = srgb_to_linear(col.rgb); + // col.rgb = srgb_to_linear(col.rgb); // Colour space and shader fixes for BUG-228586 (Rye) float fa = falloff+1.0; float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index f80f1a985a..f24fca77d5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -37,7 +37,8 @@ out vec4 frag_color; uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; uniform sampler2DRect normalMap; -uniform sampler2DRect lightMap; +// Colour space and shader fixes for BUG-228586 (Rye) +// uniform sampler2DRect lightMap; uniform sampler2DRect depthMap; uniform samplerCube environmentMap; uniform sampler2D lightFunc; @@ -90,7 +91,7 @@ void main() vec4 diffuse = texture2DRect(diffuseRect, tc); //convert to gamma space - //diffuse.rgb = linear_to_srgb(diffuse.rgb); + diffuse.rgb = linear_to_srgb(diffuse.rgb);// Colour space and shader fixes for BUG-228586 (Rye) uniform sampler2DRect depthMap; vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); vec3 color = vec3(0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index 694b19cdfb..b1f8187f75 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -177,8 +177,11 @@ void main() float da = dot(norm, lv); vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; - //light shaders output linear and are gamma corrected later in postDeferredGammaCorrectF.glsl - diff_tex.rgb = srgb_to_linear(diff_tex.rgb); + // Colour space and shader fixes for BUG-228586 + // This makes the comment below incorrect, it will presumably be removed if/when the lab apply the proper changes) + // // light shaders output linear and are gamma corrected later in postDeferredGammaCorrectF.glsl + // diff_tex.rgb = srgb_to_linear(diff_tex.rgb); + // vec4 spec = texture2DRect(specularRect, frag.xy); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl index b768d609f4..d87403c78f 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl @@ -43,13 +43,13 @@ void default_lighting() { vec4 color = texture2D(diffuseMap,vary_texcoord0.xy); - color *= vertex_color; - if (color.a < minimum_alpha) { discard; } - + + color *= vertex_color; + color.rgb = atmosLighting(color.rgb); color.rgb = scaleSoftClip(color.rgb); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl index d04cd79f4b..37cac5f437 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl @@ -43,13 +43,13 @@ void fullbright_lighting_water() { vec4 color = diffuseLookup(vary_texcoord0.xy); - color.rgb *= vertex_color.rgb; - if (color.a < minimum_alpha) { discard; } + color.rgb *= vertex_color.rgb; + color.rgb = fullbrightAtmosTransport(color.rgb); frag_color = applyWaterFog(color); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl index 3b9c04b22b..c98db4795c 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl @@ -41,13 +41,15 @@ VARYING vec2 vary_texcoord0; void fullbright_lighting_water() { - vec4 color = texture2D(diffuseMap, vary_texcoord0.xy) * vertex_color; + vec4 color = texture2D(diffuseMap, vary_texcoord0.xy); if (color.a < minimum_alpha) { discard; } + color.rgb *= vertex_color.rgb; + color.rgb = fullbrightAtmosTransport(color.rgb); frag_color = applyWaterFog(color); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl index 0916797259..9c89c09573 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl @@ -41,13 +41,13 @@ void default_lighting_water() { vec4 color = diffuseLookup(vary_texcoord0.xy); - color.rgb *= vertex_color.rgb; - if (color.a < minimum_alpha) { discard; } + color.rgb *= vertex_color.rgb; + color.rgb = atmosLighting(color.rgb); frag_color = applyWaterFog(color); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl index f2a84f1d42..9de7a03180 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl @@ -43,13 +43,13 @@ void default_lighting_water() { vec4 color = texture2D(diffuseMap,vary_texcoord0.xy); - color.rgb *= vertex_color.rgb; - if (color.a < minimum_alpha) { discard; } + color.rgb *= vertex_color.rgb; + color.rgb = atmosLighting(color.rgb); color = applyWaterFog(color); diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index 5d7a28c359..e67c1041ee 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -191,11 +191,12 @@ void main() float da = dot(norm, lv); vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; - // SL-12005 Projector light pops as we get closer, more objectionable than being in wrong color space. - // We can't switch to linear here unless we do it everywhere* - // *gbuffer IS sRGB, convert to linear since this shader outputs linear - diff_tex.rgb = srgb_to_linear(diff_tex.rgb); - + // Colour space and shader fixes for BUG-228586 + // removing comments as colour space change + // // SL-12005 Projector light pops as we get closer, more objectionable than being in wrong color space. + // // We can't switch to linear here unless we do it everywhere* + // // *gbuffer IS sRGB, convert to linear since this shader outputs linear + // diff_tex.rgb = srgb_to_linear(diff_tex.rgb); vec4 spec = texture2DRect(specularRect, frag.xy); vec3 dlit = vec3(0, 0, 0); diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index f4db53e0b7..34a0ad2126 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -88,6 +88,10 @@ void main() da = pow(da, light_gamma); vec4 diffuse = texture2DRect(diffuseRect, tc); + // Colour space and shader fixes for BUG-228586 (Rye) + // convert to gamma space + diffuse.rgb = linear_to_srgb(diffuse.rgb); + // vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index 5ab0b5c5b4..bcf4e14382 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -188,8 +188,10 @@ void main() lv = proj_origin-pos.xyz; lv = normalize(lv); float da = dot(norm, lv); - - vec3 diff_tex = srgb_to_linear(texture2DRect(diffuseRect, frag.xy).rgb); + // Colour space and shader fixes for BUG-228586 (Rye) + // vec3 diff_tex = srgb_to_linear(texture2DRect(diffuseRect, frag.xy).rgb); + vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; + // vec4 spec = texture2DRect(specularRect, frag.xy); vec3 dlit = vec3(0, 0, 0); diff --git a/indra/newview/fschathistory.cpp b/indra/newview/fschathistory.cpp index 262d0fe1f2..61bcf6b519 100644 --- a/indra/newview/fschathistory.cpp +++ b/indra/newview/fschathistory.cpp @@ -1505,17 +1505,10 @@ void FSChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } name_params.use_default_link_style = false; - name_params.link_href = LLSLURL("agent", chat.mFromID, "inspect").getSLURLString(); + name_params.link_href = LLSLURL(from_me ? "agentself" : "agent", chat.mFromID, "inspect").getSLURLString(); - if (from_me && gSavedSettings.getBOOL("FSChatHistoryShowYou")) - { - appendText(LLTrans::getString("AgentNameSubst"), prependNewLineState, name_params); - } - else - { - // Add link to avatar's inspector and delimiter to message. - appendText(std::string(name_params.link_href), prependNewLineState, name_params); - } + // Add link to avatar's inspector and delimiter to message. + appendText(std::string(name_params.link_href), prependNewLineState, name_params); prependNewLineState = false; diff --git a/indra/newview/fspanelimcontrolpanel.cpp b/indra/newview/fspanelimcontrolpanel.cpp index ab18bccb25..217383da3d 100644 --- a/indra/newview/fspanelimcontrolpanel.cpp +++ b/indra/newview/fspanelimcontrolpanel.cpp @@ -72,6 +72,8 @@ void FSPanelGroupControlPanel::setSessionId(const LLUUID& session_id) if(!mParticipantList) { LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(session_id); + // potential crash avoidance. getSpeakerManager can return NULL, the constructor does not check + if ( speaker_manager == nullptr ){ return;} mParticipantList = new FSParticipantList(speaker_manager, getChild("grp_speakers_list"), true,false); } } diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index abe4f5b065..f0df7e5977 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1029,6 +1029,18 @@ boost::signals2::connection LLAgent::addParcelChangedCallback(parcel_changed_cal return mParcelChangedSignal.connect(cb); } +// static +void LLAgent::capabilityReceivedCallback(const LLUUID ®ion_id) +{ + LLViewerRegion* region = gAgent.getRegion(); + if (region && region->getRegionID() == region_id) + { + region->requestSimulatorFeatures(); + LLAppViewer::instance()->updateNameLookupUrl(); + } +} + + //----------------------------------------------------------------------------- // setRegion() //----------------------------------------------------------------------------- @@ -1079,10 +1091,11 @@ void LLAgent::setRegion(LLViewerRegion *regionp) if (regionp->capabilitiesReceived()) { regionp->requestSimulatorFeatures(); + LLAppViewer::instance()->updateNameLookupUrl(); } else { - regionp->setCapabilitiesReceivedCallback(boost::bind(&LLViewerRegion::requestSimulatorFeatures, regionp)); + regionp->setCapabilitiesReceivedCallback(LLAgent::capabilityReceivedCallback); } } @@ -1101,6 +1114,15 @@ void LLAgent::setRegion(LLViewerRegion *regionp) // Update all of the regions. LLWorld::getInstance()->updateAgentOffset(mAgentOriginGlobal); + + if (regionp->capabilitiesReceived()) + { + LLAppViewer::instance()->updateNameLookupUrl(); + } + else + { + regionp->setCapabilitiesReceivedCallback([](const LLUUID ®ion_id) {LLAppViewer::instance()->updateNameLookupUrl(); }); + } } // Pass new region along to metrics components that care about this level of detail. @@ -5967,8 +5989,8 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void * if ((S32)texture_index < TEX_NUM_INDICES ) - { - const LLAvatarAppearanceDictionary::TextureEntry *texture_entry = LLAvatarAppearanceDictionary::instance().getTexture((ETextureIndex)texture_index); + { + const LLAvatarAppearanceDictionary::TextureEntry *texture_entry = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)texture_index); if (texture_entry) { EBakedTextureIndex baked_index = texture_entry->mBakedTextureIndex; @@ -6034,8 +6056,8 @@ void LLAgent::dumpSentAppearance(const std::string& dump_prefix) F32 value = appearance_version_param->getWeight(); dump_visual_param(file, appearance_version_param, value); } - 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 ETextureIndex index = iter->first; @@ -6144,7 +6166,7 @@ void LLAgent::sendAgentSetAppearance() { for(U8 baked_index = 0; baked_index < gAgentAvatarp->getNumBakes(); baked_index++ ) { - const ETextureIndex texture_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index); + const ETextureIndex texture_index = LLAvatarAppearance::getDictionary()->bakedToLocalTextureIndex((EBakedTextureIndex)baked_index); // if we're not wearing a skirt, we don't need the texture to be baked if (texture_index == TEX_SKIRT_BAKED && !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT)) @@ -6203,7 +6225,7 @@ void LLAgent::sendAgentSetAppearance() const LLUUID hash = gAgentWearables.computeBakedTextureHash((EBakedTextureIndex) baked_index, generate_valid_hash); if (hash.notNull()) { - ETextureIndex texture_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex) baked_index); + ETextureIndex texture_index = LLAvatarAppearance::getDictionary()->bakedToLocalTextureIndex((EBakedTextureIndex) baked_index); msg->nextBlockFast(_PREHASH_WearableData); msg->addUUIDFast(_PREHASH_CacheID, hash); msg->addU8Fast(_PREHASH_TextureIndex, (U8)texture_index); diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 78ac900284..1f77c7b1b4 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -258,6 +258,8 @@ public: boost::signals2::connection addParcelChangedCallback(parcel_changed_callback_t); private: + static void capabilityReceivedCallback(const LLUUID ®ion_id); + typedef boost::signals2::signal parcel_changed_signal_t; parcel_changed_signal_t mParcelChangedSignal; diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 0bd8fbfa21..23e6d443e1 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -1323,6 +1323,38 @@ void LLAgentCamera::updateCamera() gAgentCamera.getPanDownKey() > 0.f); // bottom } + // Phototools camera + camera_floater = LLFloaterReg::findTypedInstance("phototools_camera"); + if (camera_floater) + { + camera_floater->mRotate->setToggleState(gAgentCamera.getOrbitRightKey() > 0.f, // left + gAgentCamera.getOrbitUpKey() > 0.f, // top + gAgentCamera.getOrbitLeftKey() > 0.f, // right + gAgentCamera.getOrbitDownKey() > 0.f); // bottom + + camera_floater->mTrack->setToggleState(gAgentCamera.getPanLeftKey() > 0.f, // left + gAgentCamera.getPanUpKey() > 0.f, // top + gAgentCamera.getPanRightKey() > 0.f, // right + gAgentCamera.getPanDownKey() > 0.f); // bottom + } + // + + // Optional small camera floater + camera_floater = LLFloaterReg::findTypedInstance("fs_camera_small"); + if (camera_floater) + { + camera_floater->mRotate->setToggleState(gAgentCamera.getOrbitRightKey() > 0.f, // left + gAgentCamera.getOrbitUpKey() > 0.f, // top + gAgentCamera.getOrbitLeftKey() > 0.f, // right + gAgentCamera.getOrbitDownKey() > 0.f); // bottom + + camera_floater->mTrack->setToggleState(gAgentCamera.getPanLeftKey() > 0.f, // left + gAgentCamera.getPanUpKey() > 0.f, // top + gAgentCamera.getPanRightKey() > 0.f, // right + gAgentCamera.getPanDownKey() > 0.f); // bottom + } + // + // Handle camera movement based on keyboard. const F32 ORBIT_OVER_RATE = 90.f * DEG_TO_RAD; // radians per second const F32 ORBIT_AROUND_RATE = 90.f * DEG_TO_RAD; // radians per second diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 21b63f069a..f09198699d 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -2141,7 +2141,7 @@ void LLAgentWearables::queryWearableCache() num_queries++; // *NOTE: make sure at least one request gets packed - ETextureIndex te_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index); + ETextureIndex te_index = LLAvatarAppearance::getDictionary()->bakedToLocalTextureIndex((EBakedTextureIndex)baked_index); //LL_INFOS() << "Requesting texture for hash " << hash << " in baked texture slot " << baked_index << LL_ENDL; gMessageSystem->nextBlockFast(_PREHASH_WearableData); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index e4272b2bed..6b3699de30 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2066,7 +2066,7 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) } // Moved from LLWearableList::ContextMenu for wider utility. -bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids) +bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids) const { // TODO: investigate wearables may not be loaded at this point EXT-8231 @@ -2076,7 +2076,7 @@ bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids) // Count given clothes (by wearable type) and objects. for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it) { - LLViewerInventoryItem* item = gInventory.getItem(*it); + const LLViewerInventoryItem* item = gInventory.getItem(*it); if (!item) { return false; diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 6357ebbf38..75e3275a91 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -106,7 +106,7 @@ public: bool getCanReplaceCOF(const LLUUID& outfit_cat_id); // Can we add all referenced items to the avatar? - bool canAddWearables(const uuid_vec_t& item_ids); + bool canAddWearables(const uuid_vec_t& item_ids) const; // Copy all items in a category. void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id, diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9623545256..9463d94060 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -316,7 +316,7 @@ extern BOOL gHiDPISupport; //////////////////////////////////////////////////////////// // All from the last globals push... -F32 gSimLastTime; // Used in LLAppViewer::init and send_stats() +F32 gSimLastTime; // Used in LLAppViewer::init and send_viewer_stats() F32 gSimFrames; BOOL gShowObjectUpdates = FALSE; @@ -753,6 +753,7 @@ LLAppViewer::LLAppViewer() mPurgeCacheOnExit(false), mPurgeUserDataOnExit(false), mSecondInstance(false), + mUpdaterNotFound(false), mSavedFinalSnapshot(false), mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded. mQuitRequested(false), @@ -766,6 +767,7 @@ LLAppViewer::LLAppViewer() mFastTimerLogThread(NULL), mSettingsLocationList(NULL), mIsFirstRun(false), + //mMinMicroSecPerFrame(0.f), // FIRE-22297: FPS limiter not working properly on Mac/Linux mSaveSettingsOnExit(true), // Backup Settings mPurgeTextures(false) // FIRE-13066 { @@ -1370,78 +1372,101 @@ bool LLAppViewer::init() gGLActive = FALSE; - // Disable updater + // Disable updater +//#if LL_RELEASE_FOR_DOWNLOAD // if (!gSavedSettings.getBOOL("CmdLineSkipUpdater")) // { -// LLProcess::Params updater; -// updater.desc = "updater process"; -// // Because it's the updater, it MUST persist beyond the lifespan of the -// // viewer itself. -// updater.autokill = false; +// LLProcess::Params updater; +// updater.desc = "updater process"; +// // Because it's the updater, it MUST persist beyond the lifespan of the +// // viewer itself. +// updater.autokill = false; +// std::string updater_file; //#if LL_WINDOWS -// updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "SLVersionChecker.exe"); +// updater_file = "SLVersionChecker.exe"; +// updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, updater_file); //#elif LL_DARWIN -// // explicitly run the system Python interpreter on SLVersionChecker.py -// updater.executable = "python"; -// updater.args.add(gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", "SLVersionChecker.py")); +// // explicitly run the system Python interpreter on SLVersionChecker.py +// updater.executable = "python"; +// updater_file = "SLVersionChecker.py"; +// updater.args.add(gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", updater_file)); //#else -// updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "SLVersionChecker"); +// updater_file = "SLVersionChecker"; +// updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, updater_file); //#endif -// // add LEAP mode command-line argument to whichever of these we selected -// updater.args.add("leap"); -// // UpdaterServiceSettings -// updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting"))); -// // channel -// updater.args.add(LLVersionInfo::getChannel()); -// // testok -// updater.args.add(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest"))); -// // ForceAddressSize -// updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize"))); -//#if LL_WINDOWS && !LL_RELEASE_FOR_DOWNLOAD && !LL_SEND_CRASH_REPORTS -// // This is neither a release package, nor crash-reporting enabled test build -// // try to run version updater, but don't bother if it fails (file might be missing) -// LLLeap *leap_p = LLLeap::create(updater, false); -// if (!leap_p) -// { -// LL_WARNS("LLLeap") << "Failed to run LLLeap" << LL_ENDL; +// // add LEAP mode command-line argument to whichever of these we selected +// updater.args.add("leap"); +// // UpdaterServiceSettings +// updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting"))); +// // channel +// updater.args.add(LLVersionInfo::instance().getChannel()); +// // testok +// updater.args.add(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest"))); +// // ForceAddressSize +// updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize"))); +// +// try +// { +// // Run the updater. An exception from launching the updater should bother us. +// LLLeap::create(updater, true); +// mUpdaterNotFound = false; +// } +// catch (...) +// { +// LLUIString details = LLNotifications::instance().getGlobalString("LLLeapUpdaterFailure"); +// details.setArg("[UPDATER_APP]", updater_file); +// OSMessageBox( +// details.getString(), +// LLStringUtil::null, +// OSMB_OK); +// mUpdaterNotFound = true; +// } // } -//#else -// // Run the updater. An exception from launching the updater should bother us. -// LLLeap::create(updater, true); -//#endif +// else +// { +// LL_WARNS("InitInfo") << "Skipping updater check." << LL_ENDL; +// } +// +// if (mUpdaterNotFound) +// { +// LL_WARNS("InitInfo") << "Failed to launch updater. Skipping Leap commands." << LL_ENDL; +// } +// else +// { +// // Iterate over --leap command-line options. But this is a bit tricky: if +// // there's only one, it won't be an array at all. +// LLSD LeapCommand(gSavedSettings.getLLSD("LeapCommand")); +// LL_DEBUGS("InitInfo") << "LeapCommand: " << LeapCommand << LL_ENDL; +// if (LeapCommand.isDefined() && !LeapCommand.isArray()) +// { +// // If LeapCommand is actually a scalar value, make an array of it. +// // Have to do it in two steps because LeapCommand.append(LeapCommand) +// // trashes content! :-P +// LLSD item(LeapCommand); +// LeapCommand.append(item); +// } +// BOOST_FOREACH(const std::string& leap, llsd::inArray(LeapCommand)) +// { +// LL_INFOS("InitInfo") << "processing --leap \"" << leap << '"' << LL_ENDL; +// // We don't have any better description of this plugin than the +// // user-specified command line. Passing "" causes LLLeap to derive a +// // description from the command line itself. +// // Suppress LLLeap::Error exception: trust LLLeap's own logging. We +// // don't consider any one --leap command mission-critical, so if one +// // fails, log it, shrug and carry on. +// LLLeap::create("", leap, false); // exception=false +// } +// } +// +// if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0) +// { +// LL_WARNS("InitInfo") << "QAModeEventHostPort DEPRECATED: " +// << "lleventhost no longer supported as a dynamic library" +// << LL_ENDL; +// } +//#endif //LL_RELEASE_FOR_DOWNLOAD // - // Iterate over --leap command-line options. But this is a bit tricky: if - // there's only one, it won't be an array at all. - LLSD LeapCommand(gSavedSettings.getLLSD("LeapCommand")); - LL_DEBUGS("InitInfo") << "LeapCommand: " << LeapCommand << LL_ENDL; - if (LeapCommand.isDefined() && ! LeapCommand.isArray()) - { - // If LeapCommand is actually a scalar value, make an array of it. - // Have to do it in two steps because LeapCommand.append(LeapCommand) - // trashes content! :-P - LLSD item(LeapCommand); - LeapCommand.append(item); - } - BOOST_FOREACH(const std::string& leap, llsd::inArray(LeapCommand)) - { - LL_INFOS("InitInfo") << "processing --leap \"" << leap << '"' << LL_ENDL; - // We don't have any better description of this plugin than the - // user-specified command line. Passing "" causes LLLeap to derive a - // description from the command line itself. - // Suppress LLLeap::Error exception: trust LLLeap's own logging. We - // don't consider any one --leap command mission-critical, so if one - // fails, log it, shrug and carry on. - LLLeap::create("", leap, false); // exception=false - } - - if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0) - { - LL_WARNS("InitInfo") << "QAModeEventHostPort DEPRECATED: " - << "lleventhost no longer supported as a dynamic library" - << LL_ENDL; - } - LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match; //EXT-7013 - On windows for some locale (Japanese) standard @@ -1495,6 +1520,12 @@ bool LLAppViewer::init() joystick = LLViewerJoystick::getInstance(); joystick->setNeedsReset(true); + /*----------------------------------------------------------------------*/ + + // FIRE-22297: FPS limiter not working properly on Mac/Linux + //gSavedSettings.getControl("FramePerSecondLimit")->getSignal()->connect(boost::bind(&LLAppViewer::onChangeFrameLimit, this, _2)); + //onChangeFrameLimit(gSavedSettings.getLLSD("FramePerSecondLimit")); + // return true; } @@ -1772,6 +1803,23 @@ bool LLAppViewer::doFrame() display(); + // FIRE-22297: FPS limiter not working properly on Mac/Linux + //static U64 last_call = 0; + //if (!gTeleportDisplay) + //{ + // // Frame/draw throttling, controlled by FramePerSecondLimit + // U64 elapsed_time = LLTimer::getTotalTime() - last_call; + // if (elapsed_time < mMinMicroSecPerFrame) + // { + // LL_RECORD_BLOCK_TIME(FTM_SLEEP); + // // llclamp for when time function gets funky + // U64 sleep_time = llclamp(mMinMicroSecPerFrame - elapsed_time, (U64)1, (U64)1e6); + // micro_sleep(sleep_time, 0); + // } + //} + //last_call = LLTimer::getTotalTime(); + // + pingMainloopTimeout("Main:Snapshot"); LLFloaterSnapshot::update(); // take snapshots LLFloaterOutfitSnapshot::update(); @@ -2213,9 +2261,6 @@ bool LLAppViewer::cleanup() SUBSYSTEM_CLEANUP(LLAvatarAppearance); - // Comment out duplicate clean up - //SUBSYSTEM_CLEANUP(LLAvatarAppearance); - SUBSYSTEM_CLEANUP(LLPostProcess); LLTracker::cleanupInstance(); @@ -2455,6 +2500,7 @@ bool LLAppViewer::cleanup() LLUIImageList::getInstance()->cleanUp(); // This should eventually be done in LLAppViewer + SUBSYSTEM_CLEANUP(LLImage); SUBSYSTEM_CLEANUP(LLVFSThread); SUBSYSTEM_CLEANUP(LLLFSThread); @@ -2498,6 +2544,7 @@ bool LLAppViewer::cleanup() LLWeb::loadURLExternal( gLaunchFileOnQuit, false ); LL_INFOS() << "File launched." << LL_ENDL; } + // make sure nothing uses applyProxySettings by this point. LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL; SUBSYSTEM_CLEANUP(LLProxy); LLCore::LLHttp::cleanup(); @@ -2553,7 +2600,7 @@ bool LLAppViewer::initThreads() { static const bool enable_threads = true; - LLImage::initParamSingleton(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); + LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); LLVFSThread::initClass(enable_threads && false); LLLFSThread::initClass(enable_threads && false); @@ -3782,7 +3829,7 @@ LLSD LLAppViewer::getViewerInfo() const info["POSITION_LOCAL"] = ll_sd_from_vector3(gAgent.getPosAgentFromGlobal(pos)); info["REGION"] = gAgent.getRegion()->getName(); boost::regex regex("\\.(secondlife|lindenlab)\\..*"); - info["HOSTNAME"] = boost::regex_replace(gAgent.getRegion()->getHost().getHostName(), regex, ""); + info["HOSTNAME"] = boost::regex_replace(gAgent.getRegion()->getSimHostName(), regex, ""); LLSLURL slurl; LLAgentUI::buildSLURL(slurl); info["SLURL"] = slurl.getSLURLString(); @@ -4368,7 +4415,7 @@ void LLAppViewer::handleViewerCrash() if(gAgent.getRegion()) { - gDebugInfo["Dynamic"]["CurrentSimHost"] = gAgent.getRegionHost().getHostName(); + gDebugInfo["Dynamic"]["CurrentSimHost"] = gAgent.getRegion()->getSimHostName(); gDebugInfo["Dynamic"]["CurrentRegion"] = gAgent.getRegion()->getName(); const LLVector3& loc = gAgent.getPositionAgent(); @@ -4775,7 +4822,11 @@ void LLAppViewer::requestQuit() gFloaterView->closeAllChildren(true); } - send_stats(); + // Send preferences once, when exiting + // Don't send all non-default settings which might result in a violation of GDPR + //bool include_preferences = true; + bool include_preferences = false; + send_viewer_stats(include_preferences); gLogoutTimer.reset(); mQuitRequested = true; @@ -5653,7 +5704,8 @@ void LLAppViewer::idle() if (viewer_stats_timer.getElapsedTimeF32() >= SEND_STATS_PERIOD && !gDisconnected) { LL_INFOS() << "Transmitting sessions stats" << LL_ENDL; - send_stats(); + bool include_preferences = false; + send_viewer_stats(include_preferences); viewer_stats_timer.reset(); } @@ -6074,11 +6126,56 @@ void LLAppViewer::sendLogoutRequest() } } +void LLAppViewer::updateNameLookupUrl() +{ + LLViewerRegion* region = gAgent.getRegion(); + if (!region || !region->capabilitiesReceived()) + { + return; + } + + LLAvatarNameCache *name_cache = LLAvatarNameCache::getInstance(); + bool had_capability = LLAvatarNameCache::getInstance()->hasNameLookupURL(); + std::string name_lookup_url; + name_lookup_url.reserve(128); // avoid a memory allocation below + name_lookup_url = region->getCapability("GetDisplayNames"); + bool have_capability = !name_lookup_url.empty(); + if (have_capability) + { + // we have support for display names, use it + U32 url_size = name_lookup_url.size(); + // capabilities require URLs with slashes before query params: + // https://:/cap//?ids= + // but the caps are granted like: + // https://:/cap/ + if (url_size > 0 && name_lookup_url[url_size - 1] != '/') + { + name_lookup_url += '/'; + } + name_cache->setNameLookupURL(name_lookup_url); + } + else + { + // Display names not available on this region + name_cache->setNameLookupURL(std::string()); + } + + // Error recovery - did we change state? + if (had_capability != have_capability) + { + // name tags are persistant on screen, so make sure they refresh + LLVOAvatar::invalidateNameTags(); + } +} + void LLAppViewer::idleNameCache() { // Neither old nor new name cache can function before agent has a region LLViewerRegion* region = gAgent.getRegion(); - if (!region) return; + if (!region) + { + return; + } // deal with any queued name requests and replies. gCacheName->processPending(); @@ -6086,47 +6183,12 @@ void LLAppViewer::idleNameCache() // Can't run the new cache until we have the list of capabilities // for the agent region, and can therefore decide whether to use // display names or fall back to the old name system. - if (!region->capabilitiesReceived()) return; + if (!region->capabilitiesReceived()) + { + return; + } - // Agent may have moved to a different region, so need to update cap URL - // for name lookups. Can't do this in the cap grant code, as caps are - // granted to neighbor regions before the main agent gets there. Can't - // do it in the move-into-region code because cap not guaranteed to be - // granted yet, for example on teleport. - LLAvatarNameCache *name_cache = LLAvatarNameCache::getInstance(); - bool had_capability = LLAvatarNameCache::getInstance()->hasNameLookupURL(); - std::string name_lookup_url; - name_lookup_url.reserve(128); // avoid a memory allocation below - name_lookup_url = region->getCapability("GetDisplayNames"); - bool have_capability = !name_lookup_url.empty(); - if (have_capability) - { - // we have support for display names, use it - U32 url_size = name_lookup_url.size(); - // capabilities require URLs with slashes before query params: - // https://:/cap//?ids= - // but the caps are granted like: - // https://:/cap/ - if (url_size > 0 && name_lookup_url[url_size-1] != '/') - { - name_lookup_url += '/'; - } - name_cache->setNameLookupURL(name_lookup_url); - } - else - { - // Display names not available on this region - name_cache->setNameLookupURL( std::string() ); - } - - // Error recovery - did we change state? - if (had_capability != have_capability) - { - // name tags are persistant on screen, so make sure they refresh - LLVOAvatar::invalidateNameTags(); - } - - name_cache->idle(); + LLAvatarNameCache::getInstance()->idle(); } // @@ -6137,6 +6199,7 @@ void LLAppViewer::idleNameCache() #ifdef TIME_THROTTLE_MESSAGES #define CHECK_MESSAGES_DEFAULT_MAX_TIME .020f // 50 ms = 50 fps (just for messages!) +#define CHECK_MESSAGES_MAX_TIME_LIMIT 1.0f // 1 second, a long time but still able to stay connected static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME; #endif @@ -6202,11 +6265,24 @@ void LLAppViewer::idleNetwork() #ifdef TIME_THROTTLE_MESSAGES if (total_time >= CheckMessagesMaxTime) { - // Increase CheckMessagesMaxTime so that we will eventually catch up - CheckMessagesMaxTime *= 1.035f; // 3.5% ~= x2 in 20 frames, ~8x in 60 frames + // Don't allow busy network to excessively starve rendering loop + // // Increase CheckMessagesMaxTime so that we will eventually catch up + // CheckMessagesMaxTime *= 1.035f; // 3.5% ~= x2 in 20 frames, ~8x in 60 frames + // } + // else + // { + if( CheckMessagesMaxTime < CHECK_MESSAGES_MAX_TIME_LIMIT ) // cap the increase to avoid logout through ping starvation + {// Increase CheckMessagesMaxTime so that we will eventually catch up + CheckMessagesMaxTime *= 1.035f; // 3.5% ~= x2 in 20 frames, ~8x in 60 frames + } + else + { + CheckMessagesMaxTime = CHECK_MESSAGES_MAX_TIME_LIMIT; + } } else { + // // Reset CheckMessagesMaxTime to default value CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME; } @@ -6348,6 +6424,21 @@ void LLAppViewer::disconnectViewer() LLUrlEntryParcel::setDisconnected(gDisconnected); } +// FIRE-22297: FPS limiter not working properly on Mac/Linux +//bool LLAppViewer::onChangeFrameLimit(LLSD const & evt) +//{ +// if (evt.asInteger() > 0) +// { +// mMinMicroSecPerFrame = (U64)(1000000.0f / F32(evt.asInteger())); +// } +// else +// { +// mMinMicroSecPerFrame = 0; +// } +// return false; +//} +// + void LLAppViewer::forceErrorLLError() { LL_ERRS() << "This is a deliberate llerror" << LL_ENDL; @@ -6517,7 +6608,7 @@ void LLAppViewer::handleLoginComplete() /* if(gAgent.getRegion()) { - gDebugInfo["CurrentSimHost"] = gAgent.getRegionHost().getHostName(); + gDebugInfo["CurrentSimHost"] = gAgent.getRegion()->getSimHostName(); gDebugInfo["CurrentRegion"] = gAgent.getRegion()->getName(); } */ diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index d802d0bf49..339c647615 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -95,6 +95,7 @@ public: bool quitRequested() { return mQuitRequested; } bool logoutRequestSent() { return mLogoutRequestSent; } bool isSecondInstance() { return mSecondInstance; } + bool isUpdaterMissing() { return mUpdaterNotFound; } void writeDebugInfo(bool isStatic=true); @@ -217,7 +218,9 @@ public: // llcorehttp init/shutdown/config information. LLAppCoreHttp & getAppCoreHttp() { return mAppCoreHttp; } - + + void updateNameLookupUrl(); + protected: virtual bool initWindow(); // Initialize the viewer's window. virtual void initLoggingAndGetLastDuration(); // Initialize log files, logging system @@ -266,11 +269,15 @@ private: void sendLogoutRequest(); void disconnectViewer(); + // FIRE-22297: FPS limiter not working properly on Mac/Linux + //bool onChangeFrameLimit(LLSD const & evt); + // *FIX: the app viewer class should be some sort of singleton, no? // Perhaps its child class is the singleton and this should be an abstract base. static LLAppViewer* sInstance; bool mSecondInstance; // Is this a second instance of the app? + bool mUpdaterNotFound; // True when attempt to start updater failed std::string mMarkerFileName; LLAPRFile mMarkerFile; // A file created to indicate the app is running. @@ -332,7 +339,11 @@ private: // llcorehttp library init/shutdown helper LLAppCoreHttp mAppCoreHttp; - bool mIsFirstRun; + bool mIsFirstRun; + // FIRE-22297: FPS limiter not working properly on Mac/Linux + //U64 mMinMicroSecPerFrame; // frame throttling + + // Backup Settings public: void setSaveSettingsOnExit(bool state) {mSaveSettingsOnExit = state; }; diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 9fa14a1d70..c91790f9c0 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -543,8 +543,11 @@ bool LLConversationLog::loadFromFile(const std::string& filename) return false; } bool purge_required = false; - - char buffer[MAX_STRING]; + // FIRE-30705 protect against silly display names that cause lines to exceed max string length + // char buffer[MAX_STRING]; + static constexpr int BUFFER_1K { 1024 }; // long enough to handle the most extreme Unicode nonsense and some to spare + char buffer[BUFFER_1K]; + // char conv_name_buffer[MAX_STRING]; char part_id_buffer[MAX_STRING]; char conv_id_buffer[MAX_STRING]; @@ -555,12 +558,21 @@ bool LLConversationLog::loadFromFile(const std::string& filename) // before CHUI-348 it was a flag of conversation voice state int prereserved_unused; - while (!feof(fp) && fgets(buffer, MAX_STRING, fp)) + // FIRE-30705 protect against silly display names that cause lines to exceed max string length + // while (!feof(fp) && fgets(buffer, MAX_STRING, fp)) + // { + // conv_name_buffer[0] = '\0'; + // part_id_buffer[0] = '\0'; + // conv_id_buffer[0] = '\0'; + memset( buffer, '\0', BUFFER_1K ); + while (!feof(fp) && fgets(buffer, BUFFER_1K, fp)) { - conv_name_buffer[0] = '\0'; - part_id_buffer[0] = '\0'; - conv_id_buffer[0] = '\0'; - + // force blank for added safety + memset( conv_name_buffer, '\0', MAX_STRING ); + memset( part_id_buffer, '\0', MAX_STRING ); + memset( conv_id_buffer, '\0', MAX_STRING ); + memset( history_file_name, '\0', MAX_STRING ); + // sscanf(buffer, "[%lld] %d %d %d %[^|]| %s %s %[^|]|", &time, &stype, @@ -598,6 +610,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename) } mConversations.push_back(conversation); + memset( buffer, '\0', BUFFER_1K ); // FIRE-30705 clear buffer down } fclose(fp); diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 832811a787..95ec93d823 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -1110,7 +1110,7 @@ void LLEnvironment::onRegionChange() } if (!cur_region->capabilitiesReceived()) { - cur_region->setCapabilitiesReceivedCallback([](LLUUID region_id) { LLEnvironment::instance().requestRegion(); }); + cur_region->setCapabilitiesReceivedCallback([](const LLUUID ®ion_id) { LLEnvironment::instance().requestRegion(); }); return; } requestRegion(); diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp index 25f93cd5eb..974958c9a3 100644 --- a/indra/newview/llfloateravatartextures.cpp +++ b/indra/newview/llfloateravatartextures.cpp @@ -56,7 +56,7 @@ BOOL LLFloaterAvatarTextures::postBuild() { for (U32 i=0; i < TEX_NUM_INDICES; i++) { - const std::string tex_name = LLAvatarAppearanceDictionary::getInstance()->getTexture(ETextureIndex(i))->mName; + const std::string tex_name = LLAvatarAppearance::getDictionary()->getTexture(ETextureIndex(i))->mName; mTextures[i] = getChild(tex_name); // Mask avatar textures and disable mTextures[i]->setIsMasked(TRUE); @@ -85,7 +85,7 @@ static void update_texture_ctrl(LLVOAvatar* avatarp, ETextureIndex te) { LLUUID id = IMG_DEFAULT_AVATAR; - const LLAvatarAppearanceDictionary::TextureEntry* tex_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture(te); + const LLAvatarAppearanceDictionary::TextureEntry* tex_entry = LLAvatarAppearance::getDictionary()->getTexture(te); if (tex_entry && tex_entry->mIsLocalTexture) { if (avatarp->isSelf()) @@ -180,14 +180,14 @@ void LLFloaterAvatarTextures::onClickDump(void* data) const LLTextureEntry* te = avatarp->getTE(i); if (!te) continue; - const LLAvatarAppearanceDictionary::TextureEntry* tex_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)(i)); + const LLAvatarAppearanceDictionary::TextureEntry* tex_entry = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)(i)); if (!tex_entry) continue; if (LLVOAvatar::isIndexLocalTexture((ETextureIndex)i)) { LLUUID id = IMG_DEFAULT_AVATAR; - LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType((ETextureIndex)i); + LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex)i); if (avatarp->isSelf()) { LLViewerWearable *wearable = gAgentWearables.getViewerWearable(wearable_type, 0); diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp index c8786ef11d..d8e45acac7 100644 --- a/indra/newview/llfloatercamera.cpp +++ b/indra/newview/llfloatercamera.cpp @@ -268,6 +268,12 @@ void LLFloaterCamera::resetCameraMode() if (!floater_camera) return; floater_camera->switchMode(CAMERA_CTRL_MODE_PAN); // + + // Optional small camera floater + floater_camera = LLFloaterCamera::findSmallInstance(); + if (!floater_camera) return; + floater_camera->switchMode(CAMERA_CTRL_MODE_PAN); + // } void LLFloaterCamera::onAvatarEditingAppearance(bool editing) @@ -282,6 +288,12 @@ void LLFloaterCamera::onAvatarEditingAppearance(bool editing) if (!floater_camera) return; floater_camera->handleAvatarEditingAppearance(editing); // + + // Optional small camera floater + floater_camera = LLFloaterCamera::findSmallInstance(); + if (!floater_camera) return; + floater_camera->handleAvatarEditingAppearance(editing); + // } void LLFloaterCamera::handleAvatarEditingAppearance(bool editing) @@ -324,6 +336,18 @@ void LLFloaterCamera::toPrevMode() } } // + + // Optional small camera floater + floater_camera = LLFloaterCamera::findSmallInstance(); + if (floater_camera) + { + floater_camera->updateItemsSelection(); + if(floater_camera->inFreeCameraMode()) + { + activate_camera_tool(); + } + } + // } LLFloaterCamera* LLFloaterCamera::findInstance() @@ -338,6 +362,13 @@ LLFloaterCamera* LLFloaterCamera::findPhototoolsInstance() } // +// Optional small camera floater +LLFloaterCamera* LLFloaterCamera::findSmallInstance() +{ + return LLFloaterReg::findTypedInstance("fs_camera_small"); +} +// + void LLFloaterCamera::onOpen(const LLSD& key) { LLFirstUse::viewPopup(); @@ -353,7 +384,9 @@ void LLFloaterCamera::onOpen(const LLSD& key) toPrevMode(); mClosed = FALSE; - populatePresetCombo(); + // Optional small camera floater + if (mPresetCombo) + populatePresetCombo(); } void LLFloaterCamera::onClose(bool app_quitting) @@ -381,7 +414,8 @@ LLFloaterCamera::LLFloaterCamera(const LLSD& val) : LLFloater(val), mClosed(FALSE), mCurrMode(CAMERA_CTRL_MODE_PAN), - mPrevMode(CAMERA_CTRL_MODE_PAN) + mPrevMode(CAMERA_CTRL_MODE_PAN), + mPresetCombo(nullptr) // Optional small camera floater { LLHints::getInstance()->registerHintTarget("view_popup", getHandle()); mCommitCallbackRegistrar.add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraItem, _2)); @@ -395,7 +429,7 @@ BOOL LLFloaterCamera::postBuild() mRotate = getChild(ORBIT); mZoom = findChild(ZOOM); mTrack = getChild(PAN); - mPresetCombo = getChild("preset_combo"); + mPresetCombo = findChild("preset_combo"); // Optional small camera floater // Improved camera floater //getChild("precise_ctrs_label")->setShowCursorHand(false); @@ -421,8 +455,15 @@ BOOL LLFloaterCamera::postBuild() } // - mPresetCombo->setCommitCallback(boost::bind(&LLFloaterCamera::onCustomPresetSelected, this)); - LLPresetsManager::getInstance()->setPresetListChangeCameraCallback(boost::bind(&LLFloaterCamera::populatePresetCombo, this)); + // Optional small camera floater + //mPresetCombo->setCommitCallback(boost::bind(&LLFloaterCamera::onCustomPresetSelected, this)); + //LLPresetsManager::getInstance()->setPresetListChangeCameraCallback(boost::bind(&LLFloaterCamera::populatePresetCombo, this)); + if (mPresetCombo) + { + mPresetCombo->setCommitCallback(boost::bind(&LLFloaterCamera::onCustomPresetSelected, this)); + LLPresetsManager::getInstance()->setPresetListChangeCameraCallback(boost::bind(&LLFloaterCamera::populatePresetCombo, this)); + } + // update(); @@ -598,6 +639,19 @@ void LLFloaterCamera::onClickCameraItem(const LLSD& param) camera_floater->fromFreeToPresets(); } // + + // Optional small camera floater + camera_floater = LLFloaterCamera::findSmallInstance(); + if (camera_floater) + { + // FIRE-29950: Re-add weird legacy object view camera toggle + //camera_floater->switchMode(CAMERA_CTRL_MODE_FREE_CAMERA); + camera_floater->mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA ? camera_floater->switchMode(CAMERA_CTRL_MODE_PAN) : camera_floater->switchMode(CAMERA_CTRL_MODE_FREE_CAMERA); + // + camera_floater->updateItemsSelection(); + camera_floater->fromFreeToPresets(); + } + // } // Improved camera floater else if ("reset_view" == name) @@ -612,6 +666,12 @@ void LLFloaterCamera::onClickCameraItem(const LLSD& param) camera_floater->switchMode(CAMERA_CTRL_MODE_PAN); // + // Optional small camera floater + camera_floater = LLFloaterCamera::findSmallInstance(); + if (camera_floater) + camera_floater->switchMode(CAMERA_CTRL_MODE_PAN); + // + gAgentCamera.changeCameraToDefault(); switchToPreset("rear_view"); } @@ -628,6 +688,12 @@ void LLFloaterCamera::onClickCameraItem(const LLSD& param) camera_floater->switchMode(CAMERA_CTRL_MODE_PAN); // + // Optional small camera floater + camera_floater = LLFloaterCamera::findSmallInstance(); + if (camera_floater) + camera_floater->switchMode(CAMERA_CTRL_MODE_PAN); + // + switchToPreset(name); } } @@ -696,6 +762,15 @@ void LLFloaterCamera::switchToPreset(const std::string& name) camera_floater->fromFreeToPresets(); } // + + // Optional small camera floater + camera_floater = LLFloaterCamera::findSmallInstance(); + if (camera_floater) + { + camera_floater->updateItemsSelection(); + camera_floater->fromFreeToPresets(); + } + // } void LLFloaterCamera::fromFreeToPresets() diff --git a/indra/newview/llfloatercamera.h b/indra/newview/llfloatercamera.h index 95572fec23..269e4d1617 100644 --- a/indra/newview/llfloatercamera.h +++ b/indra/newview/llfloatercamera.h @@ -95,6 +95,8 @@ private: static LLFloaterCamera* findInstance(); // Phototools camera static LLFloaterCamera* findPhototoolsInstance(); + // Optional small camera floater + static LLFloaterCamera* findSmallInstance(); /*virtual*/ BOOL postBuild(); diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index 75d2341ed8..3bd05cd86d 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -102,11 +102,15 @@ BOOL LLFloaterConversationPreview::postBuild() file = "chat"; } mChatHistoryFileName = file; - // Obsolete because of https://bitbucket.org/lindenlab/viewer/commits/57b32eb01cd35bbac440569df885036eb24f2369 - //if (mIsGroup && !LLStringUtil::endsWith(mChatHistoryFileName, GROUP_CHAT_SUFFIX)) - //{ - // mChatHistoryFileName += GROUP_CHAT_SUFFIX; - //} + // Broken version got removed in https://bitbucket.org/lindenlab/viewer/commits/57b32eb01cd35bbac440569df885036eb24f2369 + // but this is actually needed in the fixed form: If a group chat + // log is stored in conversation.log without the suffix, the filename + // will not be updated until the conversation is removed from the log, + // resulting in the old chat log being displayed. + if (mIsGroup && !LLStringUtil::endsWith(mChatHistoryFileName, GROUP_CHAT_SUFFIX)) + { + mChatHistoryFileName += GROUP_CHAT_SUFFIX; + } // LLStringUtil::format_map_t args; args["[NAME]"] = name; diff --git a/indra/newview/llfloaterdeleteprefpreset.cpp b/indra/newview/llfloaterdeleteprefpreset.cpp index 0765756b43..819b2bcee2 100644 --- a/indra/newview/llfloaterdeleteprefpreset.cpp +++ b/indra/newview/llfloaterdeleteprefpreset.cpp @@ -59,8 +59,17 @@ BOOL LLFloaterDeletePrefPreset::postBuild() void LLFloaterDeletePrefPreset::onOpen(const LLSD& key) { mSubdirectory = key.asString(); - std::string floater_title = getString(std::string("title_") + mSubdirectory); - setTitle(floater_title); + std::string title_type = std::string("title_") + mSubdirectory; + if (hasString(title_type)) + { + std::string floater_title = getString(title_type); + setTitle(floater_title); + } + else + { + LL_WARNS() << title_type << " not found" << LL_ENDL; + setTitle(title_type); + } LLComboBox* combo = getChild("preset_combo"); EDefaultOptions option = DEFAULT_HIDE; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 84fdaecaf4..59d5f72146 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -458,19 +458,23 @@ void LLFloaterIMContainer::idleUpdate() const LLConversationItem *current_session = getCurSelectedViewModelItem(); if (current_session) { - // Update moderator options visibility - LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = current_session->getChildrenBegin(); - LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = current_session->getChildrenEnd(); - bool is_moderator = isGroupModerator(); - bool can_ban = haveAbilityToBan(); - while (current_participant_model != end_participant_model) + if (current_session->getType() == LLConversationItem::CONV_SESSION_GROUP) { - LLConversationItemParticipant* participant_model = dynamic_cast(*current_participant_model); - participant_model->setModeratorOptionsVisible(is_moderator); - participant_model->setGroupBanVisible(can_ban && participant_model->getUUID() != gAgentID); + // Update moderator options visibility + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = current_session->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = current_session->getChildrenEnd(); + bool is_moderator = isGroupModerator(); + bool can_ban = haveAbilityToBan(); + while (current_participant_model != end_participant_model) + { + LLConversationItemParticipant* participant_model = dynamic_cast(*current_participant_model); + participant_model->setModeratorOptionsVisible(is_moderator); + participant_model->setGroupBanVisible(can_ban && participant_model->getUUID() != gAgentID); - current_participant_model++; + current_participant_model++; + } } + // Update floater's title as required by the currently selected session or use the default title LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(current_session->getUUID()); setTitle(conversation_floaterp && conversation_floaterp->needsTitleOverwrite() ? conversation_floaterp->getTitle() : mGeneralTitle); diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 76900697bc..41339620a5 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -165,7 +165,6 @@ void LLFloaterIMSession::onClickCloseBtn(bool) else { LL_WARNS() << "Empty session with id: " << (mSessionID.asString()) << LL_ENDL; - return; } LLFloaterIMSessionTab::onClickCloseBtn(); diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp index 0cd109cfb5..3d5af0149e 100644 --- a/indra/newview/llfloaterjoystick.cpp +++ b/indra/newview/llfloaterjoystick.cpp @@ -40,7 +40,17 @@ #include "llviewercontrol.h" #include "llappviewer.h" #include "llviewerjoystick.h" +#include "llviewerwindow.h" +#include "llwindow.h" #include "llcheckboxctrl.h" +#include "llcombobox.h" + +#if LL_WINDOWS && !LL_MESA_HEADLESS +// Require DirectInput version 8 +#define DIRECTINPUT_VERSION 0x0800 + +#include +#endif static LLTrace::SampleStatHandle<> sJoystickAxis0("Joystick axis 0"), sJoystickAxis1("Joystick axis 1"), @@ -58,8 +68,33 @@ static LLTrace::SampleStatHandle<>* sJoystickAxes[6] = &sJoystickAxis5 }; + +#if LL_WINDOWS && !LL_MESA_HEADLESS + +BOOL CALLBACK di8_list_devices_callback(LPCDIDEVICEINSTANCE device_instance_ptr, LPVOID pvRef) +{ + // Note: If a single device can function as more than one DirectInput + // device type, it is enumerated as each device type that it supports. + // Capable of detecting devices like Oculus Rift + if (device_instance_ptr && pvRef) + { + std::string product_name = utf16str_to_utf8str(llutf16string(device_instance_ptr->tszProductName)); + S32 size = sizeof(GUID); + LLSD::Binary data; //just an std::vector + data.resize(size); + memcpy(&data[0], &device_instance_ptr->guidInstance /*POD _GUID*/, size); + + LLFloaterJoystick * floater = (LLFloaterJoystick*)pvRef; + LLSD value = data; + floater->addDevice(product_name, value); + } + return DIENUM_CONTINUE; +} +#endif + LLFloaterJoystick::LLFloaterJoystick(const LLSD& data) - : LLFloater(data) + : LLFloater(data), + mHasDeviceList(false) { if (!LLViewerJoystick::getInstance()->isJoystickInitialized()) { @@ -71,14 +106,13 @@ LLFloaterJoystick::LLFloaterJoystick(const LLSD& data) void LLFloaterJoystick::draw() { - bool joystick_inited = LLViewerJoystick::getInstance()->isJoystickInitialized(); - getChildView("enable_joystick")->setEnabled(joystick_inited); - getChildView("joystick_type")->setEnabled(joystick_inited); - std::string desc = LLViewerJoystick::getInstance()->getDescription(); - if (desc.empty()) desc = getString("NoDevice"); - getChild("joystick_type")->setValue(desc); + LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); + bool joystick_inited = joystick->isJoystickInitialized(); + if (joystick_inited != mHasDeviceList) + { + refreshListOfDevices(); + } - LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); for (U32 i = 0; i < 6; i++) { F32 value = joystick->getJoystickAxis(i); @@ -117,8 +151,8 @@ BOOL LLFloaterJoystick::postBuild() } } - mCheckJoystickEnabled = getChild("enable_joystick"); - childSetCommitCallback("enable_joystick",onCommitJoystickEnabled,this); + mJoysticksCombo = getChild("joystick_combo"); + childSetCommitCallback("joystick_combo",onCommitJoystickEnabled,this); mCheckFlycamEnabled = getChild("JoystickFlycamEnabled"); childSetCommitCallback("JoystickFlycamEnabled",onCommitJoystickEnabled,this); @@ -127,6 +161,7 @@ BOOL LLFloaterJoystick::postBuild() childSetAction("ok_btn", onClickOK, this); refresh(); + refreshListOfDevices(); return TRUE; } @@ -143,6 +178,7 @@ void LLFloaterJoystick::apply() void LLFloaterJoystick::initFromSettings() { mJoystickEnabled = gSavedSettings.getBOOL("JoystickEnabled"); + mJoystickId = gSavedSettings.getLLSD("JoystickDeviceUUID"); mJoystickAxis[0] = gSavedSettings.getS32("JoystickAxis0"); mJoystickAxis[1] = gSavedSettings.getS32("JoystickAxis1"); @@ -212,12 +248,80 @@ void LLFloaterJoystick::initFromSettings() void LLFloaterJoystick::refresh() { LLFloater::refresh(); + initFromSettings(); } +void LLFloaterJoystick::addDevice(std::string &name, LLSD& value) +{ + mJoysticksCombo->add(name, value, ADD_BOTTOM, 1); +} + +void LLFloaterJoystick::refreshListOfDevices() +{ + mJoysticksCombo->removeall(); + std::string no_device = getString("JoystickDisabled"); + LLSD value = LLSD::Integer(0); + addDevice(no_device, value); + + mHasDeviceList = false; + + // di8_devices_callback callback is immediate and happens in scope of getInputDevices() +#if LL_WINDOWS && !LL_MESA_HEADLESS + // space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib + U32 device_type = DI8DEVCLASS_GAMECTRL; + void* callback = &di8_list_devices_callback; +#else + // MAC doesn't support device search yet + // On MAC there is an ndof_idsearch and it is possible to specify product + // and manufacturer in NDOF_Device for ndof_init_first to pick specific one + U32 device_type = 0; + void* callback = NULL; +#endif + if (gViewerWindow->getWindow()->getInputDevices(device_type, callback, this)) + { + mHasDeviceList = true; + } + + bool is_device_id_set = LLViewerJoystick::getInstance()->isDeviceUUIDSet(); + + if (LLViewerJoystick::getInstance()->isJoystickInitialized() && + (!mHasDeviceList || !is_device_id_set)) + { +#if LL_WINDOWS && !LL_MESA_HEADLESS + LL_WARNS() << "NDOF connected to device without using SL provided handle" << LL_ENDL; +#endif + std::string desc = LLViewerJoystick::getInstance()->getDescription(); + if (!desc.empty()) + { + LLSD value = LLSD::Integer(0); + addDevice(desc, value); + mHasDeviceList = true; + } + } + + if (gSavedSettings.getBOOL("JoystickEnabled") && mHasDeviceList) + { + if (is_device_id_set) + { + LLSD guid = LLViewerJoystick::getInstance()->getDeviceUUID(); + mJoysticksCombo->selectByValue(guid); + } + else + { + mJoysticksCombo->selectByValue(LLSD::Integer(1)); + } + } + else + { + mJoysticksCombo->selectByValue(LLSD::Integer(0)); + } +} + void LLFloaterJoystick::cancel() { gSavedSettings.setBOOL("JoystickEnabled", mJoystickEnabled); + gSavedSettings.setLLSD("JoystickDeviceUUID", mJoystickId); gSavedSettings.setS32("JoystickAxis0", mJoystickAxis[0]); gSavedSettings.setS32("JoystickAxis1", mJoystickAxis[1]); @@ -287,7 +391,21 @@ void LLFloaterJoystick::cancel() void LLFloaterJoystick::onCommitJoystickEnabled(LLUICtrl*, void *joy_panel) { LLFloaterJoystick* self = (LLFloaterJoystick*)joy_panel; - BOOL joystick_enabled = self->mCheckJoystickEnabled->get(); + + LLSD value = self->mJoysticksCombo->getValue(); + bool joystick_enabled = true; + if (value.isInteger()) + { + // ndof already has a device selected, we are just setting it enabled or disabled + joystick_enabled = value.asInteger(); + } + else + { + LLViewerJoystick::getInstance()->initDevice(value); + // else joystick is enabled, because combobox holds id of device + joystick_enabled = true; + } + gSavedSettings.setBOOL("JoystickEnabled", joystick_enabled); BOOL flycam_enabled = self->mCheckFlycamEnabled->get(); if (!joystick_enabled || !flycam_enabled) @@ -299,6 +417,12 @@ void LLFloaterJoystick::onCommitJoystickEnabled(LLUICtrl*, void *joy_panel) joystick->toggleFlycam(); } } + + std::string device_id = LLViewerJoystick::getInstance()->getDeviceUUIDString(); + gSavedSettings.setString("JoystickDeviceUUID", device_id); + LL_DEBUGS("Joystick") << "Selected " << device_id << " as joystick." << LL_ENDL; + + self->refreshListOfDevices(); } void LLFloaterJoystick::onClickRestoreSNDefaults(void *joy_panel) diff --git a/indra/newview/llfloaterjoystick.h b/indra/newview/llfloaterjoystick.h index a1b5951389..1d46efd3f6 100644 --- a/indra/newview/llfloaterjoystick.h +++ b/indra/newview/llfloaterjoystick.h @@ -31,6 +31,7 @@ #include "llstatview.h" class LLCheckBoxCtrl; +class LLComboBox; class LLFloaterJoystick : public LLFloater { @@ -45,8 +46,11 @@ public: virtual void draw(); static void setSNDefaults(); + void addDevice(std::string &name, LLSD& value); + protected: + void refreshListOfDevices(); void onClose(bool app_quitting); void onClickCloseBtn(bool app_quitting); @@ -65,6 +69,7 @@ private: private: // Device prefs bool mJoystickEnabled; + LLSD mJoystickId; S32 mJoystickAxis[7]; bool m3DCursor; bool mAutoLeveling; @@ -85,8 +90,10 @@ private: F32 mFlycamFeathering; // Controls that can disable the flycam - LLCheckBoxCtrl *mCheckJoystickEnabled; LLCheckBoxCtrl *mCheckFlycamEnabled; + LLComboBox *mJoysticksCombo; + + bool mHasDeviceList; // stats view LLStatBar* mAxisStatsBar[6]; diff --git a/indra/newview/llfloaterloadprefpreset.cpp b/indra/newview/llfloaterloadprefpreset.cpp index f89daf3e04..8ed76b1df4 100644 --- a/indra/newview/llfloaterloadprefpreset.cpp +++ b/indra/newview/llfloaterloadprefpreset.cpp @@ -58,9 +58,17 @@ BOOL LLFloaterLoadPrefPreset::postBuild() void LLFloaterLoadPrefPreset::onOpen(const LLSD& key) { mSubdirectory = key.asString(); - std::string floater_title = getString(std::string("title_") + mSubdirectory); - - setTitle(floater_title); + std::string title_type = std::string("title_") + mSubdirectory; + if (hasString(title_type)) + { + std::string floater_title = getString(title_type); + setTitle(floater_title); + } + else + { + LL_WARNS() << title_type << " not found" << LL_ENDL; + setTitle(title_type); + } LLComboBox* combo = getChild("preset_combo"); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 7b41808c94..f7ef007017 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -2513,7 +2513,6 @@ void LLFloaterPreference::disableUnavailableSettings() LLComboBox* ctrl_reflections = getChild("Reflections"); LLCheckBoxCtrl* ctrl_avatar_vp = getChild("AvatarVertexProgram"); LLCheckBoxCtrl* ctrl_avatar_cloth = getChild("AvatarCloth"); - LLCheckBoxCtrl* ctrl_shader_enable = getChild("BasicShaders"); LLCheckBoxCtrl* ctrl_wind_light = getChild("WindLightUseAtmosShaders"); LLCheckBoxCtrl* ctrl_deferred = getChild("UseLightShaders"); LLComboBox* ctrl_shadows = getChild("ShadowDetail"); @@ -2521,39 +2520,6 @@ void LLFloaterPreference::disableUnavailableSettings() LLCheckBoxCtrl* ctrl_dof = getChild("UseDoF"); LLSliderCtrl* sky = getChild("SkyMeshDetail"); - // if vertex shaders off, disable all shader related products - if (!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable")) - { - ctrl_shader_enable->setEnabled(FALSE); - ctrl_shader_enable->setValue(FALSE); - - ctrl_wind_light->setEnabled(FALSE); - ctrl_wind_light->setValue(FALSE); - - sky->setEnabled(FALSE); - - ctrl_reflections->setEnabled(FALSE); - ctrl_reflections->setValue(0); - - ctrl_avatar_vp->setEnabled(FALSE); - ctrl_avatar_vp->setValue(FALSE); - - ctrl_avatar_cloth->setEnabled(FALSE); - ctrl_avatar_cloth->setValue(FALSE); - - ctrl_shadows->setEnabled(FALSE); - ctrl_shadows->setValue(0); - - ctrl_ssao->setEnabled(FALSE); - ctrl_ssao->setValue(FALSE); - - ctrl_dof->setEnabled(FALSE); - ctrl_dof->setValue(FALSE); - - ctrl_deferred->setEnabled(FALSE); - ctrl_deferred->setValue(FALSE); - } - // disabled windlight if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders")) { diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index 53eaa8df43..7175a929b8 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -64,7 +64,7 @@ void LLFloaterSidePanelContainer::onOpen(const LLSD& key) void LLFloaterSidePanelContainer::closeFloater(bool app_quitting) { LLPanelOutfitEdit* panel_outfit_edit = - dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit")); + dynamic_cast(LLFloaterSidePanelContainer::findPanel("appearance", "panel_outfit_edit")); if (panel_outfit_edit) { LLFloater *parent = gFloaterView->getParentFloater(panel_outfit_edit); @@ -171,7 +171,6 @@ LLPanel* LLFloaterSidePanelContainer::getPanel(const std::string& floater_name, return NULL; } -// Convenience method LLPanel* LLFloaterSidePanelContainer::findPanel(const std::string& floater_name, const std::string& panel_name) { LLFloaterSidePanelContainer* floaterp = LLFloaterReg::findTypedInstance(floater_name); @@ -183,4 +182,3 @@ LLPanel* LLFloaterSidePanelContainer::findPanel(const std::string& floater_name, return NULL; } -// diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h index 2d2fd209fc..e955214e5b 100644 --- a/indra/newview/llfloatersidepanelcontainer.h +++ b/indra/newview/llfloatersidepanelcontainer.h @@ -67,6 +67,8 @@ public: static void showPanel(const std::string& floater_name, const std::string& panel_name, const LLSD& key); static LLPanel* getPanel(const std::string& floater_name, const std::string& panel_name = sMainPanelName); + + static LLPanel* findPanel(const std::string& floater_name, const std::string& panel_name = sMainPanelName); /** * Gets the panel of given type T (doesn't show it or do anything else with it). @@ -86,9 +88,6 @@ public: return panel; } - // Convenience method - static LLPanel* findPanel(const std::string& floater_name, const std::string& panel_name = sMainPanelName); - template static T* findPanel(const std::string& floater_name, const std::string& panel_name = sMainPanelName) { diff --git a/indra/newview/llgiveinventory.cpp b/indra/newview/llgiveinventory.cpp index 278497ff72..6966be90ce 100644 --- a/indra/newview/llgiveinventory.cpp +++ b/indra/newview/llgiveinventory.cpp @@ -136,23 +136,14 @@ bool LLGiveInventory::isInventoryGiveAcceptable(const LLInventoryItem* item) switch(item->getType()) { case LLAssetType::AT_OBJECT: - if (get_is_item_worn(item->getUUID())) - { - acceptable = false; - } - break; case LLAssetType::AT_BODYPART: case LLAssetType::AT_CLOTHING: { - BOOL copyable = false; - if (item->getPermissions().allowCopyBy(gAgentID)) copyable = true; - - if (!copyable && get_is_item_worn(item->getUUID())) + if (get_is_item_worn(item->getUUID())) { - // worn no-copy items can't be transfered, - // but it is valid to transfer a copy of a worn item acceptable = false; } + break; } break; default: diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index f1ab6274c3..e786192df6 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2536,6 +2536,19 @@ BOOL LLOutgoingCallDialog::postBuild() // Class LLIncomingCallDialog //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const std::array voice_call_types = +{ + "VoiceInviteP2P", + "VoiceInviteGroup", + "VoiceInviteAdHoc", + "InviteAdHoc" +}; + +bool is_voice_call_type(const std::string &value) +{ + return std::find(voice_call_types.begin(), voice_call_types.end(), value) != voice_call_types.end(); +} + LLIncomingCallDialog::LLIncomingCallDialog(const LLSD& payload) : LLCallDialog(payload), mAvatarNameCacheConnection() @@ -2565,9 +2578,28 @@ BOOL LLIncomingCallDialog::postBuild() { LLCallDialog::postBuild(); + if (!mPayload.isMap() || mPayload.size() == 0) + { + LL_INFOS("IMVIEW") << "IncomingCall: invalid argument" << LL_ENDL; + return TRUE; + } + LLUUID session_id = mPayload["session_id"].asUUID(); LLSD caller_id = mPayload["caller_id"]; std::string caller_name = mPayload["caller_name"].asString(); + + if (session_id.isNull() && caller_id.asUUID().isNull()) + { + LL_INFOS("IMVIEW") << "IncomingCall: invalid ids" << LL_ENDL; + return TRUE; + } + + std::string notify_box_type = mPayload["notify_box_type"].asString(); + if (!is_voice_call_type(notify_box_type)) + { + LL_INFOS("IMVIEW") << "IncomingCall: notify_box_type was not provided" << LL_ENDL; + return TRUE; + } // init notification's lifetime std::istringstream ss( getString("lifetime") ); @@ -2584,15 +2616,14 @@ BOOL LLIncomingCallDialog::postBuild() if (gAgent.getGroupData(session_id, data)) { args["[GROUP]"] = data.mName; - call_type = getString(mPayload["notify_box_type"], args); + call_type = getString(notify_box_type, args); } } else { - call_type = getString(mPayload["notify_box_type"]); + call_type = getString(notify_box_type); } - - + // check to see if this is an Avaline call bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id); if (caller_name == "anonymous") @@ -2622,7 +2653,6 @@ BOOL LLIncomingCallDialog::postBuild() childSetAction("Start IM", onStartIM, this); setDefaultBtn("Accept"); - std::string notify_box_type = mPayload["notify_box_type"].asString(); if(notify_box_type != "VoiceInviteGroup" && notify_box_type != "VoiceInviteAdHoc") { // starting notification's timer for P2P and AVALINE invitations @@ -2776,10 +2806,10 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload correct_session_name.append(ADHOC_NAME_SUFFIX); } } - LL_INFOS() << "Corrected session name is " << correct_session_name << LL_ENDL; + LL_INFOS("IMVIEW") << "Corrected session name is " << correct_session_name << LL_ENDL; break; default: - LL_WARNS() << "Received an empty session name from a server and failed to generate a new proper session name" << LL_ENDL; + LL_WARNS("IMVIEW") << "Received an empty session name from a server and failed to generate a new proper session name" << LL_ENDL; break; } } @@ -3001,6 +3031,14 @@ void LLIMMgr::addMessage( if (new_session) { + // Group chat session was initiated by muted resident, do not start this session viewerside + // do not send leave msg either, so we are able to get group messages from other participants + if ((IM_SESSION_INVITE == dialog) && gAgent.isInGroup(new_session_id) && + LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !from_linden) + { + return; + } + LLAvatarName av_name; if (LLAvatarNameCache::get(other_participant_id, &av_name) && !name_is_setted) { @@ -3083,7 +3121,7 @@ void LLIMMgr::addMessage( LL_WARNS() << "Leaving IM session from initiating muted resident " << from << LL_ENDL; if (!gIMMgr->leaveSession(new_session_id)) { - LL_INFOS() << "Session " << new_session_id << " does not exist." << LL_ENDL; + LL_INFOS("IMVIEW") << "Session " << new_session_id << " does not exist." << LL_ENDL; } return; } @@ -3415,7 +3453,7 @@ LLUUID LLIMMgr::addSession( //we don't need to show notes about online/offline, mute/unmute users' statuses for existing sessions if (!new_session) return session_id; - LL_INFOS() << "LLIMMgr::addSession, new session added, name = " << name << ", session id = " << session_id << LL_ENDL; + LL_INFOS("IMVIEW") << "LLIMMgr::addSession, new session added, name = " << name << ", session id = " << session_id << LL_ENDL; //Per Plan's suggestion commented "explicit offline status warning" out to make Dessie happier (see EXT-3609) //*TODO After February 2010 remove this commented out line if no one will be missing that warning @@ -3475,7 +3513,7 @@ void LLIMMgr::removeSession(const LLUUID& session_id) LLIMModel::getInstance()->clearSession(session_id); - LL_INFOS() << "LLIMMgr::removeSession, session removed, session id = " << session_id << LL_ENDL; + LL_INFOS("IMVIEW") << "LLIMMgr::removeSession, session removed, session id = " << session_id << LL_ENDL; notifyObserverSessionRemoved(session_id); } @@ -3541,13 +3579,13 @@ void LLIMMgr::inviteToSession( if (LLMuteList::getInstance()->isMuted(caller_id, LLMute::flagVoiceChat) && voice_invite && "VoiceInviteQuestionDefault" == question_type) { - LL_INFOS() << "Rejecting voice call from initiating muted resident " << caller_name << LL_ENDL; + LL_INFOS("IMVIEW") << "Rejecting voice call from initiating muted resident " << caller_name << LL_ENDL; LLIncomingCallDialog::processCallResponse(1, payload); return; } else if (LLMuteList::getInstance()->isMuted(caller_id, LLMute::flagAll & ~LLMute::flagVoiceChat) && !voice_invite) { - LL_INFOS() << "Rejecting session invite from initiating muted resident " << caller_name << LL_ENDL; + LL_INFOS("IMVIEW") << "Rejecting session invite from initiating muted resident " << caller_name << LL_ENDL; return; } } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 5a653d26c2..7ec2e1db64 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4422,7 +4422,9 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items } // // Fix "outfits" context menu - if (outfits_id == mUUID) + if (model->isObjectDescendentOf(mUUID, outfits_id) && getCategory() && + (getCategory()->getPreferredType() == LLFolderType::FT_NONE || + getCategory()->getPreferredType() == LLFolderType::FT_MY_OUTFITS)) { items.push_back(std::string("New Outfit")); } @@ -4530,17 +4532,17 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items // Not sure what the right thing is to do here. if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT)) { - // Fix "outfits" context menu - //if (!isInboxFolder()) // don't allow creation in inbox - if (!isInboxFolder() && outfits_id != mUUID) // don't allow creation in inbox - // + if (!isInboxFolder()) // don't allow creation in inbox { // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) { items.push_back(std::string("New Folder")); } - if (!isMarketplaceListingsFolder()) + // Fix "outfits" context menu + //if (!isMarketplaceListingsFolder()) + if (!isMarketplaceListingsFolder() && !model->isObjectDescendentOf(mUUID, outfits_id)) + // { items.push_back(std::string("New Script")); items.push_back(std::string("New Note")); @@ -8501,11 +8503,11 @@ void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_dequ disable_context_entries_if_present(menu, disabled_items); } -bool LLFolderViewGroupedItemBridge::canWearSelected(uuid_vec_t item_ids) +bool LLFolderViewGroupedItemBridge::canWearSelected(const uuid_vec_t& item_ids) const { for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it) { - LLViewerInventoryItem* item = gInventory.getItem(*it); + const LLViewerInventoryItem* item = gInventory.getItem(*it); // Fix broken add wearable check //if (!item || (item->getType() >= LLAssetType::AT_COUNT) || (item->getType() <= LLAssetType::AT_NONE)) if (!item || (item->getType() != LLAssetType::AT_CLOTHING && item->getType() != LLAssetType::AT_OBJECT && item->getType() != LLAssetType::AT_BODYPART && item->getType() != LLAssetType::AT_GESTURE)) diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 5328a71ffb..17ab5eab8d 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -823,7 +823,7 @@ class LLFolderViewGroupedItemBridge: public LLFolderViewGroupedItemModel public: LLFolderViewGroupedItemBridge(); virtual void groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu); - bool canWearSelected(uuid_vec_t item_ids); + bool canWearSelected(const uuid_vec_t& item_ids) const; }; #endif // LL_LLINVENTORYBRIDGE_H diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 719352a61f..93970a9949 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -2695,24 +2695,19 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root { bool open_multi_preview = true; - for (std::set::iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) + if ("open" == action) { - LLFolderViewItem* folder_item = *set_iter; - if (folder_item) + for (std::set::iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) { - LLInvFVBridge* bridge = dynamic_cast(folder_item->getViewModelItem()); - // FIRE-30518: Multi-preview not working for contents of rezzed objects - // This should prevent multi-previews of settings, but for object inventory items - // this check is always false, since content items in object inventories - // have LLTaskInvFVBridges instead of LLInvFVBridges. Since settings can't be - // opened from inside objects anyway, so restrict the check for actions performed - // on avatar inventories. - //if (!bridge || !bridge->isMultiPreviewAllowed()) - if ("open" == action && (!bridge || !bridge->isMultiPreviewAllowed())) - // + LLFolderViewItem* folder_item = *set_iter; + if (folder_item) { - open_multi_preview = false; - break; + LLInvFVBridge* bridge = dynamic_cast(folder_item->getViewModelItem()); + if (!bridge || !bridge->isMultiPreviewAllowed()) + { + open_multi_preview = false; + break; + } } } } diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index b4dab6265d..28edaf130a 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -161,7 +161,8 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mShowEmptyMessage(p.show_empty_message), mSuppressFolderMenu(p.suppress_folder_menu), mSuppressOpenItemAction(false), - mViewsInitialized(false), + mBuildViewsOnInit(p.preinitialize_views), + mViewsInitialized(VIEWS_UNINITIALIZED), mInvFVBridgeBuilder(NULL), mInventoryViewModel(p.name), mGroupedItemBridge(new LLFolderViewGroupedItemBridge) @@ -307,14 +308,22 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) mCompletionObserver = new LLInvPanelComplObserver(boost::bind(&LLInventoryPanel::onItemsCompletion, this)); mInventory->addObserver(mCompletionObserver); - // Build view of inventory if we need default full hierarchy and inventory ready, otherwise do in onIdle. - // Initializing views takes a while so always do it onIdle if viewer already loaded. - if (mInventory->isInventoryUsable() && !mViewsInitialized && LLStartUp::getStartupState() <= STATE_WEARABLES_WAIT) - { - initializeViews(); - } - - gIdleCallbacks.addFunction(onIdle, (void*)this); + if (mBuildViewsOnInit) + { + // Build view of inventory if we need default full hierarchy and inventory is ready, otherwise do in onIdle. + // Initializing views takes a while so always do it onIdle if viewer already loaded. + if (mInventory->isInventoryUsable() + && mViewsInitialized == VIEWS_UNINITIALIZED + && LLStartUp::getStartupState() <= STATE_WEARABLES_WAIT) + { + initializeViews(); + } + else if (mViewsInitialized != VIEWS_INITIALIZING) + { + mViewsInitialized = VIEWS_INITIALIZING; + gIdleCallbacks.addFunction(onIdle, (void*)this); + } + } if (mSortOrderSetting != INHERIT_SORT_ORDER) { @@ -375,6 +384,17 @@ LLInventoryPanel::~LLInventoryPanel() clearFolderRoot(); } +/*virtual*/ +void LLInventoryPanel::onVisibilityChange(BOOL new_visibility) +{ + if (new_visibility && mViewsInitialized == VIEWS_UNINITIALIZED) + { + mViewsInitialized = VIEWS_INITIALIZING; + gIdleCallbacks.addFunction(onIdle, (void*)this); + } + LLPanel::onVisibilityChange(new_visibility); +} + void LLInventoryPanel::draw() { // Select the desired item (in case it wasn't loaded when the selection was requested) @@ -714,7 +734,7 @@ void LLInventoryPanel::modelChanged(U32 mask) { LL_RECORD_BLOCK_TIME(FTM_REFRESH); - if (!mViewsInitialized) return; + if (mViewsInitialized != VIEWS_INITIALIZED) return; const LLInventoryModel* model = getModel(); if (!model) return; @@ -780,11 +800,11 @@ void LLInventoryPanel::onIdle(void *userdata) LLInventoryPanel *self = (LLInventoryPanel*)userdata; // Inventory just initialized, do complete build - if (!self->mViewsInitialized) + if (self->mViewsInitialized != VIEWS_INITIALIZED) { self->initializeViews(); } - if (self->mViewsInitialized) + if (self->mViewsInitialized == VIEWS_INITIALIZED) { gIdleCallbacks.deleteFunction(onIdle, (void*)self); } @@ -867,7 +887,7 @@ void LLInventoryPanel::initializeViews() gIdleCallbacks.addFunction(idle, this); - mViewsInitialized = true; + mViewsInitialized = VIEWS_INITIALIZED; openStartFolderOrMyInventory(); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 1eccb5a87b..6937c63cd6 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -108,6 +108,10 @@ public: Optional folder; Optional item; + // All item and folder views will be initialized on init if true (default) + // Will initialize on visibility change otherwise. + Optional preinitialize_views; + Params() : sort_order_setting("sort_order_setting"), inventory("", &gInventory), @@ -126,7 +130,8 @@ public: accepts_drag_and_drop("accepts_drag_and_drop"), folder_view("folder_view"), folder("folder"), - item("item") + item("item"), + preinitialize_views("preinitialize_views", true) {} }; @@ -154,6 +159,7 @@ public: LLFolderViewModelInventory& getRootViewModel() { return mInventoryViewModel; } // LLView methods + /*virtual*/ void onVisibilityChange(BOOL new_visibility); void draw(); /*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); BOOL handleHover(S32 x, S32 y, MASK mask); @@ -329,7 +335,7 @@ public: void addHideFolderType(LLFolderType::EType folder_type); public: - BOOL getIsViewsInitialized() const { return mViewsInitialized; } + bool getViewsInitialized() const { return mViewsInitialized == VIEWS_INITIALIZED; } protected: // Builds the UI. Call this once the inventory is usable. @@ -366,8 +372,15 @@ private: LLFolderViewItem *target_view, LLFolderViewFolder *parent_folder_view); - bool mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild() - bool mViewsInitialized; // Views have been generated + typedef enum e_views_initialization_state + { + VIEWS_UNINITIALIZED = 0, + VIEWS_INITIALIZING, + VIEWS_INITIALIZED, + } EViewsInitializationState; + + bool mBuildViewsOnInit; + EViewsInitializationState mViewsInitialized; // Whether views have been generated }; class LLInventoryFavoriteItemsPanel : public LLInventoryPanel diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index f86a94f5db..821ab12537 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -308,6 +308,7 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p) LLButton::Params maturity_button = p.maturity_button; mMaturityButton = LLUICtrlFactory::create(maturity_button); addChild(mMaturityButton); + // Keep help links mMaturityButton->setClickedCallback(boost::bind(&LLLocationInputCtrl::onMaturityButtonClicked, this)); LLButton::Params for_sale_button = p.for_sale_button; @@ -705,10 +706,12 @@ void LLLocationInputCtrl::onAgentParcelChange() refresh(); } +// Keep help links void LLLocationInputCtrl::onMaturityButtonClicked() { LLUI::getInstance()->mHelpImpl->showTopic(mMaturityHelpTopic); } +// void LLLocationInputCtrl::onRegionBoundaryCrossed() { diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h index ce28db675c..87d9568769 100644 --- a/indra/newview/lllocationinputctrl.h +++ b/indra/newview/lllocationinputctrl.h @@ -164,7 +164,7 @@ private: void onForSaleButtonClicked(); void onAddLandmarkButtonClicked(); void onAgentParcelChange(); - void onMaturityButtonClicked(); + void onMaturityButtonClicked(); // Keep help links void onRegionBoundaryCrossed(); void onNavMeshStatusChange(const LLPathfindingNavMeshStatus &pNavMeshStatus); // callbacks diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 6a23d9acf1..3a8397fa37 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -470,7 +470,13 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list& m if (is_group) { std::string old_name(file_name); - old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size()); + // FIRE-30582: Fix out of range crash + //old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size()); + if (LLStringUtil::endsWith(old_name, GROUP_CHAT_SUFFIX)) + { + old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size()); + } + // fptr = LLFile::fopen(LLLogChat::makeLogFileName(old_name), "r"); if (fptr) { @@ -1234,7 +1240,13 @@ void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list FIRE-30582: Fix out of range crash + //old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size()); + if (LLStringUtil::endsWith(old_name, GROUP_CHAT_SUFFIX)) + { + old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size()); + } + // fptr = LLFile::fopen(LLLogChat::makeLogFileName(old_name), "r"); if (fptr) { diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index c643c0fcdc..70c80e3315 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -441,6 +441,7 @@ void LLLoginInstance::handleLoginSuccess(const LLSD& event) LL_INFOS("LLLogin") << "LLLoginInstance::handleLoginSuccess" << LL_ENDL; attemptComplete(); + mRequestData.clear(); } void LLLoginInstance::handleDisconnect(const LLSD& event) diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index d9a83f07fd..8ee616ad80 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -172,6 +172,14 @@ LLMuteList::LLMuteList() : gMessageSystem.callWhenReady(boost::bind(&LLMessageSystem::setHandlerFuncFast, _1, _PREHASH_UseCachedMuteList, processUseCachedMuteList, static_cast(NULL))); + + // make sure mute list's instance gets initialized before we start any name requests + LLAvatarNameCache::getInstance()->setAccountNameChangedCallback([this](const LLUUID& id, const LLAvatarName& av_name) + { + // it would be better to just pass LLAvatarName instead of doing unnesssesary copies + // but this way is just more convinient + onAccountNameChanged(id, av_name.getUserName()); + }); } //----------------------------------------------------------------------------- @@ -182,6 +190,11 @@ LLMuteList::~LLMuteList() } +void LLMuteList::cleanupSingleton() +{ + LLAvatarNameCache::getInstance()->setAccountNameChangedCallback(NULL); +} + BOOL LLMuteList::isLinden(const std::string& name) const { std::string username = boost::replace_all_copy(name, ".", " "); @@ -235,8 +248,8 @@ BOOL LLMuteList::add(const LLMute& mute, U32 flags) LL_WARNS() << "Trying to self; ignored" << LL_ENDL; return FALSE; } - - S32 mute_list_limit = gSavedSettings.getS32("MuteListLimit"); + + static LLCachedControl mute_list_limit(gSavedSettings, "MuteListLimit", 1000); if (getMutes().size() >= mute_list_limit) { LL_WARNS() << "Mute limit is reached; ignored" << LL_ENDL; @@ -376,6 +389,10 @@ void LLMuteList::updateAdd(const LLMute& mute, bool show_message /* = true */) msg->addU32("MuteFlags", mute.mFlags); gAgent.sendReliableMessage(); + if (!mIsLoaded) + { + LL_WARNS() << "Added elements to non-initialized block list" << LL_ENDL; + } mIsLoaded = TRUE; // why is this here? -MG // FIRE-15746: Show block report in nearby chat @@ -418,6 +435,8 @@ BOOL LLMuteList::remove(const LLMute& mute, U32 flags) else { // The caller didn't pass any flags -- just remove the mute entry entirely. + // set flags to notify observers with (flag being present means that something is allowed) + localmute.mFlags = LLMute::flagAll; } // Always remove the entry from the set -- it will be re-added with new flags if necessary. @@ -441,8 +460,8 @@ BOOL LLMuteList::remove(const LLMute& mute, U32 flags) } // Must be after erase. + notifyObservers(); notifyObserversDetailed(localmute); - setLoaded(); // why is this here? -MG // Return correct return value found = TRUE; @@ -458,8 +477,8 @@ BOOL LLMuteList::remove(const LLMute& mute, U32 flags) updateRemove(mute); mLegacyMutes.erase(legacy_it); // Must be after erase. + notifyObservers(); notifyObserversDetailed(mute); - setLoaded(); // why is this here? -MG // Return correct return value found = TRUE; @@ -629,6 +648,19 @@ BOOL LLMuteList::loadFromFile(const std::string& filename) } fclose(fp); setLoaded(); + + // server does not maintain up-to date account names (not display names!) + // in this list, so it falls to viewer. + pending_names_t::iterator iter = mPendingAgentNameUpdates.begin(); + pending_names_t::iterator end = mPendingAgentNameUpdates.end(); + while (iter != end) + { + // this will send updates to server, make sure mIsLoaded is set + onAccountNameChanged(iter->first, iter->second); + iter++; + } + mPendingAgentNameUpdates.clear(); + return TRUE; } @@ -828,6 +860,48 @@ void LLMuteList::onFileMuteList(void** user_data, S32 error_code, LLExtStat ext_ delete local_filename_and_path; } +void LLMuteList::onAccountNameChanged(const LLUUID& id, const std::string& username) +{ + if (mIsLoaded) + { + LLMute mute(id, username, LLMute::AGENT); + mute_set_t::iterator mute_it = mMutes.find(mute); + if (mute_it != mMutes.end() + && mute_it->mName != mute.mName + && mute_it->mType == LLMute::AGENT) // just in case, it is std::set, not map + { + // existing mute, but name changed, copy data + mute.mFlags = mute_it->mFlags; + + // erase old variant + mMutes.erase(mute_it); + + // (re)add the mute entry. + { + std::pair result = mMutes.insert(mute); + if (result.second) + { + LL_INFOS() << "Muting " << mute.mName << " id " << mute.mID << " flags " << mute.mFlags << LL_ENDL; + updateAdd(mute); + // Do not notify observers here, observers do not know or need to handle name changes + // Example: block list considers notifyObserversDetailed as a selection update; + // Various chat/voice statuses care only about id and flags + // Since apropriate update time for account names is considered to be in 'hours' it is + // fine not to update UI (will be fine after restart or couple other changes) + + } + } + } + } + else + { + // Delay update until we load file + // Ex: Buddies list can arrive too early since we prerequest + // names from Buddies list before we load blocklist + mPendingAgentNameUpdates[id] = username; + } +} + void LLMuteList::addObserver(LLMuteListObserver* observer) { mObservers.insert(observer); diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index 2e96652ddb..b3f0a0f96e 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -73,6 +73,7 @@ class LLMuteList : public LLSingleton { LLSINGLETON(LLMuteList); ~LLMuteList(); + /*virtual*/ void cleanupSingleton(); public: // reasons for auto-unmuting a resident enum EAutoReason @@ -134,6 +135,7 @@ private: static void processUseCachedMuteList(LLMessageSystem* msg, void**); static void onFileMuteList(void** user_data, S32 code, LLExtStat ext_status); + void onAccountNameChanged(const LLUUID& id, const std::string& username); private: struct compare_by_name @@ -158,7 +160,9 @@ private: }; typedef std::set mute_set_t; mute_set_t mMutes; - + typedef std::map pending_names_t; + pending_names_t mPendingAgentNameUpdates; + typedef std::set string_set_t; string_set_t mLegacyMutes; diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index aceb73a79a..2a579178f1 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -351,10 +351,14 @@ void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& s } } -void LLOutputMonitorCtrl::onChange() +void LLOutputMonitorCtrl::onChangeDetailed(const LLMute& mute) { - // check only blocking on voice. EXT-3542 - mIsMuted = LLMuteList::getInstance()->isMuted(mSpeakerId, LLMute::flagVoiceChat); + if (mute.mID == mSpeakerId) + { + // Check only blocking on voice. + // Logic goes in reverse, if flag is set, action is allowed + mIsMuted = !(LLMute::flagVoiceChat & mute.mFlags); + } } // virtual diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index 0c4619422a..7e9dbf9e6f 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -108,7 +108,8 @@ public: void setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id = LLUUID::null, bool show_other_participants_speaking = false); //called by mute list - virtual void onChange(); + virtual void onChange() {}; + virtual void onChangeDetailed(const LLMute& mute); /** * Implementation of LLSpeakingIndicator interface. diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp index 817e630c20..54c3aa3480 100644 --- a/indra/newview/llpanelcontents.cpp +++ b/indra/newview/llpanelcontents.cpp @@ -54,6 +54,7 @@ #include "lltrans.h" #include "llviewerassettype.h" #include "llviewerinventory.h" +#include "llviewermenu.h" // Script reset in edit floater #include "llviewerobject.h" #include "llviewerregion.h" #include "llviewerwindow.h" @@ -86,6 +87,7 @@ BOOL LLPanelContents::postBuild() childSetAction("button new script",&LLPanelContents::onClickNewScript, this); childSetAction("button permissions",&LLPanelContents::onClickPermissions, this); + childSetAction("btn_reset_scripts", &LLPanelContents::onClickResetScripts, this); // Script reset in edit floater childSetAction("button refresh",&LLPanelContents::onClickRefresh, this); mPanelInventoryObject = getChild("contents_inventory"); @@ -111,7 +113,7 @@ void LLPanelContents::getState(LLViewerObject *objectp ) if( !objectp ) { getChildView("button new script")->setEnabled(FALSE); - getChildView("button reset scripts")->setEnabled(FALSE); + getChildView("btn_reset_scripts")->setEnabled(FALSE); // Script reset in edit floater return; } @@ -143,21 +145,22 @@ void LLPanelContents::getState(LLViewerObject *objectp ) } // [/RLVa:KB] - // Edit/reset script buttons - ok if object is editable and there's an unambiguous destination for the object. + // Edit script buttons - ok if object is editable and there's an unambiguous destination for the object. // FIRE-3219: Reset Scripts button in Build floater // getChildView("button new script")->setEnabled( // editable && // all_volume && // ((LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1) // || (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1))); - bool objectIsOK = FALSE; + + BOOL objectIsOK = FALSE; if( editable && all_volume && ( (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1) || (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1) ) ) { objectIsOK = TRUE; } getChildView("button new script")->setEnabled(objectIsOK); - getChildView("button reset scripts")->setEnabled(objectIsOK); + getChildView("btn_reset_scripts")->setEnabled(objectIsOK); // getChildView("button permissions")->setEnabled(!objectp->isPermanentEnforced()); @@ -257,6 +260,14 @@ void LLPanelContents::onClickPermissions(void *userdata) gFloaterView->getParentFloater(self)->addDependentFloater(LLFloaterReg::showInstance("bulk_perms")); } +// Script reset in edit floater +// static +void LLPanelContents::onClickResetScripts(void *userdata) +{ + handle_selected_script_action("reset"); +} +// + // static void LLPanelContents::onClickRefresh(void *userdata) { diff --git a/indra/newview/llpanelcontents.h b/indra/newview/llpanelcontents.h index 69a3570762..6e0a79ad88 100644 --- a/indra/newview/llpanelcontents.h +++ b/indra/newview/llpanelcontents.h @@ -53,6 +53,7 @@ public: static void onClickNewScript(void*); static void onClickPermissions(void*); + static void onClickResetScripts(void*); // Script reset in edit floater static void onClickRefresh(void*); // Key suffix for "tentative" fields diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index 8c0d9c3915..7fc3ffc80d 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -667,6 +667,13 @@ void LLPanelGroup::draw() { LLPanel::draw(); + // FIRE-30667 - group hang fixes + LLPanelGroupNotices* panel_notices = findChild("group_notices_tab_panel"); + if(panel_notices) + { + panel_notices->updateSelected(); + } + // if (mRefreshTimer.hasExpired()) { mRefreshTimer.stop(); diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 227e021a94..4d244b5225 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -203,15 +203,15 @@ std::string build_notice_date(const U32& the_time) time(&t); } - // FIRE-17649: Localizable date formats for group notices - //std::string dateStr = "["+LLTrans::getString("LTimeYear")+"]/[" - // +LLTrans::getString("LTimeMthNum")+"]/[" - // +LLTrans::getString("LTimeDay")+"] [" - // +LLTrans::getString("LTimeHour")+"]:[" - // +LLTrans::getString("LTimeMin")+"]:[" - // +LLTrans::getString("LTimeSec")+"]"; - std::string dateStr = LLTrans::getString("GroupNoticesPanelDateString"); - // + // FIRE-17649: Localizable date formats for group notices + //std::string dateStr = "["+ LLTrans::getString("LTimeYear") + "]/[" + // + LLTrans::getString("LTimeMthNum") + "]/[" + // + LLTrans::getString("LTimeDay") + "] [" + // + LLTrans::getString("LTimeHour") + "]:[" + // + LLTrans::getString("LTimeMin") + "]:[" + // + LLTrans::getString("LTimeSec") + "]"; + std::string dateStr = LLTrans::getString("GroupNoticesPanelDateString"); + // LLSD substitution; substitution["datetime"] = (S32) t; @@ -473,6 +473,8 @@ void LLPanelGroupNotices::clearNoticeList() { mPrevSelectedNotice = mNoticesList->getStringUUIDSelectedItem(); mNoticesList->deleteAllItems(); + // FIRE-30766 group hang prevention. + mNoticeIDs.clear(); } void LLPanelGroupNotices::onClickRefreshNotices(void* data) @@ -536,7 +538,8 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg) //save sort state and set unsorted state to prevent unnecessary //sorting while adding notices - bool save_sort = mNoticesList->isSorted(); + // FIRE-30667 et al. we will need sorting at the end + // bool save_sort = mNoticesList->isSorted(); mNoticesList->setNeedsSort(false); for (;igetItemIndex(id); - - if(pos!=-1)//if items with this ID already in the list - skip it + // FIRE-30667 et al. add a set for tracking to avoid the linear time lookup + // S32 pos = mNoticesList->getItemIndex(id); + // if(pos!=-1)//if items with this ID already in the list - skip it + auto exists = mNoticeIDs.emplace(id); + if (!exists.second) + // continue; msg->getString("Data","Subject",subj,i); @@ -596,15 +602,32 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg) mNoticesList->addElement(row, ADD_BOTTOM); } - mNoticesList->setNeedsSort(save_sort); - mNoticesList->updateSort(); - if (mPanelViewNotice->getVisible()) + mNoticesList->setNeedsSort(true); + // FIRE-30667 et al. defer sorting and updating selection + // mNoticesList->updateSort(); + // if (mPanelViewNotice->getVisible()) + // { + // if (!mNoticesList->selectByID(mPrevSelectedNotice)) + // { + // mNoticesList->selectFirstItem(); + // } + // } +} + +void LLPanelGroupNotices::updateSelected() +{ + if( mNoticesList->mLastUpdateFrame == 0 ) { - if (!mNoticesList->selectByID(mPrevSelectedNotice)) + if (mPanelViewNotice->getVisible()) { - mNoticesList->selectFirstItem(); + if (!mNoticesList->selectByID(mPrevSelectedNotice)) + { + mNoticesList->selectFirstItem(); + } } + mNoticesList->mLastUpdateFrame = 1; } + // } void LLPanelGroupNotices::onSelectNotice(LLUICtrl* ctrl, void* data) diff --git a/indra/newview/llpanelgroupnotices.h b/indra/newview/llpanelgroupnotices.h index 01b35e0007..3eafdd3e36 100644 --- a/indra/newview/llpanelgroupnotices.h +++ b/indra/newview/llpanelgroupnotices.h @@ -64,6 +64,7 @@ public: LLOfferInfo* inventory_offer); void refreshNotices(); + void updateSelected(); // FS:Beq FIRE-30667 group notices hang void clearNoticeList(); @@ -111,6 +112,7 @@ private: //LLIconCtrl *mViewInventoryIcon; LLScrollListCtrl *mNoticesList; + std::set mNoticeIDs; // FS:Beq FIRE-30667 group notices hang std::string mNoNoticesStr; diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 37b18f3a6a..7a304ffc78 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -1339,8 +1339,10 @@ void LLPanelLogin::onSelectServer() switch (index) { case 0: // last location + LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_LAST)); + break; case 1: // home location - // do nothing - these are grid-agnostic locations + LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME)); break; default: diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index c4cac31361..25a25eca19 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -183,6 +183,7 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p) mFilterMap["filter_type_textures"] = 0x01 << LLInventoryType::IT_TEXTURE; mFilterMap["filter_type_snapshots"] = 0x01 << LLInventoryType::IT_SNAPSHOT; mFilterMap["filter_type_meshes"] = 0x01 << LLInventoryType::IT_MESH; + mFilterMap["filter_type_settings"] = 0x01 << LLInventoryType::IT_SETTINGS; // initialize empty filter mask mFilterMask = 0; @@ -234,6 +235,7 @@ BOOL LLPanelMainInventory::postBuild() recent_items_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::RECENTITEMS_SORT_ORDER)); // recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + //recent_items_panel->setFilterLinks(LLInventoryFilter::FILTERLINK_EXCLUDE_LINKS); // Undo nonsense change LLInventoryFilter& recent_filter = recent_items_panel->getFilter(); recent_filter.setFilterObjectTypes(recent_filter.getFilterObjectTypes() & ~(0x1 << LLInventoryType::IT_CATEGORY)); recent_filter.setEmptyLookupMessage("InventoryNoMatchingRecentItems"); diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index a3aadf5cc6..532d24126c 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -574,6 +574,8 @@ BOOL LLPanelOutfitEdit::postBuild() mAvatarComplexityAddingLabel = getChild("avatar_complexity_adding_label"); mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this)); + + onOutfitChanging(gAgentWearables.isCOFChangeInProgress()); return TRUE; } @@ -718,6 +720,10 @@ void LLPanelOutfitEdit::onListViewFilterCommitted(LLUICtrl* ctrl) S32 curr_filter_type = mListViewFilterCmbBox->getCurrentIndex(); if (curr_filter_type < 0) return; + if (curr_filter_type >= LVIT_SHAPE) + { + mWearableItemsList->setMenuWearableType(LLWearableType::EType(curr_filter_type - LVIT_SHAPE)); + } mWearableListManager->setFilterCollector(mListViewItemTypes[curr_filter_type]->collector); } @@ -1297,6 +1303,7 @@ void LLPanelOutfitEdit::showFilteredWearablesListView(LLWearableType::EType type //e_list_view_item_type implicitly contains LLWearableType::EType starting from LVIT_SHAPE applyListViewFilter(static_cast(LVIT_SHAPE + type)); + mWearableItemsList->setMenuWearableType(type); } static void update_status_widget_rect(LLView * widget, S32 right_border) diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index e439eefe07..55c6de7696 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -630,7 +630,7 @@ void LLPanelPermissions::refresh() } else { -// FIRE-777: allow batch edit for name and description +// FIRE-777:allow batch edit for name and description // getChild("Object Name")->setValue(LLStringUtil::null); // LineEditorObjectDesc->setText(LLStringUtil::null); if (keyboard_focus_view != LineEditorObjectName) @@ -650,7 +650,7 @@ void LLPanelPermissions::refresh() // figure out the contents of the name, description, & category BOOL edit_name_desc = FALSE; -// FIRE-777: allow batch edit for name and description +// FIRE-777:allow batch edit for name and description // if (is_one_object && objectp->permModify() && !objectp->isPermanentEnforced()) if (objectp->permModify()) // /FIRE-777 @@ -910,7 +910,7 @@ void LLPanelPermissions::refresh() getChildView("checkbox allow everyone copy")->setEnabled(FALSE); } - // Opensim export permissions - Codeblock courtesy of Liru Færs. + // Opensim export permissions - Codeblock courtesy of Liru Frs. // Is this user allowed to toggle export on this object? if (LFSimFeatureHandler::instance().simSupportsExport() && self_owned && mCreatorID == mOwnerID @@ -1173,13 +1173,45 @@ void LLPanelPermissions::refresh() getChildView("clickaction")->setEnabled(is_perm_modify && is_nonpermanent_enforced && all_volume); } +//// Shorten name if it doesn't fit into max_pixels of two lines +//void shorten_name(std::string &name, const LLStyle::Params& style_params, S32 max_pixels) +//{ +// const LLFontGL* font = style_params.font(); +// +// LLWString wline = utf8str_to_wstring(name); +// // panel supports two lines long names +// S32 segment_length = font->maxDrawableChars(wline.c_str(), max_pixels, wline.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE); +// if (segment_length == wline.length()) +// { +// // no work needed +// return; +// } +// +// S32 first_line_length = segment_length; +// segment_length = font->maxDrawableChars(wline.substr(first_line_length).c_str(), max_pixels, wline.length(), LLFontGL::ANYWHERE); +// if (segment_length + first_line_length == wline.length()) +// { +// // no work needed +// return; +// } +// +// // name does not fit, cut it, add ... +// const LLWString dots_pad(utf8str_to_wstring(std::string("...."))); +// S32 elipses_width = font->getWidthF32(dots_pad.c_str()); +// segment_length = font->maxDrawableChars(wline.substr(first_line_length).c_str(), max_pixels - elipses_width, wline.length(), LLFontGL::ANYWHERE); +// +// name = name.substr(0, segment_length + first_line_length) + std::string("..."); +//} +// //void LLPanelPermissions::updateOwnerName(const LLUUID& owner_id, const LLAvatarName& owner_name, const LLStyle::Params& style_params) //{ // if (mOwnerCacheConnection.connected()) // { // mOwnerCacheConnection.disconnect(); // } -// mLabelOwnerName->setText(owner_name.getCompleteName(), style_params); +// std::string name = owner_name.getCompleteName(); +// shorten_name(name, style_params, mLabelOwnerName->getLocalRect().getWidth()); +// mLabelOwnerName->setText(name, style_params); //} // //void LLPanelPermissions::updateCreatorName(const LLUUID& creator_id, const LLAvatarName& creator_name, const LLStyle::Params& style_params) @@ -1188,7 +1220,9 @@ void LLPanelPermissions::refresh() // { // mCreatorCacheConnection.disconnect(); // } -// mLabelCreatorName->setText(creator_name.getCompleteName(), style_params); +// std::string name = creator_name.getCompleteName(); +// shorten_name(name, style_params, mLabelCreatorName->getLocalRect().getWidth()); +// mLabelCreatorName->setText(name, style_params); //} // static diff --git a/indra/newview/llpanelpresetscamerapulldown.cpp b/indra/newview/llpanelpresetscamerapulldown.cpp index d21a484fb0..b1cbbe7931 100644 --- a/indra/newview/llpanelpresetscamerapulldown.cpp +++ b/indra/newview/llpanelpresetscamerapulldown.cpp @@ -146,5 +146,9 @@ void LLPanelPresetsCameraPulldown::onViewButtonClick(const LLSD& user_data) // close the minicontrol, we're bringing up the big one setVisible(FALSE); - LLFloaterReg::toggleInstanceOrBringToFront("camera"); + // Optional small camera floater + //LLFloaterReg::toggleInstanceOrBringToFront("camera"); + std::string floater_name = gSavedSettings.getBOOL("FSUseSmallCameraFloater") ? "fs_camera_small" : "camera"; + LLFloaterReg::toggleInstanceOrBringToFront(floater_name); + // } diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index b17b52ccea..345ac191e3 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -213,6 +213,20 @@ public: }; LLAgentHandler gAgentHandler; +// FIRE-30611: "You" in transcript is underlined +class FSAgentSelfHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + FSAgentSelfHandler() : LLCommandHandler("agentself", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + { + return gAgentHandler.handle(params, query_map, web); + } +}; +FSAgentSelfHandler gAgentSelfHandler; +// //-- LLPanelProfile::ChildStack begins ---------------------------------------- LLPanelProfile::ChildStack::ChildStack() diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index d51008b7f4..369f50b2e7 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -798,8 +798,10 @@ void LLScriptEdCore::initMenu() menuItem = getChild("Go to line..."); menuItem->setClickCallback(boost::bind(&LLFloaterGotoLine::show, this)); + // Keep help links menuItem = getChild("Help..."); menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnHelp, this)); + // menuItem = getChild("Keyword Help..."); menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnDynamicHelp, this)); @@ -1359,10 +1361,12 @@ bool LLScriptEdCore::handleSaveChangesDialog(const LLSD& notification, const LLS return false; } +// Keep help links void LLScriptEdCore::onBtnHelp() { LLUI::getInstance()->mHelpImpl->showTopic(HELP_LSL_PORTAL_TOPIC); } +// void LLScriptEdCore::onBtnDynamicHelp() { diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index af0e23c8b1..2bdc6e48c9 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -174,7 +174,7 @@ private: void performAction(const std::string& action); bool enableAction(const std::string& action); // NaCl End - void onBtnHelp(); + void onBtnHelp(); // Keep help links void onBtnDynamicHelp(); void onBtnUndoChanges(); diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 07c1bcdb9b..b162afddf0 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -577,7 +577,7 @@ void LLPreviewTexture::onFileLoadedForSaveTGA(BOOL success, // Undo MAINT-2897 and use our own texture format selection //const U32 ext_length = 3; //std::string extension = self->mSaveFileName.substr( self->mSaveFileName.length() - ext_length); - + //LLStringUtil::toLower(extension); //// We only support saving in PNG or TGA format //LLPointer image; //if(extension == "png") diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index 2cf2d62dfc..821d3d647c 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -513,9 +513,10 @@ void LLProgressView::initLogos() // 108x41 icon_width = 74; + icon_height = default_height; loadLogo(temp_str + "vivox_logo.png", image_codec, - LLRect(texture_start_x, texture_start_y + default_height, texture_start_x + icon_width, texture_start_y), + LLRect(texture_start_x, texture_start_y + icon_height, texture_start_x + icon_width, texture_start_y), default_clip, default_clip); } diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index fe2f94d03e..d7c03ac369 100644 --- a/indra/newview/llscenemonitor.cpp +++ b/indra/newview/llscenemonitor.cpp @@ -526,8 +526,7 @@ void LLSceneMonitor::fetchQueryResult() //dump results to a file _scene_xmonitor_results.csv void LLSceneMonitor::dumpToFile(std::string file_name) -{ using namespace LLTrace; - +{ if (!hasResults()) return; LL_INFOS("SceneMonitor") << "Saving scene load stats to " << file_name << LL_ENDL; @@ -536,7 +535,7 @@ void LLSceneMonitor::dumpToFile(std::string file_name) os << std::setprecision(10); - PeriodicRecording& scene_load_recording = mSceneLoadRecording.getResults(); + LLTrace::PeriodicRecording& scene_load_recording = mSceneLoadRecording.getResults(); const U32 frame_count = scene_load_recording.getNumRecordedPeriods(); F64Seconds frame_time; @@ -558,7 +557,7 @@ void LLSceneMonitor::dumpToFile(std::string file_name) os << '\n'; - typedef StatType trace_count; + typedef LLTrace::StatType trace_count; for (auto& it : trace_count::instance_snapshot()) { std::ostringstream row; @@ -576,7 +575,7 @@ void LLSceneMonitor::dumpToFile(std::string file_name) for (S32 frame = 1; frame <= frame_count; frame++) { - Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame); + LLTrace::Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame); samples += recording.getSampleCount(it); row << ", " << recording.getSum(it); } @@ -589,7 +588,7 @@ void LLSceneMonitor::dumpToFile(std::string file_name) } } - typedef StatType trace_event; + typedef LLTrace::StatType trace_event; for (auto& it : trace_event::instance_snapshot()) { @@ -607,7 +606,7 @@ void LLSceneMonitor::dumpToFile(std::string file_name) for (S32 frame = 1; frame <= frame_count; frame++) { - Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame); + LLTrace::Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame); samples += recording.getSampleCount(it); F64 mean = recording.getMean(it); if (llisnan(mean)) @@ -628,7 +627,7 @@ void LLSceneMonitor::dumpToFile(std::string file_name) } } - typedef StatType trace_sample; + typedef LLTrace::StatType trace_sample; for (auto& it : trace_sample::instance_snapshot()) { @@ -646,7 +645,7 @@ void LLSceneMonitor::dumpToFile(std::string file_name) for (S32 frame = 1; frame <= frame_count; frame++) { - Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame); + LLTrace::Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame); samples += recording.getSampleCount(it); F64 mean = recording.getMean(it); if (llisnan(mean)) @@ -667,7 +666,7 @@ void LLSceneMonitor::dumpToFile(std::string file_name) } } - typedef StatType trace_mem; + typedef LLTrace::StatType trace_mem; for (auto& it : trace_mem::instance_snapshot()) { os << it.getName() << "(KiB)"; diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index bdf5a3a2bd..0729979208 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -145,6 +145,8 @@ BOOL LLSidepanelAppearance::postBuild() setVisibleCallback(boost::bind(&LLSidepanelAppearance::onVisibilityChanged,this,_2)); + setWearablesLoading(gAgentWearables.isCOFChangeInProgress()); + return TRUE; } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 2d5f0dc923..8a470cc97d 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1011,8 +1011,8 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) } LLSpatialGroup* group = drawablep->getSpatialGroup(); - llassert(group != NULL); - + // avoid crash for race condition with unseating of an avatar + // llassert(group != NULL); if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING)) { group->setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS); diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 5532843972..806750b989 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -2135,46 +2135,6 @@ LLPointer LLTextureCache::readFromFastCache(const LLUUID& id, S32& d return raw; } -#if LL_WINDOWS - -static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific - -U32 exception_dupe_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) -{ - if (code == STATUS_MSC_EXCEPTION) - { - // C++ exception, go on - return EXCEPTION_CONTINUE_SEARCH; - } - else - { - // handle it - return EXCEPTION_EXECUTE_HANDLER; - } -} - -//due to unwinding -void dupe(LLPointer &raw) -{ - raw = raw->duplicate(); -} - -void logExceptionDupplicate(LLPointer &raw) -{ - __try - { - dupe(raw); - } - __except (exception_dupe_filter(GetExceptionCode(), GetExceptionInformation())) - { - // convert to C++ styled exception - char integer_string[32]; - sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); - throw std::exception(integer_string); - } -} -#endif - //return the fast cache location bool LLTextureCache::writeToFastCache(LLUUID image_id, S32 id, LLPointer raw, S32 discardlevel) { @@ -2191,7 +2151,8 @@ bool LLTextureCache::writeToFastCache(LLUUID image_id, S32 id, LLPointergetComponents(); S32 i = 0 ; - + + // Search for a discard level that will fit into fast cache while(((w >> i) * (h >> i) * c) > TEXTURE_FAST_CACHE_DATA_SIZE) { ++i ; @@ -2204,30 +2165,7 @@ bool LLTextureCache::writeToFastCache(LLUUID image_id, S32 id, LLPointer 0) //valid { // Make a duplicate to keep the original raw image untouched. - // Might be good idea to do a copy during writeToCache() call instead of here - try - { -#if LL_WINDOWS - // Temporary diagnostics for scale/duplicate crash - logExceptionDupplicate(raw); -#else - raw = raw->duplicate(); -#endif - } - catch (...) - { - removeFromCache(image_id); - LL_WARNS() << "Failed to cache image: " << image_id - << " local id: " << id - << " Exception: " << boost::current_exception_diagnostic_information() - << " Image new width: " << w - << " Image new height: " << h - << " Image new components: " << c - << " Image discard difference: " << i - << LL_ENDL; - - return false; - } + raw = raw->duplicate(); if (raw->isBufferInvalid()) { diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 6406ef7ff4..45959f0d15 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -430,8 +430,8 @@ void LLAvatarTexBar::draw() LLColor4 color; U32 line_num = 1; - for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearance::getDictionary()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearance::getDictionary()->getBakedTextures().end(); ++baked_iter) { const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp index a0513b8c44..99138bbbd5 100644 --- a/indra/newview/lltoolgrab.cpp +++ b/indra/newview/lltoolgrab.cpp @@ -1162,7 +1162,9 @@ LLVector3d LLToolGrabBase::getGrabPointGlobal() void send_ObjectGrab_message(LLViewerObject* object, const LLPickInfo & pick, const LLVector3 &grab_offset) { - if (!object) return; + // Crash fix + //if (!object) return; + if (!object || !object->getRegion()) return; LLMessageSystem *msg = gMessageSystem; @@ -1199,7 +1201,9 @@ void send_ObjectGrab_message(LLViewerObject* object, const LLPickInfo & pick, co void send_ObjectDeGrab_message(LLViewerObject* object, const LLPickInfo & pick) { - if (!object) return; + // Crash fix + //if (!object) return; + if (!object || !object->getRegion()) return; LLMessageSystem *msg = gMessageSystem; diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index 9e6dbf3822..1ad96660a5 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -322,34 +322,35 @@ bool LLResourceUploadInfo::findAssetTypeOfExtension(const std::string& exten, LL bool LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(const std::string& exten, LLAssetType::EType& asset_type, U32& codec, bool bulk_upload) { bool succ = false; - - codec = LLImageBase::getCodecFromExtension(exten); + std::string exten_lc(exten); + LLStringUtil::toLower(exten_lc); + codec = LLImageBase::getCodecFromExtension(exten_lc); if (codec != IMG_CODEC_INVALID) { asset_type = LLAssetType::AT_TEXTURE; succ = true; } - else if (exten == "wav") + else if (exten_lc == "wav") { asset_type = LLAssetType::AT_SOUND; succ = true; } - else if (exten == "anim") + else if (exten_lc == "anim") { asset_type = LLAssetType::AT_ANIMATION; succ = true; } - else if (!bulk_upload && (exten == "bvh")) + else if (!bulk_upload && (exten_lc == "bvh")) { asset_type = LLAssetType::AT_ANIMATION; succ = true; } - else if (exten == "ogg") + else if (exten_lc == "ogg") { asset_type = LLAssetType::AT_SOUND; succ = true; } - else if (exten == "j2k") + else if (exten_lc == "j2k") { asset_type = LLAssetType::AT_TEXTURE; succ = true; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 48f9ed7477..eebce59f9a 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -1019,6 +1019,20 @@ void handleRenderHiDPIChanged(const LLSD& newvalue) } // FIRE-24081 +// Optional small camera floater +void handleSmallCameraFloaterChanged(const LLSD& newValue) +{ + std::string old_floater_name = newValue.asBoolean() ? "camera" : "fs_camera_small"; + std::string new_floater_name = newValue.asBoolean() ? "fs_camera_small" : "camera"; + + if (LLFloaterReg::instanceVisible(old_floater_name)) + { + LLFloaterReg::hideInstance(old_floater_name); + LLFloaterReg::showInstance(new_floater_name); + } +} +// + //////////////////////////////////////////////////////////////////////////// void settings_setup_listeners() @@ -1263,6 +1277,9 @@ void settings_setup_listeners() // Dynamic texture memory calculation gSavedSettings.getControl("FSDynamicTextureMemory")->getSignal()->connect(boost::bind(&handleDynamicTextureMemoryChanged, _2)); + + // Optional small camera floater + gSavedSettings.getControl("FSUseSmallCameraFloater")->getSignal()->connect(boost::bind(&handleSmallCameraFloaterChanged, _2)); } #if TEST_CACHED_CONTROL diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 8ee1f6f195..6195ca2974 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -267,6 +267,8 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + // Optional small camera floater + LLFloaterReg::add("fs_camera_small", "floater_fs_camera_small.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("camera_presets", "floater_camera_presets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); // [FS communication UI] diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index 3e1b7663f2..d8bb7c1960 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -42,11 +42,21 @@ #include "lltoolmgr.h" #include "llselectmgr.h" #include "llviewermenu.h" +#include "llviewerwindow.h" +#include "llwindow.h" #include "llagent.h" #include "llagentcamera.h" #include "llfocusmgr.h" #include "llmoveview.h" +#if LL_WINDOWS && !LL_MESA_HEADLESS +// Require DirectInput version 8 +#define DIRECTINPUT_VERSION 0x0800 + +#include +#endif + + // ---------------------------------------------------------------------------- // Constants @@ -68,6 +78,7 @@ F32 LLViewerJoystick::sDelta[] = {0,0,0,0,0,0,0}; #define MAX_SPACENAVIGATOR_INPUT 3000.0f #define MAX_JOYSTICK_INPUT_VALUE MAX_SPACENAVIGATOR_INPUT + #if LIB_NDOF std::ostream& operator<<(std::ostream& out, NDOF_Device* ptr) { @@ -105,6 +116,126 @@ std::ostream& operator<<(std::ostream& out, NDOF_Device* ptr) } #endif // LIB_NDOF + +#if LL_WINDOWS && !LL_MESA_HEADLESS +// this should reflect ndof and set axises, see ndofdev_win.cpp from ndof package +BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* inst, VOID* user_data) +{ + if (inst->dwType & DIDFT_AXIS) + { + LPDIRECTINPUTDEVICE8 device = *((LPDIRECTINPUTDEVICE8 *)user_data); + DIPROPRANGE diprg; + diprg.diph.dwSize = sizeof(DIPROPRANGE); + diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = inst->dwType; // specify the enumerated axis + + // Set the range for the axis + diprg.lMin = (long)-MAX_JOYSTICK_INPUT_VALUE; + diprg.lMax = (long)+MAX_JOYSTICK_INPUT_VALUE; + HRESULT hr = device->SetProperty(DIPROP_RANGE, &diprg.diph); + + if (FAILED(hr)) + { + return DIENUM_STOP; + } + } + + return DIENUM_CONTINUE; +} + +BOOL CALLBACK di8_devices_callback(LPCDIDEVICEINSTANCE device_instance_ptr, LPVOID pvRef) +{ + // Note: If a single device can function as more than one DirectInput + // device type, it is enumerated as each device type that it supports. + // Capable of detecting devices like Oculus Rift + if (device_instance_ptr) + { + std::string product_name = utf16str_to_utf8str(llutf16string(device_instance_ptr->tszProductName)); + + LLSD guid = LLViewerJoystick::getInstance()->getDeviceUUID(); + + bool init_device = false; + if (guid.isBinary()) + { + std::vector bin_bucket = guid.asBinary(); + init_device = memcmp(&bin_bucket[0], &device_instance_ptr->guidInstance, sizeof(GUID)) == 0; + } + else + { + // It might be better to init space navigator here, but if system doesn't has one, + // ndof will pick a random device, it is simpler to pick first device now to have an id + init_device = true; + } + + if (init_device) + { + LL_DEBUGS("Joystick") << "Found and attempting to use device: " << product_name << LL_ENDL; + LPDIRECTINPUT8 di8_interface = *((LPDIRECTINPUT8 *)gViewerWindow->getWindow()->getDirectInput8()); + LPDIRECTINPUTDEVICE8 device = NULL; + + HRESULT status = di8_interface->CreateDevice( + device_instance_ptr->guidInstance, // REFGUID rguid, + &device, // LPDIRECTINPUTDEVICE * lplpDirectInputDevice, + NULL // LPUNKNOWN pUnkOuter + ); + + if (status == DI_OK) + { + // prerequisite for aquire() + LL_DEBUGS("Joystick") << "Device created" << LL_ENDL; + status = device->SetDataFormat(&c_dfDIJoystick); // c_dfDIJoystick2 + } + + if (status == DI_OK) + { + // set properties + LL_DEBUGS("Joystick") << "Format set" << LL_ENDL; + status = device->EnumObjects(EnumObjectsCallback, &device, DIDFT_ALL); + } + + if (status == DI_OK) + { + LL_DEBUGS("Joystick") << "Properties updated" << LL_ENDL; + + S32 size = sizeof(GUID); + LLSD::Binary data; //just an std::vector + data.resize(size); + memcpy(&data[0], &device_instance_ptr->guidInstance /*POD _GUID*/, size); + LLViewerJoystick::getInstance()->initDevice(&device, product_name, LLSD(data)); + return DIENUM_STOP; + } + } + else + { + LL_DEBUGS("Joystick") << "Found device: " << product_name << LL_ENDL; + } + } + return DIENUM_CONTINUE; +} + +// Windows guids +// This is GUID2 so teoretically it can be memcpy copied into LLUUID +void guid_from_string(GUID &guid, const std::string &input) +{ + CLSIDFromString(utf8str_to_utf16str(input).c_str(), &guid); +} + +std::string string_from_guid(const GUID &guid) +{ + OLECHAR* guidString; //wchat + StringFromCLSID(guid, &guidString); + + // use guidString... + + std::string res = utf16str_to_utf8str(llutf16string(guidString)); + // ensure memory is freed + ::CoTaskMemFree(guidString); + + return res; +} +#endif + // ----------------------------------------------------------------------------- void LLViewerJoystick::updateEnabled(bool autoenable) { @@ -114,7 +245,8 @@ void LLViewerJoystick::updateEnabled(bool autoenable) } else { - if (isLikeSpaceNavigator() && autoenable) + // autoenable if user specifically chose this device + if (autoenable && (isLikeSpaceNavigator() || isDeviceUUIDSet())) { gSavedSettings.setBOOL("JoystickEnabled", TRUE ); } @@ -150,14 +282,14 @@ NDOF_HotPlugResult LLViewerJoystick::HotPlugAddCallback(NDOF_Device *dev) LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); if (joystick->mDriverState == JDS_UNINITIALIZED) { - LL_INFOS("joystick") << "HotPlugAddCallback: will use device:" << LL_ENDL; + LL_INFOS("Joystick") << "HotPlugAddCallback: will use device:" << LL_ENDL; // Disable for Linux till vs017 gets merged in to no having to support multiple version of libndofdev #ifndef LL_LINUX ndof_dump(stderr, dev); #endif // - + joystick->mNdofDev = dev; joystick->mDriverState = JDS_INITIALIZED; res = NDOF_KEEP_HOTPLUGGED; @@ -174,7 +306,7 @@ void LLViewerJoystick::HotPlugRemovalCallback(NDOF_Device *dev) LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); if (joystick->mNdofDev == dev) { - LL_INFOS("joystick") << "HotPlugRemovalCallback: joystick->mNdofDev=" + LL_INFOS("Joystick") << "HotPlugRemovalCallback: joystick->mNdofDev=" << joystick->mNdofDev << "; removed device:" << LL_ENDL; // Disable for Linux till vs017 gets merged in to no having to support multiple version of libndofdev @@ -207,6 +339,8 @@ LLViewerJoystick::LLViewerJoystick() // factor in bandwidth? bandwidth = gViewerStats->mKBitStat mPerfScale = 4000.f / gSysCPU.getMHz(); // hmm. why? + + mLastDeviceUUID = LLSD::Integer(1); } // ----------------------------------------------------------------------------- @@ -225,12 +359,14 @@ void LLViewerJoystick::init(bool autoenable) static bool libinit = false; mDriverState = JDS_INITIALIZING; + loadDeviceIdFromSettings(); + if (libinit == false) { // Note: The HotPlug callbacks are not actually getting called on Windows if (ndof_libinit(HotPlugAddCallback, HotPlugRemovalCallback, - NULL)) + gViewerWindow->getWindow()->getDirectInput8())) { mDriverState = JDS_UNINITIALIZED; } @@ -247,41 +383,33 @@ void LLViewerJoystick::init(bool autoenable) if (libinit) { if (mNdofDev) - { - LL_DEBUGS("joystick") << "ndof_create() returned: " << mNdofDev << LL_ENDL; - // Different joysticks will return different ranges of raw values. - // Since we want to handle every device in the same uniform way, - // we initialize the mNdofDev struct and we set the range - // of values we would like to receive. - // - // HACK: On Windows, libndofdev passes our range to DI with a - // SetProperty call. This works but with one notable exception, the - // SpaceNavigator, who doesn't seem to care about the SetProperty - // call. In theory, we should handle this case inside libndofdev. - // However, the range we're setting here is arbitrary anyway, - // so let's just use the SpaceNavigator range for our purposes. - mNdofDev->axes_min = (long)-MAX_JOYSTICK_INPUT_VALUE; - mNdofDev->axes_max = (long)+MAX_JOYSTICK_INPUT_VALUE; - - // libndofdev could be used to return deltas. Here we choose to - // just have the absolute values instead. - mNdofDev->absolute = 1; - - LL_DEBUGS("joystick") << "ndof_init_first() received: " << mNdofDev << LL_ENDL; - // init & use the first suitable NDOF device found on the USB chain - if (ndof_init_first(mNdofDev, NULL)) - { - mDriverState = JDS_UNINITIALIZED; - LL_WARNS("joystick") << "ndof_init_first FAILED" << LL_ENDL; -#ifndef LL_LINUX - ndof_dump_list(stderr); + { + // di8_devices_callback callback is immediate and happens in scope of getInputDevices() +#if LL_WINDOWS && !LL_MESA_HEADLESS + // space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib + U32 device_type = DI8DEVCLASS_GAMECTRL; + void* callback = &di8_devices_callback; +#else + // MAC doesn't support device search yet + // On MAC there is an ndof_idsearch and it is possible to specify product + // and manufacturer in NDOF_Device for ndof_init_first to pick specific one + U32 device_type = 0; + void* callback = NULL; #endif - } - else - { - mDriverState = JDS_INITIALIZED; - } - LL_DEBUGS("joystick") << "ndof_init_first() left: " << mNdofDev << LL_ENDL; + if (!gViewerWindow->getWindow()->getInputDevices(device_type, callback, NULL)) + { + LL_INFOS("Joystick") << "Failed to gather devices from window. Falling back to ndof's init" << LL_ENDL; + // Failed to gather devices from windows, init first suitable one + mLastDeviceUUID = LLSD(); + void *preffered_device = NULL; + initDevice(preffered_device); + } + + if (mDriverState == JDS_INITIALIZING) + { + LL_INFOS("Joystick") << "Found no matching joystick devices." << LL_ENDL; + mDriverState = JDS_UNINITIALIZED; + } } else { @@ -320,11 +448,92 @@ void LLViewerJoystick::init(bool autoenable) // No device connected, don't change any settings } - LL_INFOS("joystick") << "ndof: mDriverState=" << mDriverState << "; mNdofDev=" + LL_INFOS("Joystick") << "ndof: mDriverState=" << mDriverState << "; mNdofDev=" << mNdofDev << "; libinit=" << libinit << LL_ENDL; #endif } +void LLViewerJoystick::initDevice(LLSD &guid) +{ +#if LIB_NDOF + mLastDeviceUUID = guid; + +#if LL_WINDOWS && !LL_MESA_HEADLESS + // space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib + U32 device_type = DI8DEVCLASS_GAMECTRL; + void* callback = &di8_devices_callback; +#else + // MAC doesn't support device search yet + // On MAC there is an ndof_idsearch and it is possible to specify product + // and manufacturer in NDOF_Device for ndof_init_first to pick specific one + U32 device_type = 0; + void* callback = NULL; +#endif + + mDriverState = JDS_INITIALIZING; + if (!gViewerWindow->getWindow()->getInputDevices(device_type, callback, NULL)) + { + LL_INFOS("Joystick") << "Failed to gather devices from window. Falling back to ndof's init" << LL_ENDL; + // Failed to gather devices from windows, init first suitable one + void *preffered_device = NULL; + mLastDeviceUUID = LLSD(); + initDevice(preffered_device); + } + + if (mDriverState == JDS_INITIALIZING) + { + LL_INFOS("Joystick") << "Found no matching joystick devices." << LL_ENDL; + mDriverState = JDS_UNINITIALIZED; + } +#endif +} + +void LLViewerJoystick::initDevice(void * preffered_device /*LPDIRECTINPUTDEVICE8*/, std::string &name, LLSD &guid) +{ +#if LIB_NDOF + mLastDeviceUUID = guid; + + strncpy(mNdofDev->product, name.c_str(), sizeof(mNdofDev->product)); + mNdofDev->manufacturer[0] = '\0'; + + initDevice(preffered_device); +#endif +} + +void LLViewerJoystick::initDevice(void * preffered_device /* LPDIRECTINPUTDEVICE8* */) +{ +#if LIB_NDOF + // Different joysticks will return different ranges of raw values. + // Since we want to handle every device in the same uniform way, + // we initialize the mNdofDev struct and we set the range + // of values we would like to receive. + // + // HACK: On Windows, libndofdev passes our range to DI with a + // SetProperty call. This works but with one notable exception, the + // SpaceNavigator, who doesn't seem to care about the SetProperty + // call. In theory, we should handle this case inside libndofdev. + // However, the range we're setting here is arbitrary anyway, + // so let's just use the SpaceNavigator range for our purposes. + mNdofDev->axes_min = (long)-MAX_JOYSTICK_INPUT_VALUE; + mNdofDev->axes_max = (long)+MAX_JOYSTICK_INPUT_VALUE; + + // libndofdev could be used to return deltas. Here we choose to + // just have the absolute values instead. + mNdofDev->absolute = 1; + // init & use the first suitable NDOF device found on the USB chain + // On windows preffered_device needs to be a pointer to LPDIRECTINPUTDEVICE8 + if (ndof_init_first(mNdofDev, preffered_device)) + { + mDriverState = JDS_UNINITIALIZED; + LL_WARNS() << "ndof_init_first FAILED" << LL_ENDL; + } + else + { + mDriverState = JDS_INITIALIZED; + } +#endif +} + // ----------------------------------------------------------------------------- void LLViewerJoystick::terminate() { @@ -334,7 +543,7 @@ void LLViewerJoystick::terminate() ndof_libcleanup(); // frees alocated memory in mNdofDev mDriverState = JDS_UNINITIALIZED; mNdofDev = NULL; - LL_INFOS("joystick") << "Terminated connection with NDOF device." << LL_ENDL; + LL_INFOS("Joystick") << "Terminated connection with NDOF device." << LL_ENDL; } #endif } @@ -1132,6 +1341,74 @@ void LLViewerJoystick::scanJoystick() } } +// ----------------------------------------------------------------------------- +bool LLViewerJoystick::isDeviceUUIDSet() +{ +#if LL_WINDOWS && !LL_MESA_HEADLESS + // for ease of comparison and to dial less with platform specific variables, we store id as LLSD binary + return mLastDeviceUUID.isBinary(); +#else + return false; +#endif +} + +LLSD LLViewerJoystick::getDeviceUUID() +{ + return mLastDeviceUUID; +} + +std::string LLViewerJoystick::getDeviceUUIDString() +{ +#if LL_WINDOWS && !LL_MESA_HEADLESS + // Might be simpler to just convert _GUID into string everywhere, store and compare as string + if (mLastDeviceUUID.isBinary()) + { + S32 size = sizeof(GUID); + LLSD::Binary data = mLastDeviceUUID.asBinary(); + GUID guid; + memcpy(&guid, &data[0], size); + return string_from_guid(guid); + } + else + { + return std::string(); + } +#else + return std::string(); + // return mLastDeviceUUID; +#endif +} + +void LLViewerJoystick::loadDeviceIdFromSettings() +{ +#if LL_WINDOWS && !LL_MESA_HEADLESS + // We can't save binary data to gSavedSettings, somebody editing the file will corrupt it, + // so _GUID data gets converted to string (we probably can convert it to LLUUID with memcpy) + // and here we need to convert it back to binary from string + std::string device_string = gSavedSettings.getString("JoystickDeviceUUID"); + if (device_string.empty()) + { + mLastDeviceUUID = LLSD(); + } + else + { + LL_DEBUGS("Joystick") << "Looking for device by id: " << device_string << LL_ENDL; + GUID guid; + guid_from_string(guid, device_string); + S32 size = sizeof(GUID); + LLSD::Binary data; //just an std::vector + data.resize(size); + memcpy(&data[0], &guid /*POD _GUID*/, size); + // We store this data in LLSD since LLSD is versatile and will be able to handle both GUID2 + // and any data MAC will need for device selection + mLastDeviceUUID = LLSD(data); + } +#else + mLastDeviceUUID = LLSD(); + //mLastDeviceUUID = gSavedSettings.getLLSD("JoystickDeviceUUID"); +#endif +} + // ----------------------------------------------------------------------------- std::string LLViewerJoystick::getDescription() { @@ -1173,7 +1450,7 @@ void LLViewerJoystick::setSNDefaults() #endif //gViewerWindow->alertXml("CacheWillClear"); - LL_INFOS("joystick") << "restoring SpaceNavigator defaults..." << LL_ENDL; + LL_INFOS("Joystick") << "restoring SpaceNavigator defaults..." << LL_ENDL; gSavedSettings.setS32("JoystickAxis0", 1); // z (at) gSavedSettings.setS32("JoystickAxis1", 0); // x (slide) diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h index 016b435ee8..782c523d4f 100644 --- a/indra/newview/llviewerjoystick.h +++ b/indra/newview/llviewerjoystick.h @@ -50,6 +50,9 @@ class LLViewerJoystick : public LLSingleton public: void init(bool autoenable); + void initDevice(LLSD &guid); + void initDevice(void * preffered_device /*LPDIRECTINPUTDEVICE8*/); + void initDevice(void * preffered_device /*LPDIRECTINPUTDEVICE8*/, std::string &name, LLSD &guid); void terminate(); void updateStatus(); @@ -68,8 +71,11 @@ public: void setOverrideCamera(bool val); bool toggleFlycam(); void setSNDefaults(); + bool isDeviceUUIDSet(); + LLSD getDeviceUUID(); //unconverted, OS dependent value wrapped into LLSD, for comparison/search + std::string getDeviceUUIDString(); // converted readable value for settings std::string getDescription(); - + protected: void updateEnabled(bool autoenable); void handleRun(F32 inc); @@ -80,6 +86,7 @@ protected: void agentYaw(F32 yaw_inc); void agentJump(); void resetDeltas(S32 axis[]); + void loadDeviceIdFromSettings(); #if LIB_NDOF static NDOF_HotPlugResult HotPlugAddCallback(NDOF_Device *dev); static void HotPlugRemovalCallback(NDOF_Device *dev); @@ -95,6 +102,7 @@ private: bool mCameraUpdated; bool mOverrideCamera; U32 mJoystickRun; + LLSD mLastDeviceUUID; // _GUID as U8 binary map, integer 1 for no device/ndof's device static F32 sLastDelta[7]; static F32 sDelta[7]; diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index e7b095a1b6..676d7b11ad 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -194,8 +194,6 @@ static F32 sGlobalVolume = 1.0f; static bool sForceUpdate = false; static LLUUID sOnlyAudibleTextureID = LLUUID::null; static F64 sLowestLoadableImplInterest = 0.0f; -// Unused -//static bool sAnyMediaShowing = false; ////////////////////////////////////////////////////////////////////////////////////////// static void add_media_impl(LLViewerMediaImpl* media) @@ -883,10 +881,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg) if (!pimpl->getUsedInUI() && pimpl->hasMedia()) { - // Need to set the right instance var - // sAnyMediaShowing = true; - mAnyMediaShowing = true; - // + mAnyMediaShowing = true; } if (!pimpl->getUsedInUI() && pimpl->hasMedia() && (pimpl->isMediaPlaying() || !pimpl->isMediaTimeBased())) diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp index 1c5eac6f98..5a13731915 100644 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -340,7 +340,8 @@ BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent) clearFocus(); } - + + // Keep help links if ( KEY_F1 == key && LLUI::getInstance()->mHelpImpl && mMediaControls.get()) { std::string help_topic; @@ -349,6 +350,7 @@ BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent) LLUI::getInstance()->mHelpImpl->showTopic(help_topic); } } + // } return true; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index a360d1b70b..54e22a771f 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -5304,8 +5304,9 @@ void handle_reset_view() // switching to outfit selector should automagically save any currently edited wearable LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "my_outfits")); } - + // Added optional V1 behavior so the avatar turns into camera direction after hitting ESC + // gAgentCamera.setFocusOnAvatar(TRUE, FALSE, FALSE); if (!gSavedSettings.getBOOL("ResetViewTurnsAvatar")) { // The only thing we actually want to do here is set LLAgent::mFocusOnAvatar to TRUE, @@ -9026,6 +9027,64 @@ class LLToolsSelectedScriptAction : public view_listener_t { bool handleEvent(const LLSD& userdata) { + // Script reset in edit floater + //std::string action = userdata.asString(); + //bool mono = false; + //std::string msg, name; + //std::string title; + //if (action == "compile mono") + //{ + // name = "compile_queue"; + // mono = true; + // msg = "Recompile"; + // title = LLTrans::getString("CompileQueueTitle"); + //} + //if (action == "compile lsl") + //{ + // name = "compile_queue"; + // msg = "Recompile"; + // title = LLTrans::getString("CompileQueueTitle"); + //} + //else if (action == "reset") + //{ + // name = "reset_queue"; + // msg = "Reset"; + // title = LLTrans::getString("ResetQueueTitle"); + //} + //else if (action == "start") + //{ + // name = "start_queue"; + // msg = "SetRunning"; + // title = LLTrans::getString("RunQueueTitle"); + //} + //else if (action == "stop") + //{ + // name = "stop_queue"; + // msg = "SetRunningNot"; + // title = LLTrans::getString("NotRunQueueTitle"); + //} + //LLUUID id; id.generate(); + + //LLFloaterScriptQueue* queue = LLFloaterReg::getTypedInstance(name, LLSD(id)); + //if (queue) + //{ + // queue->setMono(mono); + // queue_actions(queue, msg); + // queue->setTitle(title); + //} + //else + //{ + // LL_WARNS() << "Failed to generate LLFloaterScriptQueue with action: " << action << LL_ENDL; + //} + handle_selected_script_action(userdata.asString()); + // + return true; + } +}; + +// Script reset in edit floater +void handle_selected_script_action(const std::string& action) +{ // [RLVa:KB] - Checked: 2010-04-19 (RLVa-1.2.0f) | Modified: RLVa-1.0.5a // We'll allow resetting the scripts of objects on a non-attachable attach point since they wouldn't be able to circumvent anything if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_REMOVE)) ) @@ -9033,69 +9092,59 @@ class LLToolsSelectedScriptAction : public view_listener_t LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection(); RlvSelectHasLockedAttach f; if ( (hSel->isAttachment()) && (hSel->getFirstNode(&f) != NULL) ) - return true; + return; } // [/RLVa:KB] - std::string action = userdata.asString(); - bool mono = false; - std::string msg, name; - std::string title; - if (action == "compile mono") - { - name = "compile_queue"; - mono = true; - msg = "Recompile"; - title = LLTrans::getString("CompileQueueTitle"); - } - if (action == "compile lsl") - { - name = "compile_queue"; - msg = "Recompile"; - title = LLTrans::getString("CompileQueueTitle"); - } - else if (action == "reset") - { - name = "reset_queue"; - msg = "Reset"; - title = LLTrans::getString("ResetQueueTitle"); - } - else if (action == "start") - { - name = "start_queue"; - msg = "SetRunning"; - title = LLTrans::getString("RunQueueTitle"); - } - else if (action == "stop") - { - name = "stop_queue"; - msg = "SetRunningNot"; - title = LLTrans::getString("NotRunQueueTitle"); - } - // Delete scripts - else if (action == "delete") - { - name = "delete_queue"; - msg = "delete"; - title = LLTrans::getString("DeleteQueueTitle"); - } - // Delete scripts - LLUUID id; id.generate(); - - LLFloaterScriptQueue* queue =LLFloaterReg::getTypedInstance(name, LLSD(id)); - if (queue) - { - queue->setMono(mono); - queue_actions(queue, msg); - queue->setTitle(title); - } - else - { - LL_WARNS() << "Failed to generate LLFloaterScriptQueue with action: " << action << LL_ENDL; - } - return true; + bool mono = false; + std::string msg, name; + std::string title; + if (action == "compile mono") + { + name = "compile_queue"; + mono = true; + msg = "Recompile"; + title = LLTrans::getString("CompileQueueTitle"); } -}; + if (action == "compile lsl") + { + name = "compile_queue"; + msg = "Recompile"; + title = LLTrans::getString("CompileQueueTitle"); + } + else if (action == "reset") + { + name = "reset_queue"; + msg = "Reset"; + title = LLTrans::getString("ResetQueueTitle"); + } + else if (action == "start") + { + name = "start_queue"; + msg = "SetRunning"; + title = LLTrans::getString("RunQueueTitle"); + } + else if (action == "stop") + { + name = "stop_queue"; + msg = "SetRunningNot"; + title = LLTrans::getString("NotRunQueueTitle"); + } + LLUUID id; id.generate(); + + LLFloaterScriptQueue* queue = LLFloaterReg::getTypedInstance(name, LLSD(id)); + if (queue) + { + queue->setMono(mono); + queue_actions(queue, msg); + queue->setTitle(title); + } + else + { + LL_WARNS() << "Failed to generate LLFloaterScriptQueue with action: " << action << LL_ENDL; + } +} +// void handle_selected_texture_info(void*) { @@ -10087,7 +10136,7 @@ void handle_grab_baked_texture(void* data) if(folder_id.notNull()) { std::string name; - name = "Baked " + LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_tex_index)->mNameCapitalized + " Texture"; + name = "Baked " + LLAvatarAppearance::getDictionary()->getBakedTexture(baked_tex_index)->mNameCapitalized + " Texture"; LLUUID item_id; item_id.generate(); @@ -11433,6 +11482,27 @@ bool use_http_textures() } // +// Optional small camera floater +class FSToggleCameraFloater : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + std::string floater_name = gSavedSettings.getBOOL("FSUseSmallCameraFloater") ? "fs_camera_small" : "camera"; + LLFloaterReg::toggleInstance(floater_name); + return true; + } +}; + +class FSCheckCameraFloater : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + static LLCachedControl fsUseSmallCameraFloater(gSavedSettings, "FSUseSmallCameraFloater"); + return LLFloaterReg::instanceVisible(fsUseSmallCameraFloater ? "fs_camera_small" : "camera"); + } +}; +// + void initialize_menus() { // A parameterized event handler used as ctrl-8/9/0 zoom controls below. @@ -11531,7 +11601,11 @@ void initialize_menus() // Add reset camera angles menu view_listener_t::addMenu(new LLViewResetCameraAngles(), "View.ResetCameraAngles"); // - + // Optional small camera floater + view_listener_t::addMenu(new FSToggleCameraFloater(), "View.ToggleCameraFloater"); + view_listener_t::addMenu(new FSCheckCameraFloater(), "View.CheckCameraFloater"); + // + // Keep this for menu check item // Me > Movement view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying"); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 3a282702ea..b13e38e561 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -126,6 +126,7 @@ void handle_object_edit(); void handle_attachment_edit(const LLUUID& inv_item_id); void handle_attachment_touch(const LLUUID& inv_item_id); bool enable_attachment_touch(const LLUUID& inv_item_id); +void handle_selected_script_action(const std::string& action); // Script reset in edit floater // area search // expose this function so other classes can call it diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 0cc6bca88a..5640819e80 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -84,6 +84,10 @@ #include "llviewernetwork.h" +// FIRE-30632: Bulk Windlight import +#include "llenvironment.h" +#include "llsettingsvo.h" + class LLFileEnableUpload : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -396,7 +400,9 @@ const void upload_single_file(const std::vector& filenames, LLFileP } if (type == LLFilePicker::FFLOAD_ANIM) { - if (filename.rfind(".anim") != std::string::npos) + std::string filename_lc(filename); + LLStringUtil::toLower(filename_lc); + if (filename_lc.rfind(".anim") != std::string::npos) { LLFloaterReg::showInstance("upload_anim_anim", LLSD(filename)); } @@ -721,11 +727,12 @@ class LLFileTakeSnapshotToDisk : public view_listener_t bool render_ui = gSavedSettings.getBOOL("RenderUIInSnapshot"); bool render_hud = gSavedSettings.getBOOL("RenderHUDInSnapshot"); - if (gSavedSettings.getBOOL("HighResSnapshot")) + BOOL high_res = gSavedSettings.getBOOL("HighResSnapshot"); + if (high_res) { width *= 2; height *= 2; - // not compatible wirh UI/HUD + // not compatible with UI/HUD render_ui = false; render_hud = false; } @@ -737,7 +744,9 @@ class LLFileTakeSnapshotToDisk : public view_listener_t FALSE, render_ui, render_hud, - FALSE)) + FALSE, + LLSnapshotModel::SNAPSHOT_TYPE_COLOR, + high_res ? S32_MAX : MAX_SNAPSHOT_IMAGE_SIZE)) //per side { LLPointer formatted; LLSnapshotModel::ESnapshotFormat fmt = (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); @@ -1026,6 +1035,100 @@ void upload_new_resource( } } +// FIRE-30632: Bulk Windlight import +static std::set windlight_filenames; +static bool bulk_windlight_import_active = false; + +void on_windlight_imported(LLUUID inventory_id, LLSD results, const std::string& name) +{ + if (inventory_id.isNull() || !results["success"].asBoolean()) + { + LLSD args; + args["NAME"] = name; + LLNotificationsUtil::add("CantCreateInventoryName", args); + } + + windlight_filenames.erase(name); + + if (windlight_filenames.empty()) + { + bulk_windlight_import_active = false; + LLUploadDialog::modalUploadFinished(); + LLNotificationsUtil::add("WindlightBulkImportFinished"); + } +} + +const void import_windlight_bulk(const std::vector& filenames, LLFilePicker::ELoadFilter filter_type, LLSettingsType::type_e settings_type) +{ + LLSD messages; + LLSettingsBase::ptr_t settings; + if (filenames.size() < 1) return; + + bulk_windlight_import_active = true; + LLUploadDialog::modalUploadDialog(LLTrans::getString("ImportingWindlightBulk")); + + const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS); + + windlight_filenames.clear(); + windlight_filenames.insert(filenames.begin(), filenames.end()); + + for (auto& filename : filenames) + { + switch (settings_type) + { + case LLSettingsType::ST_SKY: + settings = LLEnvironment::createSkyFromLegacyPreset(filename, messages); + break; + case LLSettingsType::ST_WATER: + settings = LLEnvironment::createWaterFromLegacyPreset(filename, messages); + break; + case LLSettingsType::ST_DAYCYCLE: + settings = LLEnvironment::createDayCycleFromLegacyPreset(filename, messages); + break; + default: + settings.reset(); + break; + } + + if (settings) + { + LLSettingsVOBase::createInventoryItem(settings, parent_id, LLURI::unescape(gDirUtilp->getBaseFileName(filename, true)), + [filename](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { on_windlight_imported(inventory_id, results, filename); }); + } + else + { + LLNotificationsUtil::add("WLImportFail", messages); + windlight_filenames.erase(filename); + } + } + + // For error cases + if (windlight_filenames.empty()) + { + bulk_windlight_import_active = false; + LLUploadDialog::modalUploadFinished(); + LLNotificationsUtil::add("WindlightBulkImportFinished"); + } +} + +class FSFileImportWindlightBulk : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLSettingsType::type_e settings_type = (LLSettingsType::type_e)userdata.asInteger(); + (new LLFilePickerReplyThread(boost::bind(&import_windlight_bulk, _1, _2, settings_type), LLFilePicker::FFLOAD_XML, true))->getFile(); + return true; + } +}; + +class FSFileEnableImportWindlightBulk : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + return !bulk_windlight_import_active; + } +}; +// void init_menu_file() { @@ -1047,5 +1150,10 @@ void init_menu_file() view_listener_t::addMenu(new LLMeshUploadVisible(), "File.VisibleUploadModel"); view_listener_t::addCommit(new FSFileImportLinkset(), "File.ImportLinkset"); // Import linkset item + // FIRE-30632: Bulk Windlight import + view_listener_t::addCommit(new FSFileImportWindlightBulk(), "File.ImportWindlightBulk"); + view_listener_t::addEnable(new FSFileEnableImportWindlightBulk(), "File.EnableImportWindlightBulk"); + // + // "File.SaveTexture" moved to llpanelmaininventory so that it can be properly handled. } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index c3ba6aeebd..f20d40bbe1 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -7300,8 +7300,9 @@ void process_script_question(LLMessageSystem *msg, void **user_data) // so we'll reuse the same namespace for both throttle types. std::string throttle_name = owner_name; std::string self_name; - LLAgentUI::buildFullname( self_name ); - if( owner_name == self_name ) + LLAgentUI::buildFullname( self_name ); // does not include ' Resident' + std::string clean_owner_name = LLCacheName::cleanFullName(owner_name); // removes ' Resident' + if( clean_owner_name == self_name ) { throttle_name = taskid.getString(); } @@ -7338,7 +7339,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data) S32 count = 0; LLSD args; args["OBJECTNAME"] = object_name; - args["NAME"] = LLCacheName::cleanFullName(owner_name); + args["NAME"] = clean_owner_name; S32 known_questions = 0; bool has_not_only_debit = questions ^ SCRIPT_PERMISSIONS[SCRIPT_PERMISSION_DEBIT].permbit; // check the received permission flags against each permission diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index ec68ee5297..daa4200552 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -298,6 +298,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) LL_INFOS("AppInit", "Capabilities") << "Requesting seed from " << url << " region name " << regionp->getName() + << " region id " << regionp->getRegionID() << " handle " << regionp->getHandle() << " (attempt #" << mSeedCapAttempts + 1 << ")" << LL_ENDL; LL_DEBUGS("AppInit", "Capabilities") << "Capabilities requested: " << capabilityNames << LL_ENDL; @@ -417,7 +418,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle) LLSD capabilityNames = LLSD::emptyArray(); buildCapabilityNames(capabilityNames); - LL_INFOS("AppInit", "Capabilities") << "Requesting second Seed from " << url << LL_ENDL; + LL_INFOS("AppInit", "Capabilities") << "Requesting second Seed from " << url << " for region " << regionp->getRegionID() << LL_ENDL; regionp = NULL; result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames); @@ -2388,7 +2389,7 @@ void LLViewerRegion::requestSimulatorFeatures() LLCoros::instance().launch("LLViewerRegionImpl::requestSimulatorFeatureCoro", boost::bind(&LLViewerRegionImpl::requestSimulatorFeatureCoro, mImpl, url, getHandle())); - LL_INFOS("AppInit", "SimulatorFeatures") << "Launching " << coroname << " requesting simulator features from " << url << LL_ENDL; + LL_INFOS("AppInit", "SimulatorFeatures") << "Launching " << coroname << " requesting simulator features from " << url << " for region " << getRegionID() << LL_ENDL; } else { @@ -3255,7 +3256,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url) if (getCapability("Seed") == url) { setCapabilityDebug("Seed", url); - LL_WARNS("CrossingCaps") << "Received duplicate seed capability, posting to seed " << + LL_WARNS("CrossingCaps") << "Received duplicate seed capability for " << getRegionID() << ", posting to seed " << url << LL_ENDL; //Instead of just returning we build up a second set of seed caps and compare them @@ -3276,7 +3277,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url) LLCoros::instance().launch("LLViewerRegionImpl::requestBaseCapabilitiesCoro", boost::bind(&LLViewerRegionImpl::requestBaseCapabilitiesCoro, mImpl, getHandle())); - LL_INFOS("AppInit", "Capabilities") << "Launching " << coroname << " requesting seed capabilities from " << url << LL_ENDL; + LL_INFOS("AppInit", "Capabilities") << "Launching " << coroname << " requesting seed capabilities from " << url << " for region " << getRegionID() << LL_ENDL; } S32 LLViewerRegion::getNumSeedCapRetries() @@ -3598,3 +3599,12 @@ U32 LLViewerRegion::getMaxMaterialsPerTransaction() const return max_entries; } +std::string LLViewerRegion::getSimHostName() +{ + if (mSimulatorFeaturesReceived) + { + return mSimulatorFeatures.has("HostName") ? mSimulatorFeatures["HostName"].asString() : getHost().getHostName(); + } + return std::string("..."); +} + diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index db524663cd..9c1715d6aa 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -250,6 +250,7 @@ public: S32 getRegionMaxBakes() const { return mMaxBakes; } // FS BOM for OS max bakes restriction S32 getRegionMaxTEs() const { return mMaxTEs; } // FS BOM for OS max TEs restriction + void idleUpdate(F32 max_update_time); void lightIdleUpdate(); bool addVisibleGroup(LLViewerOctreeGroup* group); @@ -421,6 +422,8 @@ public: BOOL isPaused() const {return mPaused;} S32 getLastUpdate() const {return mLastUpdate;} + std::string getSimHostName(); + static BOOL isNewObjectCreationThrottleDisabled() {return sNewObjectCreationThrottle < 0;} private: diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index e46a572db0..a06f906762 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -60,6 +60,7 @@ #include "llviewernetwork.h" #include "llmeshrepository.h" //for LLMeshRepository::sBytesReceived #include "llsdserialize.h" +#include "llsdutil.h" #include "llcorehttputil.h" #include "llvoicevivox.h" @@ -431,7 +432,7 @@ void update_statistics() * If you move stats around here, make the corresponding changes in * those locations, too. */ -void send_stats() +void send_viewer_stats(bool include_preferences) { // IW 9/23/02 I elected not to move this into LLViewerStats // because it depends on too many viewer.cpp globals. @@ -519,6 +520,8 @@ void send_stats() system["gpu_version"] = gGLManager.mDriverVersionVendorString; system["opengl_version"] = gGLManager.mGLVersionString; + gGLManager.asLLSD(system["gl"]); + S32 shader_level = 0; if (LLPipeline::sRenderDeferred) { @@ -578,6 +581,7 @@ void send_stats() fail["failed_resends"] = (S32) gMessageSystem->mFailedResendPackets; fail["off_circuit"] = (S32) gMessageSystem->mOffCircuitPackets; fail["invalid"] = (S32) gMessageSystem->mInvalidOnCircuitPackets; + fail["missing_updater"] = (S32) LLAppViewer::instance()->isUpdaterMissing(); body["stats"]["voice"] = LLVoiceVivoxStats::getInstance()->read(); @@ -623,10 +627,25 @@ void send_stats() body["DisplayNamesEnabled"] = gSavedSettings.getBOOL("UseDisplayNames"); body["DisplayNamesShowUsername"] = gSavedSettings.getBOOL("NameTagShowUsernames"); - + + // Preferences + if (include_preferences) + { + bool diffs_only = true; // only log preferences that differ from default + body["preferences"]["settings"] = gSavedSettings.asLLSD(diffs_only); + body["preferences"]["settings_per_account"] = gSavedPerAccountSettings.asLLSD(diffs_only); + } + body["MinimalSkin"] = false; + LL_INFOS("LogViewerStatsPacket") << "Sending viewer statistics: " << body << LL_ENDL; + if (debugLoggingEnabled("LogViewerStatsPacket")) + { + std::string filename("viewer_stats_packet.xml"); + llofstream of(filename.c_str()); + LLSDSerialize::toPrettyXML(body,of); + } // The session ID token must never appear in logs body["session_id"] = gAgentSessionID; diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index f94b2f91da..efcb2fb566 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -299,7 +299,7 @@ static const F32 SEND_STATS_PERIOD = 300.0f; // The following are from (older?) statistics code found in appviewer. void update_statistics(); -void send_stats(); +void send_viewer_stats(bool include_preferences); extern LLFrameTimer gTextureTimer; extern U32Bytes gTotalTextureData; diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 2a1d4972bd..a6768dff49 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -184,7 +184,7 @@ BOOL LLViewerWearable::isOldVersion() const S32 te_count = 0; for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) + if (LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex) te) == mType) { te_count++; if( !is_in_map(mTEMap, te ) ) @@ -236,7 +236,7 @@ BOOL LLViewerWearable::isDirty() const 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 current_iter = mTEMap.find(te); if(current_iter != mTEMap.end()) @@ -284,7 +284,7 @@ void LLViewerWearable::setTexturesToDefaults() { for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) + if (LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex) te) == mType) { LLUUID id = getDefaultTextureImageID((ETextureIndex) te); LLViewerFetchedTexture * image = LLViewerTextureManager::getFetchedTexture( id ); @@ -308,7 +308,7 @@ void LLViewerWearable::setTexturesToDefaults() // virtual LLUUID LLViewerWearable::getDefaultTextureImageID(ETextureIndex index) const { - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearance::getDictionary()->getTexture(index); const std::string &default_image_name = texture_dict ? texture_dict->mDefaultImageName : ""; if (default_image_name == "") { @@ -339,7 +339,7 @@ void LLViewerWearable::writeToAvatar(LLAvatarAppearance *avatarp) // Pull texture entries 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 = mTEMap.find(te); LLUUID image_id; @@ -440,7 +440,7 @@ void LLViewerWearable::copyDataFrom(const LLViewerWearable* src) // Deep copy of mTEMap (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->mTEMap.find(te); LLUUID image_id; @@ -479,8 +479,7 @@ void LLViewerWearable::revertValues() { LLWearable::revertValues(); - - LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); + LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::findPanel("appearance")); if( panel ) { panel->updateScrollingPanelList(); @@ -496,7 +495,7 @@ void LLViewerWearable::saveValues() { LLWearable::saveValues(); - LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); + LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::findPanel("appearance")); if( panel ) { panel->updateScrollingPanelList(); diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 307e3f474f..d040980b62 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -138,7 +138,7 @@ private: }; -static const U32 MAX_SNAPSHOT_IMAGE_SIZE = 6 * 1024; // max snapshot image size 6144 * 6144 +static const U32 MAX_SNAPSHOT_IMAGE_SIZE = 7680; // max snapshot image size 7680 * 7680 UHDTV2 class LLViewerWindow : public LLWindowCallbacks { diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 4d552837de..9ea5cfef74 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -592,7 +592,6 @@ private: //----------------------------------------------------------------------------- // Static Data //----------------------------------------------------------------------------- -LLAvatarAppearanceDictionary *LLVOAvatar::sAvatarDictionary = NULL; S32 LLVOAvatar::sFreezeCounter = 0; U32 LLVOAvatar::sMaxNonImpostors = 12; // overridden based on graphics setting F32 LLVOAvatar::sRenderDistance = 256.f; @@ -1103,15 +1102,15 @@ void LLVOAvatar::dumpBakedStatus() { LL_CONT << " Unbaked ("; - for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator iter = LLAvatarAppearance::getDictionary()->getBakedTextures().begin(); + iter != LLAvatarAppearance::getDictionary()->getBakedTextures().end(); ++iter) { const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = iter->second; const ETextureIndex index = baked_dict->mTextureIndex; if (!inst->isTextureDefined(index)) { - LL_CONT << " " << (LLAvatarAppearanceDictionary::getInstance()->getTexture(index) ? LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mName : ""); + LL_CONT << " " << (LLAvatarAppearance::getDictionary()->getTexture(index) ? LLAvatarAppearance::getDictionary()->getTexture(index)->mName : ""); } } LL_CONT << " ) " << inst->getUnbakedPixelAreaRank(); @@ -5896,7 +5895,7 @@ void LLVOAvatar::collectLocalTextureUUIDs(std::set& ids) const { for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) { - LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)texture_index); + LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex)texture_index); U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); LLViewerFetchedTexture *imagep = NULL; @@ -5905,7 +5904,7 @@ void LLVOAvatar::collectLocalTextureUUIDs(std::set& ids) const imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE); if (imagep) { - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)texture_index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)texture_index); if (texture_dict && texture_dict->mIsLocalTexture) { ids.insert(imagep->getID()); @@ -6039,7 +6038,7 @@ void LLVOAvatar::updateTextures() mHasGrey = FALSE; // debug for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) { - LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)texture_index); + LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex)texture_index); U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); const LLTextureEntry *te = getTE(texture_index); @@ -6062,7 +6061,7 @@ void LLVOAvatar::updateTextures() imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE); if (imagep) { - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)texture_index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)texture_index); const EBakedTextureIndex baked_index = texture_dict ? texture_dict->mBakedTextureIndex : EBakedTextureIndex::BAKED_NUM_INDICES; if (texture_dict && texture_dict->mIsLocalTexture) { @@ -6255,7 +6254,7 @@ const std::string LLVOAvatar::getImageURL(const U8 te, const LLUUID &uuid) return url; } - const LLAvatarAppearanceDictionary::TextureEntry* texture_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te); + const LLAvatarAppearanceDictionary::TextureEntry* texture_entry = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)te); if (texture_entry != NULL) { url = appearance_service_url + "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString(); @@ -8462,12 +8461,12 @@ BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const // Gets called quite a lot from processObjectUpdates. Remove the frequent getInstance calls. - // for (LLAvatarAppearanceDictionary::Textures::const_iterator tex_iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); - // tex_iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); + // for (LLAvatarAppearanceDictionary::Textures::const_iterator tex_iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); + // tex_iter != LLAvatarAppearance::getDictionary()->getTextures().end(); // ++tex_iter) - LLAvatarAppearanceDictionary::Textures::const_iterator itrEnd = LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); - for (LLAvatarAppearanceDictionary::Textures::const_iterator tex_iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + LLAvatarAppearanceDictionary::Textures::const_iterator itrEnd = LLAvatarAppearance::getDictionary()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator tex_iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); tex_iter != itrEnd; ++tex_iter) { @@ -8481,7 +8480,7 @@ BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const if (texture_dict->mIsUsedByBakedTexture) { const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - return isTextureDefined(LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex); + return isTextureDefined(LLAvatarAppearance::getDictionary()->getBakedTexture(baked_index)->mTextureIndex); } return FALSE; } @@ -8904,7 +8903,7 @@ bool LLVOAvatar::isTooComplex() const // Performance improvement //bool render_friend = (LLAvatarTracker::instance().isBuddy(getID()) && gSavedSettings.getBOOL("AlwaysRenderFriends")); static LLCachedControl alwaysRenderFriends(gSavedSettings, "AlwaysRenderFriends"); - bool render_friend = (LLAvatarTracker::instance().isBuddy(getID()) && alwaysRenderFriends); + bool render_friend = ( alwaysRenderFriends && LLAvatarTracker::instance().isBuddy( getID() ) ); // Beq note: isBuddy can be slow only check if we have to // if (isSelf() || render_friend || mVisuallyMuteSetting == AV_ALWAYS_RENDER) @@ -9270,8 +9269,8 @@ void LLVOAvatar::updateMeshTextures() for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = - LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + LLAvatarAppearance::getDictionary()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearance::getDictionary()->getBakedTextures().end(); ++baked_iter) { const EBakedTextureIndex baked_index = baked_iter->first; @@ -9452,7 +9451,7 @@ void LLVOAvatar::releaseComponentTextures() for (U8 baked_index = 0; baked_index < getNumBakes(); baked_index++) // { - const LLAvatarAppearanceDictionary::BakedEntry * bakedDicEntry = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); + const LLAvatarAppearanceDictionary::BakedEntry * bakedDicEntry = LLAvatarAppearance::getDictionary()->getBakedTexture((EBakedTextureIndex)baked_index); // skip if this is a skirt and av is not wearing one, or if we don't have a baked texture UUID if (!isTextureDefined(bakedDicEntry->mTextureIndex) && ( (baked_index != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT) )) @@ -9471,8 +9470,8 @@ void LLVOAvatar::releaseComponentTextures() void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const { LL_DEBUGS("Avatar") << avString() << (isSelf() ? "Self: " : "Other: ") << context << LL_ENDL; - 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; @@ -10300,8 +10299,8 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture self->mBakedTextureDatas[BAKED_HEAD].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); maskData->mLastDiscardLevel = discard_level; */ BOOL found_texture_id = false; - 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) { @@ -10432,7 +10431,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) } const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = - LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + LLAvatarAppearance::getDictionary()->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) @@ -10582,7 +10581,7 @@ void LLVOAvatar::dumpArchetypeXMLCallback(const std::vector& filena for (U8 te = 0; te < TEX_NUM_INDICES; te++) { - if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) == type) + if (LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex)te) == type) { // MULTIPLE_WEARABLES: extend to multiple wearables? LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); @@ -11557,7 +11556,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() // { const LLAvatarAppearanceDictionary::BakedEntry *baked_dict - = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); + = LLAvatarAppearance::getDictionary()->getBakedTexture((EBakedTextureIndex)baked_index); ETextureIndex tex_index = baked_dict->mTextureIndex; if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT))) { @@ -11638,8 +11637,8 @@ void LLVOAvatar::calculateUpdateRenderComplexity() // } // // print any avatar textures we didn't already know about - // 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; @@ -11778,7 +11777,7 @@ BOOL LLVOAvatar::isIndexLocalTexture(ETextureIndex index) { return (index < 0 || index >= TEX_NUM_INDICES) ? false - : LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsLocalTexture; + : LLAvatarAppearance::getDictionary()->getTexture(index)->mIsLocalTexture; } // static @@ -11786,15 +11785,15 @@ BOOL LLVOAvatar::isIndexBakedTexture(ETextureIndex index) { return (index < 0 || index >= TEX_NUM_INDICES) ? false - : LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsBakedTexture; + : LLAvatarAppearance::getDictionary()->getTexture(index)->mIsBakedTexture; } const std::string LLVOAvatar::getBakedStatusForPrintout() const { std::string line; - 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 ETextureIndex index = iter->first; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 6dc1c0fecb..c0c6fd99fe 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -709,9 +709,6 @@ public: public: static BOOL isIndexLocalTexture(LLAvatarAppearanceDefines::ETextureIndex i); static BOOL isIndexBakedTexture(LLAvatarAppearanceDefines::ETextureIndex i); -private: - static const LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary *getDictionary() { return sAvatarDictionary; } - static LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* sAvatarDictionary; //-------------------------------------------------------------------- // Messaging diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index a583a517f0..3631c94815 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1511,8 +1511,8 @@ void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode) //void LLVOAvatarSelf::wearableUpdated(LLWearableType::EType type) void LLVOAvatarSelf::wearableUpdated(LLWearableType::EType type, BOOL upload_result) { - 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; @@ -1824,7 +1824,7 @@ BOOL LLVOAvatarSelf::detachAttachmentIntoInventory(const LLUUID &item_id) U32 LLVOAvatarSelf::getNumWearables(LLAvatarAppearanceDefines::ETextureIndex i) const { - LLWearableType::EType type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType(i); + LLWearableType::EType type = sAvatarDictionary->getTEWearableType(i); return gAgentWearables.getWearableCount(type); } @@ -1935,8 +1935,8 @@ BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLViewerTexLayerSet* laye { /* if (layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */ - 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 EBakedTextureIndex baked_index = baked_iter->first; @@ -1949,7 +1949,7 @@ BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLViewerTexLayerSet* laye ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { @@ -1983,13 +1983,13 @@ BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLViewerTexLayerSet* layerset { if (layerset == mBakedTextureDatas[i].mTexLayerSet) { - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = sAvatarDictionary->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { @@ -2020,13 +2020,13 @@ BOOL LLVOAvatarSelf::isAllLocalTextureDataFinal() const for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = sAvatarDictionary->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { @@ -2048,7 +2048,7 @@ BOOL LLVOAvatarSelf::isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex t BOOL isDefined = TRUE; if (isIndexLocalTexture(type)) { - const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(type); + const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(type); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); if (index >= wearable_count) { @@ -2283,7 +2283,7 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te LL_ERRS() << "Tried to set local texture with invalid type: (" << (U32) type << ", " << index << ")" << LL_ENDL; return; } - LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType(type); + LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(type); if (!gAgentWearables.getViewerWearable(wearable_type,index)) { // no wearable is loaded, cannot set the texture. @@ -2360,8 +2360,8 @@ void LLVOAvatarSelf::dumpLocalTextures() const /* ETextureIndex baked_equiv[] = { TEX_UPPER_BAKED, if (isTextureDefined(baked_equiv[i])) */ - for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = sAvatarDictionary->getTextures().begin(); + iter != sAvatarDictionary->getTextures().end(); ++iter) { const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; @@ -2369,7 +2369,7 @@ void LLVOAvatarSelf::dumpLocalTextures() const continue; const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - const ETextureIndex baked_equiv = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex; + const ETextureIndex baked_equiv = sAvatarDictionary->getBakedTexture(baked_index)->mTextureIndex; const std::string &name = texture_dict->mName; const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(iter->first, 0); @@ -2604,8 +2604,8 @@ const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLV { std::ostringstream outbuf; for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = - LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + sAvatarDictionary->getBakedTextures().begin(); + baked_iter != sAvatarDictionary->getBakedTextures().end(); ++baked_iter) { const EBakedTextureIndex baked_index = baked_iter->first; @@ -2618,9 +2618,9 @@ const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLV ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const std::string tex_name = LLAvatarAppearanceDictionary::getInstance()->getTexture(tex_index)->mName; + const std::string tex_name = sAvatarDictionary->getTexture(tex_index)->mName; outbuf << " tex_index " << (S32) tex_index << " name " << tex_name << "\n"; - const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); if (wearable_count > 0) { @@ -2664,8 +2664,8 @@ const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLV void LLVOAvatarSelf::dumpAllTextures() const { std::string vd_text = "Local textures per baked index and wearable:\n"; - for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = sAvatarDictionary->getBakedTextures().begin(); + baked_iter != sAvatarDictionary->getBakedTextures().end(); ++baked_iter) { const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; @@ -2686,8 +2686,8 @@ const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTe /* if (layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */ - 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 EBakedTextureIndex baked_index = baked_iter->first; @@ -2700,7 +2700,7 @@ const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTe ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); if (wearable_count > 0) { @@ -2727,14 +2727,14 @@ const std::string LLVOAvatarSelf::debugDumpAllLocalTextureDataInfo() const for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = sAvatarDictionary->getBakedTexture((EBakedTextureIndex)i); BOOL is_texture_final = TRUE; for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { @@ -2914,7 +2914,7 @@ const LLUUID& LLVOAvatarSelf::grabBakedTexture(EBakedTextureIndex baked_index) c { if (canGrabBakedTexture(baked_index)) { - ETextureIndex tex_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(baked_index); + ETextureIndex tex_index = sAvatarDictionary->bakedToLocalTextureIndex(baked_index); if (tex_index == TEX_NUM_INDICES) { return LLUUID::null; @@ -2926,7 +2926,7 @@ const LLUUID& LLVOAvatarSelf::grabBakedTexture(EBakedTextureIndex baked_index) c BOOL LLVOAvatarSelf::canGrabBakedTexture(EBakedTextureIndex baked_index) const { - ETextureIndex tex_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(baked_index); + ETextureIndex tex_index = sAvatarDictionary->bakedToLocalTextureIndex(baked_index); if (tex_index == TEX_NUM_INDICES) { return FALSE; @@ -2945,13 +2945,13 @@ BOOL LLVOAvatarSelf::canGrabBakedTexture(EBakedTextureIndex baked_index) const // baked texture. We don't want people copying people's // work via baked textures. - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = sAvatarDictionary->getBakedTexture(baked_index); for (texture_vec_t::const_iterator iter = baked_dict->mLocalTextures.begin(); iter != baked_dict->mLocalTextures.end(); ++iter) { const ETextureIndex t_index = (*iter); - LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(t_index); + LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(t_index); U32 count = gAgentWearables.getWearableCount(wearable_type); LL_DEBUGS() << "Checking index " << (U32) t_index << " count: " << count << LL_ENDL; @@ -3039,7 +3039,7 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLAvatarAppearanceDefines::ETextureIndex i, U32 wearable_index) const { - LLWearableType::EType type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType(i); + LLWearableType::EType type = sAvatarDictionary->getTEWearableType(i); LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, wearable_index); if (wearable) { @@ -3113,8 +3113,8 @@ void LLVOAvatarSelf::outputRezDiagnostics() const LL_DEBUGS("Avatar") << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << LL_ENDL; } - for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = sAvatarDictionary->getBakedTextures().begin(); + baked_iter != sAvatarDictionary->getBakedTextures().end(); ++baked_iter) { const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; @@ -3184,7 +3184,7 @@ void LLVOAvatarSelf::requestLayerSetUpdate(ETextureIndex index ) case LOCTEX_UPPER_SHIRT: if( mUpperBodyLayerSet ) mUpperBodyLayerSet->requestUpdate(); */ - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = sAvatarDictionary->getTexture(index); if (!texture_dict) return; if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) @@ -3202,7 +3202,7 @@ LLViewerTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const case TEX_HEAD_BAKED: case TEX_HEAD_BODYPAINT: return mHeadLayerSet; */ - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = sAvatarDictionary->getTexture(index); if (texture_dict && texture_dict->mIsUsedByBakedTexture) { const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; @@ -3300,8 +3300,8 @@ bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const { LLUUID texture_id[TEX_NUM_INDICES]; // pack away current TEs to make sure we don't send them out - for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = sAvatarDictionary->getTextures().begin(); + iter != sAvatarDictionary->getTextures().end(); ++iter) { const ETextureIndex index = iter->first; @@ -3354,8 +3354,8 @@ bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const bool success = packTEMessage(mesgsys); // unpack TEs to make sure we don't re-trigger a bake - for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = sAvatarDictionary->getTextures().begin(); + iter != sAvatarDictionary->getTextures().end(); ++iter) { const ETextureIndex index = iter->first; @@ -3613,7 +3613,7 @@ void LLVOAvatarSelf::checkForUnsupportedServerBakeAppearance() void LLVOAvatarSelf::setNewBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex i, const LLUUID &uuid) { - ETextureIndex index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(i); + ETextureIndex index = LLAvatarAppearance::getDictionary()->bakedToLocalTextureIndex(i); setNewBakedTexture(index, uuid); } @@ -3635,7 +3635,7 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) /* switch(te) case TEX_HEAD_BAKED: LL_INFOS() << "New baked texture: HEAD" << LL_ENDL; */ - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(te); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearance::getDictionary()->getTexture(te); if (texture_dict->mIsBakedTexture) { debugBakedTextureUpload(texture_dict->mBakedTextureIndex, TRUE); // FALSE for start of upload, TRUE for finish. @@ -3722,8 +3722,8 @@ void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**) /* ETextureIndex baked_texture_indices[BAKED_NUM_INDICES] = TEX_HEAD_BAKED, TEX_UPPER_BAKED, */ - 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 ETextureIndex index = iter->first; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index b3586612ea..14c9a90bc4 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -2532,7 +2532,8 @@ bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture) //setup new materials for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) { - mmgr.put(getID(), it->first, *it->second); // Factor out instance() calls + // These are placeholder materials, they shouldn't be sent to server + mmgr.setLocalMaterial(getRegion()->getRegionID(), it->second); // Factor out instance() calls LLViewerObject::setTEMaterialParams(it->first, it->second); } @@ -2560,7 +2561,7 @@ bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture) switch(range_it->second.map) { - case LLRender::DIFFUSE_MAP: + case LLRender::DIFFUSE_MAP: { if(LLMaterial::DIFFUSE_ALPHA_MODE_NONE != cur_material->getDiffuseAlphaMode()) { //missing texture + !LLMaterial::DIFFUSE_ALPHA_MODE_NONE => LLMaterial::DIFFUSE_ALPHA_MODE_NONE diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 18dccaea3a..8fa1f1f530 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -754,6 +754,7 @@ LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p) , mAttachmentsChangedCallbackConnection() // Better attachment list { setSortOrder(E_SORT_BY_TYPE_LAYER, false); + mMenuWearableType = LLWearableType::WT_NONE; mIsStandalone = p.standalone; if (mIsStandalone) { @@ -890,10 +891,15 @@ void LLWearableItemsList::onRightClick(S32 x, S32 y) getSelectedUUIDs(selected_uuids); if (selected_uuids.empty()) { - return; + if ((mMenuWearableType != LLWearableType::WT_NONE) && (size() == 0)) + { + ContextMenu::instance().show(this, mMenuWearableType, x, y); + } + } + else + { + ContextMenu::instance().show(this, selected_uuids, x, y); } - - ContextMenu::instance().show(this, selected_uuids, x, y); } void LLWearableItemsList::setSortOrder(ESortOrder sort_order, bool sort_now) @@ -982,6 +988,46 @@ void LLWearableItemsList::ContextMenu::show(LLView* spawning_view, const uuid_ve mParent = NULL; // to avoid dereferencing an invalid pointer } +void LLWearableItemsList::ContextMenu::show(LLView* spawning_view, LLWearableType::EType w_type, S32 x, S32 y) +{ + mParent = dynamic_cast(spawning_view); + LLContextMenu* menup = mMenuHandle.get(); + if (menup) + { + //preventing parent (menu holder) from deleting already "dead" context menus on exit + LLView* parent = menup->getParent(); + if (parent) + { + parent->removeChild(menup); + } + delete menup; + mUUIDs.clear(); + } + + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + registrar.add("Wearable.CreateNew", boost::bind(createNewWearableByType, w_type)); + menup = createFromFile("menu_wearable_list_item.xml"); + if (!menup) + { + LL_WARNS() << "Context menu creation failed" << LL_ENDL; + return; + } + setMenuItemVisible(menup, "create_new", true); + setMenuItemEnabled(menup, "create_new", true); + setMenuItemVisible(menup, "wearable_attach_to", false); + setMenuItemVisible(menup, "wearable_attach_to_hud", false); + + std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getTypeName(w_type)); + LLMenuItemGL* menu_item = menup->getChild("create_new"); + menu_item->setLabel(new_label); + + mMenuHandle = menup->getHandle(); + menup->show(x, y); + LLMenuGL::showPopup(spawning_view, menup, x, y); + + mParent = NULL; // to avoid dereferencing an invalid pointer +} + // virtual LLContextMenu* LLWearableItemsList::ContextMenu::createMenu() { @@ -1262,4 +1308,10 @@ void LLWearableItemsList::ContextMenu::createNewWearable(const LLUUID& item_id) LLAgentWearables::createWearable(item->getWearableType(), true); } +// static +void LLWearableItemsList::ContextMenu::createNewWearableByType(LLWearableType::EType type) +{ + LLAgentWearables::createWearable(type, true); +} + // EOF diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index c3a156b542..4b0a70f252 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -452,6 +452,8 @@ public: public: /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); + void show(LLView* spawning_view, LLWearableType::EType w_type, S32 x, S32 y); + protected: enum { MASK_CLOTHING = 0x01, @@ -468,6 +470,7 @@ public: static void setMenuItemEnabled(LLContextMenu* menu, const std::string& name, bool val); static void updateMask(U32& mask, LLAssetType::EType at); static void createNewWearable(const LLUUID& item_id); + static void createNewWearableByType(LLWearableType::EType type); LLWearableItemsList* mParent; }; @@ -511,6 +514,8 @@ public: void setSortOrder(ESortOrder sort_order, bool sort_now = true); + void setMenuWearableType(LLWearableType::EType type) { mMenuWearableType = type; } + bool showCreateNew() const { return mShowCreateNew; } // Optional "Create new" menu item void updateItemComplexity(const std::map& item_complexity, U32 body_parts_complexity); // Show per-item complexity in COF @@ -528,6 +533,8 @@ protected: ESortOrder mSortOrder; + LLWearableType::EType mMenuWearableType; + // Show per-item complexity in COF void updateComplexity(); diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp index 6b8374fd48..730aa3774f 100644 --- a/indra/newview/llwlhandlers.cpp +++ b/indra/newview/llwlhandlers.cpp @@ -51,7 +51,7 @@ bool LLEnvironmentRequest::initiate(LLEnvironment::environment_apply_fn cb) if (!cur_region->capabilitiesReceived()) { LL_INFOS("WindlightCaps") << "Deferring windlight settings request until we've got region caps" << LL_ENDL; - cur_region->setCapabilitiesReceivedCallback([cb](LLUUID region_id) { LLEnvironmentRequest::onRegionCapsReceived(region_id, cb); }); + cur_region->setCapabilitiesReceivedCallback([cb](const LLUUID ®ion_id) { LLEnvironmentRequest::onRegionCapsReceived(region_id, cb); }); return false; } diff --git a/indra/newview/quickprefs.cpp b/indra/newview/quickprefs.cpp index 81570ce6e7..b9d272ec4f 100644 --- a/indra/newview/quickprefs.cpp +++ b/indra/newview/quickprefs.cpp @@ -61,12 +61,17 @@ class FSSettingsCollector : public LLInventoryCollectFunctor { public: - FSSettingsCollector() {} + FSSettingsCollector() + { + mMarketplaceFolderUUID = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + } + virtual ~FSSettingsCollector() {} bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) { if (item && item->getType() == LLAssetType::AT_SETTINGS && + !gInventory.isObjectDescendentOf(item->getUUID(), mMarketplaceFolderUUID) && mSeen.find(item->getAssetUUID()) == mSeen.end()) { mSeen.insert(item->getAssetUUID()); @@ -79,6 +84,7 @@ public: } protected: + LLUUID mMarketplaceFolderUUID; std::set mSeen; }; diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index 4323cdcd17..eb32856565 100755 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -160,7 +160,7 @@ BEGIN VALUE "FileDescription", "Firestorm" VALUE "FileVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}" VALUE "InternalName", "Firestorm" - VALUE "LegalCopyright", "Copyright \251 2010-2020, The Phoenix Firestorm Project, Inc." + VALUE "LegalCopyright", "Copyright \251 2010-2021, The Phoenix Firestorm Project, Inc." VALUE "OriginalFilename", "Firestorm.exe" VALUE "ProductName", "Firestorm" VALUE "ProductVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}" diff --git a/indra/newview/skins/ansastorm/textures/bottomtray/Cam_Rotate_In.png b/indra/newview/skins/ansastorm/textures/bottomtray/Cam_Rotate_In.png new file mode 100644 index 0000000000..afcfbf6071 Binary files /dev/null and b/indra/newview/skins/ansastorm/textures/bottomtray/Cam_Rotate_In.png differ diff --git a/indra/newview/skins/ansastorm/textures/bottomtray/Cam_Tracking_In.png b/indra/newview/skins/ansastorm/textures/bottomtray/Cam_Tracking_In.png new file mode 100644 index 0000000000..1df98a8f29 Binary files /dev/null and b/indra/newview/skins/ansastorm/textures/bottomtray/Cam_Tracking_In.png differ diff --git a/indra/newview/skins/ansastorm/themes/blood/textures/bottomtray/Cam_Rotate_In.png b/indra/newview/skins/ansastorm/themes/blood/textures/bottomtray/Cam_Rotate_In.png new file mode 100644 index 0000000000..6b37e0db87 Binary files /dev/null and b/indra/newview/skins/ansastorm/themes/blood/textures/bottomtray/Cam_Rotate_In.png differ diff --git a/indra/newview/skins/ansastorm/themes/blood/textures/bottomtray/Cam_Tracking_In.png b/indra/newview/skins/ansastorm/themes/blood/textures/bottomtray/Cam_Tracking_In.png new file mode 100644 index 0000000000..e1ce710bf6 Binary files /dev/null and b/indra/newview/skins/ansastorm/themes/blood/textures/bottomtray/Cam_Tracking_In.png differ diff --git a/indra/newview/skins/ansastorm/themes/classic_brown/textures/bottomtray/Cam_Rotate_In.png b/indra/newview/skins/ansastorm/themes/classic_brown/textures/bottomtray/Cam_Rotate_In.png new file mode 100644 index 0000000000..e734d4a3bf Binary files /dev/null and b/indra/newview/skins/ansastorm/themes/classic_brown/textures/bottomtray/Cam_Rotate_In.png differ diff --git a/indra/newview/skins/ansastorm/themes/classic_brown/textures/bottomtray/Cam_Tracking_In.png b/indra/newview/skins/ansastorm/themes/classic_brown/textures/bottomtray/Cam_Tracking_In.png new file mode 100644 index 0000000000..873702f8bf Binary files /dev/null and b/indra/newview/skins/ansastorm/themes/classic_brown/textures/bottomtray/Cam_Tracking_In.png differ diff --git a/indra/newview/skins/ansastorm/themes/ectoplasma/textures/bottomtray/Cam_Rotate_In.png b/indra/newview/skins/ansastorm/themes/ectoplasma/textures/bottomtray/Cam_Rotate_In.png new file mode 100644 index 0000000000..be2bb347bc Binary files /dev/null and b/indra/newview/skins/ansastorm/themes/ectoplasma/textures/bottomtray/Cam_Rotate_In.png differ diff --git a/indra/newview/skins/ansastorm/themes/ectoplasma/textures/bottomtray/Cam_Tracking_In.png b/indra/newview/skins/ansastorm/themes/ectoplasma/textures/bottomtray/Cam_Tracking_In.png new file mode 100644 index 0000000000..c95c076362 Binary files /dev/null and b/indra/newview/skins/ansastorm/themes/ectoplasma/textures/bottomtray/Cam_Tracking_In.png differ diff --git a/indra/newview/skins/ansastorm/xui/de/panel_main_inventory.xml b/indra/newview/skins/ansastorm/xui/de/panel_main_inventory.xml index 1d4f0f4af8..3f627a0015 100644 --- a/indra/newview/skins/ansastorm/xui/de/panel_main_inventory.xml +++ b/indra/newview/skins/ansastorm/xui/de/panel_main_inventory.xml @@ -93,7 +93,8 @@ - + + diff --git a/indra/newview/skins/ansastorm/xui/en/floater_camera.xml b/indra/newview/skins/ansastorm/xui/en/floater_camera.xml index cc5f62062f..1a8e1977cc 100644 --- a/indra/newview/skins/ansastorm/xui/en/floater_camera.xml +++ b/indra/newview/skins/ansastorm/xui/en/floater_camera.xml @@ -170,7 +170,6 @@ left_pad="2"> diff --git a/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml b/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml index 7ff5a56a21..5aab15c2da 100644 --- a/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml @@ -523,6 +523,7 @@ + diff --git a/indra/newview/skins/ansastorm/xui/pl/panel_main_inventory.xml b/indra/newview/skins/ansastorm/xui/pl/panel_main_inventory.xml index a68437d9c1..5194cc65b2 100644 --- a/indra/newview/skins/ansastorm/xui/pl/panel_main_inventory.xml +++ b/indra/newview/skins/ansastorm/xui/pl/panel_main_inventory.xml @@ -92,6 +92,7 @@ + diff --git a/indra/newview/skins/ansastorm/xui/ru/panel_main_inventory.xml b/indra/newview/skins/ansastorm/xui/ru/panel_main_inventory.xml index 56df130050..ea0a4c56e2 100644 --- a/indra/newview/skins/ansastorm/xui/ru/panel_main_inventory.xml +++ b/indra/newview/skins/ansastorm/xui/ru/panel_main_inventory.xml @@ -89,6 +89,7 @@ + diff --git a/indra/newview/skins/default/xui/de/floater_fs_camera_small.xml b/indra/newview/skins/default/xui/de/floater_fs_camera_small.xml new file mode 100644 index 0000000000..6751954dee --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_fs_camera_small.xml @@ -0,0 +1,57 @@ + + + + Kamera um Fokus drehen + + + Kamera auf Fokus zoomen + + + Kamera nach oben, unten, links und rechts bewegen + + + Objekt ansehen + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/de/floater_joystick.xml b/indra/newview/skins/default/xui/de/floater_joystick.xml index cc2703a339..e1883f0af1 100644 --- a/indra/newview/skins/default/xui/de/floater_joystick.xml +++ b/indra/newview/skins/default/xui/de/floater_joystick.xml @@ -1,7 +1,11 @@ - - + + Keiner + + + Joystick: + @@ -74,7 +78,4 @@ - - Kein Gerät erkannt - diff --git a/indra/newview/skins/default/xui/de/floater_tools.xml b/indra/newview/skins/default/xui/de/floater_tools.xml index ec65f42ebb..87cd62e168 100644 --- a/indra/newview/skins/default/xui/de/floater_tools.xml +++ b/indra/newview/skins/default/xui/de/floater_tools.xml @@ -513,7 +513,7 @@ Ndrg ↔ Nst + + + + + + + + + + + + + + + + + + + + + + + "" + + + + + + + + + + "" + + + + + + + + + + "" + + + + + + + + + + + + + "" + + + + + + + + + + "" + + + + + + + + + + "" + + + + diff --git a/indra/newview/skins/default/xui/en/floater_joystick.xml b/indra/newview/skins/default/xui/en/floater_joystick.xml index 5fdabc26a1..64cae4f4d7 100644 --- a/indra/newview/skins/default/xui/en/floater_joystick.xml +++ b/indra/newview/skins/default/xui/en/floater_joystick.xml @@ -8,27 +8,32 @@ title="Joystick Configuration" width="569"> - no device detected + name="JoystickDisabled"> + None - + follows="left|top" + halign="left" + height="12" + top="22" + left="14" + width="50" + mouse_opaque="false" + name="joystick_lbl"> + Joystick: + + Control Modes: + name="btn_reset_scripts" + width="90" /> - + @@ -431,11 +431,9 @@ label="Camera Controls" name="Camera Controls"> + function="View.CheckCameraFloater" /> + function="View.ToggleCameraFloater" /> @@ -1318,7 +1316,38 @@ function="RLV.EnableIfNot" parameter="setenv" /> - + + + + + + + + + + + + + + + @@ -13593,5 +13597,19 @@ No valid environment setting selected. Please note that "Shared Environment" and "Day cycle based" cannot be selected! fail - + + + fail +Cannot create inventory item: [NAME] + + + +Bulk import of Windlights has finished. + 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 5efda8ef4f..c6472279a2 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -87,6 +87,7 @@ + diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml index 4bbe189c45..aa6540a5f6 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -324,6 +324,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap name="folder_view" top_pad="0" width="313" + preinitialize_views="false" visible="false"/> + Picture for Outfit (Unknown script) L$[COST] + + Importing Windlights... diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_list.xml b/indra/newview/skins/default/xui/en/widgets/scroll_list.xml index e43989c6c7..89418ca132 100644 --- a/indra/newview/skins/default/xui/en/widgets/scroll_list.xml +++ b/indra/newview/skins/default/xui/en/widgets/scroll_list.xml @@ -13,7 +13,7 @@ draw_stripes="true" scroll_bar_bg_visible="false" scroll_bar_bg_color="black" - mouse_wheel_opaque="false" + mouse_wheel_opaque="true" mouse_opaque="true" background_visible="true" heading_height="23" diff --git a/indra/newview/skins/default/xui/es/floater_tools.xml b/indra/newview/skins/default/xui/es/floater_tools.xml index a7c02cc342..563c4c7bc6 100644 --- a/indra/newview/skins/default/xui/es/floater_tools.xml +++ b/indra/newview/skins/default/xui/es/floater_tools.xml @@ -468,7 +468,7 @@