diff options
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/llappearancemgr.cpp | 31 | ||||
-rw-r--r-- | indra/newview/llappearancemgr.h | 3 | ||||
-rw-r--r-- | indra/newview/llcofwearables.cpp | 8 | ||||
-rw-r--r-- | indra/newview/lloutfitslist.cpp | 10 | ||||
-rw-r--r-- | indra/newview/llpaneloutfitedit.cpp | 4 | ||||
-rw-r--r-- | indra/newview/llpaneloutfitedit.h | 2 | ||||
-rw-r--r-- | indra/newview/lltexlayer.cpp | 6 | ||||
-rw-r--r-- | indra/newview/lltexturefetch.cpp | 74 | ||||
-rw-r--r-- | indra/newview/lltexturefetch.h | 13 | ||||
-rw-r--r-- | indra/newview/llviewerregion.cpp | 32 | ||||
-rw-r--r-- | indra/newview/llviewerregion.h | 10 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 12 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/panel_login.xml | 1 |
13 files changed, 165 insertions, 41 deletions
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 78edcb3e25..2729053390 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1275,6 +1275,11 @@ bool LLAppearanceMgr::getCanRemoveFromCOF(const LLUUID& outfit_cat_id) // static bool LLAppearanceMgr::getCanAddToCOF(const LLUUID& outfit_cat_id) { + if (gAgentWearables.isCOFChangeInProgress()) + { + return false; + } + LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false); @@ -1286,6 +1291,32 @@ bool LLAppearanceMgr::getCanAddToCOF(const LLUUID& outfit_cat_id) return items.size() > 0; } +bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) +{ + // Don't allow wearing anything while we're changing appearance. + if (gAgentWearables.isCOFChangeInProgress()) + { + return false; + } + + // Check whether it's the base outfit. + if (outfit_cat_id.isNull() || outfit_cat_id == getBaseOutfitUUID()) + { + 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; +} + void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) { LLInventoryModel::cat_array_t cats; diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 9f554dbdef..eb495bd274 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -84,6 +84,9 @@ public: // Determine whether we can add anything (but body parts) from the outfit contents to COF. static bool getCanAddToCOF(const LLUUID& outfit_cat_id); + // Determine whether we can replace current outfit with the given one. + bool getCanReplaceCOF(const LLUUID& outfit_cat_id); + // Copy all items in a category. void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id, LLPointer<LLInventoryCallback> cb); diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index 893400185c..eb950bf6c1 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -163,7 +163,7 @@ public: } protected: - static void replaceWearable() + static void replaceWearable(const LLUUID& item_id) { // *TODO: Most probable that accessing to LLPanelOutfitEdit instance should be: // LLSideTray::getInstance()->getSidepanelAppearance()->getPanelOutfitEdit() @@ -175,7 +175,7 @@ protected: "panel_outfit_edit")); if (panel_outfit_edit != NULL) { - panel_outfit_edit->showAddWearablesPanel(true); + panel_outfit_edit->onReplaceMenuItemClicked(item_id); } } @@ -187,7 +187,7 @@ protected: functor_t take_off = boost::bind(&LLAppearanceMgr::removeItemFromAvatar, LLAppearanceMgr::getInstance(), _1); registrar.add("Clothing.TakeOff", boost::bind(handleMultiple, take_off, mUUIDs)); - registrar.add("Clothing.Replace", boost::bind(replaceWearable)); + registrar.add("Clothing.Replace", boost::bind(replaceWearable, selected_id)); registrar.add("Clothing.Edit", boost::bind(LLAgentWearables::editWearable, selected_id)); registrar.add("Clothing.Create", boost::bind(&CofClothingContextMenu::createNew, this, selected_id)); @@ -244,7 +244,7 @@ protected: // *HACK* need to pass pointer to LLPanelOutfitEdit instead of LLSideTray::getInstance()->getPanel(). // LLSideTray::getInstance()->getPanel() is rather slow variant LLPanelOutfitEdit* panel_oe = dynamic_cast<LLPanelOutfitEdit*>(LLSideTray::getInstance()->getPanel("panel_outfit_edit")); - registrar.add("BodyPart.Replace", boost::bind(&LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked, panel_oe, selected_id)); + registrar.add("BodyPart.Replace", boost::bind(&LLPanelOutfitEdit::onReplaceMenuItemClicked, panel_oe, selected_id)); registrar.add("BodyPart.Edit", boost::bind(LLAgentWearables::editWearable, selected_id)); registrar.add("BodyPart.Create", boost::bind(&CofBodyPartContextMenu::createNew, this, selected_id)); diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 8147a97317..f921bca623 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -275,11 +275,10 @@ protected: } else if ("wear_replace" == param) { - return !gAgentWearables.isCOFChangeInProgress(); + return LLAppearanceMgr::instance().getCanReplaceCOF(outfit_cat_id); } else if ("wear_add" == param) { - if (gAgentWearables.isCOFChangeInProgress()) return false; return LLAppearanceMgr::getCanAddToCOF(outfit_cat_id); } else if ("take_off" == param) @@ -676,7 +675,7 @@ bool LLOutfitsList::isActionEnabled(const LLSD& userdata) } // outfit selected - return LLAppearanceMgr::getCanAddToCOF(mSelectedOutfitUUID); + return LLAppearanceMgr::instance().getCanReplaceCOF(mSelectedOutfitUUID); } if (command_name == "take_off") { @@ -689,11 +688,6 @@ bool LLOutfitsList::isActionEnabled(const LLSD& userdata) if (command_name == "wear_add") { // *TODO: do we ever get here? - if (gAgentWearables.isCOFChangeInProgress()) - { - return false; - } - return LLAppearanceMgr::getCanAddToCOF(mSelectedOutfitUUID); } diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 8b9baef54a..c12f1fbe99 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -609,11 +609,11 @@ void LLPanelOutfitEdit::onAddWearableClicked(void) } } -void LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked(LLUUID selected_item_id) +void LLPanelOutfitEdit::onReplaceMenuItemClicked(LLUUID selected_item_id) { LLViewerInventoryItem* item = gInventory.getLinkedItem(selected_item_id); - if (item && item->getType() == LLAssetType::AT_BODYPART) + if (item) { showFilteredWearablesListView(item->getWearableType()); } diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index 0efc6dc189..5ce707e6eb 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -164,7 +164,7 @@ public: void onRemoveFromOutfitClicked(void); void onEditWearableClicked(void); void onAddWearableClicked(void); - void onReplaceBodyPartMenuItemClicked(LLUUID selected_item_id); + void onReplaceMenuItemClicked(LLUUID selected_item_id); void onShopButtonClicked(); void displayCurrentOutfit(); diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index f4f8241b99..1feb987682 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -542,8 +542,7 @@ void LLTexLayerSetBuffer::doUpload() args["TIME"] = llformat("%d",(U32)mNeedsUploadTimer.getElapsedTimeF32()); args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); args["RESOLUTION"] = lod_str; - args["ACTION"] = "uploaded"; - LLNotificationsUtil::add("AvatarRezSelfBakeNotification",args); + LLNotificationsUtil::add("AvatarRezSelfBakedTextureUploadNotification",args); llinfos << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << llendl; } } @@ -593,8 +592,7 @@ void LLTexLayerSetBuffer::doUpdate() args["TIME"] = llformat("%d",(U32)mNeedsUpdateTimer.getElapsedTimeF32()); args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); args["RESOLUTION"] = lod_str; - args["ACTION"] = "locally updated"; - LLNotificationsUtil::add("AvatarRezSelfBakeNotification",args); + LLNotificationsUtil::add("AvatarRezSelfBakedTextureUpdateNotification",args); llinfos << "Locally updating [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << llendl; } } diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index dddfed097d..65a40a5b3a 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -850,15 +850,14 @@ bool LLTextureFetchWorker::doWork(S32 param) { if(mCanUseHTTP) { - const S32 HTTP_QUEUE_MAX_SIZE = 8; // *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->getHTTPQueueSize() >= HTTP_QUEUE_MAX_SIZE) || - (mFetcher->getTextureBandwidth() > max_bandwidth)) + 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); @@ -1250,7 +1249,7 @@ bool LLTextureFetchWorker::deleteOK() if ((haveWork() && // not ok to delete from these states - ((mState >= SEND_HTTP_REQ && mState <= WAIT_HTTP_REQ) || + ((mState == WAIT_HTTP_REQ) || (mState >= WRITE_TO_CACHE && mState <= WAIT_ON_WRITE)))) { delete_ok = false; @@ -1511,6 +1510,11 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image { 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() @@ -1658,6 +1662,65 @@ void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id) 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. +} + void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel) { lockQueue() ; @@ -1824,7 +1887,8 @@ 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 634e590fe0..c31c38b04a 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -95,7 +95,8 @@ protected: void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel); void addToHTTPQueue(const LLUUID& id); void removeFromHTTPQueue(const LLUUID& id); - S32 getHTTPQueueSize() { return getNumHTTPRequests(); } + bool isHTTPThrottled(S32 requested_size); + void clearHTTPThrottleFlag(); void removeRequest(LLTextureFetchWorker* worker, bool cancel); // Called from worker thread (during doWork) void processCurlRequests(); @@ -134,6 +135,16 @@ private: F32 mTextureBandwidth; 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]; }; #endif // LL_LLTEXTUREFETCH_H diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 004d138221..82fef1d916 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -79,6 +79,8 @@ // format changes. JC const U32 INDRA_OBJECT_CACHE_VERSION = 14; +// Format string used to construct filename for the object cache +static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc"; extern BOOL gNoRender; @@ -323,13 +325,25 @@ LLViewerRegion::~LLViewerRegion() delete mEventPoll; LLHTTPSender::clearSender(mHost); - saveCache(); + saveObjectCache(); std::for_each(mObjectPartition.begin(), mObjectPartition.end(), DeletePointer()); } -void LLViewerRegion::loadCache() +const std::string LLViewerRegion::getObjectCacheFilename(U64 mHandle) const +{ + std::string filename; + U32 region_x, region_y; + + grid_from_region_handle(mHandle, ®ion_x, ®ion_y); + filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, + llformat(OBJECT_CACHE_FILENAME, region_x, region_y)); + + return filename; +} + +void LLViewerRegion::loadObjectCache() { if (mCacheLoaded) { @@ -341,9 +355,8 @@ void LLViewerRegion::loadCache() LLVOCacheEntry *entry; - std::string filename; - filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"") + gDirUtilp->getDirDelimiter() + - llformat("objects_%d_%d.slc",U32(mHandle>>32)/REGION_WIDTH_UNITS, U32(mHandle)/REGION_WIDTH_UNITS ); + std::string filename = getObjectCacheFilename(mHandle); + LL_DEBUGS("ObjectCache") << filename << LL_ENDL; LLFILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */ if (!fp) @@ -414,7 +427,7 @@ void LLViewerRegion::loadCache() } -void LLViewerRegion::saveCache() +void LLViewerRegion::saveObjectCache() { if (!mCacheLoaded) { @@ -427,9 +440,8 @@ void LLViewerRegion::saveCache() return; } - std::string filename; - filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"") + gDirUtilp->getDirDelimiter() + - llformat("objects_%d_%d.slc", U32(mHandle>>32)/REGION_WIDTH_UNITS, U32(mHandle)/REGION_WIDTH_UNITS ); + std::string filename = getObjectCacheFilename(mHandle); + LL_DEBUGS("ObjectCache") << filename << LL_ENDL; LLFILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */ if (!fp) @@ -1454,7 +1466,7 @@ void LLViewerRegion::unpackRegionHandshake() // Now that we have the name, we can load the cache file // off disk. - loadCache(); + loadObjectCache(); // After loading cache, signal that simulator can start // sending data. diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index a9e7ef771c..8254cf1cad 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -99,9 +99,8 @@ public: ~LLViewerRegion(); // Call this after you have the region name and handle. - void loadCache(); - - void saveCache(); + void loadObjectCache(); + void saveObjectCache(); void sendMessage(); // Send the current message to this region's simulator void sendReliableMessage(); // Send the current message to this region's simulator @@ -330,6 +329,9 @@ public: LLDynamicArray<LLUUID> mMapAvatarIDs; private: + // determine the cache filename for the region from the region handle + const std::string getObjectCacheFilename(U64 mHandle) const; + // The surfaces and other layers LLSurface* mLandp; @@ -404,7 +406,7 @@ private: // Cache ID is unique per-region, across renames, moving locations, // etc. LLUUID mCacheID; - + typedef std::map<std::string, std::string> CapabilityMap; CapabilityMap mCapabilities; diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 95ee374e39..3576462cca 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6340,10 +6340,18 @@ Avatar '[NAME]' left as fully loaded. <notification icon="notifytip.tga" - name="AvatarRezSelfBakeNotification" + name="AvatarRezSelfBakedTextureUploadNotification" type="notifytip"> ( [EXISTENCE] seconds alive ) -You [ACTION] a [RESOLUTION] baked texture for '[BODYREGION]' after [TIME] seconds. +You uploaded a [RESOLUTION] baked texture for '[BODYREGION]' after [TIME] seconds. + </notification> + + <notification + icon="notifytip.tga" + name="AvatarRezSelfBakedTextureUpdateNotification" + type="notifytip"> +( [EXISTENCE] seconds alive ) +You locally updated a [RESOLUTION] baked texture for '[BODYREGION]' after [TIME] seconds. </notification> <notification diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index 185e458a85..0499873fb0 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -156,6 +156,7 @@ width="135" visible="false" /> </layout_panel> <layout_panel +tab_stop="false" follows="right|bottom" name="links" width="200" |