diff options
53 files changed, 883 insertions, 479 deletions
diff --git a/autobuild.xml b/autobuild.xml index a8203bb643..3e1bd522de 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -580,9 +580,9 @@ <key>archive</key> <map> <key>hash</key> - <string>cc26af2ebfa241891caca829a6e46b88</string> + <string>b50d355c1c7088cafe5e12d31f1fb07f</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65005/607316/dullahan-1.7.0.202008031101_81.3.10_gb223419_chromium-81.0.4044.138-darwin64-546064.tar.bz2</string> + <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72181/697551/dullahan-1.7.0.202011111255_81.3.10_gb223419_chromium-81.0.4044.138-darwin64-552103.tar.bz2</string> </map> <key>name</key> <string>darwin64</string> @@ -592,9 +592,9 @@ <key>archive</key> <map> <key>hash</key> - <string>4e5b9e2fe65d94e30a4f3d831c767199</string> + <string>0a52a79ad9a182529f7856f78bf4a96f</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65004/607304/dullahan-1.7.0.202008031759_81.3.10_gb223419_chromium-81.0.4044.138-windows-546064.tar.bz2</string> + <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72199/697588/dullahan-1.7.0.202011112115_81.3.10_gb223419_chromium-81.0.4044.138-windows-552103.tar.bz2</string> </map> <key>name</key> <string>windows</string> @@ -604,16 +604,16 @@ <key>archive</key> <map> <key>hash</key> - <string>6f7bf7f915f3d75dbdad08a2d41ca74e</string> + <string>715fe1bad3ba216508648b5763ea0404</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65003/607308/dullahan-1.7.0.202008031800_81.3.10_gb223419_chromium-81.0.4044.138-windows64-546064.tar.bz2</string> + <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72196/697581/dullahan-1.7.0.202011112112_81.3.10_gb223419_chromium-81.0.4044.138-windows64-552103.tar.bz2</string> </map> <key>name</key> <string>windows64</string> </map> </map> <key>version</key> - <string>1.7.0.202008031800_81.3.10_gb223419_chromium-81.0.4044.138</string> + <string>1.7.0.202011112112_81.3.10_gb223419_chromium-81.0.4044.138</string> </map> <key>elfio</key> <map> diff --git a/doc/contributions.txt b/doc/contributions.txt index bbdfaf655d..ed470c7ae8 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -1352,7 +1352,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/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp index af8394b60c..fb0d12f0af 100644 --- a/indra/llappearance/llviewervisualparam.cpp +++ b/indra/llappearance/llviewervisualparam.cpp @@ -70,7 +70,7 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node) static LLStdStringHandle wearable_string = LLXmlTree::addAttributeString("wearable"); if( node->getFastAttributeString( wearable_string, wearable) ) { - mWearableType = LLWearableType::typeNameToType( wearable ); + mWearableType = LLWearableType::getInstance()->typeNameToType( wearable ); } static LLStdStringHandle edit_group_string = LLXmlTree::addAttributeString("edit_group"); diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index 6079913a8e..e8df3d19f6 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -73,17 +73,17 @@ LLWearable::~LLWearable() const std::string& LLWearable::getTypeLabel() const { - return LLWearableType::getTypeLabel(mType); + return LLWearableType::getInstance()->getTypeLabel(mType); } const std::string& LLWearable::getTypeName() const { - return LLWearableType::getTypeName(mType); + return LLWearableType::getInstance()->getTypeName(mType); } LLAssetType::EType LLWearable::getAssetType() const { - return LLWearableType::getAssetType(mType); + return LLWearableType::getInstance()->getAssetType(mType); } BOOL LLWearable::exportFile(const std::string& filename) const diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp index 2bf3b9085b..9cc65dc2ce 100644 --- a/indra/llappearance/llwearabledata.cpp +++ b/indra/llappearance/llwearabledata.cpp @@ -231,10 +231,11 @@ BOOL LLWearableData::getWearableIndex(const LLWearable *wearable, U32& index_fou U32 LLWearableData::getClothingLayerCount() const { U32 count = 0; + LLWearableType *wr_inst = LLWearableType::getInstance(); for (S32 i = 0; i < LLWearableType::WT_COUNT; i++) { LLWearableType::EType type = (LLWearableType::EType)i; - if (LLWearableType::getAssetType(type)==LLAssetType::AT_CLOTHING) + if (wr_inst->getAssetType(type)==LLAssetType::AT_CLOTHING) { count += getWearableCount(type); } @@ -244,7 +245,7 @@ U32 LLWearableData::getClothingLayerCount() const BOOL LLWearableData::canAddWearable(const LLWearableType::EType type) const { - LLAssetType::EType a_type = LLWearableType::getAssetType(type); + LLAssetType::EType a_type = LLWearableType::getInstance()->getAssetType(type); if (a_type==LLAssetType::AT_CLOTHING) { return (getClothingLayerCount() < MAX_CLOTHING_LAYERS); diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp index 281060d01d..4ac611b1de 100644 --- a/indra/llappearance/llwearabletype.cpp +++ b/indra/llappearance/llwearabletype.cpp @@ -30,153 +30,98 @@ #include "llinventorydefines.h" -struct WearableEntry : public LLDictionaryEntry +LLWearableType::LLWearableDictionary::LLWearableDictionary(LLTranslationBridge::ptr_t& trans) { - WearableEntry(LLWearableType& wtype, - const std::string &name, - const std::string& default_new_name, - LLAssetType::EType assetType, - LLInventoryType::EIconName iconName, - BOOL disable_camera_switch = FALSE, - BOOL allow_multiwear = TRUE) : - LLDictionaryEntry(name), - mAssetType(assetType), - mDefaultNewName(default_new_name), - mLabel(wtype.mTrans->getString(name)), - mIconName(iconName), - mDisableCameraSwitch(disable_camera_switch), - mAllowMultiwear(allow_multiwear) - { - - } - const LLAssetType::EType mAssetType; - const std::string mLabel; - const std::string mDefaultNewName; //keep mLabel for backward compatibility - LLInventoryType::EIconName mIconName; - BOOL mDisableCameraSwitch; - BOOL mAllowMultiwear; -}; - -class LLWearableDictionary : public LLParamSingleton<LLWearableDictionary>, - public LLDictionary<LLWearableType::EType, WearableEntry> -{ - LLSINGLETON(LLWearableDictionary, LLWearableType&); -}; - -LLWearableDictionary::LLWearableDictionary(LLWearableType& wtype) -{ - addEntry(LLWearableType::WT_SHAPE, new WearableEntry(wtype, "shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SHAPE, FALSE, FALSE)); - addEntry(LLWearableType::WT_SKIN, new WearableEntry(wtype, "skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SKIN, FALSE, FALSE)); - addEntry(LLWearableType::WT_HAIR, new WearableEntry(wtype, "hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_HAIR, FALSE, FALSE)); - addEntry(LLWearableType::WT_EYES, new WearableEntry(wtype, "eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_EYES, FALSE, FALSE)); - addEntry(LLWearableType::WT_SHIRT, new WearableEntry(wtype, "shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_PANTS, new WearableEntry(wtype, "pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PANTS, FALSE, TRUE)); - addEntry(LLWearableType::WT_SHOES, new WearableEntry(wtype, "shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHOES, FALSE, TRUE)); - addEntry(LLWearableType::WT_SOCKS, new WearableEntry(wtype, "socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE)); - addEntry(LLWearableType::WT_JACKET, new WearableEntry(wtype, "jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_JACKET, FALSE, TRUE)); - addEntry(LLWearableType::WT_GLOVES, new WearableEntry(wtype, "gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE)); - addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry(wtype, "undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry(wtype, "underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE)); - addEntry(LLWearableType::WT_SKIRT, new WearableEntry(wtype, "skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_ALPHA, new WearableEntry(wtype, "alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE)); - addEntry(LLWearableType::WT_TATTOO, new WearableEntry(wtype, "tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE)); - addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(wtype, "universal", "New Universal", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNIVERSAL, FALSE, TRUE)); - - addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(wtype, "physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE)); - - addEntry(LLWearableType::WT_INVALID, new WearableEntry(wtype, "invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_UNKNOWN, FALSE, FALSE)); - addEntry(LLWearableType::WT_NONE, new WearableEntry(wtype, "none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE)); + addEntry(LLWearableType::WT_SHAPE, new WearableEntry(trans, "shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SHAPE, FALSE, FALSE)); + addEntry(LLWearableType::WT_SKIN, new WearableEntry(trans, "skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SKIN, FALSE, FALSE)); + addEntry(LLWearableType::WT_HAIR, new WearableEntry(trans, "hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_HAIR, FALSE, FALSE)); + addEntry(LLWearableType::WT_EYES, new WearableEntry(trans, "eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_EYES, FALSE, FALSE)); + addEntry(LLWearableType::WT_SHIRT, new WearableEntry(trans, "shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE)); + addEntry(LLWearableType::WT_PANTS, new WearableEntry(trans, "pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PANTS, FALSE, TRUE)); + addEntry(LLWearableType::WT_SHOES, new WearableEntry(trans, "shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHOES, FALSE, TRUE)); + addEntry(LLWearableType::WT_SOCKS, new WearableEntry(trans, "socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE)); + addEntry(LLWearableType::WT_JACKET, new WearableEntry(trans, "jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_JACKET, FALSE, TRUE)); + addEntry(LLWearableType::WT_GLOVES, new WearableEntry(trans, "gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE)); + addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry(trans, "undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE)); + addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry(trans, "underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE)); + addEntry(LLWearableType::WT_SKIRT, new WearableEntry(trans, "skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE)); + addEntry(LLWearableType::WT_ALPHA, new WearableEntry(trans, "alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE)); + addEntry(LLWearableType::WT_TATTOO, new WearableEntry(trans, "tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE)); + addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(trans, "universal", "New Universal", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNIVERSAL, FALSE, TRUE)); + + addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(trans, "physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE)); + + addEntry(LLWearableType::WT_INVALID, new WearableEntry(trans, "invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_UNKNOWN, FALSE, FALSE)); + addEntry(LLWearableType::WT_NONE, new WearableEntry(trans, "none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE)); } // class LLWearableType -LLWearableType::LLWearableType(LLTranslationBridge* trans) +LLWearableType::LLWearableType(LLTranslationBridge::ptr_t &trans) +: mDictionary(trans) { - // LLTranslationBridge exists, but is not ready at this point in time since strings.xml is not yet loaded - mTrans = trans; } LLWearableType::~LLWearableType() { - delete mTrans; } void LLWearableType::initSingleton() { - // To make sure all wrapping functions will crash without initing LLWearableType; - LLWearableDictionary::initParamSingleton(*this); - - // Todo: consider merging LLWearableType and LLWearableDictionary } -// static LLWearableType::EType LLWearableType::typeNameToType(const std::string& type_name) { - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const LLWearableType::EType wearable = dict->lookup(type_name); + const LLWearableType::EType wearable = mDictionary.lookup(type_name); return wearable; } -// static const std::string& LLWearableType::getTypeName(LLWearableType::EType type) { - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const WearableEntry *entry = dict->lookup(type); + const WearableEntry *entry = mDictionary.lookup(type); if (!entry) return getTypeName(WT_INVALID); return entry->mName; } -//static const std::string& LLWearableType::getTypeDefaultNewName(LLWearableType::EType type) { - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const WearableEntry *entry = dict->lookup(type); + const WearableEntry *entry = mDictionary.lookup(type); if (!entry) return getTypeDefaultNewName(WT_INVALID); return entry->mDefaultNewName; } -// static const std::string& LLWearableType::getTypeLabel(LLWearableType::EType type) { - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const WearableEntry *entry = dict->lookup(type); + const WearableEntry *entry = mDictionary.lookup(type); if (!entry) return getTypeLabel(WT_INVALID); return entry->mLabel; } -// static LLAssetType::EType LLWearableType::getAssetType(LLWearableType::EType type) { - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const WearableEntry *entry = dict->lookup(type); + const WearableEntry *entry = mDictionary.lookup(type); if (!entry) return getAssetType(WT_INVALID); return entry->mAssetType; } -// static LLInventoryType::EIconName LLWearableType::getIconName(LLWearableType::EType type) { - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const WearableEntry *entry = dict->lookup(type); + const WearableEntry *entry = mDictionary.lookup(type); if (!entry) return getIconName(WT_INVALID); return entry->mIconName; } -// static BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type) { - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const WearableEntry *entry = dict->lookup(type); + const WearableEntry *entry = mDictionary.lookup(type); if (!entry) return FALSE; return entry->mDisableCameraSwitch; } -// static BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type) { - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const WearableEntry *entry = dict->lookup(type); + const WearableEntry *entry = mDictionary.lookup(type); if (!entry) return FALSE; return entry->mAllowMultiwear; } diff --git a/indra/llappearance/llwearabletype.h b/indra/llappearance/llwearabletype.h index 57f3ef160d..c83f03e621 100644 --- a/indra/llappearance/llwearabletype.h +++ b/indra/llappearance/llwearabletype.h @@ -35,10 +35,9 @@ class LLWearableType : public LLParamSingleton<LLWearableType> { - LLSINGLETON(LLWearableType, LLTranslationBridge* trans); + LLSINGLETON(LLWearableType, LLTranslationBridge::ptr_t &trans); ~LLWearableType(); void initSingleton(); - friend struct WearableEntry; public: enum EType { @@ -67,20 +66,53 @@ public: // Most methods are wrappers for dictionary, but if LLWearableType is not initialized, // they will crash. Whole LLWearableType is just wrapper for convinient calls. - static const std::string& getTypeName(EType type); - static const std::string& getTypeDefaultNewName(EType type); - static const std::string& getTypeLabel(EType type); - static LLAssetType::EType getAssetType(EType type); - static EType typeNameToType(const std::string& type_name); - static LLInventoryType::EIconName getIconName(EType type); - static BOOL getDisableCameraSwitch(EType type); - static BOOL getAllowMultiwear(EType type); + const std::string& getTypeName(EType type); + const std::string& getTypeDefaultNewName(EType type); + const std::string& getTypeLabel(EType type); + LLAssetType::EType getAssetType(EType type); + EType typeNameToType(const std::string& type_name); + LLInventoryType::EIconName getIconName(EType type); + BOOL getDisableCameraSwitch(EType type); + BOOL getAllowMultiwear(EType type); static EType inventoryFlagsToWearableType(U32 flags); -protected: +private: + struct WearableEntry : public LLDictionaryEntry + { + WearableEntry(LLTranslationBridge::ptr_t& trans, + const std::string &name, + const std::string& default_new_name, + LLAssetType::EType assetType, + LLInventoryType::EIconName iconName, + BOOL disable_camera_switch = FALSE, + BOOL allow_multiwear = TRUE) : + LLDictionaryEntry(name), + mAssetType(assetType), + mDefaultNewName(default_new_name), + mLabel(trans->getString(name)), + mIconName(iconName), + mDisableCameraSwitch(disable_camera_switch), + mAllowMultiwear(allow_multiwear) + { - LLTranslationBridge* mTrans; + } + const LLAssetType::EType mAssetType; + const std::string mLabel; + const std::string mDefaultNewName; //keep mLabel for backward compatibility + LLInventoryType::EIconName mIconName; + BOOL mDisableCameraSwitch; + BOOL mAllowMultiwear; + }; + + class LLWearableDictionary : public LLDictionary<LLWearableType::EType, WearableEntry> + { + public: + LLWearableDictionary(LLTranslationBridge::ptr_t& trans); + ~LLWearableDictionary() {} + }; + + LLWearableDictionary mDictionary; }; #endif // LL_LLWEARABLETYPE_H diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index f876b8ee4a..781c41f3de 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -435,6 +435,60 @@ namespace typedef std::vector<LLError::RecorderPtr> Recorders; typedef std::vector<LLError::CallSite*> CallSiteVector; + class SettingsConfig : public LLRefCount + { + friend class Globals; + + public: + virtual ~SettingsConfig(); + + LLError::ELevel mDefaultLevel; + + bool mLogAlwaysFlush; + + U32 mEnabledLogTypesMask; + + LevelMap mFunctionLevelMap; + LevelMap mClassLevelMap; + LevelMap mFileLevelMap; + LevelMap mTagLevelMap; + std::map<std::string, unsigned int> mUniqueLogMessages; + + LLError::FatalFunction mCrashFunction; + LLError::TimeFunction mTimeFunction; + + Recorders mRecorders; + + int mShouldLogCallCounter; + + private: + SettingsConfig(); + }; + + typedef LLPointer<SettingsConfig> SettingsConfigPtr; + + SettingsConfig::SettingsConfig() + : LLRefCount(), + mDefaultLevel(LLError::LEVEL_DEBUG), + mLogAlwaysFlush(true), + mEnabledLogTypesMask(255), + mFunctionLevelMap(), + mClassLevelMap(), + mFileLevelMap(), + mTagLevelMap(), + mUniqueLogMessages(), + mCrashFunction(NULL), + mTimeFunction(NULL), + mRecorders(), + mShouldLogCallCounter(0) + { + } + + SettingsConfig::~SettingsConfig() + { + mRecorders.clear(); + } + class Globals { public: @@ -449,14 +503,21 @@ namespace void addCallSite(LLError::CallSite&); void invalidateCallSites(); + SettingsConfigPtr getSettingsConfig(); + + void resetSettingsConfig(); + LLError::SettingsStoragePtr saveAndResetSettingsConfig(); + void restore(LLError::SettingsStoragePtr pSettingsStorage); private: CallSiteVector callSites; + SettingsConfigPtr mSettingsConfig; }; Globals::Globals() : messageStream(), messageStreamInUse(false), - callSites() + callSites(), + mSettingsConfig(new SettingsConfig()) { } @@ -486,120 +547,31 @@ namespace callSites.clear(); } -} - -namespace LLError -{ - class SettingsConfig : public LLRefCount - { - friend class Settings; - - public: - virtual ~SettingsConfig(); - - LLError::ELevel mDefaultLevel; - - bool mLogAlwaysFlush; - - U32 mEnabledLogTypesMask; - - LevelMap mFunctionLevelMap; - LevelMap mClassLevelMap; - LevelMap mFileLevelMap; - LevelMap mTagLevelMap; - std::map<std::string, unsigned int> mUniqueLogMessages; - - LLError::FatalFunction mCrashFunction; - LLError::TimeFunction mTimeFunction; - - Recorders mRecorders; - - int mShouldLogCallCounter; - - private: - SettingsConfig(); - }; - - typedef LLPointer<SettingsConfig> SettingsConfigPtr; - - class Settings - { - public: - static Settings* getInstance(); - protected: - Settings(); - public: - SettingsConfigPtr getSettingsConfig(); - - void reset(); - SettingsStoragePtr saveAndReset(); - void restore(SettingsStoragePtr pSettingsStorage); - - private: - SettingsConfigPtr mSettingsConfig; - }; - - SettingsConfig::SettingsConfig() - : LLRefCount(), - mDefaultLevel(LLError::LEVEL_DEBUG), - mLogAlwaysFlush(true), - mEnabledLogTypesMask(255), - mFunctionLevelMap(), - mClassLevelMap(), - mFileLevelMap(), - mTagLevelMap(), - mUniqueLogMessages(), - mCrashFunction(NULL), - mTimeFunction(NULL), - mRecorders(), - mShouldLogCallCounter(0) - { - } - SettingsConfig::~SettingsConfig() - { - mRecorders.clear(); - } - - Settings::Settings(): - mSettingsConfig(new SettingsConfig()) - { - } - - Settings* Settings::getInstance() + SettingsConfigPtr Globals::getSettingsConfig() { - // According to C++11 Function-Local Initialization - // of static variables is supposed to be thread safe - // without risk of deadlocks. - static Settings inst; - - return &inst; + return mSettingsConfig; } - SettingsConfigPtr Settings::getSettingsConfig() - { - return mSettingsConfig; - } - - void Settings::reset() - { - Globals::getInstance()->invalidateCallSites(); - mSettingsConfig = new SettingsConfig(); - } + void Globals::resetSettingsConfig() + { + invalidateCallSites(); + mSettingsConfig = new SettingsConfig(); + } - SettingsStoragePtr Settings::saveAndReset() - { - SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get()); - reset(); - return oldSettingsConfig; - } + LLError::SettingsStoragePtr Globals::saveAndResetSettingsConfig() + { + LLError::SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get()); + resetSettingsConfig(); + return oldSettingsConfig; + } - void Settings::restore(SettingsStoragePtr pSettingsStorage) - { - Globals::getInstance()->invalidateCallSites(); - SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get())); - mSettingsConfig = newSettingsConfig; - } + void Globals::restore(LLError::SettingsStoragePtr pSettingsStorage) + { + invalidateCallSites(); + SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get())); + mSettingsConfig = newSettingsConfig; + } } namespace LLError @@ -723,7 +695,7 @@ namespace void commonInit(const std::string& user_dir, const std::string& app_dir, bool log_to_stderr = true) { - LLError::Settings::getInstance()->reset(); + Globals::getInstance()->resetSettingsConfig(); LLError::setDefaultLevel(LLError::LEVEL_INFO); LLError::setAlwaysFlush(true); @@ -765,13 +737,13 @@ namespace LLError void setFatalFunction(const FatalFunction& f) { - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); s->mCrashFunction = f; } FatalFunction getFatalFunction() { - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); return s->mCrashFunction; } @@ -782,72 +754,77 @@ namespace LLError void setTimeFunction(TimeFunction f) { - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); s->mTimeFunction = f; } void setDefaultLevel(ELevel level) { - Globals::getInstance()->invalidateCallSites(); - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + Globals *g = Globals::getInstance(); + g->invalidateCallSites(); + SettingsConfigPtr s = g->getSettingsConfig(); s->mDefaultLevel = level; } ELevel getDefaultLevel() { - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); return s->mDefaultLevel; } void setAlwaysFlush(bool flush) { - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); s->mLogAlwaysFlush = flush; } bool getAlwaysFlush() { - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); return s->mLogAlwaysFlush; } void setEnabledLogTypesMask(U32 mask) { - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); s->mEnabledLogTypesMask = mask; } U32 getEnabledLogTypesMask() { - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); return s->mEnabledLogTypesMask; } void setFunctionLevel(const std::string& function_name, ELevel level) { - Globals::getInstance()->invalidateCallSites(); - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + Globals *g = Globals::getInstance(); + g->invalidateCallSites(); + SettingsConfigPtr s = g->getSettingsConfig(); s->mFunctionLevelMap[function_name] = level; } void setClassLevel(const std::string& class_name, ELevel level) { - Globals::getInstance()->invalidateCallSites(); - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + Globals *g = Globals::getInstance(); + g->invalidateCallSites(); + SettingsConfigPtr s = g->getSettingsConfig(); s->mClassLevelMap[class_name] = level; } void setFileLevel(const std::string& file_name, ELevel level) { - Globals::getInstance()->invalidateCallSites(); - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + Globals *g = Globals::getInstance(); + g->invalidateCallSites(); + SettingsConfigPtr s = g->getSettingsConfig(); s->mFileLevelMap[file_name] = level; } void setTagLevel(const std::string& tag_name, ELevel level) { - Globals::getInstance()->invalidateCallSites(); - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + Globals *g = Globals::getInstance(); + g->invalidateCallSites(); + SettingsConfigPtr s = g->getSettingsConfig(); s->mTagLevelMap[tag_name] = level; } @@ -892,8 +869,9 @@ namespace LLError { void configure(const LLSD& config) { - Globals::getInstance()->invalidateCallSites(); - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + Globals *g = Globals::getInstance(); + g->invalidateCallSites(); + SettingsConfigPtr s = g->getSettingsConfig(); s->mFunctionLevelMap.clear(); s->mClassLevelMap.clear(); @@ -1020,7 +998,7 @@ namespace LLError { return; } - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); s->mRecorders.push_back(recorder); } @@ -1030,7 +1008,7 @@ namespace LLError { return; } - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); s->mRecorders.erase(std::remove(s->mRecorders.begin(), s->mRecorders.end(), recorder), s->mRecorders.end()); } @@ -1046,7 +1024,7 @@ namespace LLError std::pair<boost::shared_ptr<RECORDER>, Recorders::iterator> findRecorderPos() { - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); // Since we promise to return an iterator, use a classic iterator // loop. auto end{s->mRecorders.end()}; @@ -1089,7 +1067,7 @@ namespace LLError auto found = findRecorderPos<RECORDER>(); if (found.first) { - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); s->mRecorders.erase(found.second); } return bool(found.first); @@ -1187,7 +1165,7 @@ namespace void writeToRecorders(const LLError::CallSite& site, const std::string& message) { LLError::ELevel level = site.mLevel; - LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); std::string escaped_message; @@ -1325,7 +1303,8 @@ namespace LLError return false; } - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + Globals *g = Globals::getInstance(); + SettingsConfigPtr s = g->getSettingsConfig(); s->mShouldLogCallCounter++; @@ -1355,7 +1334,7 @@ namespace LLError : false); site.mCached = true; - Globals::getInstance()->addCallSite(site); + g->addCallSite(site); return site.mShouldLog = site.mLevel >= compareLevel; } @@ -1419,7 +1398,7 @@ namespace LLError } Globals* g = Globals::getInstance(); - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = g->getSettingsConfig(); std::string message = out->str(); if (out == &g->messageStream) @@ -1478,12 +1457,12 @@ namespace LLError { SettingsStoragePtr saveAndResetSettings() { - return Settings::getInstance()->saveAndReset(); + return Globals::getInstance()->saveAndResetSettingsConfig(); } void restoreSettings(SettingsStoragePtr pSettingsStorage) { - return Settings::getInstance()->restore(pSettingsStorage); + return Globals::getInstance()->restore(pSettingsStorage); } std::string removePrefix(std::string& s, const std::string& p) @@ -1529,7 +1508,7 @@ namespace LLError int shouldLogCallCount() { - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); return s->mShouldLogCallCounter; } @@ -1707,8 +1686,8 @@ bool debugLoggingEnabled(const std::string& tag) { return false; } - - LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig(); + + SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); LLError::ELevel level = LLError::LEVEL_DEBUG; bool res = checkLevelMap(s->mTagLevelMap, tag, level); return res; diff --git a/indra/llmessage/lldatapacker.cpp b/indra/llmessage/lldatapacker.cpp index 6cf6af6437..96c1297e0d 100644 --- a/indra/llmessage/lldatapacker.cpp +++ b/indra/llmessage/lldatapacker.cpp @@ -173,6 +173,71 @@ BOOL LLDataPacker::unpackFixed(F32 &value, const char *name, return ok; } +BOOL LLDataPacker::unpackU16s(U16 *values, S32 count, const char *name) +{ + for (S32 idx = 0; idx < count; ++idx) + { + if (!unpackU16(values[idx], name)) + { + LL_WARNS("DATAPACKER") << "Buffer overflow reading Unsigned 16s \"" << name << "\" at index " << idx << "!" << LL_ENDL; + return FALSE; + } + } + return TRUE; +} + +BOOL LLDataPacker::unpackS16s(S16 *values, S32 count, const char *name) +{ + for (S32 idx = 0; idx < count; ++idx) + { + if (!unpackS16(values[idx], name)) + { + LL_WARNS("DATAPACKER") << "Buffer overflow reading Signed 16s \"" << name << "\" at index " << idx << "!" << LL_ENDL; + return FALSE; + } + } + return TRUE; +} + +BOOL LLDataPacker::unpackF32s(F32 *values, S32 count, const char *name) +{ + for (S32 idx = 0; idx < count; ++idx) + { + if (!unpackF32(values[idx], name)) + { + LL_WARNS("DATAPACKER") << "Buffer overflow reading Float 32s \"" << name << "\" at index " << idx << "!" << LL_ENDL; + return FALSE; + } + } + return TRUE; +} + +BOOL LLDataPacker::unpackColor4Us(LLColor4U *values, S32 count, const char *name) +{ + for (S32 idx = 0; idx < count; ++idx) + { + if (!unpackColor4U(values[idx], name)) + { + LL_WARNS("DATAPACKER") << "Buffer overflow reading Float 32s \"" << name << "\" at index " << idx << "!" << LL_ENDL; + return FALSE; + } + } + return TRUE; +} + +BOOL LLDataPacker::unpackUUIDs(LLUUID *values, S32 count, const char *name) +{ + for (S32 idx = 0; idx < count; ++idx) + { + if (!unpackUUID(values[idx], name)) + { + LL_WARNS("DATAPACKER") << "Buffer overflow reading UUIDs \"" << name << "\" at index " << idx << "!" << LL_ENDL; + return FALSE; + } + } + return TRUE; +} + //--------------------------------------------------------------------------- // LLDataPackerBinaryBuffer implementation //--------------------------------------------------------------------------- @@ -319,6 +384,29 @@ BOOL LLDataPackerBinaryBuffer::unpackU16(U16 &value, const char *name) return success; } +BOOL LLDataPackerBinaryBuffer::packS16(const S16 value, const char *name) +{ + BOOL success = verifyLength(sizeof(S16), name); + + if (mWriteEnabled && success) + { + htolememcpy(mCurBufferp, &value, MVT_S16, 2); + } + mCurBufferp += 2; + return success; +} + +BOOL LLDataPackerBinaryBuffer::unpackS16(S16 &value, const char *name) +{ + BOOL success = verifyLength(sizeof(S16), name); + + if (success) + { + htolememcpy(&value, mCurBufferp, MVT_S16, 2); + } + mCurBufferp += 2; + return success; +} BOOL LLDataPackerBinaryBuffer::packU32(const U32 value, const char *name) { @@ -884,6 +972,52 @@ BOOL LLDataPackerAsciiBuffer::unpackU16(U16 &value, const char *name) return success; } +BOOL LLDataPackerAsciiBuffer::packS16(const S16 value, const char *name) +{ + BOOL success = TRUE; + writeIndentedName(name); + int numCopied = 0; + if (mWriteEnabled) + { + numCopied = snprintf(mCurBufferp, getBufferSize() - getCurrentSize(), "%d\n", value); /* Flawfinder: ignore */ + } + else + { + numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value); /* Flawfinder: ignore */ + } + + // snprintf returns number of bytes that would have been written + // had the output not being truncated. In that case, it will + // return either -1 or value >= passed in size value . So a check needs to be added + // to detect truncation, and if there is any, only account for the + // actual number of bytes written..and not what could have been + // written. + if(numCopied < 0 || numCopied > getBufferSize() - getCurrentSize()) + { + numCopied = getBufferSize() - getCurrentSize(); + LL_WARNS() << "LLDataPackerAsciiBuffer::packS16: val truncated: " << LL_ENDL; + } + + mCurBufferp += numCopied; + + return success; +} + + +BOOL LLDataPackerAsciiBuffer::unpackS16(S16 &value, const char *name) +{ + BOOL success = TRUE; + char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */ + if (!getValueStr(name, valuestr, DP_BUFSIZE)) + { + return FALSE; + } + + S32 in_val; + sscanf(valuestr, "%d", &in_val); + value = in_val; + return success; +} BOOL LLDataPackerAsciiBuffer::packU32(const U32 value, const char *name) { @@ -1587,6 +1721,36 @@ BOOL LLDataPackerAsciiFile::unpackU16(U16 &value, const char *name) return success; } +BOOL LLDataPackerAsciiFile::packS16(const S16 value, const char *name) +{ + BOOL success = TRUE; + writeIndentedName(name); + if (mFP) + { + fprintf(mFP, "%d\n", value); + } + else if (mOutputStream) + { + *mOutputStream << "" << value << "\n"; + } + return success; +} + + +BOOL LLDataPackerAsciiFile::unpackS16(S16 &value, const char *name) +{ + BOOL success = TRUE; + char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */ + if (!getValueStr(name, valuestr, DP_BUFSIZE)) + { + return FALSE; + } + + S32 in_val; + sscanf(valuestr, "%d", &in_val); + value = in_val; + return success; +} BOOL LLDataPackerAsciiFile::packU32(const U32 value, const char *name) { diff --git a/indra/llmessage/lldatapacker.h b/indra/llmessage/lldatapacker.h index 5140f56c01..ac28cadbce 100644 --- a/indra/llmessage/lldatapacker.h +++ b/indra/llmessage/lldatapacker.h @@ -60,6 +60,11 @@ public: virtual BOOL packU16(const U16 value, const char *name) = 0; virtual BOOL unpackU16(U16 &value, const char *name) = 0; + BOOL unpackU16s(U16 *value, S32 count, const char *name); + + virtual BOOL packS16(const S16 value, const char *name) = 0; + virtual BOOL unpackS16(S16 &value, const char *name) = 0; + BOOL unpackS16s(S16 *value, S32 count, const char *name); virtual BOOL packU32(const U32 value, const char *name) = 0; virtual BOOL unpackU32(U32 &value, const char *name) = 0; @@ -69,6 +74,7 @@ public: virtual BOOL packF32(const F32 value, const char *name) = 0; virtual BOOL unpackF32(F32 &value, const char *name) = 0; + BOOL unpackF32s(F32 *values, S32 count, const char *name); // Packs a float into an integer, using the given size // and picks the right U* data type to pack into. @@ -82,6 +88,7 @@ public: virtual BOOL packColor4U(const LLColor4U &value, const char *name) = 0; virtual BOOL unpackColor4U(LLColor4U &value, const char *name) = 0; + BOOL unpackColor4Us(LLColor4U *values, S32 count, const char *name); virtual BOOL packVector2(const LLVector2 &value, const char *name) = 0; virtual BOOL unpackVector2(LLVector2 &value, const char *name) = 0; @@ -94,6 +101,7 @@ public: virtual BOOL packUUID(const LLUUID &value, const char *name) = 0; virtual BOOL unpackUUID(LLUUID &value, const char *name) = 0; + BOOL unpackUUIDs(LLUUID *values, S32 count, const char *name); U32 getPassFlags() const { return mPassFlags; } void setPassFlags(U32 flags) { mPassFlags = flags; } protected: @@ -139,6 +147,9 @@ public: /*virtual*/ BOOL packU16(const U16 value, const char *name); /*virtual*/ BOOL unpackU16(U16 &value, const char *name); + /*virtual*/ BOOL packS16(const S16 value, const char *name); + /*virtual*/ BOOL unpackS16(S16 &value, const char *name); + /*virtual*/ BOOL packU32(const U32 value, const char *name); /*virtual*/ BOOL unpackU32(U32 &value, const char *name); @@ -247,6 +258,9 @@ public: /*virtual*/ BOOL packU16(const U16 value, const char *name); /*virtual*/ BOOL unpackU16(U16 &value, const char *name); + /*virtual*/ BOOL packS16(const S16 value, const char *name); + /*virtual*/ BOOL unpackS16(S16 &value, const char *name); + /*virtual*/ BOOL packU32(const U32 value, const char *name); /*virtual*/ BOOL unpackU32(U32 &value, const char *name); @@ -375,6 +389,9 @@ public: /*virtual*/ BOOL packU16(const U16 value, const char *name); /*virtual*/ BOOL unpackU16(U16 &value, const char *name); + /*virtual*/ BOOL packS16(const S16 value, const char *name); + /*virtual*/ BOOL unpackS16(S16 &value, const char *name); + /*virtual*/ BOOL packU32(const U32 value, const char *name); /*virtual*/ BOOL unpackU32(U32 &value, const char *name); diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 53b83a40d7..e08b1914e8 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -114,6 +114,35 @@ const char *SCULPT_DEFAULT_TEXTURE = "be293869-d0d9-0a69-5989-ad27f1946fd4"; // // can't be divided by 2. See DEV-19108 const F32 TEXTURE_ROTATION_PACK_FACTOR = ((F32) 0x08000); +struct material_id_type // originally from llrendermaterialtable +{ + material_id_type() + { + memset(m_value, 0, sizeof(m_value)); + } + + bool operator==(const material_id_type& other) const + { + return (memcmp(m_value, other.m_value, sizeof(m_value)) == 0); + } + + bool operator!=(const material_id_type& other) const + { + return !operator==(other); + } + + bool isNull() const + { + return (memcmp(m_value, s_null_id, sizeof(m_value)) == 0); + } + + U8 m_value[MATERIAL_ID_SIZE]; // server side this is MD5RAW_BYTES + + static const U8 s_null_id[MATERIAL_ID_SIZE]; +}; + +const U8 material_id_type::s_null_id[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; + //static // LEGACY: by default we use the LLVolumeMgr::gVolumeMgr global // TODO -- eliminate this global from the codebase! @@ -1079,50 +1108,85 @@ S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_fa return (S32)(cur_ptr - start_loc); } -S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type) -{ - U8 *start_loc = cur_ptr; - U64 i; - htolememcpy(data_ptr,cur_ptr, type,data_size); - cur_ptr += data_size; - - for (i = 1; i < face_count; i++) - { - // Already unswizzled, don't need to unswizzle it again! - memcpy(data_ptr+(i*data_size),data_ptr,data_size); /* Flawfinder: ignore */ - } - - while ((cur_ptr < buffer_end) && (*cur_ptr != 0)) - { - LL_DEBUGS("TEFieldDecode") << "TE exception" << LL_ENDL; - i = 0; - while (*cur_ptr & 0x80) - { - i |= ((*cur_ptr++) & 0x7F); - i = i << 7; - } - - i |= *cur_ptr++; - - for (S32 j = 0; j < face_count; j++) - { - if (i & 0x01) - { - htolememcpy(data_ptr+(j*data_size),cur_ptr,type,data_size); - LL_DEBUGS("TEFieldDecode") << "Assigning " ; - char foo[64]; - sprintf(foo,"%x %x",*(data_ptr+(j*data_size)), *(data_ptr+(j*data_size)+1)); - LL_CONT << foo << " to face " << j << LL_ENDL; - } - i = i >> 1; - } - cur_ptr += data_size; - } - llassert(cur_ptr <= buffer_end); // buffer underrun - return (S32)(cur_ptr - start_loc); +namespace +{ + template< typename T > + bool unpack_TEField(T dest[], U8 dest_count, U8 * &source, U8 *source_end, EMsgVariableType type) + { + const size_t size(sizeof(T)); + + LL_DEBUGS("TEXTUREENTRY") << "Request to read items of size " << size << " with swizzle " << type << " froum buffer sized " << (source_end - source) << LL_ENDL; + + if ((source + size + 1) > source_end) + { + // we add 1 above to take into account the byte that we know must follow the value. + LL_WARNS("TEXTUREENTRY") << "Buffer exhausted! Requires " << size << " + 1 bytes for default, " << (source_end - source) << " bytes remaning." << LL_ENDL; + source = source_end; + return false; + } + + // Extract the default value and fill the array. + htolememcpy(dest, source, type, size); + source += size; + for (S32 idx = 1; idx < dest_count; ++idx) + { + dest[idx] = dest[0]; + } + + while (source < source_end) + { + U64 index_flags(0); + U8 sbit(0); + + // Unpack the variable length bitfield. Each bit represents whether the following + // value will be placed at the corresponding array index. + do + { + if (source >= source_end) + { + LL_WARNS("TEXTUREENTRY") << "Buffer exhausted! Reading index flags." << LL_ENDL; + source = source_end; + return false; + } + + sbit = *source++; + index_flags <<= 7; // original code had this after? + index_flags |= (sbit & 0x7F); + } while (sbit & 0x80); + + if (!index_flags) + { // We've hit the terminating 0 byte. + break; + } + + if ((source + size + 1) > source_end) + { + // we add 1 above to take into account the byte that we know must follow the value. + LL_WARNS("TEXTUREENTRY") << "Buffer exhausted! Requires " << size << " + 1 bytes for default, " << (source_end - source) << " bytes remaning." << LL_ENDL; + source = source_end; + return false; + } + + // get the value for the indexs. + T value; + htolememcpy(&value, source, type, size); + source += size; + + for (S32 idx = 0; idx < dest_count; idx++) + { + if (index_flags & 1ULL << idx) + { + dest[idx] = value; + } + } + + } + return true; + } } + // Pack information about all texture entries into container: // { TextureEntry Variable 2 } // Includes information about image ID, color, scale S,T, offset S,T and rotation @@ -1298,9 +1362,9 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, LLTEContents& tec) { S32 retval = 0; - // temp buffer for material ID processing - // data will end up in tec.material_id[] - U8 material_data[LLTEContents::MAX_TES*16]; + // temp buffer for material ID processing + // data will end up in tec.material_id[] + material_id_type material_data[LLTEContents::MAX_TES]; if (block_num < 0) { @@ -1316,54 +1380,49 @@ S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name tec.face_count = 0; return retval; } + else if (tec.size >= LLTEContents::MAX_TE_BUFFER) + { + LL_WARNS("TEXTUREENTRY") << "Excessive buffer size detected in Texture Entry! Truncating." << LL_ENDL; + tec.size = LLTEContents::MAX_TE_BUFFER - 1; + } - if (block_num < 0) - { - mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, 0, LLTEContents::MAX_TE_BUFFER); - } - else - { - mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, block_num, LLTEContents::MAX_TE_BUFFER); - } + // if block_num < 0 ask for block 0 + mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, std::max(block_num, 0), LLTEContents::MAX_TE_BUFFER - 1); - + // The last field is not zero terminated. + // Rather than special case the upack functions. Just make it 0x00 terminated. + tec.packed_buffer[tec.size] = 0x00; + ++tec.size; tec.face_count = llmin((U32)getNumTEs(),(U32)LLTEContents::MAX_TES); U8 *cur_ptr = tec.packed_buffer; - cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_data, 16, tec.face_count, MVT_LLUUID); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.colors, 4, tec.face_count, MVT_U8); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.scale_s, 4, tec.face_count, MVT_F32); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.scale_t, 4, tec.face_count, MVT_F32); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.offset_s, 2, tec.face_count, MVT_S16Array); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.offset_t, 2, tec.face_count, MVT_S16Array); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_rot, 2, tec.face_count, MVT_S16Array); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.bump, 1, tec.face_count, MVT_U8); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.media_flags, 1, tec.face_count, MVT_U8); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.glow, 1, tec.face_count, MVT_U8); - - if (cur_ptr < tec.packed_buffer + tec.size) - { - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)material_data, 16, tec.face_count, MVT_LLUUID); - } - else + LL_DEBUGS("TEXTUREENTRY") << "Texture Entry with buffere sized: " << tec.size << LL_ENDL; + U8 *buffer_end = tec.packed_buffer + tec.size; + + if (!( unpack_TEField<LLUUID>(tec.image_data, tec.face_count, cur_ptr, buffer_end, MVT_LLUUID) && + unpack_TEField<LLColor4U>(tec.colors, tec.face_count, cur_ptr, buffer_end, MVT_U8) && + unpack_TEField<F32>(tec.scale_s, tec.face_count, cur_ptr, buffer_end, MVT_F32) && + unpack_TEField<F32>(tec.scale_t, tec.face_count, cur_ptr, buffer_end, MVT_F32) && + unpack_TEField<S16>(tec.offset_s, tec.face_count, cur_ptr, buffer_end, MVT_S16) && + unpack_TEField<S16>(tec.offset_t, tec.face_count, cur_ptr, buffer_end, MVT_S16) && + unpack_TEField<S16>(tec.image_rot, tec.face_count, cur_ptr, buffer_end, MVT_S16) && + unpack_TEField<U8>(tec.bump, tec.face_count, cur_ptr, buffer_end, MVT_U8) && + unpack_TEField<U8>(tec.media_flags, tec.face_count, cur_ptr, buffer_end, MVT_U8) && + unpack_TEField<U8>(tec.glow, tec.face_count, cur_ptr, buffer_end, MVT_U8))) + { + LL_WARNS("TEXTUREENTRY") << "Failure parsing Texture Entry Message due to malformed TE Field! Dropping changes on the floor. " << LL_ENDL; + return 0; + } + + if (cur_ptr >= buffer_end || !unpack_TEField<material_id_type>(material_data, tec.face_count, cur_ptr, buffer_end, MVT_LLUUID)) { memset(material_data, 0, sizeof(material_data)); } for (U32 i = 0; i < tec.face_count; i++) { - tec.material_ids[i].set(&material_data[i * 16]); + tec.material_ids[i].set(&(material_data[i])); } retval = 1; @@ -1375,7 +1434,6 @@ S32 LLPrimitive::applyParsedTEMessage(LLTEContents& tec) S32 retval = 0; LLColor4 color; - LLColor4U coloru; for (U32 i = 0; i < tec.face_count; i++) { LLUUID& req_id = ((LLUUID*)tec.image_data)[i]; @@ -1388,20 +1446,15 @@ S32 LLPrimitive::applyParsedTEMessage(LLTEContents& tec) retval |= setTEGlow(i, (F32)tec.glow[i] / (F32)0xFF); retval |= setTEMaterialID(i, tec.material_ids[i]); - coloru = LLColor4U(tec.colors + 4*i); - // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) // as all zeros. However, the subtraction and addition must be done in unsigned // byte space, not in float space, otherwise off-by-one errors occur. JC - color.mV[VRED] = F32(255 - coloru.mV[VRED]) / 255.f; - color.mV[VGREEN] = F32(255 - coloru.mV[VGREEN]) / 255.f; - color.mV[VBLUE] = F32(255 - coloru.mV[VBLUE]) / 255.f; - color.mV[VALPHA] = F32(255 - coloru.mV[VALPHA]) / 255.f; + color.mV[VRED] = F32(255 - tec.colors[i].mV[VRED]) / 255.f; + color.mV[VGREEN] = F32(255 - tec.colors[i].mV[VGREEN]) / 255.f; + color.mV[VBLUE] = F32(255 - tec.colors[i].mV[VBLUE]) / 255.f; + color.mV[VALPHA] = F32(255 - tec.colors[i].mV[VALPHA]) / 255.f; retval |= setTEColor(i, color); - - - } return retval; @@ -1423,24 +1476,32 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) const U32 MAX_TES = 45; // Avoid construction of 32 UUIDs per call - static LLUUID image_ids[MAX_TES]; static LLMaterialID material_ids[MAX_TES]; - U8 image_data[MAX_TES*16]; - U8 colors[MAX_TES*4]; - F32 scale_s[MAX_TES]; - F32 scale_t[MAX_TES]; - S16 offset_s[MAX_TES]; - S16 offset_t[MAX_TES]; - S16 image_rot[MAX_TES]; - U8 bump[MAX_TES]; - U8 media_flags[MAX_TES]; - U8 glow[MAX_TES]; - U8 material_data[MAX_TES*16]; - - const U32 MAX_TE_BUFFER = 4096; - U8 packed_buffer[MAX_TE_BUFFER]; - U8 *cur_ptr = packed_buffer; + const U32 MAX_TE_BUFFER = 4096; + U8 packed_buffer[MAX_TE_BUFFER]; + memset(packed_buffer, 0, MAX_TE_BUFFER); + + LLUUID image_data[MAX_TES]; + LLColor4U colors[MAX_TES]; + F32 scale_s[MAX_TES]; + F32 scale_t[MAX_TES]; + S16 offset_s[MAX_TES]; + S16 offset_t[MAX_TES]; + S16 image_rot[MAX_TES]; + U8 bump[MAX_TES]; + U8 media_flags[MAX_TES]; + U8 glow[MAX_TES]; + material_id_type material_data[MAX_TES]; + + memset(scale_s, 0, sizeof(scale_s)); + memset(scale_t, 0, sizeof(scale_t)); + memset(offset_s, 0, sizeof(offset_s)); + memset(offset_t, 0, sizeof(offset_t)); + memset(image_rot, 0, sizeof(image_rot)); + memset(bump, 0, sizeof(bump)); + memset(media_flags, 0, sizeof(media_flags)); + memset(glow, 0, sizeof(glow)); S32 size; U32 face_count = 0; @@ -1456,50 +1517,52 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) { return retval; } + else if (size >= MAX_TE_BUFFER) + { + LL_WARNS("TEXTUREENTRY") << "Excessive buffer size detected in Texture Entry! Truncating." << LL_ENDL; + size = MAX_TE_BUFFER - 1; + } + // The last field is not zero terminated. + // Rather than special case the upack functions. Just make it 0x00 terminated. + packed_buffer[size] = 0x00; + ++size; face_count = llmin((U32) getNumTEs(), MAX_TES); U32 i; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_data, 16, face_count, MVT_LLUUID); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)colors, 4, face_count, MVT_U8); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 4, face_count, MVT_F32); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 4, face_count, MVT_F32); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_s, 2, face_count, MVT_S16Array); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_t, 2, face_count, MVT_S16Array); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_rot, 2, face_count, MVT_S16Array); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)bump, 1, face_count, MVT_U8); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)media_flags, 1, face_count, MVT_U8); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)glow, 1, face_count, MVT_U8); - if (cur_ptr < packed_buffer + size) - { - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)material_data, 16, face_count, MVT_LLUUID); - } - else + U8 *cur_ptr = packed_buffer; + LL_DEBUGS("TEXTUREENTRY") << "Texture Entry with buffer sized: " << size << LL_ENDL; + U8 *buffer_end = packed_buffer + size; + + if (!( unpack_TEField<LLUUID>(image_data, face_count, cur_ptr, buffer_end, MVT_LLUUID) && + unpack_TEField<LLColor4U>(colors, face_count, cur_ptr, buffer_end, MVT_U8) && + unpack_TEField<F32>(scale_s, face_count, cur_ptr, buffer_end, MVT_F32) && + unpack_TEField<F32>(scale_t, face_count, cur_ptr, buffer_end, MVT_F32) && + unpack_TEField<S16>(offset_s, face_count, cur_ptr, buffer_end, MVT_S16) && + unpack_TEField<S16>(offset_t, face_count, cur_ptr, buffer_end, MVT_S16) && + unpack_TEField<S16>(image_rot, face_count, cur_ptr, buffer_end, MVT_S16) && + unpack_TEField<U8>(bump, face_count, cur_ptr, buffer_end, MVT_U8) && + unpack_TEField<U8>(media_flags, face_count, cur_ptr, buffer_end, MVT_U8) && + unpack_TEField<U8>(glow, face_count, cur_ptr, buffer_end, MVT_U8))) + { + LL_WARNS("TEXTUREENTRY") << "Failure parsing Texture Entry Message due to malformed TE Field! Dropping changes on the floor. " << LL_ENDL; + return 0; + } + + if (cur_ptr >= buffer_end || !unpack_TEField<material_id_type>(material_data, face_count, cur_ptr, buffer_end, MVT_LLUUID)) { memset(material_data, 0, sizeof(material_data)); } for (i = 0; i < face_count; i++) { - memcpy(image_ids[i].mData,&image_data[i*16],16); /* Flawfinder: ignore */ - material_ids[i].set(&material_data[i * 16]); + material_ids[i].set(&(material_data[i])); } LLColor4 color; - LLColor4U coloru; for (i = 0; i < face_count; i++) { - retval |= setTETexture(i, image_ids[i]); + retval |= setTETexture(i, ((LLUUID*)image_data)[i]); retval |= setTEScale(i, scale_s[i], scale_t[i]); retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF); retval |= setTERotation(i, ((F32)image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI); @@ -1507,15 +1570,14 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) retval |= setTEMediaTexGen(i, media_flags[i]); retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF); retval |= setTEMaterialID(i, material_ids[i]); - coloru = LLColor4U(colors + 4*i); // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) // as all zeros. However, the subtraction and addition must be done in unsigned // byte space, not in float space, otherwise off-by-one errors occur. JC - color.mV[VRED] = F32(255 - coloru.mV[VRED]) / 255.f; - color.mV[VGREEN] = F32(255 - coloru.mV[VGREEN]) / 255.f; - color.mV[VBLUE] = F32(255 - coloru.mV[VBLUE]) / 255.f; - color.mV[VALPHA] = F32(255 - coloru.mV[VALPHA]) / 255.f; + color.mV[VRED] = F32(255 - colors[i].mV[VRED]) / 255.f; + color.mV[VGREEN] = F32(255 - colors[i].mV[VGREEN]) / 255.f; + color.mV[VBLUE] = F32(255 - colors[i].mV[VBLUE]) / 255.f; + color.mV[VALPHA] = F32(255 - colors[i].mV[VALPHA]) / 255.f; retval |= setTEColor(i, color); } diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index b1f8112223..309b18faa9 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -330,8 +330,8 @@ struct LLTEContents { static const U32 MAX_TES = 45; - U8 image_data[MAX_TES*16]; - U8 colors[MAX_TES*4]; + LLUUID image_data[MAX_TES]; + LLColor4U colors[MAX_TES]; F32 scale_s[MAX_TES]; F32 scale_t[MAX_TES]; S16 offset_s[MAX_TES]; @@ -423,7 +423,6 @@ public: void copyTEs(const LLPrimitive *primitive); S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const; - S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type); BOOL packTEMessage(LLMessageSystem *mesgsys) const; BOOL packTEMessage(LLDataPacker &dp) const; S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num); // Variable num of blocks diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index ff72417867..d92f10bdbb 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -184,6 +184,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mFontShadow(p.font_shadow), mPopupMenuHandle(), mReadOnly(p.read_only), + mSkipTripleClick(false), mSkipLinkUnderline(p.skip_link_underline), mSpellCheck(p.spellcheck), mSpellCheckStart(-1), @@ -1017,6 +1018,11 @@ BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask) // handle triple click if (!mTripleClickTimer.hasExpired()) { + if (mSkipTripleClick) + { + return TRUE; + } + S32 real_line = getLineNumFromDocIndex(mCursorPos, false); S32 line_start = -1; S32 line_end = -1; diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 4e966b7cef..2e2e1b9833 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -699,7 +699,7 @@ protected: bool mPlainText; // didn't use Image or Icon segments bool mAutoIndent; S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes - + bool mSkipTripleClick; bool mSkipLinkUnderline; // support widgets diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 0afd32f332..4dc2a6a597 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -45,7 +45,9 @@ LLTextBox::LLTextBox(const LLTextBox::Params& p) : LLTextBase(p), mClickedCallback(NULL), mShowCursorHand(true) -{} +{ + mSkipTripleClick = true; +} LLTextBox::~LLTextBox() {} diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 52dc4744f2..96da0743a4 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12641,6 +12641,17 @@ <key>Value</key> <integer>50</integer> </map> + <key>TextureSaveLocation</key> + <map> + <key>Comment</key> + <string>Current location for bulk saving textures to disk</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string /> + </map> <key>ThrottleBandwidthKBPS</key> <map> <key>Comment</key> 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/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 7f18ea6fe2..be168ff5dd 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1049,13 +1049,14 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it } // updating inventory + LLWearableType* wearable_type_inst = LLWearableType::getInstance(); // TODO: Removed check for ensuring that teens don't remove undershirt and underwear. Handle later // note: shirt is the first non-body part wearable item. Update if wearable order changes. // This loop should remove all clothing, but not any body parts for (S32 j = 0; j < (S32)LLWearableType::WT_COUNT; j++) { - if (LLWearableType::getAssetType((LLWearableType::EType)j) == LLAssetType::AT_CLOTHING) + if (wearable_type_inst->getAssetType((LLWearableType::EType)j) == LLAssetType::AT_CLOTHING) { removeWearable((LLWearableType::EType)j, true, 0); } @@ -1075,7 +1076,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it new_wearable->setName(new_item->getName()); new_wearable->setItemID(new_item->getUUID()); - if (LLWearableType::getAssetType(type) == LLAssetType::AT_BODYPART) + if (wearable_type_inst->getAssetType(type) == LLAssetType::AT_BODYPART) { // exactly one wearable per body part setWearable(type,0,new_wearable); @@ -1162,7 +1163,7 @@ void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLViewerWearab if ((old_wearable->getAssetID() == new_wearable->getAssetID()) && (old_item_id == new_item->getUUID())) { - LL_DEBUGS() << "No change to wearable asset and item: " << LLWearableType::getTypeName(type) << LL_ENDL; + LL_DEBUGS() << "No change to wearable asset and item: " << LLWearableType::getInstance()->getTypeName(type) << LL_ENDL; return; } @@ -1594,7 +1595,7 @@ void LLAgentWearables::editWearable(const LLUUID& item_id) return; } - const BOOL disable_camera_switch = LLWearableType::getDisableCameraSwitch(wearable->getType()); + const BOOL disable_camera_switch = LLWearableType::getInstance()->getDisableCameraSwitch(wearable->getType()); LLPanel* panel = LLFloaterSidePanelContainer::getPanel("appearance"); LLSidepanelAppearance::editWearable(wearable, panel, disable_camera_switch); } diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index e5c505501e..5ceeb65d0e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1021,7 +1021,7 @@ void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type // Try to recover by replacing missing wearable with a new one. LLNotificationsUtil::add("ReplacedMissingWearable"); - LL_DEBUGS() << "Wearable " << LLWearableType::getTypeLabel(type) + LL_DEBUGS() << "Wearable " << LLWearableType::getInstance()->getTypeLabel(type) << " could not be downloaded. Replaced inventory item with default wearable." << LL_ENDL; LLViewerWearable* wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 515d6ffc14..e8466610d2 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -777,10 +777,6 @@ bool LLAppViewer::init() // Start of the application // - // initialize LLWearableType translation bridge. - // Memory will be cleaned up in ::cleanupClass() - LLWearableType::initParamSingleton(new LLUITranslationBridge()); - // initialize the LLSettingsType translation bridge. LLTranslationBridge::ptr_t trans = std::make_shared<LLUITranslationBridge>(); LLSettingsType::initParamSingleton(trans); @@ -802,9 +798,14 @@ bool LLAppViewer::init() // init_default_trans_args(); + // inits from settings.xml and from strings.xml if (!initConfiguration()) return false; + // initialize LLWearableType translation bridge. + // Will immediately use LLTranslationBridge to init LLWearableDictionary + LLWearableType::initParamSingleton(trans); + LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ; //set the max heap size. diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index b31981b235..aa2ba752b7 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -74,7 +74,7 @@ protected: } // Set proper label for the "Create new <WEARABLE_TYPE>" menu item. - std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getTypeName(w_type)); + std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getInstance()->getTypeName(w_type)); menu_item->setLabel(new_label); } diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 347997a69a..c76920c9ce 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -677,8 +677,12 @@ void LLFavoritesBarCtrl::changed(U32 mask) //virtual void LLFavoritesBarCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) { + S32 delta_width = width - getRect().getWidth(); + S32 delta_height = height - getRect().getHeight(); + + bool force_update = delta_width || delta_height || sForceReshape; LLUICtrl::reshape(width, height, called_from_parent); - updateButtons(); + updateButtons(force_update); } void LLFavoritesBarCtrl::draw() @@ -741,8 +745,13 @@ const LLButton::Params& LLFavoritesBarCtrl::getButtonParams() return button_params; } -void LLFavoritesBarCtrl::updateButtons() +void LLFavoritesBarCtrl::updateButtons(bool force_update) { + if (LLApp::isExiting()) + { + return; + } + mItems.clear(); if (!collectFavoriteItems(mItems)) @@ -773,28 +782,29 @@ void LLFavoritesBarCtrl::updateButtons() const child_list_t* childs = getChildList(); child_list_const_iter_t child_it = childs->begin(); int first_changed_item_index = 0; - int rightest_point = getRect().mRight - mMoreTextBox->getRect().getWidth(); - //lets find first changed button - while (child_it != childs->end() && first_changed_item_index < mItems.size()) - { - LLFavoriteLandmarkButton* button = dynamic_cast<LLFavoriteLandmarkButton*> (*child_it); - if (button) - { - const LLViewerInventoryItem *item = mItems[first_changed_item_index].get(); - if (item) - { - // an child's order and mItems should be same - if (button->getLandmarkId() != item->getUUID() // sort order has been changed - || button->getLabelSelected() != item->getName() // favorite's name has been changed - || button->getRect().mRight < rightest_point) // favbar's width has been changed - { - break; - } - } - first_changed_item_index++; - } - child_it++; - } + if (!force_update) + { + //lets find first changed button + while (child_it != childs->end() && first_changed_item_index < mItems.size()) + { + LLFavoriteLandmarkButton* button = dynamic_cast<LLFavoriteLandmarkButton*> (*child_it); + if (button) + { + const LLViewerInventoryItem *item = mItems[first_changed_item_index].get(); + if (item) + { + // an child's order and mItems should be same + if (button->getLandmarkId() != item->getUUID() // sort order has been changed + || button->getLabelSelected() != item->getName()) // favorite's name has been changed + { + break; + } + } + first_changed_item_index++; + } + child_it++; + } + } // now first_changed_item_index should contains a number of button that need to change if (first_changed_item_index <= mItems.size()) diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 571208aa31..d4a6f7b06b 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -75,7 +75,7 @@ public: void setLandingTab(LLUICtrl* tab) { mLandingTab = tab; } protected: - void updateButtons(); + void updateButtons(bool force_update = false); LLButton* createButton(const LLPointer<LLViewerInventoryItem> item, const LLButton::Params& button_params, S32 x_offset ); const LLButton::Params& getButtonParams(); BOOL collectFavoriteItems(LLInventoryModel::item_array_t &items); diff --git a/indra/newview/llfloaterlinkreplace.cpp b/indra/newview/llfloaterlinkreplace.cpp index 595d584799..8ee7a72055 100644 --- a/indra/newview/llfloaterlinkreplace.cpp +++ b/indra/newview/llfloaterlinkreplace.cpp @@ -162,7 +162,7 @@ void LLFloaterLinkReplace::onStartClicked() else { LLSD args; - args["TYPE"] = LLWearableType::getTypeName(source_item->getWearableType()); + args["TYPE"] = LLWearableType::getInstance()->getTypeName(source_item->getWearableType()); params.substitutions(args); LLNotifications::instance().add(params); } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 1cd8841bb4..c7d3ccbb69 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -2492,7 +2492,7 @@ BOOL LLPanelPreference::postBuild() } //////////////////////PanelSetup /////////////////// - if (hasChild("max_bandwidth"), TRUE) + if (hasChild("max_bandwidth", TRUE)) { mBandWidthUpdater = new LLPanelPreference::Updater(boost::bind(&handleBandwidthChanged, _1), BANDWIDTH_UPDATER_TIMEOUT); gSavedSettings.getControl("ThrottleBandwidthKBPS")->getSignal()->connect(boost::bind(&LLPanelPreference::Updater::update, mBandWidthUpdater, _2)); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index e9aaca13eb..5be58e43ea 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -5469,11 +5469,20 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) getClipboardEntries(true, items, disabled_items, flags); items.push_back(std::string("Texture Separator")); - items.push_back(std::string("Save As")); - if (!canSaveTexture()) - { - disabled_items.push_back(std::string("Save As")); - } + + if ((flags & ITEM_IN_MULTI_SELECTION) != 0) + { + items.push_back(std::string("Save Selected As")); + } + else + { + items.push_back(std::string("Save As")); + if (!canSaveTexture()) + { + disabled_items.push_back(std::string("Save As")); + } + } + } addLinkReplaceMenuOption(items, disabled_items); hide_context_entries(menu, items, disabled_items); @@ -5491,6 +5500,23 @@ void LLTextureBridge::performAction(LLInventoryModel* model, std::string action) preview_texture->saveAs(); } } + else if ("save_selected_as" == action) + { + openItem(); + if (canSaveTexture()) + { + LLPreviewTexture* preview_texture = LLFloaterReg::getTypedInstance<LLPreviewTexture>("preview_texture", mUUID); + if (preview_texture) + { + preview_texture->saveMultipleToFile(); + } + } + else + { + LL_WARNS() << "You don't have permission to save " << getName() << " to disk." << LL_ENDL; + } + + } else LLItemBridge::performAction(model, action); } @@ -6820,7 +6846,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) disabled_items.push_back(std::string("Wearable Edit")); } - if (LLWearableType::getAllowMultiwear(mWearableType)) + if (LLWearableType::getInstance()->getAllowMultiwear(mWearableType)) { items.push_back(std::string("Wearable Add")); if (!gAgentWearables.canAddWearable(mWearableType)) diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index d069aa3223..937e38aaf0 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -47,6 +47,7 @@ #include "llappviewer.h" #include "llavataractions.h" #include "llclipboard.h" +#include "lldirpicker.h" #include "lldonotdisturbnotificationstorage.h" #include "llfloatersidepanelcontainer.h" #include "llfocusmgr.h" @@ -2489,6 +2490,10 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root { LLAppearanceMgr::instance().removeItemsFromAvatar(ids); } + else if ("save_selected_as" == action) + { + (new LLDirPickerThread(boost::bind(&LLInventoryAction::saveMultipleTextures, _1, selected_items, model), std::string()))->getFile(); + } else { std::set<LLFolderViewItem*>::iterator set_iter; @@ -2516,6 +2521,32 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root } } +void LLInventoryAction::saveMultipleTextures(const std::vector<std::string>& filenames, std::set<LLFolderViewItem*> selected_items, LLInventoryModel* model) +{ + gSavedSettings.setString("TextureSaveLocation", filenames[0]); + + LLMultiPreview* multi_previewp = new LLMultiPreview(); + gFloaterView->addChild(multi_previewp); + + LLFloater::setFloaterHost(multi_previewp); + + std::set<LLFolderViewItem*>::iterator set_iter; + for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) + { + LLFolderViewItem* folder_item = *set_iter; + if(!folder_item) continue; + LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem(); + if(!bridge) continue; + bridge->performAction(model, "save_selected_as"); + } + + LLFloater::setFloaterHost(NULL); + if (multi_previewp) + { + multi_previewp->openFloater(LLSD()); + } +} + void LLInventoryAction::removeItemFromDND(LLFolderView* root) { if(gAgent.isDoNotDisturb()) diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 04eb962372..c1c4b8fe6c 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -466,6 +466,8 @@ struct LLInventoryAction static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFolderView> root); static void removeItemFromDND(LLFolderView* root); + static void saveMultipleTextures(const std::vector<std::string>& filenames, std::set<LLFolderViewItem*> selected_items, LLInventoryModel* model); + static const int sConfirmOnDeleteItemsNumber; private: diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp index 81c001b8bd..44e493fdf4 100644 --- a/indra/newview/llinventoryicon.cpp +++ b/indra/newview/llinventoryicon.cpp @@ -196,7 +196,7 @@ const std::string& LLInventoryIcon::getIconName(LLInventoryType::EIconName idx) LLInventoryType::EIconName LLInventoryIcon::assignWearableIcon(U32 misc_flag) { const LLWearableType::EType wearable_type = LLWearableType::inventoryFlagsToWearableType(misc_flag); - return LLWearableType::getIconName(wearable_type); + return LLWearableType::getInstance()->getIconName(wearable_type); } LLInventoryType::EIconName LLInventoryIcon::assignSettingsIcon(U32 misc_flag) diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index 272e7ae351..ca7bd8cb2c 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -893,7 +893,7 @@ void LLOutfitGalleryContextMenu::onOutfitsRemovalConfirmation(const LLSD& notifi void LLOutfitGalleryContextMenu::onCreate(const LLSD& data) { - LLWearableType::EType type = LLWearableType::typeNameToType(data.asString()); + LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(data.asString()); if (type == LLWearableType::WT_NONE) { LL_WARNS() << "Invalid wearable type" << LL_ENDL; diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 71ab826e1c..a71432e314 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -1210,7 +1210,7 @@ void LLOutfitListGearMenuBase::onRename() void LLOutfitListGearMenuBase::onCreate(const LLSD& data) { - LLWearableType::EType type = LLWearableType::typeNameToType(data.asString()); + LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(data.asString()); if (type == LLWearableType::WT_NONE) { LL_WARNS() << "Invalid wearable type" << LL_ENDL; diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index c601a6c210..be11a4a9f3 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1276,7 +1276,7 @@ void LLPanelEditWearable::changeCamera(U8 subpart) { // Don't change the camera if this type doesn't have a camera switch. // Useful for wearables like physics that don't have an associated physical body part. - if (LLWearableType::getDisableCameraSwitch(mWearablePtr->getType())) + if (LLWearableType::getInstance()->getDisableCameraSwitch(mWearablePtr->getType())) { return; } diff --git a/indra/newview/llpanelgroupcreate.cpp b/indra/newview/llpanelgroupcreate.cpp index 052212dc27..52be75072c 100644 --- a/indra/newview/llpanelgroupcreate.cpp +++ b/indra/newview/llpanelgroupcreate.cpp @@ -45,6 +45,7 @@ #include "llfloaterreg.h" #include "llfloater.h" #include "llgroupmgr.h" +#include "llstatusbar.h" // to re-request balance #include "lltrans.h" #include "llnotificationsutil.h" #include "lluicolortable.h" @@ -117,6 +118,7 @@ void LLPanelGroupCreate::refreshCreatedGroup(const LLUUID& group_id) params["group_id"] = group_id; params["open_tab_name"] = "panel_group_info_sidetray"; LLFloaterSidePanelContainer::showPanel("people", "panel_group_info_sidetray", params); + LLStatusBar::sendMoneyBalanceRequest(); } void LLPanelGroupCreate::addMembershipRow(const std::string &name) diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 1d87aa6f5d..9828e14262 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -97,7 +97,7 @@ std::string LLShopURLDispatcher::resolveURL(LLWearableType::EType wearable_type, { const std::string prefix = "MarketplaceURL"; const std::string sex_str = (sex == SEX_MALE) ? "Male" : "Female"; - const std::string type_str = LLWearableType::getTypeName(wearable_type); + const std::string type_str = LLWearableType::getInstance()->getTypeName(wearable_type); std::string setting_name = prefix; @@ -173,7 +173,7 @@ public: private: static void onCreate(const LLSD& param) { - LLWearableType::EType type = LLWearableType::typeNameToType(param.asString()); + LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(param.asString()); if (type == LLWearableType::WT_NONE) { LL_WARNS() << "Invalid wearable type" << LL_ENDL; @@ -188,19 +188,20 @@ private: { LLView* menu_clothes = gMenuHolder->getChildView("COF.Gear.New_Clothes", FALSE); LLView* menu_bp = gMenuHolder->getChildView("COF.Gear.New_Body_Parts", FALSE); + LLWearableType * wearable_type_inst = LLWearableType::getInstance(); for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i) { LLWearableType::EType type = (LLWearableType::EType) i; - const std::string& type_name = LLWearableType::getTypeName(type); + const std::string& type_name = wearable_type_inst->getTypeName(type); LLMenuItemCallGL::Params p; p.name = type_name; - p.label = LLTrans::getString(LLWearableType::getTypeDefaultNewName(type)); + p.label = LLTrans::getString(wearable_type_inst->getTypeDefaultNewName(type)); p.on_click.function_name = "Wearable.Create"; p.on_click.parameter = LLSD(type_name); - LLView* parent = LLWearableType::getAssetType(type) == LLAssetType::AT_CLOTHING ? menu_clothes : menu_bp; + LLView* parent = wearable_type_inst->getAssetType(type) == LLAssetType::AT_CLOTHING ? menu_clothes : menu_bp; LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent); } } diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 1b60610668..59be35fe92 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -232,6 +232,7 @@ void LLPreviewNotecard::loadAsset() if (!editor) return; + bool fail = false; if(item) { @@ -315,7 +316,31 @@ void LLPreviewNotecard::loadAsset() getChildView("Delete")->setEnabled(TRUE); } } - else + else if (mObjectUUID.notNull() && mItemUUID.notNull()) + { + LLViewerObject* objectp = gObjectList.findObject(mObjectUUID); + if (objectp && (objectp->isInventoryPending() || objectp->isInventoryDirty())) + { + // It's a notecard in object's inventory and we failed to get it because inventory is not up to date. + // Subscribe for callback and retry at inventoryChanged() + registerVOInventoryListener(objectp, NULL); //removes previous listener + + if (objectp->isInventoryDirty()) + { + objectp->requestInventory(); + } + } + else + { + fail = true; + } + } + else + { + fail = true; + } + + if (fail) { editor->setText(LLStringUtil::null); editor->makePristine(); @@ -600,6 +625,17 @@ void LLPreviewNotecard::syncExternal() } } +/*virtual*/ +void LLPreviewNotecard::inventoryChanged(LLViewerObject* object, + LLInventoryObject::object_list_t* inventory, + S32 serial_num, + void* user_data) +{ + removeVOInventoryListener(); + loadAsset(); +} + + void LLPreviewNotecard::deleteNotecard() { LLNotificationsUtil::add("DeleteNotecard", LLSD(), LLSD(), boost::bind(&LLPreviewNotecard::handleConfirmDeleteDialog,this, _1, _2)); diff --git a/indra/newview/llpreviewnotecard.h b/indra/newview/llpreviewnotecard.h index d9c14815c1..3a706b8645 100644 --- a/indra/newview/llpreviewnotecard.h +++ b/indra/newview/llpreviewnotecard.h @@ -31,6 +31,7 @@ #include "llassetstorage.h" #include "llpreviewscript.h" #include "lliconctrl.h" +#include "llvoinventorylistener.h" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLPreviewNotecard @@ -41,7 +42,7 @@ class LLViewerTextEditor; class LLButton; -class LLPreviewNotecard : public LLPreview +class LLPreviewNotecard : public LLPreview, public LLVOInventoryListener { public: LLPreviewNotecard(const LLSD& key); @@ -75,6 +76,11 @@ public: void syncExternal(); + void inventoryChanged(LLViewerObject* object, + LLInventoryObject::object_list_t* inventory, + S32 serial_num, + void* user_data) override; + protected: void updateTitleButtons() override; diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 9d8be4b2fe..303034ca3d 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -50,6 +50,7 @@ #include "llviewertexture.h" #include "llviewertexturelist.h" #include "lluictrlfactory.h" +#include "llviewercontrol.h" #include "llviewerwindow.h" #include "lllineeditor.h" @@ -317,6 +318,44 @@ void LLPreviewTexture::saveTextureToFile(const std::vector<std::string>& filenam 0, TRUE, FALSE, new LLUUID(mItemUUID), &mCallbackTextureList); } + +void LLPreviewTexture::saveMultipleToFile() +{ + std::string texture_location(gSavedSettings.getString("TextureSaveLocation")); + std::string texture_name = getItem()->getName(); + + std::string filepath; + S32 i = 0; + S32 err = 0; + std::string extension(".png"); + do + { + filepath = texture_location; + filepath += gDirUtilp->getDirDelimiter(); + filepath += texture_name; + + if (i != 0) + { + filepath += llformat("_%.3d", i); + } + + filepath += extension; + + llstat stat_info; + err = LLFile::stat( filepath, &stat_info ); + i++; + } while (-1 != err); // Search until the file is not found (i.e., stat() gives an error). + + + mSaveFileName = filepath; + mLoadingFullImage = TRUE; + getWindow()->incBusyCount(); + + mImage->forceToSaveRawImage(0);//re-fetch the raw image if the old one is removed. + mImage->setLoadedCallback(LLPreviewTexture::onFileLoadedForSave, + 0, TRUE, FALSE, new LLUUID(mItemUUID), &mCallbackTextureList); +} + // virtual void LLPreviewTexture::reshape(S32 width, S32 height, BOOL called_from_parent) { diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h index ad77d9e118..cc6c7854b6 100644 --- a/indra/newview/llpreviewtexture.h +++ b/indra/newview/llpreviewtexture.h @@ -63,6 +63,7 @@ public: void openToSave(); void saveTextureToFile(const std::vector<std::string>& filenames); + void saveMultipleToFile(); static void onSaveAsBtn(void* data); diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 6e2b4a00fc..81b67134d2 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -204,7 +204,7 @@ void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility) // when editing its physics. if (!gAgentCamera.cameraCustomizeAvatar()) { - LLVOAvatarSelf::onCustomizeStart(LLWearableType::getDisableCameraSwitch(wearable_ptr->getType())); + LLVOAvatarSelf::onCustomizeStart(LLWearableType::getInstance()->getDisableCameraSwitch(wearable_ptr->getType())); } if (is_wearable_edit_visible) { diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 8aa5b07561..6363edfb36 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -143,6 +143,20 @@ static bool handleSetShaderChanged(const LLSD& newvalue) gBumpImageList.destroyGL(); gBumpImageList.restoreGL(); + if (gPipeline.isInit()) + { + // ALM depends onto atmospheric shaders, state might have changed + bool old_state = LLPipeline::sRenderDeferred; + LLPipeline::refreshCachedSettings(); + gPipeline.updateRenderDeferred(); + if (old_state != LLPipeline::sRenderDeferred) + { + gPipeline.releaseGLBuffers(); + gPipeline.createGLBuffers(); + gPipeline.resetVertexBuffers(); + } + } + // else, leave terrain detail as is LLViewerShaderMgr::instance()->setShaders(); return true; diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index bbed741a33..55ac817479 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1756,7 +1756,7 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, else { // Use for all clothing and body parts. Adding new wearable types requires updating LLWearableDictionary. - LLWearableType::EType wearable_type = LLWearableType::typeNameToType(type_name); + LLWearableType::EType wearable_type = LLWearableType::getInstance()->typeNameToType(type_name); if (wearable_type >= LLWearableType::WT_SHAPE && wearable_type < LLWearableType::WT_COUNT) { const LLUUID parent_id = bridge ? bridge->getUUID() : LLUUID::null; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 4890867f29..c0e5a7abce 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -8477,7 +8477,7 @@ class LLEditEnableTakeOff : public view_listener_t bool handleEvent(const LLSD& userdata) { std::string clothing = userdata.asString(); - LLWearableType::EType type = LLWearableType::typeNameToType(clothing); + LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing); if (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT) return LLAgentWearables::selfHasWearable(type); return false; @@ -8493,7 +8493,7 @@ class LLEditTakeOff : public view_listener_t LLAppearanceMgr::instance().removeAllClothesFromAvatar(); else { - LLWearableType::EType type = LLWearableType::typeNameToType(clothing); + LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing); if (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT && (gAgentWearables.getWearableCount(type) > 0)) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index be5c22e7c3..945b51d819 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -466,8 +466,8 @@ void LLViewerShaderMgr::setShaders() bool canRenderDeferred = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"); bool hasWindLightShaders = LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"); S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail"); - bool useRenderDeferred = canRenderDeferred && gSavedSettings.getBOOL("RenderDeferred") && gSavedSettings.getBOOL("RenderAvatarVP"); bool doingWindLight = hasWindLightShaders && gSavedSettings.getBOOL("WindLightUseAtmosShaders"); + bool useRenderDeferred = doingWindLight && canRenderDeferred && gSavedSettings.getBOOL("RenderDeferred") && gSavedSettings.getBOOL("RenderAvatarVP"); //using shaders, disable fixed function LLGLSLShader::sNoFixedFunction = true; diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 2d7a0f920f..ebb31f9453 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -563,7 +563,7 @@ void LLViewerWearable::saveNewAsset() const void LLViewerWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userdata, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) { LLWearableSaveData* data = (LLWearableSaveData*)userdata; - const std::string& type_name = LLWearableType::getTypeName(data->mType); + const std::string& type_name = LLWearableType::getInstance()->getTypeName(data->mType); if(0 == status) { // Success @@ -589,7 +589,7 @@ void LLViewerWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w) { - s << "wearable " << LLWearableType::getTypeName(w.mType) << "\n"; + s << "wearable " << LLWearableType::getInstance()->getTypeName(w.mType) << "\n"; s << " Name: " << w.mName << "\n"; s << " Desc: " << w.mDescription << "\n"; //w.mPermissions diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 0aee4a3398..603af7e5cc 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -8734,7 +8734,7 @@ void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value) S32 u8_value = F32_to_U8(value,viewer_param->getMinWeight(),viewer_param->getMaxWeight()); apr_file_printf(file, "\t\t<param id=\"%d\" name=\"%s\" display=\"%s\" value=\"%.3f\" u8=\"%d\" type=\"%s\" wearable=\"%s\" group=\"%d\"/>\n", viewer_param->getID(), viewer_param->getName().c_str(), viewer_param->getDisplayName().c_str(), value, u8_value, type_string.c_str(), - LLWearableType::getTypeName(LLWearableType::EType(wtype)).c_str(), + LLWearableType::getInstance()->getTypeName(LLWearableType::EType(wtype)).c_str(), viewer_param->getGroup()); } @@ -9508,6 +9508,7 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml"); LLAPRFile outfile; + LLWearableType *wr_inst = LLWearableType::getInstance(); std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename); if (APR_SUCCESS == outfile.open(fullpath, LL_APR_WB )) { @@ -9524,7 +9525,7 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara { for (S32 type = LLWearableType::WT_SHAPE; type < LLWearableType::WT_COUNT; type++) { - const std::string& wearable_name = LLWearableType::getTypeName((LLWearableType::EType)type); + const std::string& wearable_name = wr_inst->getTypeName((LLWearableType::EType)type); apr_file_printf( file, "\n\t\t<!-- wearable: %s -->\n", wearable_name.c_str() ); for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index aea12380e8..c0f063e54a 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2030,6 +2030,7 @@ void LLVOAvatarSelf::debugBakedTextureUpload(EBakedTextureIndex index, BOOL fini const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const { std::ostringstream outbuf; + LLWearableType *wr_inst = LLWearableType::getInstance(); for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); @@ -2053,7 +2054,7 @@ const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLV { for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { - outbuf << " " << LLWearableType::getTypeName(wearable_type) << " " << wearable_index << ":"; + outbuf << " " << wr_inst->getTypeName(wearable_type) << " " << wearable_index << ":"; const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(tex_index, wearable_index); if (local_tex_obj) { @@ -2108,6 +2109,7 @@ void LLVOAvatarSelf::dumpAllTextures() const const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const { std::string text=""; + LLWearableType *wr_inst = LLWearableType::getInstance(); text = llformat("[Final:%d Avail:%d] ",isLocalTextureDataFinal(layerset), isLocalTextureDataAvailable(layerset)); @@ -2131,7 +2133,7 @@ const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTe const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); if (wearable_count > 0) { - text += LLWearableType::getTypeName(wearable_type) + ":"; + text += wr_inst->getTypeName(wearable_type) + ":"; for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { const U32 discard_level = getLocalDiscardLevel(tex_index, wearable_index); @@ -2838,9 +2840,10 @@ void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile) apr_file_printf( file, "\n<wearable_info>\n" ); LLWearableData *wd = getWearableData(); + LLWearableType *wr_inst = LLWearableType::getInstance(); for (S32 type = 0; type < LLWearableType::WT_COUNT; type++) { - const std::string& type_name = LLWearableType::getTypeName((LLWearableType::EType)type); + const std::string& type_name = wr_inst->getTypeName((LLWearableType::EType)type); for (U32 j=0; j< wd->getWearableCount((LLWearableType::EType)type); j++) { LLViewerWearable *wearable = gAgentWearables.getViewerWearable((LLWearableType::EType)type,j); diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index e7f62e77b4..12a6fc02ac 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -959,7 +959,7 @@ void LLWearableItemsList::ContextMenu::updateItemsLabels(LLContextMenu* menu) if (!item || !item->isWearableType()) return; LLWearableType::EType w_type = item->getWearableType(); - std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getTypeName(w_type)); + std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getInstance()->getTypeName(w_type)); LLMenuItemGL* menu_item = menu->getChild<LLMenuItemGL>("create_new"); menu_item->setLabel(new_label); diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index b61fbbd073..b07905629a 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -241,7 +241,8 @@ LLViewerWearable* LLWearableList::createNewWearable( LLWearableType::EType type, LLViewerWearable *wearable = generateNewWearable(); wearable->setType( type, avatarp ); - std::string name = LLTrans::getString( LLWearableType::getTypeDefaultNewName(wearable->getType()) ); + // LLWearableType has pre-translated getTypeLabel(), but it uses default translation + std::string name = LLTrans::getString( LLWearableType::getInstance()->getTypeDefaultNewName(wearable->getType()) ); wearable->setName( name ); LLPermissions perm; diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index eda9739976..0f790bf26a 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -807,6 +807,14 @@ function="Inventory.DoToSelected" parameter="save_as" /> </menu_item_call> + <menu_item_call + label="Save Selected As" + layout="topleft" + name="Save Selected As"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="save_selected_as" /> + </menu_item_call> <menu_item_separator layout="topleft" name="Wearable And Object Separator"/> |