From 873b399ee8ba0028204bec3a2bf99407f43f6078 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Thu, 7 Jul 2016 16:37:25 -0400 Subject: [PATCH] Sync with obsidian in attempt to fix SV-2086 Applies MAINT-4897 FIXED Frequent error when texturing a linkset - "Unable to add texture. Please wait a few seconds and try again." Applies MAINT-5547 FIXED errors when texturing a linkset "Unable to add texture. Please wait a few seconds and try again." --- indra/newview/lltooldraganddrop.cpp | 19 ++++++++++++------- indra/newview/llviewerobject.cpp | 16 ++++++++++++---- indra/newview/llviewerobject.h | 25 ++++++++++++++----------- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 29dfeba7a..bb525d745 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -976,11 +976,14 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj, return TRUE; } - // In case the inventory has not been updated (e.g. due to some recent operation - // causing a dirty inventory), stall the user while fetching the inventory. - if (hit_obj->isInventoryDirty()) + // In case the inventory has not been loaded (e.g. due to some recent operation + // causing a dirty inventory) and we can do an update, stall the user + // while fetching the inventory. + // + // Fetch if inventory is dirty and listener is present (otherwise we will not receive update) + if (hit_obj->isInventoryDirty() && hit_obj->hasInventoryListeners()) { - hit_obj->fetchInventoryFromServer(); + hit_obj->requestInventory(); LLSD args; args["ERROR_MESSAGE"] = "Unable to add texture.\nPlease wait a few seconds and try again."; LLNotificationsUtil::add("ErrorMessage", args); @@ -1060,10 +1063,12 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj, { hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); } - // Force the object to update its refetch its inventory so it has this texture. - hit_obj->fetchInventoryFromServer(); + // Force the object to update and refetch its inventory so it has this texture. + hit_obj->dirtyInventory(); + hit_obj->requestInventory(); // TODO: Check to see if adding the item was successful; if not, then - // we should return false here. + // we should return false here. This will requre a separate listener + // since without listener, we have no way to receive update } return TRUE; } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index fc517cf30..edcdad0c6 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2594,6 +2594,11 @@ void LLViewerObject::clearInventoryListeners() mInventoryCallbacks.clear(); } +bool LLViewerObject::hasInventoryListeners() +{ + return !mInventoryCallbacks.empty(); +} + void LLViewerObject::requestInventory() { if(mInventoryDirty && mInventory && !mInventoryCallbacks.empty()) @@ -2601,15 +2606,20 @@ void LLViewerObject::requestInventory() mInventory->clear(); // will deref and delete entries delete mInventory; mInventory = NULL; - mInventoryDirty = FALSE; //since we are going to request it now } + if(mInventory) { + // inventory is either up to date or doesn't has a listener + // if it is dirty, leave it this way in case we gain a listener doInventoryCallback(); } - // throw away duplicate requests else { + // since we are going to request it now + mInventoryDirty = FALSE; + + // Note: throws away duplicate requests fetchInventoryFromServer(); } } @@ -2619,8 +2629,6 @@ void LLViewerObject::fetchInventoryFromServer() if (!mInventoryPending) { delete mInventory; - mInventory = NULL; - mInventoryDirty = FALSE; LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_RequestTaskInventory); msg->nextBlockFast(_PREHASH_AgentData); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 675ff1f8f..19e7aab91 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -54,27 +54,27 @@ class LLAgent; // TODO: Get rid of this. class LLAudioSource; class LLAudioSourceVO; class LLBBox; -class LLDataPacker; class LLColor4; -class LLFrameTimer; +class LLDataPacker; class LLDrawable; +class LLFrameTimer; class LLHost; -class LLWorld; +class LLMessageSystem; class LLNameValue; class LLNetMap; -class LLMessageSystem; class LLPartSysData; -class LLPrimitive; class LLPipeline; +class LLPrimitive; class LLTextureEntry; -class LLViewerTexture; +class LLVOAvatar; +class LLVOInventoryListener; class LLViewerInventoryItem; class LLViewerObject; +class LLViewerObjectMedia; class LLViewerPartSourceScript; class LLViewerRegion; -class LLViewerObjectMedia; -class LLVOInventoryListener; -class LLVOAvatar; +class LLViewerTexture; +class LLWorld; typedef enum e_object_update_type { @@ -112,7 +112,7 @@ struct PotentialReturnableObject //============================================================================ -class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate +class LLViewerObject: public LLPrimitive, public LLRefCount, public LLGLUpdate { protected: ~LLViewerObject(); // use unref() @@ -446,8 +446,8 @@ public: void removeInventoryListener(LLVOInventoryListener* listener); BOOL isInventoryPending() { return mInventoryPending; } void clearInventoryListeners(); + bool hasInventoryListeners(); void requestInventory(); - void fetchInventoryFromServer(); static void processTaskInv(LLMessageSystem* msg, void** user_data); void removeInventory(const LLUUID& item_id); @@ -595,6 +595,9 @@ private: // Motion prediction between updates void interpolateLinearMotion(const F64SecondsImplicit & time, const F32SecondsImplicit & dt); + // forms task inventory request if none are pending + void fetchInventoryFromServer(); + public: // // Viewer-side only types - use the LL_PCODE_APP mask.