From 5be5c3f0daf25d2b190a8a563ea9efa278a8e716 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Wed, 11 Aug 2010 19:31:20 -0600 Subject: fix for EXT-7399: 2.0.2 with http textures loads textures slower than 1.23.5 and EXT-7397: decoding textures get stuck in REQ status --- indra/newview/lltexturefetch.cpp | 129 +++++++++++---------------------------- indra/newview/lltexturefetch.h | 14 +---- 2 files changed, 36 insertions(+), 107 deletions(-) diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 846cba4a3b..f4899d0d5d 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -54,6 +54,7 @@ #include "llviewertexturelist.h" #include "llviewertexture.h" #include "llviewerregion.h" +#include "llviewerstats.h" #include "llworld.h" ////////////////////////////////////////////////////////////////////////////// @@ -150,7 +151,7 @@ public: ~LLTextureFetchWorker(); void relese() { --mActiveCount; } - void callbackHttpGet(const LLChannelDescriptors& channels, + S32 callbackHttpGet(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer, bool partial, bool success); void callbackCacheRead(bool success, LLImageFormatted* image, @@ -335,8 +336,9 @@ public: worker->setGetStatus(status, reason); // llwarns << "CURL GET FAILED, status:" << status << " reason:" << reason << llendl; } - mFetcher->removeFromHTTPQueue(mID); - worker->callbackHttpGet(channels, buffer, partial, success); + + S32 data_size = worker->callbackHttpGet(channels, buffer, partial, success); + mFetcher->removeFromHTTPQueue(mID, data_size); } else { @@ -850,19 +852,10 @@ bool LLTextureFetchWorker::doWork(S32 param) { if(mCanUseHTTP) { - // *TODO: Integrate this with llviewerthrottle - // Note: LLViewerThrottle uses dynamic throttling which makes sense for UDP, - // but probably not for Textures. - // Set the throttle to the entire bandwidth, assuming UDP packets will get priority - // when they are needed - //F32 max_bandwidth = mFetcher->mMaxBandwidth; - if (mFetcher->isHTTPThrottled(mDesiredSize))// || - //mFetcher->getTextureBandwidth() > max_bandwidth) - { - // Make normal priority and return (i.e. wait until there is room in the queue) - setPriority(LLWorkerThread::PRIORITY_NORMAL | mWorkPriority); - return false; - } + //NOTE: + //it seems ok to let sim control the UDP traffic + //so there is no throttle for http here. + // mFetcher->removeFromNetworkQueue(this, false); @@ -979,6 +972,7 @@ bool LLTextureFetchWorker::doWork(S32 param) else { resetFormattedData(); + mState = DONE; return true; // failed } } @@ -1271,8 +1265,7 @@ bool LLTextureFetchWorker::deleteOK() if ((haveWork() && // not ok to delete from these states - ((mState == WAIT_HTTP_REQ) || - (mState >= WRITE_TO_CACHE && mState <= WAIT_ON_WRITE)))) + ((mState >= WRITE_TO_CACHE && mState <= WAIT_ON_WRITE)))) { delete_ok = false; } @@ -1351,29 +1344,29 @@ bool LLTextureFetchWorker::processSimulatorPackets() ////////////////////////////////////////////////////////////////////////////// -void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, +S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer, bool partial, bool success) { + S32 data_size = 0 ; + LLMutexLock lock(&mWorkMutex); if (mState != WAIT_HTTP_REQ) { llwarns << "callbackHttpGet for unrequested fetch worker: " << mID << " req=" << mSentRequest << " state= " << mState << llendl; - return; + return data_size; } if (mLoaded) { llwarns << "Duplicate callback for " << mID.asString() << llendl; - return; // ignore duplicate callback + return data_size ; // ignore duplicate callback } if (success) { // get length of stream: - S32 data_size = buffer->countAfter(channels.in(), NULL); - - gTextureList.sTextureBits += data_size * 8; // Approximate - does not include header bits + data_size = buffer->countAfter(channels.in(), NULL); LL_DEBUGS("Texture") << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << LL_ENDL; if (data_size > 0) @@ -1410,6 +1403,8 @@ void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, } mLoaded = TRUE; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + + return data_size ; } ////////////////////////////////////////////////////////////////////////////// @@ -1528,15 +1523,11 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mTextureCache(cache), mImageDecodeThread(imagedecodethread), mTextureBandwidth(0), + mHTTPTextureBits(0), mCurlGetRequest(NULL) { mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS"); mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold")); - - for(S32 i = 0 ; i < TOTAL_TEXTURE_TYPES; i++) - { - mHTTPThrottleFlag[i] = FALSE ; - } } LLTextureFetch::~LLTextureFetch() @@ -1678,69 +1669,11 @@ void LLTextureFetch::addToHTTPQueue(const LLUUID& id) mHTTPTextureQueue.insert(id); } -void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id) +void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32 received_size) { LLMutexLock lock(&mNetworkQueueMutex); mHTTPTextureQueue.erase(id); -} - -void LLTextureFetch::clearHTTPThrottleFlag() -{ - static const F32 WAIT_TIME = 0.3f ; //seconds. - static LLFrameTimer timer ; - - if(timer.getElapsedTimeF32() < WAIT_TIME) //wait for WAIT_TIME - { - return ; - } - timer.reset() ; - - LLMutexLock lock(&mNetworkQueueMutex); - for(S32 i = 0 ; i < TOTAL_TEXTURE_TYPES; i++)//reset the http throttle flags. - { - mHTTPThrottleFlag[i] = FALSE ; - } -} - -//check if need to throttle this fetching request. -//rule: if a request can not be inserted into the http queue due to a full queue, -// block all future insertions of requests with larger fetching size requirement. -//because: -// later insertions are usually at lower priorities; and -// small textures need chance to be fetched. -bool LLTextureFetch::isHTTPThrottled(S32 requested_size) -{ - static const S32 SMALL_TEXTURE_MAX_SIZE = 64 * 64 * 4 ; - static const S32 MEDIUM_TEXTURE_MAX_SIZE = 256 * 256 * 4 ; - static const U32 MAX_HTTP_QUEUE_SIZE = 8 ; - - //determine the class of the texture: SMALL, MEDIUM, or LARGE. - S32 type = LARGE_TEXTURE ; - if(requested_size <= SMALL_TEXTURE_MAX_SIZE) - { - type = SMALL_TEXTURE ; - } - else if(requested_size <= MEDIUM_TEXTURE_MAX_SIZE) - { - type = MEDIUM_TEXTURE ; - } - - LLMutexLock lock(&mNetworkQueueMutex); - - if(mHTTPTextureQueue.size() >= MAX_HTTP_QUEUE_SIZE)//if the http queue is full. - { - if(!mHTTPThrottleFlag[type + 1]) - { - for(S32 i = type + 1 ; i < TOTAL_TEXTURE_TYPES; i++) //block all requests with fetching size larger than this request. - { - mHTTPThrottleFlag[i] = TRUE ; - } - } - - return true ; - } - - return mHTTPThrottleFlag[type] ; //true if this request can not be inserted to the http queue. + mHTTPTextureBits += received_size * 8; // Approximate - does not include header bits } void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel) @@ -1888,12 +1821,19 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority) //virtual S32 LLTextureFetch::update(U32 max_time_ms) { - S32 res; - static LLCachedControl band_width(gSavedSettings,"ThrottleBandwidthKBPS"); - mMaxBandwidth = band_width ; - - res = LLWorkerThread::update(max_time_ms); + + { + mNetworkQueueMutex.lock() ; + mMaxBandwidth = band_width ; + + gTextureList.sTextureBits += mHTTPTextureBits ; + mHTTPTextureBits = 0 ; + + mNetworkQueueMutex.unlock() ; + } + + S32 res = LLWorkerThread::update(max_time_ms); if (!mDebugPause) { @@ -1909,7 +1849,6 @@ S32 LLTextureFetch::update(U32 max_time_ms) lldebugs << "processed: " << processed << " messages." << llendl; } } - clearHTTPThrottleFlag(); return res; } diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index c31c38b04a..2024165e7e 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -94,9 +94,7 @@ protected: void addToNetworkQueue(LLTextureFetchWorker* worker); void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel); void addToHTTPQueue(const LLUUID& id); - void removeFromHTTPQueue(const LLUUID& id); - bool isHTTPThrottled(S32 requested_size); - void clearHTTPThrottleFlag(); + void removeFromHTTPQueue(const LLUUID& id, S32 received_size = 0); void removeRequest(LLTextureFetchWorker* worker, bool cancel); // Called from worker thread (during doWork) void processCurlRequests(); @@ -136,15 +134,7 @@ private: F32 mMaxBandwidth; LLTextureInfo mTextureInfo; - enum - { - SMALL_TEXTURE = 0 , //size <= 64 * 64 - MEDIUM_TEXTURE, //size <= 256 * 256 - LARGE_TEXTURE, //size > 256 * 256 - DUMMY, - TOTAL_TEXTURE_TYPES - }; - BOOL mHTTPThrottleFlag[TOTAL_TEXTURE_TYPES]; + U32 mHTTPTextureBits; }; #endif // LL_LLTEXTUREFETCH_H -- cgit v1.2.3 From 7a0b016c8c4b5c0e730ea6735205cfc84725737c Mon Sep 17 00:00:00 2001 From: Paul Guslisty Date: Thu, 12 Aug 2010 13:48:36 +0300 Subject: EXT-8205 FIXED (Items in \"Add more\" panel are not sorted by name) - Modified LLWearableItemTypeNameComparator so that it can be more reusable and adjustable - Set LLWearableItemTypeNameComparator for WearableItemsList ('List view' of 'Add More' panel) due to sort clothings by name - Modified and applied patch form https://codereview.productengine.com/secondlife/r/620/diff/2/#index_header. This patch was discarded because specification was changed Restored diff after bad merge at 13817 Reviewed by Vadim Savchuk at https://codereview.productengine.com/secondlife/r/765/ --HG-- branch : product-engine --- indra/newview/llpaneloutfitedit.cpp | 14 ++++++++++++++ indra/newview/llpaneloutfitedit.h | 2 ++ indra/newview/llwearableitemslist.cpp | 16 ++++++++++++---- indra/newview/llwearableitemslist.h | 20 ++++++++++---------- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index d7a46f30b0..d76a5c586f 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -386,12 +386,26 @@ BOOL LLPanelOutfitEdit::postBuild() childSetAction(REVERT_BTN, boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance())); + /* + * By default AT_CLOTHING are sorted by (in in MY OUTFITS): + * - by type (types order determined in LLWearableType::EType) + * - each LLWearableType::EType by outer layer on top + * + * In Add More panel AT_CLOTHING should be sorted in a such way: + * - by type (types order determined in LLWearableType::EType) + * - each LLWearableType::EType by name (EXT-8205) + */ + mWearableListViewItemsComparator = new LLWearableItemTypeNameComparator(); + mWearableListViewItemsComparator->setOrder(LLAssetType::AT_CLOTHING, LLWearableItemTypeNameComparator::ORDER_RANG_1, false, true); + mWearablesListViewPanel = getChild("filtered_wearables_panel"); mWearableItemsList = getChild("list_view"); mWearableItemsList->setCommitOnSelectionChange(true); mWearableItemsList->setCommitCallback(boost::bind(&LLPanelOutfitEdit::updatePlusButton, this)); mWearableItemsList->setDoubleClickCallback(boost::bind(&LLPanelOutfitEdit::onPlusBtnClicked, this)); + mWearableItemsList->setComparator(mWearableListViewItemsComparator); + mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this)); return TRUE; } diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index 5ce707e6eb..784c2bcad1 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -64,6 +64,7 @@ class LLMenuGL; class LLFindNonLinksByMask; class LLFindWearablesOfType; class LLSaveOutfitComboBtn; +class LLWearableItemTypeNameComparator; class LLPanelOutfitEdit : public LLPanel { @@ -222,6 +223,7 @@ private: LLFilteredWearableListManager* mWearableListManager; LLInventoryItemsList* mWearableItemsList; LLPanel* mWearablesListViewPanel; + LLWearableItemTypeNameComparator* mWearableListViewItemsComparator; LLCOFDragAndDropObserver* mCOFDragAndDropObserver; diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index fe8c09e329..5e23965f62 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -478,9 +478,9 @@ LLWearableItemTypeNameComparator::LLWearableItemTypeNameComparator() // 1. CLOTHING - sorted by name // 2. OBJECT - sorted by type // 3. BODYPART - sorted by name - mWearableOrder[LLAssetType::AT_CLOTHING] = LLWearableTypeOrder(ORDER_RANK_1, false, false); - mWearableOrder[LLAssetType::AT_OBJECT] = LLWearableTypeOrder(ORDER_RANK_2, true, true); - mWearableOrder[LLAssetType::AT_BODYPART] = LLWearableTypeOrder(ORDER_RANK_3, false, true); + mWearableOrder[LLAssetType::AT_CLOTHING] = LLWearableTypeOrder(ORDER_RANG_1, false, false); + mWearableOrder[LLAssetType::AT_OBJECT] = LLWearableTypeOrder(ORDER_RANG_2, true, true); + mWearableOrder[LLAssetType::AT_BODYPART] = LLWearableTypeOrder(ORDER_RANG_3, false, true); } void LLWearableItemTypeNameComparator::setOrder(LLAssetType::EType items_of_type, LLWearableItemTypeNameComparator::ETypeListOrder order_priority, bool sort_asset_items_by_name, bool sort_wearable_items_by_name) @@ -527,6 +527,8 @@ bool LLWearableItemTypeNameComparator::doCompare(const LLPanelInventoryListItemB const LLWearableType::EType item_wearable_type2 = wearable_item2->getWearableType(); if (item_wearable_type1 != item_wearable_type2) + // If items are of different LLWearableType::EType types they are compared + // by LLWearableType::EType. types order determined in LLWearableType::EType. { // If items are of different LLWearableType::EType types they are compared // by LLWearableType::EType. types order determined in LLWearableType::EType. @@ -549,10 +551,11 @@ LLWearableItemTypeNameComparator::ETypeListOrder LLWearableItemTypeNameComparato { wearable_type_order_map_t::const_iterator const_it = mWearableOrder.find(item_type); + if(const_it == mWearableOrder.end()) { llwarns<<"Absent information about order rang of items of "<second.mOrderPriority; @@ -562,25 +565,30 @@ bool LLWearableItemTypeNameComparator::sortAssetTypeByName(LLAssetType::EType it { wearable_type_order_map_t::const_iterator const_it = mWearableOrder.find(item_type); + if(const_it == mWearableOrder.end()) { llwarns<<"Absent information about sorting items of "<second.mSortAssetTypeByName; } + bool LLWearableItemTypeNameComparator::sortWearableTypeByName(LLAssetType::EType item_type) const { wearable_type_order_map_t::const_iterator const_it = mWearableOrder.find(item_type); + if(const_it == mWearableOrder.end()) { llwarns<<"Absent information about sorting items of "<second.mSortWearableTypeByName; } ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index f2f81968ee..237ba1af43 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -313,10 +313,10 @@ public: enum ETypeListOrder { - ORDER_RANK_1 = 1, - ORDER_RANK_2, - ORDER_RANK_3, - ORDER_RANK_UNKNOWN + ORDER_RANG_1 = 1, + ORDER_RANG_2, + ORDER_RANG_3, + ORDER_RANG_UNKNOWN }; void setOrder(LLAssetType::EType items_of_type, ETypeListOrder order_priority, bool sort_items_by_name, bool sort_wearable_items_by_name); @@ -325,15 +325,15 @@ protected: /** * All information about sort order is stored in mWearableOrder map * - * mWearableOrder : KYES VALUES + * mWearableOrder : KEYES VALUES * [LLAssetType] [struct LLWearableTypeOrder] * *--------------------------------------------------------------------------------------------- - * I. Determines order (ORDER_RANK) in which items of LLAssetType should be displayed in list. + * I. Determines order (ORDER_RANG) in which items of LLAssetType should be displayed in list. * For example by spec in MY OUTFITS the order is: - * 1. AT_CLOTHING (ORDER_RANK_1) - * 2. AT_OBJECT (ORDER_RANK_2) - * 3. AT_BODYPART (ORDER_RANK_3) + * 1. AT_CLOTHING (ORDER_RANG_1) + * 2. AT_OBJECT (ORDER_RANG_2) + * 3. AT_BODYPART (ORDER_RANG_3) * * II.Items of each type(LLAssetType) are sorted by name or type(LLWearableType) * For example by spec in MY OUTFITS the order within each items type(LLAssetType) is: @@ -346,7 +346,7 @@ protected: * * For each LLAssetType (KEYS in mWearableOrder) the information about: * - * I. ORDER_RANK (the flag is LLWearableTypeOrder::mOrderPriority) + * I. ORDER_RANG (the flag is LLWearableTypeOrder::mOrderPriority) * * II. whether items of this LLAssetType type should be ordered * by name or by LLWearableType::EType (the flag is LLWearableTypeOrder::mSortAssetTypeByName) -- cgit v1.2.3 From dd692f17ab12d44177253e9dde33c93e37caef5e Mon Sep 17 00:00:00 2001 From: Sergei Litovchuk Date: Thu, 12 Aug 2010 15:56:51 +0300 Subject: EXT-8628 FIXED Crash in LLVOAvatarSelf::getAttachedPointName(). The crash was reproducible only on startup. Apparently, gAgentAvatarp was not valid at that point. Worked around by checking gAgentAvatarp for being valid. I didn't investigate what the root cause of the problem was (probably the new multi-attachments implementation), I just needed my viewer to work. Reviewed by Seraph at https://codereview.productengine.com/secondlife/r/847/. --HG-- branch : product-engine --- indra/newview/llinventorybridge.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 38f3521b2d..9bbc6514b4 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3985,6 +3985,11 @@ std::string LLObjectBridge::getLabelSuffix() const { if (get_is_item_worn(mUUID)) { + if (!isAgentAvatarValid()) + { + return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); + } + std::string attachment_point_name = gAgentAvatarp->getAttachedPointName(mUUID); // e.g. "(worn on ...)" / "(attached to ...)" -- cgit v1.2.3 From 4281e2bd01c64acd2c5b0ae106f890be7d2fc443 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Thu, 12 Aug 2010 14:12:54 +0100 Subject: EXT-8589 FIXED Nothing happens if choose 'Invite to Group' from avatar's 3D context menu The groups-chooser was auto-closing when the IW selection was lost, which in the case of right-clicking on (other) avatars is immediately. The 'hg blame' is lost in merge-fubarism so I can't track why this behaviour was ever introduced, but I can think or (or find) no reason to autoclose in this case - the groups picker dialog doesn't even use the current selection, let alone care if it's lost. --- indra/newview/llfloatergroups.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp index 3952c54670..307c937f6e 100644 --- a/indra/newview/llfloatergroups.cpp +++ b/indra/newview/llfloatergroups.cpp @@ -47,7 +47,6 @@ #include "llbutton.h" #include "llgroupactions.h" #include "llscrolllistctrl.h" -#include "llselectmgr.h" #include "lltextbox.h" #include "lluictrlfactory.h" #include "lltrans.h" @@ -90,8 +89,6 @@ BOOL LLFloaterGroupPicker::postBuild() list_ctrl->setContextMenu(LLScrollListCtrl::MENU_GROUP); } - LLSelectMgr::getInstance()->mUpdateSignal.connect(boost::bind(&LLFloaterGroupPicker::onBtnCancel, this)); - childSetAction("OK", onBtnOK, this); childSetAction("Cancel", onBtnCancel, this); -- cgit v1.2.3 From 5de5510f58f641ddc8fca855db662d77238c134d Mon Sep 17 00:00:00 2001 From: Vadim Savchuk Date: Thu, 12 Aug 2010 16:13:48 +0300 Subject: EXT-8629 FIXED Enable the Wear button in My Outfits for outfits that are subsets of the current outfit. We allowed wearing any outfit that contains non-worn items. Now it appears to be wrong, therefore and I changed condition so that we allow wearing any outfit (or folder) that contains the full set of body parts. Reviewed by Sergey Litovchuk at https://codereview.productengine.com/secondlife/r/855/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 2729053390..6fdd71bfbf 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1305,16 +1305,8 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) return false; } - // Check whether the outfit contains any non-worn wearables. - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ true); - gInventory.collectDescendentsIf(outfit_cat_id, - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - not_worn); - return items.size() > 0; + // Check whether the outfit contains the full set of body parts (shape+skin+hair+eyes). + return getCanMakeFolderIntoOutfit(outfit_cat_id); } void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) -- cgit v1.2.3 From 44adcdecd0abb1726d6ae778e6e37b4da431e55a Mon Sep 17 00:00:00 2001 From: Vadim Savchuk Date: Thu, 12 Aug 2010 16:16:57 +0300 Subject: EXT-8473 FIXED Fixed renaming inventory items without hitting Enter. Problem: The bug was caused by the fix of EXT-6682 that prematurely forgets the item being renamed (by resetting mRenameItem) whenever the renamer input field loses focus. That's why we couldn't actually finish renaming item. Fix: The code is quite messy, but I'll try to explain. There are three cases when we should hide the renamer: 1) ESC key is hit (just hide). 2) ENTER key is hit (rename, then hide). 3) renamer loses focus (rename, then hide). In the first two cases we manually remove the renamer from the popups list -- by calling gViewerWindow->removePopup(mRenamer). In the third case that's done automatically. So, in all cases the onRenamerLost() pop-up is called that hides the renamer and only *then* resets mRenameItem. Not only this approach fixes the bug -- I hope it's a bit more straightforward too. Reviewed by Seraph at https://codereview.productengine.com/secondlife/r/854/ --HG-- branch : product-engine --- indra/newview/llfolderview.cpp | 48 ++++++++++++++++++------------------------ indra/newview/llfolderview.h | 2 +- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 5aa504eb35..81f00af948 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -104,7 +104,6 @@ void copy_selected_item(void* user_data); void open_selected_items(void* user_data); void properties_selected_items(void* user_data); void paste_items(void* user_data); -void renamer_focus_lost( LLFocusableElement* handler, void* user_data ); //--------------------------------------------------------------------------- @@ -275,6 +274,8 @@ LLFolderView::LLFolderView(const Params& p) // Destroys the object LLFolderView::~LLFolderView( void ) { + closeRenamer(); + // The release focus call can potentially call the // scrollcontainer, which can potentially be called with a partly // destroyed scollcontainer. Just null it out here, and no worries @@ -290,8 +291,6 @@ LLFolderView::~LLFolderView( void ) LLView::deleteViewByHandle(mPopupMenuHandle); - gViewerWindow->removePopup(mRenamer); - mAutoOpenItems.removeAllNodes(); clearSelection(); mItems.clear(); @@ -998,12 +997,7 @@ void LLFolderView::finishRenamingItem( void ) mRenameItem->rename( mRenamer->getText() ); } - gViewerWindow->removePopup(mRenamer); - - if( mRenameItem ) - { - setSelectionFromRoot( mRenameItem, TRUE ); - } + closeRenamer(); // List is re-sorted alphabeticly, so scroll to make sure the selected item is visible. scrollToShowSelection(); @@ -1011,15 +1005,10 @@ void LLFolderView::finishRenamingItem( void ) void LLFolderView::closeRenamer( void ) { - // will commit current name (which could be same as original name) - mRenamer->setFocus( FALSE ); - mRenamer->setVisible( FALSE ); - gViewerWindow->removePopup(mRenamer); - - if( mRenameItem ) + if (mRenamer && mRenamer->getVisible()) { - setSelectionFromRoot( mRenameItem, TRUE ); - mRenameItem = NULL; + // Triggers onRenamerLost() that actually closes the renamer. + gViewerWindow->removePopup(mRenamer); } } @@ -1444,8 +1433,7 @@ void LLFolderView::startRenamingSelectedItem( void ) mRenamer->setVisible( TRUE ); // set focus will fail unless item is visible mRenamer->setFocus( TRUE ); - mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this, _1)); - mRenamer->setFocusLostCallback(boost::bind(&LLFolderView::onRenamerLost, this, _1)); + mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); gViewerWindow->addPopup(mRenamer); } } @@ -1966,10 +1954,7 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLFolderView::deleteAllChildren() { - if(mRenamer == gFocusMgr.getTopCtrl()) - { - gViewerWindow->removePopup(mRenamer); - } + closeRenamer(); LLView::deleteViewByHandle(mPopupMenuHandle); mPopupMenuHandle = LLHandle(); mRenamer = NULL; @@ -2452,13 +2437,20 @@ S32 LLFolderView::notify(const LLSD& info) /// Local function definitions ///---------------------------------------------------------------------------- -void LLFolderView::onRenamerLost( LLFocusableElement* renamer) +void LLFolderView::onRenamerLost() { - mRenameItem = NULL; - LLUICtrl* uictrl = dynamic_cast(renamer); - if (uictrl) + if (mRenamer && mRenamer->getVisible()) { - uictrl->setVisible(FALSE); + mRenamer->setVisible(FALSE); + + // will commit current name (which could be same as original name) + mRenamer->setFocus(FALSE); + } + + if( mRenameItem ) + { + setSelectionFromRoot( mRenameItem, TRUE ); + mRenameItem = NULL; } } diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index f1d39a41ae..31352d04bf 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -284,7 +284,7 @@ protected: LLScrollContainer* mScrollContainer; // NULL if this is not a child of a scroll container. void commitRename( const LLSD& data ); - void onRenamerLost( LLFocusableElement* renamer); + void onRenamerLost(); void finishRenamingItem( void ); void closeRenamer( void ); -- cgit v1.2.3 From 4627c4b698cf75abd8bd59b6a05ea923c57f7574 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Thu, 12 Aug 2010 21:52:22 -0600 Subject: Fix for EXT-8578: Blurry image in profile never resolves - texture queue problem? --- indra/newview/llviewertexture.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index e38608bcfc..9b3243a1bc 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -814,7 +814,7 @@ void LLViewerTexture::generateGLTexture() LLImageGL* LLViewerTexture::getGLTexture() const { llassert(mGLTexturep.notNull()) ; - + return mGLTexturep ; } @@ -1489,8 +1489,13 @@ void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height) //virtual void LLViewerFetchedTexture::processTextureStats() { - if(mFullyLoaded) + if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0) //force to refetch the texture. { + mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel) ; + } + + if(mFullyLoaded) + { if(mDesiredDiscardLevel <= mMinDesiredDiscardLevel)//already loaded { return ; -- cgit v1.2.3 From 5881252ab2e9ab31b05c1a54d8ce723013eee15a Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Fri, 13 Aug 2010 11:12:51 -0400 Subject: EXT-8650 Can wear multiple copies of no-copy item via object links * EXT-8688 Automatically detach same object is detected * EXT-8689 Cleanup detachAttachmentIntoInventory code When an object arrives as an attachment, if it's already attached then it's automatically detached. --- indra/newview/llappearancemgr.cpp | 32 ++++++++++--------------------- indra/newview/llinventorybridge.cpp | 27 ++------------------------ indra/newview/llviewerjointattachment.cpp | 21 ++++++++++++++++---- indra/newview/llvoavatarself.cpp | 23 ++++++++++++++++++++++ indra/newview/llvoavatarself.h | 1 + 5 files changed, 53 insertions(+), 51 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 6fdd71bfbf..21a635e738 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2496,29 +2496,17 @@ void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove) switch (item_to_remove->getType()) { - case LLAssetType::AT_CLOTHING: - if (get_is_item_worn(id_to_remove)) - { - //*TODO move here the exact removing code from LLWearableBridge::removeItemFromAvatar in the future - LLWearableBridge::removeItemFromAvatar(item_to_remove); - } - break; - case LLAssetType::AT_OBJECT: - gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_to_remove->getLinkedUUID()); - gMessageSystem->sendReliable( gAgent.getRegion()->getHost()); - - { - // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = gObjectList.findObject(item_to_remove->getLinkedUUID()); - if (found_obj) + case LLAssetType::AT_CLOTHING: + if (get_is_item_worn(id_to_remove)) { - LLSelectMgr::getInstance()->remove(found_obj); - }; - } - default: break; + //*TODO move here the exact removing code from LLWearableBridge::removeItemFromAvatar in the future + LLWearableBridge::removeItemFromAvatar(item_to_remove); + } + break; + case LLAssetType::AT_OBJECT: + LLVOAvatarSelf::detachAttachmentIntoInventory(item_to_remove->getLinkedUUID()); + default: + break; } // *HACK: Force to remove garbage from COF. diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 9bbc6514b4..66bf325f04 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3957,18 +3957,7 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action) LLInventoryItem* item = gInventory.getItem(mUUID); if(item) { - gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); - gMessageSystem->sendReliable( gAgent.getRegion()->getHost()); - - // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = gObjectList.findObject(item->getLinkedUUID()); - if (found_obj) - { - LLSelectMgr::getInstance()->remove(found_obj); - } + LLVOAvatarSelf::detachAttachmentIntoInventory(item->getLinkedUUID()); } } else LLItemBridge::performAction(model, action); @@ -4321,19 +4310,7 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_ LLViewerInventoryItem *obj_item = obj_item_array.get(i); if (get_is_item_worn(obj_item->getUUID())) { - gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item->getLinkedUUID() ); - - gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); - - // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = gObjectList.findObject( obj_item->getLinkedUUID()); - if (found_obj) - { - LLSelectMgr::getInstance()->remove(found_obj); - } + LLVOAvatarSelf::detachAttachmentIntoInventory(obj_item->getLinkedUUID()); } } } diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp index da4960b69d..c9335366cd 100644 --- a/indra/newview/llviewerjointattachment.cpp +++ b/indra/newview/llviewerjointattachment.cpp @@ -35,12 +35,11 @@ #include "llviewerjointattachment.h" #include "llagentconstants.h" - #include "llviewercontrol.h" #include "lldrawable.h" #include "llgl.h" #include "llrender.h" -#include "llvoavatar.h" +#include "llvoavatarself.h" #include "llvolume.h" #include "pipeline.h" #include "llspatialpartition.h" @@ -164,6 +163,9 @@ void LLViewerJointAttachment::setupDrawable(LLViewerObject *object) //----------------------------------------------------------------------------- BOOL LLViewerJointAttachment::addObject(LLViewerObject* object) { + object->extractAttachmentItemID(); + + // Same object reattached if (isObjectAttached(object)) { llinfos << "(same object re-attached)" << llendl; @@ -171,8 +173,19 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object) // Pass through anyway to let setupDrawable() // re-connect object to the joint correctly } + + // Two instances of the same inventory item attached -- + // Request detach, and kill the object in the meantime. + if (getAttachedObject(object->getAttachmentItemID())) + { + llinfos << "(same object re-attached)" << llendl; + object->markDead(); + + // If this happens to be attached to self, then detach. + LLVOAvatarSelf::detachAttachmentIntoInventory(object->getAttachmentItemID()); + return FALSE; + } - object->extractAttachmentItemID(); mAttachedObjects.push_back(object); setupDrawable(object); @@ -195,7 +208,7 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object) } calcLOD(); mUpdateXform = TRUE; - + return TRUE; } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 73ea629bc3..09e50dcb90 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1115,6 +1115,29 @@ BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object) return FALSE; } +// static +BOOL LLVOAvatarSelf::detachAttachmentIntoInventory(const LLUUID &item_id) +{ + LLInventoryItem* item = gInventory.getItem(item_id); + if (item) + { + gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id); + gMessageSystem->sendReliable(gAgent.getRegion()->getHost()); + + // this object might have been selected, so let the selection manager know it's gone now + LLViewerObject *found_obj = gObjectList.findObject(item_id); + if (found_obj) + { + LLSelectMgr::getInstance()->remove(found_obj); + } + return TRUE; + } + return FALSE; +} + U32 LLVOAvatarSelf::getNumWearables(LLVOAvatarDefines::ETextureIndex i) const { LLWearableType::EType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i); diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 630afe7a0f..37d24d138f 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -295,6 +295,7 @@ public: const std::string getAttachedPointName(const LLUUID& inv_item_id) const; /*virtual*/ const LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object); /*virtual*/ BOOL detachObject(LLViewerObject *viewer_object); + static BOOL detachAttachmentIntoInventory(const LLUUID& item_id); //-------------------------------------------------------------------- // HUDs -- cgit v1.2.3 From f369ebec244f57205d0a9c835d4184c827e7b50f Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Fri, 13 Aug 2010 11:26:22 -0400 Subject: EXT-8650 Can wear multiple copies of no-copy item via object links * EXT-8661 Take out unused mRegisteredAttachments in LLAppearanceMgr Removed unused mRegisteredAttachments. Not sure what this was used for, but it's no longer used. --- indra/newview/llappearancemgr.cpp | 15 --------------- indra/newview/llappearancemgr.h | 2 -- 2 files changed, 17 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 21a635e738..5c713e60f9 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2646,7 +2646,6 @@ void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val) mAttachmentInvLinkEnabled = val; } -// BAP TODO - mRegisteredAttachments is currently maintained but not used for anything. Consider yanking. void dumpAttachmentSet(const std::set& atts, const std::string& msg) { llinfos << msg << llendl; @@ -2666,7 +2665,6 @@ void dumpAttachmentSet(const std::set& atts, const std::string& msg) void LLAppearanceMgr::registerAttachment(const LLUUID& item_id) { - mRegisteredAttachments.insert(item_id); gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); if (mAttachmentInvLinkEnabled) @@ -2684,7 +2682,6 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id) void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) { - mRegisteredAttachments.erase(item_id); gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); if (mAttachmentInvLinkEnabled) @@ -2697,18 +2694,6 @@ void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) } } -void LLAppearanceMgr::linkRegisteredAttachments() -{ - for (std::set::iterator it = mRegisteredAttachments.begin(); - it != mRegisteredAttachments.end(); - ++it) - { - LLUUID item_id = *it; - addCOFItemLink(item_id, false); - } - mRegisteredAttachments.clear(); -} - BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const { return gInventory.isObjectDescendentOf(obj_id, getCOF()); diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index eb495bd274..73b05ff7cd 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -119,7 +119,6 @@ public: void unregisterAttachment(const LLUUID& item_id); void registerAttachment(const LLUUID& item_id); void setAttachmentInvLinkEnable(bool val); - void linkRegisteredAttachments(); // utility function for bulk linking. void linkAll(const LLUUID& category, @@ -206,7 +205,6 @@ private: void setOutfitLocked(bool locked); - std::set mRegisteredAttachments; bool mAttachmentInvLinkEnabled; bool mOutfitIsDirty; bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls. -- cgit v1.2.3