diff options
25 files changed, 371 insertions, 159 deletions
diff --git a/indra/llaudio/llaudioengine_fmodex.cpp b/indra/llaudio/llaudioengine_fmodex.cpp index 7e65a05e48..5c3f52b201 100644 --- a/indra/llaudio/llaudioengine_fmodex.cpp +++ b/indra/llaudio/llaudioengine_fmodex.cpp @@ -758,10 +758,11 @@ FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *originalbu FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance; thisdsp->getUserData((void **)&windgen); - S32 channels, configwidth, configheight; - thisdsp->getInfo(0, 0, &channels, &configwidth, &configheight); - - windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length); + + if (windgen) + { + windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length); + } return FMOD_OK; } diff --git a/indra/llinventory/llinventorysettings.cpp b/indra/llinventory/llinventorysettings.cpp index fdad50e8d4..81485b3a97 100644 --- a/indra/llinventory/llinventorysettings.cpp +++ b/indra/llinventory/llinventorysettings.cpp @@ -33,10 +33,6 @@ #include "llsingleton.h" #include "llinvtranslationbrdg.h" -//========================================================================= -namespace { - LLTranslationBridge::ptr_t sTranslator; -} //========================================================================= struct SettingsEntry : public LLDictionaryEntry @@ -49,7 +45,7 @@ struct SettingsEntry : public LLDictionaryEntry mLabel(name), mIconName(iconName) { - std::string transdname = sTranslator->getString(mLabel); + std::string transdname = LLSettingsType::getInstance()->mTranslator->getString(mLabel); if (!transdname.empty()) { mLabel = transdname; @@ -84,6 +80,16 @@ void LLSettingsDictionary::initSingleton() //========================================================================= +LLSettingsType::LLSettingsType(LLTranslationBridge::ptr_t &trans) +{ + mTranslator = trans; +} + +LLSettingsType::~LLSettingsType() +{ + mTranslator.reset(); +} + LLSettingsType::type_e LLSettingsType::fromInventoryFlags(U32 flags) { return (LLSettingsType::type_e)(flags & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK); @@ -104,13 +110,3 @@ std::string LLSettingsType::getDefaultName(LLSettingsType::type_e type) return getDefaultName(ST_INVALID); return entry->mDefaultNewName; } - -void LLSettingsType::initClass(LLTranslationBridge::ptr_t &trans) -{ - sTranslator = trans; -} - -void LLSettingsType::cleanupClass() -{ - sTranslator.reset(); -} diff --git a/indra/llinventory/llinventorysettings.h b/indra/llinventory/llinventorysettings.h index 906540689c..6b6685d088 100644 --- a/indra/llinventory/llinventorysettings.h +++ b/indra/llinventory/llinventorysettings.h @@ -30,9 +30,15 @@ #include "llinventorytype.h" #include "llinvtranslationbrdg.h" +#include "llsingleton.h" -class LLSettingsType +class LLSettingsType : public LLParamSingleton<LLSettingsType> { + LLSINGLETON(LLSettingsType, LLTranslationBridge::ptr_t &trans); + ~LLSettingsType(); + + friend struct SettingsEntry; + public: enum type_e { @@ -48,8 +54,9 @@ public: static LLInventoryType::EIconName getIconName(type_e type); static std::string getDefaultName(type_e type); - static void initClass(LLTranslationBridge::ptr_t &trans); - static void cleanupClass(); +protected: + + LLTranslationBridge::ptr_t mTranslator; }; diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 4c56b8eace..281897f999 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -2702,10 +2702,11 @@ LLGLSPipelineBlendSkyBox::LLGLSPipelineBlendSkyBox(bool depth_test, bool depth_w } #if LL_WINDOWS -// Expose desired use of high-performance graphics processor to Optimus driver +// Expose desired use of high-performance graphics processor to Optimus driver and to AMD driver extern "C" -{ - _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; +{ + __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; + __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; } #endif diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 94a04d4ddb..7a88560266 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1193,7 +1193,7 @@ bool LLVertexBuffer::createGLBuffer(U32 size) return true; } - bool sucsess = true; + bool success = true; mEmpty = true; @@ -1215,9 +1215,9 @@ bool LLVertexBuffer::createGLBuffer(U32 size) if (!mMappedData) { - sucsess = false; + success = false; } - return sucsess; + return success; } bool LLVertexBuffer::createGLIndices(U32 size) @@ -1232,7 +1232,7 @@ bool LLVertexBuffer::createGLIndices(U32 size) return true; } - bool sucsess = true; + bool success = true; mEmpty = true; @@ -1257,9 +1257,9 @@ bool LLVertexBuffer::createGLIndices(U32 size) if (!mMappedIndexData) { - sucsess = false; + success = false; } - return sucsess; + return success; } void LLVertexBuffer::destroyGLBuffer() @@ -1306,7 +1306,7 @@ bool LLVertexBuffer::updateNumVerts(S32 nverts) { llassert(nverts >= 0); - bool sucsess = true; + bool success = true; if (nverts > 65536) { @@ -1318,34 +1318,34 @@ bool LLVertexBuffer::updateNumVerts(S32 nverts) if (needed_size > mSize || needed_size <= mSize/2) { - sucsess &= createGLBuffer(needed_size); + success &= createGLBuffer(needed_size); } sVertexCount -= mNumVerts; mNumVerts = nverts; sVertexCount += mNumVerts; - return sucsess; + return success; } bool LLVertexBuffer::updateNumIndices(S32 nindices) { llassert(nindices >= 0); - bool sucsess = true; + bool success = true; U32 needed_size = sizeof(U16) * nindices; if (needed_size > mIndicesSize || needed_size <= mIndicesSize/2) { - sucsess &= createGLIndices(needed_size); + success &= createGLIndices(needed_size); } sIndexCount -= mNumIndices; mNumIndices = nindices; sIndexCount += mNumIndices; - return sucsess; + return success; } bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) @@ -1358,10 +1358,10 @@ bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) LL_ERRS() << "Bad vertex buffer allocation: " << nverts << " : " << nindices << LL_ENDL; } - bool sucsess = true; + bool success = true; - sucsess &= updateNumVerts(nverts); - sucsess &= updateNumIndices(nindices); + success &= updateNumVerts(nverts); + success &= updateNumIndices(nindices); if (create && (nverts || nindices)) { @@ -1377,7 +1377,7 @@ bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) } } - return sucsess; + return success; } static LLTrace::BlockTimerStatHandle FTM_SETUP_VERTEX_ARRAY("Setup VAO"); diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index e718fcec46..0c1dcc301b 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -342,7 +342,9 @@ static LLTrace::BlockTimerStatHandle FTM_FILTER("Filter Folder View"); void LLFolderView::filter( LLFolderViewFilter& filter ) { LL_RECORD_BLOCK_TIME(FTM_FILTER); - filter.resetTime(llclamp(LLUI::getInstance()->mSettingGroups["config"]->getS32(mParentPanel.get()->getVisible() ? "FilterItemsMaxTimePerFrameVisible" : "FilterItemsMaxTimePerFrameUnvisible"), 1, 100)); + static LLCachedControl<S32> filter_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10); + static LLCachedControl<S32> filter_hidden(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1); + filter.resetTime(llclamp(mParentPanel.get()->getVisible() ? filter_visible() : filter_hidden(), 1, 100)); // Note: we filter the model, not the view getViewModelItem()->filter(filter); diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 9a1f7de73b..863a72b6c0 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -122,6 +122,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) : LLView(p), mLabelWidth(0), mLabelWidthDirty(false), + mLabelNeedsRefresh(false), mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT), mParentFolder( NULL ), mIsSelected( FALSE ), @@ -181,11 +182,19 @@ LLFolderViewItem::~LLFolderViewItem() BOOL LLFolderViewItem::postBuild() { - refresh(); + LLFolderViewModelItem& vmi = *getViewModelItem(); + // getDisplayName() is slightly expensive and requires a filter reset + mLabel = vmi.getDisplayName(); + setToolTip(vmi.getName()); + + // Dirty the filter flag of the model from the view (CHUI-849) + vmi.dirtyFilter(); + + mLabelNeedsRefresh = true; + mLabelWidthDirty = true; return TRUE; } - LLFolderView* LLFolderViewItem::getRoot() { return mRoot; @@ -282,22 +291,22 @@ void LLFolderViewItem::refresh() { LLFolderViewModelItem& vmi = *getViewModelItem(); - mLabel = vmi.getDisplayName(); - - setToolTip(vmi.getName()); + // icons are slightly expensive to get, can be optimized + // see LLInventoryIcon::getIcon() mIcon = vmi.getIcon(); mIconOpen = vmi.getIconOpen(); mIconOverlay = vmi.getIconOverlay(); if (mRoot->useLabelSuffix()) { + // Very Expensive! + // Can do a number of expensive checks, like checking active motions, wearables or friend list mLabelStyle = vmi.getLabelStyle(); mLabelSuffix = vmi.getLabelSuffix(); } - mLabelWidthDirty = true; - // Dirty the filter flag of the model from the view (CHUI-849) - vmi.dirtyFilter(); + mLabelWidthDirty = true; + mLabelNeedsRefresh = false; } // Utility function for LLFolderView @@ -348,6 +357,12 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height ) : 0; if (mLabelWidthDirty) { + if (mLabelNeedsRefresh) + { + // Expensive. But despite refreshing label, + // it is purely visual, so it is fine to do at our laisure + refresh(); + } mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + mLabelPaddingRight; mLabelWidthDirty = false; } diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 61c39e0175..8693e1e0f9 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -90,6 +90,7 @@ protected: std::string mLabel; S32 mLabelWidth; bool mLabelWidthDirty; + bool mLabelNeedsRefresh; S32 mLabelPaddingRight; LLFolderViewFolder* mParentFolder; LLPointer<LLFolderViewModelItem> mViewModelItem; @@ -266,7 +267,8 @@ public: virtual BOOL passedFilter(S32 filter_generation = -1); virtual BOOL isPotentiallyVisible(S32 filter_generation = -1); - // refresh information from the object being viewed. + // refresh information from the object being viewed. + // refreshes sufixes and sets icons. Expensive! virtual void refresh(); // LLView functionality diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp index 3b45fb53a2..ea106b5fae 100644 --- a/indra/llui/llfolderviewmodel.cpp +++ b/indra/llui/llfolderviewmodel.cpp @@ -48,7 +48,8 @@ std::string LLFolderViewModelCommon::getStatusText() void LLFolderViewModelCommon::filter() { - getFilter().resetTime(llclamp(LLUI::getInstance()->mSettingGroups["config"]->getS32("FilterItemsMaxTimePerFrameVisible"), 1, 100)); + static LLCachedControl<S32> filter_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10); + getFilter().resetTime(llclamp(filter_visible(), 1, 100)); mFolderView->getViewModelItem()->filter(getFilter()); } diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index f71a88c56e..84a1539094 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -285,17 +285,7 @@ public: typedef std::list<LLFolderViewModelItem*> child_list_t; virtual void addChild(LLFolderViewModelItem* child) - { - // Avoid duplicates: bail out if that child is already present in the list - // Note: this happens when models are created before views - child_list_t::const_iterator iter; - for (iter = mChildren.begin(); iter != mChildren.end(); iter++) - { - if (child == *iter) - { - return; - } - } + { mChildren.push_back(child); child->setParent(this); dirtyFilter(); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 333d03f208..e6835f73fb 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -454,13 +454,17 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const } // -// LLUrlEntrySeconlifeURL Describes *secondlife.com/ *lindenlab.com/ and *tilia-inc.com/ urls to substitute icon 'hand.png' before link +// LLUrlEntrySeconlifeURL Describes *secondlife.com/ *lindenlab.com/ *secondlifegrid.net/ and *tilia-inc.com/ urls to substitute icon 'hand.png' before link // LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL() { mPattern = boost::regex("((http://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com)" "|" - "(https://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(:\\d{1,5})?))" + "(http://([-\\w\\.]*\\.)?secondlifegrid\\.net)" + "|" + "(https://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(:\\d{1,5})?)" + "|" + "(https://([-\\w\\.]*\\.)?secondlifegrid\\.net(:\\d{1,5})?))" "\\/\\S*", boost::regex::perl|boost::regex::icase); @@ -495,12 +499,14 @@ std::string LLUrlEntrySecondlifeURL::getTooltip(const std::string &url) const } // -// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com *lindenlab.com and *tilia-inc.com urls to substitute icon 'hand.png' before link +// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com *lindenlab.com *secondlifegrid.net and *tilia-inc.com urls to substitute icon 'hand.png' before link // LLUrlEntrySimpleSecondlifeURL::LLUrlEntrySimpleSecondlifeURL() { - mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(?!\\S)", - boost::regex::perl|boost::regex::icase); + mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(?!\\S)" + "|" + "https?://([-\\w\\.]*\\.)?secondlifegrid\\.net(?!\\S)", + boost::regex::perl|boost::regex::icase); mIcon = "Hand"; mMenuName = "menu_url_http.xml"; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index ff921dcfdb..b510208813 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -781,7 +781,7 @@ bool LLAppViewer::init() // initialize the LLSettingsType translation bridge. LLTranslationBridge::ptr_t trans = std::make_shared<LLUITranslationBridge>(); - LLSettingsType::initClass(trans); + LLSettingsType::initParamSingleton(trans); // initialize SSE options LLVector4a::initClass(); diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp index fe14bc081f..06d959ba3c 100644 --- a/indra/newview/llcommandlineparser.cpp +++ b/indra/newview/llcommandlineparser.cpp @@ -402,23 +402,30 @@ bool LLCommandLineParser::parseCommandLineString(const std::string& str) } } - // Split the string content into tokens - const char* escape_chars = "\\"; - const char* separator_chars = "\r\n "; - const char* quote_chars = "\"'"; - boost::escaped_list_separator<char> sep(escape_chars, separator_chars, quote_chars); - boost::tokenizer< boost::escaped_list_separator<char> > tok(cmd_line_string, sep); std::vector<std::string> tokens; - // std::copy(tok.begin(), tok.end(), std::back_inserter(tokens)); - for(boost::tokenizer< boost::escaped_list_separator<char> >::iterator i = tok.begin(); - i != tok.end(); - ++i) + try { - if(0 != i->size()) + // Split the string content into tokens + const char* escape_chars = "\\"; + const char* separator_chars = "\r\n "; + const char* quote_chars = "\"'"; + boost::escaped_list_separator<char> sep(escape_chars, separator_chars, quote_chars); + boost::tokenizer< boost::escaped_list_separator<char> > tok(cmd_line_string, sep); + // std::copy(tok.begin(), tok.end(), std::back_inserter(tokens)); + for (boost::tokenizer< boost::escaped_list_separator<char> >::iterator i = tok.begin(); + i != tok.end(); + ++i) { - tokens.push_back(*i); + if (0 != i->size()) + { + tokens.push_back(*i); + } } } + catch (...) + { + CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("Unexpected crash while parsing: " << str)); + } po::command_line_parser clp(tokens); return parseAndStoreResults(clp); diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index c258136889..4aa74a550c 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -92,6 +92,23 @@ LLConversationItem::~LLConversationItem() } } +//virtual +void LLConversationItem::addChild(LLFolderViewModelItem* child) +{ + // Avoid duplicates: bail out if that child is already present in the list + // Note: this happens when models are created and 'parented' before views + // This is performance unfriendly, but conversation can addToFolder multiple times + child_list_t::const_iterator iter; + for (iter = mChildren.begin(); iter != mChildren.end(); iter++) + { + if (child == *iter) + { + return; + } + } + LLFolderViewModelItemCommon::addChild(child); +} + void LLConversationItem::postEvent(const std::string& event_type, LLConversationItemSession* session, LLConversationItemParticipant* participant) { LLUUID session_id = (session ? session->getUUID() : LLUUID()); diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 80385fad5f..30c7481864 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -96,6 +96,7 @@ public: virtual void buildContextMenu(LLMenuGL& menu, U32 flags) { } virtual BOOL isUpToDate() const { return TRUE; } virtual bool hasChildren() const { return FALSE; } + virtual void addChild(LLFolderViewModelItem* child); virtual bool potentiallyVisible() { return true; } virtual bool filter( LLFolderViewFilter& filter) { return false; } diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 60a5204547..fda5267041 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -430,7 +430,11 @@ void LLConversationViewSession::refresh() // Refresh the session view from its model data LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); vmi->resetRefresh(); - + + mLabel = vmi->getDisplayName(); // needs a filter reset + setToolTip(vmi->getName()); + vmi->dirtyFilter(); + if (mSessionTitle) { mSessionTitle->setText(vmi->getDisplayName()); @@ -545,7 +549,9 @@ BOOL LLConversationViewParticipant::postBuild() } updateChildren(); - return LLFolderViewItem::postBuild(); + LLFolderViewItem::postBuild(); + refresh(); + return TRUE; } void LLConversationViewParticipant::draw() @@ -619,7 +625,11 @@ void LLConversationViewParticipant::refresh() // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted()); - + + mLabel = participant_model->getDisplayName(); // needs a filter reset + setToolTip(participant_model->getName()); + participant_model->dirtyFilter(); + // Do the regular upstream refresh LLFolderViewItem::refresh(); } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 17e80dca89..e7093eac02 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -678,17 +678,59 @@ void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inv LLUUID categoryId = result["folder_id"].asUUID(); - // Add the category to the internal representation - LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(categoryId, - result["parent_id"].asUUID(), (LLFolderType::EType)result["type"].asInteger(), - result["name"].asString(), gAgent.getID()); - - cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1 - cat->setDescendentCount(0); - LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); - - accountForUpdate(update); - updateCategory(cat); + LLViewerInventoryCategory* folderp = gInventory.getCategory(categoryId); + if (!folderp) + { + // Add the category to the internal representation + LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(categoryId, + result["parent_id"].asUUID(), (LLFolderType::EType)result["type"].asInteger(), + result["name"].asString(), gAgent.getID()); + + LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); + accountForUpdate(update); + + cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1 + cat->setDescendentCount(0); + updateCategory(cat); + } + else + { + // bulk processing was faster than coroutine (coro request->processBulkUpdateInventory->coro response) + // category already exists, but needs an update + if (folderp->getVersion() != LLViewerInventoryCategory::VERSION_INITIAL + || folderp->getDescendentCount() != LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN) + { + LL_WARNS() << "Inventory desync on folder creation. Newly created folder already has descendants or got a version.\n" + << "Name: " << folderp->getName() + << " Id: " << folderp->getUUID() + << " Version: " << folderp->getVersion() + << " Descendants: " << folderp->getDescendentCount() + << LL_ENDL; + } + // Recreate category with correct values + // Creating it anew just simplifies figuring out needed change-masks + // and making all needed updates, see updateCategory + LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(categoryId, + result["parent_id"].asUUID(), (LLFolderType::EType)result["type"].asInteger(), + result["name"].asString(), gAgent.getID()); + + if (folderp->getParentUUID() != cat->getParentUUID()) + { + LL_WARNS() << "Inventory desync on folder creation. Newly created folder has wrong parent.\n" + << "Name: " << folderp->getName() + << " Id: " << folderp->getUUID() + << " Expected parent: " << cat->getParentUUID() + << " Actual parent: " << folderp->getParentUUID() + << LL_ENDL; + LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); + accountForUpdate(update); + } + // else: Do not update parent, parent is already aware of the change. See processBulkUpdateInventory + + cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1 + cat->setDescendentCount(0); + updateCategory(cat); + } if (callback) { diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index c6075b4066..689ce7e66b 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -146,7 +146,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mCompletionObserver(NULL), mScroller(NULL), mSortOrderSetting(p.sort_order_setting), - mInventory(p.inventory), + mInventory(p.inventory), //inventory("", &gInventory) mAcceptsDragAndDrop(p.accepts_drag_and_drop), mAllowMultiSelect(p.allow_multi_select), mAllowDrag(p.allow_drag), @@ -512,7 +512,18 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve view_item->destroyView(); removeItemID(idp); } - view_item = buildNewViews(item_id); + + LLInventoryObject const* objectp = mInventory->getObject(item_id); + if (objectp) + { + // providing NULL directly avoids unnessesary getItemByID calls + view_item = buildNewViews(item_id, objectp, NULL); + } + else + { + view_item = NULL; + } + viewmodel_item = static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL); view_folder = dynamic_cast<LLFolderViewFolder *>(view_item); @@ -555,7 +566,13 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve if (model_item && !view_item) { // Add the UI element for this item. - buildNewViews(item_id); + LLInventoryObject const* objectp = mInventory->getObject(item_id); + if (objectp) + { + // providing NULL directly avoids unnessesary getItemByID calls + buildNewViews(item_id, objectp, NULL); + } + // Select any newly created object that has the auto rename at top of folder root set. if(mFolderRoot.get()->getRoot()->needsAutoRename()) { @@ -852,7 +869,7 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) { - LLInventoryObject const* objectp = gInventory.getObject(id); + LLInventoryObject const* objectp = mInventory->getObject(id); return buildNewViews(id, objectp); } @@ -862,11 +879,43 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryO { return NULL; } + if (!typedViewsFilter(id, objectp)) + { + // if certain types are not allowed permanently, no reason to create views + return NULL; + } + + const LLUUID &parent_id = objectp->getParentUUID(); LLFolderViewItem* folder_view_item = getItemByID(id); + LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); + + return buildViewsTree(id, parent_id, objectp, folder_view_item, parent_folder); +} + +LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryObject const* objectp, LLFolderViewItem *folder_view_item) +{ + if (!objectp) + { + return NULL; + } + if (!typedViewsFilter(id, objectp)) + { + // if certain types are not allowed permanently, no reason to create views + return NULL; + } const LLUUID &parent_id = objectp->getParentUUID(); - LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); - + LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); + + return buildViewsTree(id, parent_id, objectp, folder_view_item, parent_folder); +} + +LLFolderViewItem* LLInventoryPanel::buildViewsTree(const LLUUID& id, + const LLUUID& parent_id, + LLInventoryObject const* objectp, + LLFolderViewItem *folder_view_item, + LLFolderViewFolder *parent_folder) +{ // Force the creation of an extra root level folder item if required by the inventory panel (default is "false") bool allow_drop = true; bool create_root = false; @@ -887,7 +936,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryO { if (objectp->getType() <= LLAssetType::AT_NONE) { - LL_WARNS() << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " + LL_WARNS() << "LLInventoryPanel::buildViewsTree called with invalid objectp->mType : " << ((S32)objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() << LL_ENDL; return NULL; @@ -896,7 +945,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryO if (objectp->getType() >= LLAssetType::AT_COUNT) { // Example: Happens when we add assets of new, not yet supported type to library - LL_DEBUGS() << "LLInventoryPanel::buildNewViews called with unknown objectp->mType : " + LL_DEBUGS() << "LLInventoryPanel::buildViewsTree called with unknown objectp->mType : " << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() << LL_ENDL; @@ -973,26 +1022,58 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryO LLViewerInventoryCategory::cat_array_t* categories; LLViewerInventoryItem::item_array_t* items; mInventory->lockDirectDescendentArrays(id, categories, items); - + + LLFolderViewFolder *parentp = dynamic_cast<LLFolderViewFolder*>(folder_view_item); + if(categories) - { + { + bool has_folders = parentp->getFoldersCount() > 0; for (LLViewerInventoryCategory::cat_array_t::const_iterator cat_iter = categories->begin(); cat_iter != categories->end(); ++cat_iter) { const LLViewerInventoryCategory* cat = (*cat_iter); - buildNewViews(cat->getUUID()); + if (typedViewsFilter(cat->getUUID(), cat)) + { + if (has_folders) + { + // This can be optimized: we don't need to call getItemByID() + // each time, especially since content is growing, we can just + // iter over copy of mItemMap in some way + LLFolderViewItem* view_itemp = getItemByID(cat->getUUID()); + buildViewsTree(cat->getUUID(), id, cat, view_itemp, parentp); + } + else + { + buildViewsTree(cat->getUUID(), id, cat, NULL, parentp); + } + } } } if(items) - { + { + bool has_items = parentp->getItemsCount() > 0; for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items->begin(); item_iter != items->end(); ++item_iter) { const LLViewerInventoryItem* item = (*item_iter); - buildNewViews(item->getUUID()); + if (typedViewsFilter(item->getUUID(), item)) + { + if (has_items) + { + // This can be optimized: we don't need to call getItemByID() + // each time, especially since content is growing, we can just + // iter over copy of mItemMap in some way + LLFolderViewItem* view_itemp = getItemByID(item->getUUID()); + buildViewsTree(item->getUUID(), id, item, view_itemp, parentp); + } + else + { + buildViewsTree(item->getUUID(), id, item, NULL, parentp); + } + } } } mInventory->unlockDirectDescendentArrays(id); @@ -1783,7 +1864,7 @@ public: std::string& tooltip_msg) override; protected: - /*virtual*/ LLFolderViewItem* buildNewViews(const LLUUID& id) override; + /*virtual*/ bool typedViewsFilter(const LLUUID& id, LLInventoryObject const* objectp) override; /*virtual*/ void itemChanged(const LLUUID& item_id, U32 mask, const LLInventoryObject* model_item) override; private: @@ -1823,21 +1904,20 @@ BOOL LLAssetFilteredInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, B return result; } -LLFolderViewItem* LLAssetFilteredInventoryPanel::buildNewViews(const LLUUID& id) +/*virtual*/ +bool LLAssetFilteredInventoryPanel::typedViewsFilter(const LLUUID& id, LLInventoryObject const* objectp) { - LLInventoryObject const* objectp = gInventory.getObject(id); - if (!objectp) { - return NULL; + return false; } if (objectp->getType() != mAssetType && objectp->getType() != LLAssetType::AT_CATEGORY) { - return NULL; + return false; } - return LLInventoryPanel::buildNewViews(id, objectp); + return true; } void LLAssetFilteredInventoryPanel::itemChanged(const LLUUID& id, U32 mask, const LLInventoryObject* model_item) diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index b55eb2b828..adca8ad3e2 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -325,8 +325,15 @@ protected: static LLUIColor sLibraryColor; static LLUIColor sLinkColor; - virtual LLFolderViewItem* buildNewViews(const LLUUID& id); - LLFolderViewItem* buildNewViews(const LLUUID& id, LLInventoryObject const* objectp); + LLFolderViewItem* buildNewViews(const LLUUID& id); + LLFolderViewItem* buildNewViews(const LLUUID& id, + LLInventoryObject const* objectp); + LLFolderViewItem* buildNewViews(const LLUUID& id, + LLInventoryObject const* objectp, + LLFolderViewItem *target_view); + // if certain types are not allowed, no reason to create views + virtual bool typedViewsFilter(const LLUUID& id, LLInventoryObject const* objectp) { return true; } + virtual void itemChanged(const LLUUID& item_id, U32 mask, const LLInventoryObject* model_item); BOOL getIsHiddenFolderType(LLFolderType::EType folder_type) const; @@ -334,6 +341,14 @@ protected: virtual LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge, bool allow_drop); virtual LLFolderViewItem* createFolderViewItem(LLInvFVBridge * bridge); private: + // buildViewsTree does not include some checks and is meant + // for recursive use, use buildNewViews() for first call + LLFolderViewItem* buildViewsTree(const LLUUID& id, + const LLUUID& parent_id, + LLInventoryObject const* objectp, + LLFolderViewItem *target_view, + LLFolderViewFolder *parent_folder_view); + bool mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild() bool mViewsInitialized; // Views have been generated }; diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 0c64531783..a623693a62 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -133,6 +133,16 @@ void append_to_last_message(std::list<LLSD>& messages, const std::string& line) messages.back()[LL_IM_TEXT] = im_text; } +std::string remove_utf8_bom(const char* buf) +{ + std::string res(buf); + if (res[0] == (char)0xEF && res[1] == (char)0xBB && res[2] == (char)0xBF) + { + res.erase(0, 3); + } + return res; +} + class LLLogChatTimeScanner: public LLSingleton<LLLogChatTimeScanner> { LLSINGLETON(LLLogChatTimeScanner); @@ -417,7 +427,7 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& m continue; } - std::string line(buffer); + std::string line(remove_utf8_bom(buffer)); //updated 1.23 plain text log format requires a space added before subsequent lines in a multilined message if (' ' == line[0]) @@ -805,7 +815,7 @@ bool LLLogChat::isTranscriptFileFound(std::string fullname) { //matching a timestamp boost::match_results<std::string::const_iterator> matches; - if (boost::regex_match(std::string(buffer), matches, TIMESTAMP)) + if (boost::regex_match(remove_utf8_bom(buffer), matches, TIMESTAMP)) { result = true; } @@ -1126,7 +1136,7 @@ void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list<LL firstline = FALSE; continue; } - std::string line(buffer); + std::string line(remove_utf8_bom(buffer)); //updated 1.23 plaint text log format requires a space added before subsequent lines in a multilined message if (' ' == line[0]) diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 1fce158eb4..d88664860f 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -99,7 +99,7 @@ // locking actions. In particular, the following operations // on LLMeshRepository are very averse to any stalls: // * loadMesh -// * getMeshHeader (For structural details, see: +// * search in mMeshHeader (For structural details, see: // http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format) // * notifyLoadedMeshes // * getSkinInfo @@ -3173,7 +3173,6 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b header_bytes = (S32)gMeshRepo.mThread->mMeshHeaderSize[mesh_id]; header = iter->second; } - gMeshRepo.mThread->mHeaderMutex->unlock(); if (header_bytes > 0 && !header.has("404") @@ -3194,7 +3193,10 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger()); lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger()); - S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id]; + // Do not unlock mutex untill we are done with LLSD. + // LLSD is smart and can work like smart pointer, is not thread safe. + gMeshRepo.mThread->mHeaderMutex->unlock(); + S32 bytes = lod_bytes + header_bytes; @@ -3230,6 +3232,8 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b { LL_WARNS(LOG_MESH) << "Trying to cache nonexistent mesh, mesh id: " << mesh_id << LL_ENDL; + gMeshRepo.mThread->mHeaderMutex->unlock(); + // headerReceived() parsed header, but header's data is invalid so none of the LODs will be available LLMutexLock lock(gMeshRepo.mThread->mMutex); for (int i(0); i < 4; ++i) @@ -4094,42 +4098,42 @@ void LLMeshRepository::buildHull(const LLVolumeParams& params, S32 detail) bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id) { - LLSD mesh = mThread->getMeshHeader(mesh_id); - if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0)) - { - return true; - } - - LLModel::Decomposition* decomp = getDecomposition(mesh_id); - if (decomp && !decomp->mHull.empty()) - { - return true; - } + if (mesh_id.isNull()) + { + return false; + } - return false; -} + if (mThread->hasPhysicsShapeInHeader(mesh_id)) + { + return true; + } -LLSD& LLMeshRepository::getMeshHeader(const LLUUID& mesh_id) -{ - LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH); + LLModel::Decomposition* decomp = getDecomposition(mesh_id); + if (decomp && !decomp->mHull.empty()) + { + return true; + } - return mThread->getMeshHeader(mesh_id); + return false; } -LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id) +bool LLMeshRepoThread::hasPhysicsShapeInHeader(const LLUUID& mesh_id) { - static LLSD dummy_ret; - if (mesh_id.notNull()) - { - LLMutexLock lock(mHeaderMutex); - mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); - if (iter != mMeshHeader.end() && mMeshHeaderSize[mesh_id] > 0) - { - return iter->second; - } - } + LLMutexLock lock(mHeaderMutex); + if (mMeshHeaderSize[mesh_id] > 0) + { + mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); + if (iter != mMeshHeader.end()) + { + LLSD &mesh = iter->second; + if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0)) + { + return true; + } + } + } - return dummy_ret; + return false; } diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index bba0c9f2cb..59ca4db51e 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -341,7 +341,7 @@ public: bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size); bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size); bool physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size); - LLSD& getMeshHeader(const LLUUID& mesh_id); + bool hasPhysicsShapeInHeader(const LLUUID& mesh_id); void notifyLoadedMeshes(); S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod); @@ -593,9 +593,6 @@ public: bool meshUploadEnabled(); bool meshRezEnabled(); - - - LLSD& getMeshHeader(const LLUUID& mesh_id); void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures, bool upload_skin, bool upload_joints, bool lock_scale_if_joint_position, diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 224cec9650..65d7aac7d6 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -684,7 +684,6 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential, if (LLPanelLogin::sInstance->mPasswordModified) { - authenticator = LLSD::emptyMap(); // password is plaintext authenticator["type"] = CRED_AUTHENTICATOR_TYPE_CLEAR; authenticator["secret"] = password; @@ -695,6 +694,15 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential, if (credential.notNull()) { authenticator = credential->getAuthenticator(); + if (authenticator.emptyMap()) + { + // Likely caused by user trying to log in to non-system grid + // with unsupported name format, just retry + LL_WARNS() << "Authenticator failed to load for: " << username << LL_ENDL; + // password is plaintext + authenticator["type"] = CRED_AUTHENTICATOR_TYPE_CLEAR; + authenticator["secret"] = password; + } } } } diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp index 10e510b842..d3f015f695 100644 --- a/indra/newview/llsecapi.cpp +++ b/indra/newview/llsecapi.cpp @@ -117,7 +117,7 @@ LLSD LLCredential::getLoginParams() else if (mIdentifier["type"].asString() == "account") { result["username"] = mIdentifier["account_name"]; - result["passwd"] = mAuthenticator["secret"]; + result["passwd"] = mAuthenticator["secret"].asString(); username = result["username"].asString(); } } diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 089498dfb9..993c13f7a9 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -10253,7 +10253,7 @@ Unable to add script! name="AssetServerTimeoutObjReturn" type="notify"> <tag>fail</tag> -Asset server didn't respond in a timely fashion. Object returned to sim. +Asset server didn't respond in a timely fashion. Object returned to the region. </notification> <notification |