From 50eb27a04d193ef145f8879e12d8a82089a66891 Mon Sep 17 00:00:00 2001 From: Alexei Arabadji Date: Tue, 8 Jun 2010 15:36:48 +0300 Subject: EXT-7644 FIXED Implemented functionality for locking outfit modification controls and used it for 'save outfit' action. 1 Added functionality for locking outfit in LLAppearanceMgr. Outfit should be locked when outfit related operation is started(now it is used for updateBaseOutfit) and unlocked when operation completed or timeout is exceeded. 2 Added outfit saved and outfit lock changed signals to LLOutfitObserver. 3 Updated LLPanelOutfitsInventory and LLPanelOutfitEdit with functionality of controlling 'save outfit' controls state('save outfit' controls should be enabled only if outfit isn't locked and outfit is dirty). 4 Renamed action label of method LLPanelOutfitsInventory::isActionEnabled "make_outfit" to "save_outfit". --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 67 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index a899926938..135629bb8d 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -38,11 +38,13 @@ #include "llagentwearables.h" #include "llappearancemgr.h" #include "llcommandhandler.h" +#include "lleventtimer.h" #include "llgesturemgr.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventoryobserver.h" #include "llnotificationsutil.h" +#include "lloutfitobserver.h" #include "llpaneloutfitsinventory.h" #include "llselectmgr.h" #include "llsidepanelappearance.h" @@ -55,6 +57,34 @@ char ORDER_NUMBER_SEPARATOR('@'); +class LLOutfitUnLockTimer: public LLEventTimer +{ +public: + LLOutfitUnLockTimer(F32 period) : LLEventTimer(period) + { + // restart timer on BOF changed event + LLOutfitObserver::instance().addBOFChangedCallback(boost::bind( + &LLOutfitUnLockTimer::reset, this)); + stop(); + } + + /*virtual*/ + BOOL tick() + { + if(mEventTimer.hasExpired()) + { + LLAppearanceMgr::instance().setOutfitLocked(false); + } + return FALSE; + } + void stop() { mEventTimer.stop(); } + void start() { mEventTimer.start(); } + void reset() { mEventTimer.reset(); } + BOOL getStarted() { return mEventTimer.getStarted(); } + + LLTimer& getEventTimer() { return mEventTimer;} +}; + // support for secondlife:///app/appearance SLapps class LLAppearanceHandler : public LLCommandHandler { @@ -762,6 +792,27 @@ void LLAppearanceMgr::onOutfitRename(const LLSD& notification, const LLSD& respo } } +void LLAppearanceMgr::setOutfitLocked(bool locked) +{ + if (mOutfitLocked == locked) + { + return; + } + + mOutfitLocked = locked; + if (locked) + { + mUnlockOutfitTimer->reset(); + mUnlockOutfitTimer->start(); + } + else + { + mUnlockOutfitTimer->stop(); + } + + LLOutfitObserver::instance().notifyOutfitLockChanged(); +} + void LLAppearanceMgr::addCategoryToCurrentOutfit(const LLUUID& cat_id) { LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); @@ -1810,6 +1861,14 @@ void LLAppearanceMgr::onFirstFullyVisible() bool LLAppearanceMgr::updateBaseOutfit() { + if (isOutfitLocked()) + { + // don't allow modify locked outfit + llassert(!isOutfitLocked()); + return false; + } + setOutfitLocked(true); + const LLUUID base_outfit_id = getBaseOutfitUUID(); if (base_outfit_id.isNull()) return false; @@ -2138,6 +2197,14 @@ LLAppearanceMgr::LLAppearanceMgr(): mAttachmentInvLinkEnabled(false), mOutfitIsDirty(false) { + LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); + + // unlock outfit on save operation completed + outfit_observer.addCOFSavedCallback(boost::bind( + &LLAppearanceMgr::setOutfitLocked, this, false)); + + mUnlockOutfitTimer.reset(new LLOutfitUnLockTimer(gSavedSettings.getS32( + "OutfitOperationsTimeout"))); } LLAppearanceMgr::~LLAppearanceMgr() -- cgit v1.2.3 From 56da8017d9622e092947b504813d8a40d21310a6 Mon Sep 17 00:00:00 2001 From: Leyla Farazha Date: Tue, 8 Jun 2010 14:52:22 -0700 Subject: EXT-7210 Baked textures should only be updated when outfit changes are saved or outfit editor is exited. reviewed and contributed to by Nyx --- indra/newview/llappearancemgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 135629bb8d..12d2752180 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2139,7 +2139,7 @@ bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_b bool result = false; if (result = gAgentWearables.moveWearable(item, closer_to_body)) { - gAgentAvatarp->wearableUpdated(item->getWearableType(), TRUE); + gAgentAvatarp->wearableUpdated(item->getWearableType(), FALSE); } setOutfitDirty(true); -- cgit v1.2.3 From 47211f0ed5c9dab26c512e59b0d8f54e9018f548 Mon Sep 17 00:00:00 2001 From: Vadim Savchuk Date: Fri, 11 Jun 2010 18:22:00 +0300 Subject: EXT-7716 FIXED Allowed removing an outfit containing links to worn wearables. Removed a redundant check disallowing removal of an outfit containing links to worn items. So now we use the same condition as in the inventory panel. Note that if an outfit that you're trying to remove contains originals of currently worn items, we still disallow removal. Reviewed by Mike Antipov at https://codereview.productengine.com/secondlife/r/559/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 12d2752180..3691d731ed 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -965,18 +965,10 @@ bool LLAppearanceMgr::getCanRemoveOutfit(const LLUUID& outfit_cat_id) return false; } - // Check if the folder contains worn items. - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLFindWorn filter_worn; - gInventory.collectDescendentsIf(outfit_cat_id, cats, items, false, filter_worn); - if (!items.empty()) - { - return false; - } - // Check for the folder's non-removable descendants. LLFindNonRemovableObjects filter_non_removable; + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; LLInventoryModel::item_array_t::const_iterator it; gInventory.collectDescendentsIf(outfit_cat_id, cats, items, false, filter_non_removable); if (!cats.empty() || !items.empty()) -- cgit v1.2.3 From 17520c17b1eff7b26d264c8b6bd1f8ebbbde8d15 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 11 Jun 2010 08:26:18 -0400 Subject: EXT-6571 WIP - adding ability to handle late-arriving assets --- indra/newview/llappearancemgr.cpp | 131 ++++++++++++++++++++++++++++++-------- 1 file changed, 105 insertions(+), 26 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index a899926938..28a0ba8817 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -223,8 +223,16 @@ public: void onWearableAssetFetch(LLWearable *wearable); void onAllComplete(); - + typedef std::list found_list_t; + found_list_t& getFoundList(); + void eraseTypeToLink(LLWearableType::EType type); + void eraseTypeToRecover(LLWearableType::EType type); + void setObjItems(const LLInventoryModel::item_array_t& items); + void setGestItems(const LLInventoryModel::item_array_t& items); + bool isValid(); + +private: found_list_t mFoundList; LLInventoryModel::item_array_t mObjItems; LLInventoryModel::item_array_t mGestItems; @@ -234,34 +242,89 @@ public: S32 mResolved; LLTimer mWaitTime; bool mFired; + typedef std::set type_set_hp; + static type_set_hp sActiveHoldingPatterns; + bool mIsValid; }; +LLWearableHoldingPattern::type_set_hp LLWearableHoldingPattern::sActiveHoldingPatterns; + LLWearableHoldingPattern::LLWearableHoldingPattern(): mResolved(0), - mFired(false) + mFired(false), + mIsValid(true) { + if (sActiveHoldingPatterns.size()>0) + { + llinfos << "Creating LLWearableHoldingPattern when " + << sActiveHoldingPatterns.size() + << " other attempts are active." + << " Flagging others as invalid." + << llendl; + for (type_set_hp::iterator it = sActiveHoldingPatterns.begin(); + it != sActiveHoldingPatterns.end(); + ++it) + { + (*it)->mIsValid = false; + } + + } + sActiveHoldingPatterns.insert(this); } LLWearableHoldingPattern::~LLWearableHoldingPattern() { + sActiveHoldingPatterns.erase(this); +} + +bool LLWearableHoldingPattern::isValid() +{ + return mIsValid; +} + +LLWearableHoldingPattern::found_list_t& LLWearableHoldingPattern::getFoundList() +{ + return mFoundList; +} + +void LLWearableHoldingPattern::eraseTypeToLink(LLWearableType::EType type) +{ + mTypesToLink.erase(type); +} + +void LLWearableHoldingPattern::eraseTypeToRecover(LLWearableType::EType type) +{ + mTypesToRecover.erase(type); +} + +void LLWearableHoldingPattern::setObjItems(const LLInventoryModel::item_array_t& items) +{ + mObjItems = items; +} + +void LLWearableHoldingPattern::setGestItems(const LLInventoryModel::item_array_t& items) +{ + mGestItems = items; } bool LLWearableHoldingPattern::isFetchCompleted() { - return (mResolved >= (S32)mFoundList.size()); // have everything we were waiting for? + return (mResolved >= (S32)getFoundList().size()); // have everything we were waiting for? } bool LLWearableHoldingPattern::isTimedOut() { - static F32 max_wait_time = 60.0; // give up if wearable fetches haven't completed in max_wait_time seconds. + F32 max_wait_time = gSavedSettings.getF32("MaxWearableWaitTime"); // give up if wearable fetches haven't completed in max_wait_time seconds. return mWaitTime.getElapsedTimeF32() > max_wait_time; } void LLWearableHoldingPattern::checkMissingWearables() { + llassert(isValid()); // TODO: handle not valid case + std::vector found_by_type(LLWearableType::WT_COUNT,0); std::vector requested_by_type(LLWearableType::WT_COUNT,0); - for (found_list_t::iterator it = mFoundList.begin(); it != mFoundList.end(); ++it) + for (found_list_t::iterator it = getFoundList().begin(); it != getFoundList().end(); ++it) { LLFoundData &data = *it; if (data.mWearableType < LLWearableType::WT_COUNT) @@ -301,6 +364,8 @@ void LLWearableHoldingPattern::checkMissingWearables() void LLWearableHoldingPattern::onAllComplete() { + llassert(isValid()); // TODO: handle not valid case + // Activate all gestures in this folder if (mGestItems.count() > 0) { @@ -340,12 +405,16 @@ void LLWearableHoldingPattern::onAllComplete() void LLWearableHoldingPattern::onFetchCompletion() { + llassert(isValid()); // TODO: handle not valid case + checkMissingWearables(); } // Runs as an idle callback until all wearables are fetched (or we time out). bool LLWearableHoldingPattern::pollFetchCompletion() { + llassert(isValid()); // TODO: handle not valid case + bool completed = isFetchCompleted(); bool timed_out = isTimedOut(); bool done = completed || timed_out; @@ -378,8 +447,10 @@ public: } void fire(const LLUUID& item_id) { + llassert(mHolder->isValid()); // TODO: handle not valid case + llinfos << "Recovered item link for type " << mType << llendl; - mHolder->mTypesToLink.erase(mType); + mHolder->eraseTypeToLink(mType); // Add wearable to FoundData for actual wearing LLViewerInventoryItem *item = gInventory.getItem(item_id); LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL; @@ -397,7 +468,7 @@ public: linked_item->isWearableType() ? linked_item->getWearableType() : LLWearableType::WT_INVALID ); found.mWearable = mWearable; - mHolder->mFoundList.push_front(found); + mHolder->getFoundList().push_front(found); } else { @@ -426,11 +497,13 @@ public: } void fire(const LLUUID& item_id) { + llassert(mHolder->isValid()); // TODO: handle not valid case + llinfos << "Recovered item for type " << mType << llendl; LLViewerInventoryItem *itemp = gInventory.getItem(item_id); mWearable->setItemID(item_id); LLPointer cb = new RecoveredItemLinkCB(mType,mWearable,mHolder); - mHolder->mTypesToRecover.erase(mType); + mHolder->eraseTypeToRecover(mType); llassert(itemp); if (itemp) { @@ -451,6 +524,8 @@ private: void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type) { + llassert(isValid()); // TODO: handle not valid case + // Try to recover by replacing missing wearable with a new one. LLNotificationsUtil::add("ReplacedMissingWearable"); lldebugs << "Wearable " << LLWearableType::getTypeLabel(type) @@ -481,7 +556,7 @@ bool LLWearableHoldingPattern::isMissingCompleted() void LLWearableHoldingPattern::clearCOFLinksForMissingWearables() { - for (found_list_t::iterator it = mFoundList.begin(); it != mFoundList.end(); ++it) + for (found_list_t::iterator it = getFoundList().begin(); it != getFoundList().end(); ++it) { LLFoundData &data = *it; if ((data.mWearableType < LLWearableType::WT_COUNT) && (!data.mWearable)) @@ -495,6 +570,8 @@ void LLWearableHoldingPattern::clearCOFLinksForMissingWearables() bool LLWearableHoldingPattern::pollMissingWearables() { + llassert(isValid()); // TODO: handle not valid case + bool timed_out = isTimedOut(); bool missing_completed = isMissingCompleted(); bool done = timed_out || missing_completed; @@ -516,8 +593,10 @@ bool LLWearableHoldingPattern::pollMissingWearables() void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) { + llassert(isValid()); // TODO: handle not valid case + mResolved += 1; // just counting callbacks, not successes. - llinfos << "onWearableAssetFetch, resolved count " << mResolved << " of requested " << mFoundList.size() << llendl; + llinfos << "onWearableAssetFetch, resolved count " << mResolved << " of requested " << getFoundList().size() << llendl; if (wearable) { llinfos << "wearable found, type " << wearable->getType() << " asset " << wearable->getAssetID() << llendl; @@ -538,8 +617,8 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) return; } - for (LLWearableHoldingPattern::found_list_t::iterator iter = mFoundList.begin(); - iter != mFoundList.end(); ++iter) + for (LLWearableHoldingPattern::found_list_t::iterator iter = getFoundList().begin(); + iter != getFoundList().end(); ++iter) { LLFoundData& data = *iter; if(wearable->getAssetID() == data.mAssetID) @@ -1143,8 +1222,8 @@ void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, boo // that we recursed through. for( S32 i = 0; i < LLWearableType::WT_COUNT; i++ ) { - for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin(); - iter != holder->mFoundList.end(); ++iter) + for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->getFoundList().begin(); + iter != holder->getFoundList().end(); ++iter) { LLFoundData& data = *iter; LLWearable* wearable = data.mWearable; @@ -1236,8 +1315,8 @@ void LLAppearanceMgr::updateAppearanceFromCOF() LLWearableHoldingPattern* holder = new LLWearableHoldingPattern; - holder->mObjItems = obj_items; - holder->mGestItems = gest_items; + holder->setObjItems(obj_items); + holder->setGestItems(gest_items); // Note: can't do normal iteration, because if all the // wearables can be resolved immediately, then the @@ -1248,6 +1327,12 @@ void LLAppearanceMgr::updateAppearanceFromCOF() { LLViewerInventoryItem *item = wear_items.get(i); LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL; + + // Fault injection: use debug setting to test asset + // fetch failures (should be replaced by new defaults in + // lost&found). + U32 skip_type = gSavedSettings.getU32("ForceAssetFail"); + if (item && item->getIsLinkType() && linked_item) { LLFoundData found(linked_item->getUUID(), @@ -1257,18 +1342,12 @@ void LLAppearanceMgr::updateAppearanceFromCOF() linked_item->isWearableType() ? linked_item->getWearableType() : LLWearableType::WT_INVALID ); -#if 0 - // Fault injection: uncomment this block to test asset - // fetch failures (should be replaced by new defaults in - // lost&found). - if (found.mWearableType == LLWearableType::WT_SHAPE || found.mWearableType == LLWearableType::WT_JACKET) + if (skip_type != LLWearableType::WT_INVALID && found.mWearableType == skip_type) { found.mAssetID.generate(); // Replace with new UUID, guaranteed not to exist in DB - } -#endif //pushing back, not front, to preserve order of wearables for LLAgentWearables - holder->mFoundList.push_back(found); + holder->getFoundList().push_back(found); } else { @@ -1283,8 +1362,8 @@ void LLAppearanceMgr::updateAppearanceFromCOF() } } - for (LLWearableHoldingPattern::found_list_t::iterator it = holder->mFoundList.begin(); - it != holder->mFoundList.end(); ++it) + for (LLWearableHoldingPattern::found_list_t::iterator it = holder->getFoundList().begin(); + it != holder->getFoundList().end(); ++it) { LLFoundData& found = *it; -- cgit v1.2.3 From 5777824df41956fbb1c4592c08ce693f28182fdc Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 11 Jun 2010 18:08:59 -0400 Subject: EXT-6571 WIP - partial handling of late arriving assets --- indra/newview/llappearancemgr.cpp | 128 +++++++++++++++++++++++++++++++++----- 1 file changed, 111 insertions(+), 17 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 1c2bdf07df..c19b3b50c1 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -261,6 +261,7 @@ public: void setObjItems(const LLInventoryModel::item_array_t& items); void setGestItems(const LLInventoryModel::item_array_t& items); bool isValid(); + void handleLateArrivals(); private: found_list_t mFoundList; @@ -275,6 +276,8 @@ private: typedef std::set type_set_hp; static type_set_hp sActiveHoldingPatterns; bool mIsValid; + std::set mLateArrivals; + bool mIsAllComplete; }; LLWearableHoldingPattern::type_set_hp LLWearableHoldingPattern::sActiveHoldingPatterns; @@ -282,7 +285,8 @@ LLWearableHoldingPattern::type_set_hp LLWearableHoldingPattern::sActiveHoldingPa LLWearableHoldingPattern::LLWearableHoldingPattern(): mResolved(0), mFired(false), - mIsValid(true) + mIsValid(true), + mIsAllComplete(false) { if (sActiveHoldingPatterns.size()>0) { @@ -350,7 +354,10 @@ bool LLWearableHoldingPattern::isTimedOut() void LLWearableHoldingPattern::checkMissingWearables() { - llassert(isValid()); // TODO: handle not valid case + if (!isValid()) + { + llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + } std::vector found_by_type(LLWearableType::WT_COUNT,0); std::vector requested_by_type(LLWearableType::WT_COUNT,0); @@ -394,7 +401,10 @@ void LLWearableHoldingPattern::checkMissingWearables() void LLWearableHoldingPattern::onAllComplete() { - llassert(isValid()); // TODO: handle not valid case + if (!isValid()) + { + llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + } // Activate all gestures in this folder if (mGestItems.count() > 0) @@ -431,11 +441,19 @@ void LLWearableHoldingPattern::onAllComplete() // Only safe to delete if all wearable callbacks and all missing wearables completed. delete this; } + else + { + mIsAllComplete = true; + handleLateArrivals(); + } } void LLWearableHoldingPattern::onFetchCompletion() { - llassert(isValid()); // TODO: handle not valid case + if (!isValid()) + { + llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + } checkMissingWearables(); } @@ -443,7 +461,10 @@ void LLWearableHoldingPattern::onFetchCompletion() // Runs as an idle callback until all wearables are fetched (or we time out). bool LLWearableHoldingPattern::pollFetchCompletion() { - llassert(isValid()); // TODO: handle not valid case + if (!isValid()) + { + llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + } bool completed = isFetchCompleted(); bool timed_out = isTimedOut(); @@ -477,7 +498,10 @@ public: } void fire(const LLUUID& item_id) { - llassert(mHolder->isValid()); // TODO: handle not valid case + if (!mHolder->isValid()) + { + llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + } llinfos << "Recovered item link for type " << mType << llendl; mHolder->eraseTypeToLink(mType); @@ -492,11 +516,11 @@ public: if (item) { LLFoundData found(linked_item->getUUID(), - linked_item->getAssetUUID(), - linked_item->getName(), - linked_item->getType(), - linked_item->isWearableType() ? linked_item->getWearableType() : LLWearableType::WT_INVALID - ); + linked_item->getAssetUUID(), + linked_item->getName(), + linked_item->getType(), + linked_item->isWearableType() ? linked_item->getWearableType() : LLWearableType::WT_INVALID + ); found.mWearable = mWearable; mHolder->getFoundList().push_front(found); } @@ -527,7 +551,10 @@ public: } void fire(const LLUUID& item_id) { - llassert(mHolder->isValid()); // TODO: handle not valid case + if (!mHolder->isValid()) + { + llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + } llinfos << "Recovered item for type " << mType << llendl; LLViewerInventoryItem *itemp = gInventory.getItem(item_id); @@ -554,7 +581,10 @@ private: void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type) { - llassert(isValid()); // TODO: handle not valid case + if (!isValid()) + { + llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + } // Try to recover by replacing missing wearable with a new one. LLNotificationsUtil::add("ReplacedMissingWearable"); @@ -600,7 +630,10 @@ void LLWearableHoldingPattern::clearCOFLinksForMissingWearables() bool LLWearableHoldingPattern::pollMissingWearables() { - llassert(isValid()); // TODO: handle not valid case + if (!isValid()) + { + llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + } bool timed_out = isTimedOut(); bool missing_completed = isMissingCompleted(); @@ -621,9 +654,63 @@ bool LLWearableHoldingPattern::pollMissingWearables() return done; } +// Handle wearables that arrived after the timeout period expired. +void LLWearableHoldingPattern::handleLateArrivals() +{ + // Only safe to run if we have previously finished the missing + // wearables and other processing - otherwise we could be in some + // intermediate state - but have not been superceded by a later + // outfit change request. + if (mLateArrivals.size() == 0) + { + // Nothing to process. + return; + } + if (!isValid()) + { + llwarns << "Late arrivals not handled - outfit change no longer valid" << llendl; + } + if (!mIsAllComplete) + { + llwarns << "Late arrivals not handled - in middle of missing wearables processing" << llendl; + } + + llinfos << "Need to handle " << mLateArrivals.size() << " late arriving wearables" << llendl; + + // Update mFoundList using late-arriving wearables. + for (LLWearableHoldingPattern::found_list_t::iterator iter = getFoundList().begin(); + iter != getFoundList().end(); ++iter) + { + LLFoundData& data = *iter; + for (std::set::iterator wear_it = mLateArrivals.begin(); + wear_it != mLateArrivals.end(); + ++wear_it) + { + LLWearable *wearable = *wear_it; + + if(wearable->getAssetID() == data.mAssetID) + { + data.mWearable = wearable; + // BAP failing this means inventory or asset server + // are corrupted in a way we don't handle. + llassert((data.mWearableType < LLWearableType::WT_COUNT) && (wearable->getType() == data.mWearableType)); + break; + } + } + } + + // TODO: handle corresponding default wearable links? + + // Update appearance based on mFoundList + LLAppearanceMgr::instance().updateAgentWearables(this, false); +} + void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) { - llassert(isValid()); // TODO: handle not valid case + if (!isValid()) + { + llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + } mResolved += 1; // just counting callbacks, not successes. llinfos << "onWearableAssetFetch, resolved count " << mResolved << " of requested " << getFoundList().size() << llendl; @@ -639,6 +726,14 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) if (mFired) { llwarns << "called after holder fired" << llendl; + if (wearable) + { + mLateArrivals.insert(wearable); + if (mIsAllComplete) + { + handleLateArrivals(); + } + } return; } @@ -1269,8 +1364,7 @@ void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, boo LLInventoryItem::item_array_t items; LLDynamicArray< LLWearable* > wearables; - // For each wearable type, find the first instance in the category - // that we recursed through. + // For each wearable type, find the wearables of that type. for( S32 i = 0; i < LLWearableType::WT_COUNT; i++ ) { for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->getFoundList().begin(); -- cgit v1.2.3 From 664a07dd8d034a729992994ae1c29f47ad32d8f1 Mon Sep 17 00:00:00 2001 From: Yuri Chebotarev Date: Mon, 14 Jun 2010 14:59:56 +0300 Subject: EXT-7727 FIX reset sidetray tab to home_tab when login is complete. Aslo add parameter to callback to prevent showing appearance panel when creating initial outfit - _sometimes_ this callback was called _after_ login was finished. rewieved by Mike Antipov at https://codereview.productengine.com/secondlife/r/574/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 3691d731ed..dba8707423 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1992,13 +1992,19 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id) class LLShowCreatedOutfit: public LLInventoryCallback { public: - LLShowCreatedOutfit(LLUUID& folder_id): mFolderID(folder_id) + LLShowCreatedOutfit(LLUUID& folder_id, bool show_panel = true): mFolderID(folder_id), mShowPanel(show_panel) {} virtual ~LLShowCreatedOutfit() { LLSD key; - LLSideTray::getInstance()->showPanel("panel_outfits_inventory", key); + + //EXT-7727. For new accounts LLShowCreatedOutfit is created during login process + // add may be processed after login process is finished + if (mShowPanel) + { + LLSideTray::getInstance()->showPanel("panel_outfits_inventory", key); + } LLPanelOutfitsInventory *outfit_panel = dynamic_cast(LLSideTray::getInstance()->getPanel("panel_outfits_inventory")); if (outfit_panel) @@ -2022,9 +2028,10 @@ public: private: LLUUID mFolderID; + bool mShowPanel; }; -LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name) +LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel) { if (!isAgentAvatarValid()) return LLUUID::null; @@ -2037,7 +2044,7 @@ LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name) updateClothingOrderingInfo(); - LLPointer cb = new LLShowCreatedOutfit(folder_id); + LLPointer cb = new LLShowCreatedOutfit(folder_id,show_panel); shallowCopyCategoryContents(getCOF(),folder_id, cb); createBaseOutfitLink(folder_id, cb); -- cgit v1.2.3 From 0ec92fb1c8a90d619d0102d0807a32abedc916f1 Mon Sep 17 00:00:00 2001 From: Alexei Arabadji Date: Mon, 14 Jun 2010 16:12:20 +0300 Subject: EXT-7783 FIXED Provided updating outfit label in My outfits and Edit outfit panels. 1 Corrected LLAppearanceMgr::getBaseOutfitLink() method to avoid returning link in case base outfit moved to trash. 2 Hooked up LLSidepanelAppearance::refreshCurrentOutfitName() method on BOFReplaced signal. reviewed by Mike Antipov at https://codereview.productengine.com/secondlife/r/571/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index dba8707423..bc17605202 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -644,6 +644,13 @@ const LLViewerInventoryItem* LLAppearanceMgr::getBaseOutfitLink() const LLViewerInventoryCategory *cat = item->getLinkedCategory(); if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) { + const LLUUID parent_id = cat->getParentUUID(); + LLViewerInventoryCategory* parent_cat = gInventory.getCategory(parent_id); + // if base outfit moved to trash it means that we don't have base outfit + if (parent_cat != NULL && parent_cat->getPreferredType() == LLFolderType::FT_TRASH) + { + return NULL; + } return item; } } -- cgit v1.2.3 From 8364708595a87e426bf348826698e674976b9e00 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 14 Jun 2010 13:15:58 -0400 Subject: EXT-6571 WIP - basic handling of late arriving assets --- indra/newview/llappearancemgr.cpp | 43 +++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index c19b3b50c1..a164cfeaa1 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -216,13 +216,15 @@ struct LLFoundData const LLUUID& asset_id, const std::string& name, const LLAssetType::EType& asset_type, - const LLWearableType::EType& wearable_type + const LLWearableType::EType& wearable_type, + const bool is_replacement = false ) : mItemID(item_id), mAssetID(asset_id), mName(name), mAssetType(asset_type), mWearableType(wearable_type), + mIsReplacement(is_replacement), mWearable( NULL ) {} LLUUID mItemID; @@ -231,6 +233,7 @@ struct LLFoundData LLAssetType::EType mAssetType; LLWearableType::EType mWearableType; LLWearable* mWearable; + bool mIsReplacement; }; @@ -519,7 +522,8 @@ public: linked_item->getAssetUUID(), linked_item->getName(), linked_item->getType(), - linked_item->isWearableType() ? linked_item->getWearableType() : LLWearableType::WT_INVALID + linked_item->isWearableType() ? linked_item->getWearableType() : LLWearableType::WT_INVALID, + true // is replacement ); found.mWearable = mWearable; mHolder->getFoundList().push_front(found); @@ -678,6 +682,7 @@ void LLWearableHoldingPattern::handleLateArrivals() llinfos << "Need to handle " << mLateArrivals.size() << " late arriving wearables" << llendl; // Update mFoundList using late-arriving wearables. + std::set replaced_types; for (LLWearableHoldingPattern::found_list_t::iterator iter = getFoundList().begin(); iter != getFoundList().end(); ++iter) { @@ -687,10 +692,15 @@ void LLWearableHoldingPattern::handleLateArrivals() ++wear_it) { LLWearable *wearable = *wear_it; - + if(wearable->getAssetID() == data.mAssetID) { data.mWearable = wearable; + + replaced_types.insert(data.mWearableType); + + LLAppearanceMgr::instance().addCOFItemLink(data.mItemID,false); + // BAP failing this means inventory or asset server // are corrupted in a way we don't handle. llassert((data.mWearableType < LLWearableType::WT_COUNT) && (wearable->getType() == data.mWearableType)); @@ -699,7 +709,32 @@ void LLWearableHoldingPattern::handleLateArrivals() } } - // TODO: handle corresponding default wearable links? + // Remove COF links for any default wearables previously used to replace the late arrivals. + // All this pussyfooting around with a while loop and explicit + // iterator incrementing is to allow removing items from the list + // without clobbering the iterator we're using to navigate. + LLWearableHoldingPattern::found_list_t::iterator iter = getFoundList().begin(); + while (iter != getFoundList().end()) + { + LLFoundData& data = *iter; + + // If an item of this type has recently shown up, removed the corresponding replacement wearable from COF. + if (data.mWearable && data.mIsReplacement && + replaced_types.find(data.mWearableType) != replaced_types.end()) + { + LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID); + std::list::iterator clobber_ator = iter; + ++iter; + getFoundList().erase(clobber_ator); + } + else + { + ++iter; + } + } + + // Clear contents of late arrivals. + mLateArrivals.clear(); // Update appearance based on mFoundList LLAppearanceMgr::instance().updateAgentWearables(this, false); -- cgit v1.2.3 From 961656863a5e50e5f80e1e316811b884dd8a949f Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 14 Jun 2010 17:19:40 -0400 Subject: EXT-6571 WIP - fixes for handling of late arriving assets --- indra/newview/llappearancemgr.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index a164cfeaa1..e54b9fe2ea 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -265,6 +265,7 @@ public: void setGestItems(const LLInventoryModel::item_array_t& items); bool isValid(); void handleLateArrivals(); + void resetTime(F32 timeout); private: found_list_t mFoundList; @@ -351,8 +352,7 @@ bool LLWearableHoldingPattern::isFetchCompleted() bool LLWearableHoldingPattern::isTimedOut() { - F32 max_wait_time = gSavedSettings.getF32("MaxWearableWaitTime"); // give up if wearable fetches haven't completed in max_wait_time seconds. - return mWaitTime.getElapsedTimeF32() > max_wait_time; + return mWaitTime.hasExpired(); } void LLWearableHoldingPattern::checkMissingWearables() @@ -395,7 +395,7 @@ void LLWearableHoldingPattern::checkMissingWearables() } } - mWaitTime.reset(); + resetTime(60.0F); if (!pollMissingWearables()) { doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollMissingWearables,this)); @@ -722,7 +722,7 @@ void LLWearableHoldingPattern::handleLateArrivals() if (data.mWearable && data.mIsReplacement && replaced_types.find(data.mWearableType) != replaced_types.end()) { - LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID); + LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID,false); std::list::iterator clobber_ator = iter; ++iter; getFoundList().erase(clobber_ator); @@ -740,6 +740,12 @@ void LLWearableHoldingPattern::handleLateArrivals() LLAppearanceMgr::instance().updateAgentWearables(this, false); } +void LLWearableHoldingPattern::resetTime(F32 timeout) +{ + mWaitTime.reset(); + mWaitTime.setTimerExpirySec(timeout); +} + void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) { if (!isValid()) @@ -1522,7 +1528,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF() linked_item->isWearableType() ? linked_item->getWearableType() : LLWearableType::WT_INVALID ); - if (skip_type != LLWearableType::WT_INVALID && found.mWearableType == skip_type) + if (skip_type != LLWearableType::WT_INVALID && skip_type == found.mWearableType) { found.mAssetID.generate(); // Replace with new UUID, guaranteed not to exist in DB } @@ -1558,6 +1564,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF() } + holder->resetTime(gSavedSettings.getF32("MaxWearableWaitTime")); if (!holder->pollFetchCompletion()) { doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollFetchCompletion,holder)); -- cgit v1.2.3 From 300cb342919b2bfa62e9c90af5cdb99afa9c962e Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Tue, 15 Jun 2010 12:38:30 +0300 Subject: EXT-7794 FIXED Implemented a common-used notification about wearing outfit to display loading indicator. Details: * Added signal "Wearable Loading Started" in AgentWearables (in parallel with "Wearables Loaded") * Now it is raised from the LLAppearanceMgr::wearInventoryCategory. Reviewed by Vadim Savchuk and Neal Orman at https://codereview.productengine.com/secondlife/r/583/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index bc17605202..a7206095d3 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1407,6 +1407,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category, void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append) { + gAgentWearables.notifyLoadingStarted(); if(!category) return; llinfos << "wearInventoryCategory( " << category->getName() -- cgit v1.2.3 From 9b014886b0062a0d2c3ac9aa4a3cf3eb6a6488be Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 15 Jun 2010 14:36:32 -0400 Subject: merge --- indra/newview/llappearancemgr.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 582c20c13f..d60db17d82 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -263,7 +263,7 @@ public: void eraseTypeToRecover(LLWearableType::EType type); void setObjItems(const LLInventoryModel::item_array_t& items); void setGestItems(const LLInventoryModel::item_array_t& items); - bool isValid(); + bool isMostRecent(); void handleLateArrivals(); void resetTime(F32 timeout); @@ -279,7 +279,7 @@ private: bool mFired; typedef std::set type_set_hp; static type_set_hp sActiveHoldingPatterns; - bool mIsValid; + bool mIsMostRecent; std::set mLateArrivals; bool mIsAllComplete; }; @@ -289,7 +289,7 @@ LLWearableHoldingPattern::type_set_hp LLWearableHoldingPattern::sActiveHoldingPa LLWearableHoldingPattern::LLWearableHoldingPattern(): mResolved(0), mFired(false), - mIsValid(true), + mIsMostRecent(true), mIsAllComplete(false) { if (sActiveHoldingPatterns.size()>0) @@ -303,7 +303,7 @@ LLWearableHoldingPattern::LLWearableHoldingPattern(): it != sActiveHoldingPatterns.end(); ++it) { - (*it)->mIsValid = false; + (*it)->mIsMostRecent = false; } } @@ -315,9 +315,9 @@ LLWearableHoldingPattern::~LLWearableHoldingPattern() sActiveHoldingPatterns.erase(this); } -bool LLWearableHoldingPattern::isValid() +bool LLWearableHoldingPattern::isMostRecent() { - return mIsValid; + return mIsMostRecent; } LLWearableHoldingPattern::found_list_t& LLWearableHoldingPattern::getFoundList() @@ -357,7 +357,7 @@ bool LLWearableHoldingPattern::isTimedOut() void LLWearableHoldingPattern::checkMissingWearables() { - if (!isValid()) + if (!isMostRecent()) { llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } @@ -404,7 +404,7 @@ void LLWearableHoldingPattern::checkMissingWearables() void LLWearableHoldingPattern::onAllComplete() { - if (!isValid()) + if (!isMostRecent()) { llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } @@ -453,7 +453,7 @@ void LLWearableHoldingPattern::onAllComplete() void LLWearableHoldingPattern::onFetchCompletion() { - if (!isValid()) + if (!isMostRecent()) { llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } @@ -464,7 +464,7 @@ void LLWearableHoldingPattern::onFetchCompletion() // Runs as an idle callback until all wearables are fetched (or we time out). bool LLWearableHoldingPattern::pollFetchCompletion() { - if (!isValid()) + if (!isMostRecent()) { llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } @@ -501,7 +501,7 @@ public: } void fire(const LLUUID& item_id) { - if (!mHolder->isValid()) + if (!mHolder->isMostRecent()) { llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } @@ -555,7 +555,7 @@ public: } void fire(const LLUUID& item_id) { - if (!mHolder->isValid()) + if (!mHolder->isMostRecent()) { llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } @@ -585,7 +585,7 @@ private: void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type) { - if (!isValid()) + if (!isMostRecent()) { llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } @@ -634,7 +634,7 @@ void LLWearableHoldingPattern::clearCOFLinksForMissingWearables() bool LLWearableHoldingPattern::pollMissingWearables() { - if (!isValid()) + if (!isMostRecent()) { llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } @@ -670,7 +670,7 @@ void LLWearableHoldingPattern::handleLateArrivals() // Nothing to process. return; } - if (!isValid()) + if (!isMostRecent()) { llwarns << "Late arrivals not handled - outfit change no longer valid" << llendl; } @@ -748,7 +748,7 @@ void LLWearableHoldingPattern::resetTime(F32 timeout) void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) { - if (!isValid()) + if (!isMostRecent()) { llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } -- cgit v1.2.3 From 0be5ce0a595ee582ee2bb7a0091e0424f908ddea Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Tue, 15 Jun 2010 17:11:01 -0400 Subject: EXT-7468 FIXED Remove all 2.1 COF debugging code #ifdef'd a bunch of llinfos spam to not show up in release mode. Removed some other legacy comments. --- indra/newview/llappearancemgr.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index d60db17d82..3c267b3308 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1283,8 +1283,9 @@ void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid, const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid); const std::string cat_name = cat ? cat->getName() : "CAT NOT FOUND"; - - llinfos << "Linking Item [ name:" << item->getName() << " UUID:" << item->getUUID() << " ] to Category [ name:" << cat_name << " UUID:" << cat_uuid << " ] " << llendl; // Seraph remove for 2.1 +#ifndef LL_RELEASE_FOR_DOWNLOAD + llinfos << "Linking Item [ name:" << item->getName() << " UUID:" << item->getUUID() << " ] to Category [ name:" << cat_name << " UUID:" << cat_uuid << " ] " << llendl; +#endif } } @@ -1353,13 +1354,24 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) llinfos << "creating LLUpdateAppearanceOnDestroy" << llendl; LLPointer link_waiter = new LLUpdateAppearanceOnDestroy; - llinfos << "Linking body items" << llendl; // Seraph remove for 2.1 +#ifndef LL_RELEASE_FOR_DOWNLOAD + llinfos << "Linking body items" << llendl; +#endif linkAll(cof, body_items, link_waiter); - llinfos << "Linking wear items" << llendl; // Seraph remove for 2.1 + +#ifndef LL_RELEASE_FOR_DOWNLOAD + llinfos << "Linking wear items" << llendl; +#endif linkAll(cof, wear_items, link_waiter); - llinfos << "Linking obj items" << llendl; // Seraph remove for 2.1 + +#ifndef LL_RELEASE_FOR_DOWNLOAD + llinfos << "Linking obj items" << llendl; +#endif linkAll(cof, obj_items, link_waiter); - llinfos << "Linking gesture items" << llendl; // Seraph remove for 2.1 + +#ifndef LL_RELEASE_FOR_DOWNLOAD + llinfos << "Linking gesture items" << llendl; +#endif linkAll(cof, gest_items, link_waiter); // Add link to outfit if category is an outfit. -- cgit v1.2.3 From 4ae0a0703b9cb8e3f44687e81e26555ef91d5559 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Tue, 15 Jun 2010 17:58:08 -0400 Subject: EXT-7468 FIXED Remove all 2.1 COF debugging code #ifdef'd a couple more llinfos spam to not show up in release mode. --- indra/newview/llappearancemgr.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 3c267b3308..e19a1294c8 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -201,7 +201,9 @@ void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item) { LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item); const std::string item_name = item ? item->getName() : "ITEM NOT FOUND"; +#ifndef LL_RELEASE_FOR_DOWNLOAD llinfos << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << llendl; +#endif mFireCount++; } -- cgit v1.2.3 From bc91053543278b56d7009ab6bbcdee88a0ee1418 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 16 Jun 2010 15:26:53 -0400 Subject: EXT-6571 FIX - avoid removing links to missing wearables, which fixes a problem with ordering in multi-wearables --- indra/newview/llappearancemgr.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 3c267b3308..1ce5206e89 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -652,7 +652,15 @@ bool LLWearableHoldingPattern::pollMissingWearables() if (done) { gAgentAvatarp->debugWearablesLoaded(); - clearCOFLinksForMissingWearables(); + + // BAP - if we don't call clearCOFLinksForMissingWearables() + // here, we won't have to add the link back in later if the + // wearable arrives late. This is to avoid corruption of + // wearable ordering info. Also has the effect of making + // unworn item links visible in the COF under some + // circumstances. + + //clearCOFLinksForMissingWearables(); onAllComplete(); } return done; @@ -698,8 +706,13 @@ void LLWearableHoldingPattern::handleLateArrivals() data.mWearable = wearable; replaced_types.insert(data.mWearableType); - - LLAppearanceMgr::instance().addCOFItemLink(data.mItemID,false); + + // BAP - if we didn't call + // clearCOFLinksForMissingWearables() earlier, we + // don't need to restore the link here. Fixes + // wearable ordering problems. + + // LLAppearanceMgr::instance().addCOFItemLink(data.mItemID,false); // BAP failing this means inventory or asset server // are corrupted in a way we don't handle. -- cgit v1.2.3 From 9745a0a9e4fab00da010793994c6d50e42635ebe Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Thu, 17 Jun 2010 17:03:05 +0300 Subject: EXT-7777 WIP Added several cases to show Loading indicator in "My Outfits:" * Outfit is loading for the first time * After user clicks: ** Item Context menu > Add ** Item Context menu > Replace Known Issues: 1. For multi-wearable indicator will disappear after first item from the batch is worn. Did not fix this to not affect the stability before 2.1 release. 2. To show loading indicator first time we have to notify subscribers of LLAgentWearables. For now this is done from the deprecated LLAgentWearables::processAgentInitialWearablesUpdate Reviewed by Vadim Savchuk at https://codereview.productengine.com/secondlife/r/602/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 52a5587a16..be58a562c0 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -923,6 +923,14 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up { if (item_id_to_wear.isNull()) return false; + // *TODO: issue with multi-wearable should be fixed: + // in this case this method will be called N times - loading started for each item + // and than N times will be called - loading completed for each item. + // That means subscribers will be notified that loading is done after first item in a batch is worn. + // (loading indicator disappears for example before all selected items are worn) + // Have not fix this issue for 2.1 because of stability reason. EXT-7777. + gAgentWearables.notifyLoadingStarted(); + LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear); if (!item_to_wear) return false; -- cgit v1.2.3 From 9f996443604a902e03de87d2d14545b4adffa69c Mon Sep 17 00:00:00 2001 From: Vadim Savchuk Date: Thu, 17 Jun 2010 19:03:57 +0300 Subject: EXT-7722 Fixed "Add to COF" and "Remove from COF" outfit context menu items to be enabled when appropriate and work properly. Work on "Take Off - Remove from Current Outfit" and "Wear - Add to Current Outfit" menu options: - The menu items of the outfit context menu and the My Outfits gear menu are now disabled when inappropriate instead of being hidden. - The menu items get enabled/disabled depending on whether you can wear (take off) anything from the selected outfit. (was: depending on whether you're wearing the outfit) - Changed the way the options work: they now only operate on clothes and attachments. "Add to COF" now only adds those body parts that are missing in COF; "Remove from COF" doesn't touch body parts at all. Without this change both "Add" and "Remove" options would be available simultaneously, because any valid outfit contains body parts. I think that would be confusing. And you don't expect you body parts to be replaced when doing "Add to COF'. (that's addition, not replacement) Reviewed by Mike Antipov at https://codereview.productengine.com/secondlife/r/585/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index be58a562c0..4e96372da9 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1068,7 +1068,7 @@ void LLAppearanceMgr::takeOffOutfit(const LLUUID& cat_id) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; - LLFindWorn collector; + LLFindWearablesEx collector(/*is_worn=*/ true, /*include_body_parts=*/ false); gInventory.collectDescendentsIf(cat_id, cats, items, FALSE, collector); @@ -1224,6 +1224,34 @@ bool LLAppearanceMgr::getCanRemoveOutfit(const LLUUID& outfit_cat_id) return true; } +// static +bool LLAppearanceMgr::getCanRemoveFromCOF(const LLUUID& outfit_cat_id) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLFindWearablesEx is_worn(/*is_worn=*/ true, /*include_body_parts=*/ false); + gInventory.collectDescendentsIf(outfit_cat_id, + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + is_worn); + return items.size() > 0; +} + +// static +bool LLAppearanceMgr::getCanAddToCOF(const LLUUID& outfit_cat_id) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false); + 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; @@ -1338,9 +1366,12 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) // - Body parts: always include COF contents as a fallback in case any // required parts are missing. + // Preserve body parts from COF if appending. LLInventoryModel::item_array_t body_items; getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART, false); getDescendentsOfAssetType(category, body_items, LLAssetType::AT_BODYPART, false); + if (append) + reverse(body_items.begin(), body_items.end()); // Reduce body items to max of one per type. removeDuplicateItems(body_items); filterWearableItems(body_items, 1); -- cgit v1.2.3 From 89825da530f0f5bb4ed2f5260c213174a34f28d8 Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Fri, 18 Jun 2010 17:28:32 +0300 Subject: EXT-7777 WIP Implemented loading indicator for "Save" and "Save As" actions in "My Outfits" & "Edit Outfit" Panels. EXT-7929 FIXED Updated functionality of attaching object: loading indicator gets hidden when attaching is completed. - Fixed crash when accessing singleton on application exit. - Updated functionality of attaching object: loading indicator was not hidden. * Reason: link to attachment was created without next appearance updating. * Fix: passed "true" into LLAppearanceMgr::addCOFItemLink to call LLAppearanceMgr::updateAppearanceFromCOF when attachments is completed. (Like for clothing). Reviewed by Vadim Savchuk at https://codereview.productengine.com/secondlife/r/611/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 4e96372da9..405cc5b282 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -177,7 +177,13 @@ class LLUpdateDirtyState: public LLInventoryCallback { public: LLUpdateDirtyState() {} - virtual ~LLUpdateDirtyState(){ LLAppearanceMgr::getInstance()->updateIsDirty(); } + virtual ~LLUpdateDirtyState() + { + if (LLAppearanceMgr::instanceExists()) + { + LLAppearanceMgr::getInstance()->updateIsDirty(); + } + } virtual void fire(const LLUUID&) {} }; @@ -2150,6 +2156,8 @@ bool LLAppearanceMgr::updateBaseOutfit() } setOutfitLocked(true); + gAgentWearables.notifyLoadingStarted(); + const LLUUID base_outfit_id = getBaseOutfitUUID(); if (base_outfit_id.isNull()) return false; @@ -2309,6 +2317,7 @@ public: } LLAppearanceMgr::getInstance()->updateIsDirty(); + gAgentWearables.notifyLoadingFinished(); // New outfit is saved. LLAppearanceMgr::getInstance()->updatePanelOutfitName(""); } @@ -2324,6 +2333,8 @@ LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, b { if (!isAgentAvatarValid()) return LLUUID::null; + gAgentWearables.notifyLoadingStarted(); + // First, make a folder in the My Outfits directory. const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); LLUUID folder_id = gInventory.createNewCategory( @@ -2530,7 +2541,9 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id) if (mAttachmentInvLinkEnabled) { - LLAppearanceMgr::addCOFItemLink(item_id, false); // Add COF link for item. + // we have to pass do_update = true to call LLAppearanceMgr::updateAppearanceFromCOF. + // it will trigger gAgentWariables.notifyLoadingFinished() + LLAppearanceMgr::addCOFItemLink(item_id, true); // Add COF link for item. } else { @@ -2560,7 +2573,7 @@ void LLAppearanceMgr::linkRegisteredAttachments() ++it) { LLUUID item_id = *it; - addCOFItemLink(item_id, false); + addCOFItemLink(item_id, true); } mRegisteredAttachments.clear(); } -- cgit v1.2.3 From 8aef04f33c7df2d96c3a2a74b777b5950196b98e Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 21 Jun 2010 11:56:59 -0400 Subject: EXT-4919 WIP - fixed problems with inventory fetch failing to time out, added copying/activation of more gesture folders --- indra/newview/llappearancemgr.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 52a5587a16..7deaaf1593 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1083,6 +1083,7 @@ void LLAppearanceMgr::shallowCopyCategory(const LLUUID& src_id, const LLUUID& ds llwarns << "folder not found for src " << src_id.asString() << llendl; return; } + llinfos << "starting, src_id " << src_id << " name " << src_cat->getName() << " dst_id " << dst_id << llendl; LLUUID parent_id = dst_id; if(parent_id.isNull()) { @@ -1103,6 +1104,7 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL LLInventoryModel::cat_array_t* cats; LLInventoryModel::item_array_t* items; gInventory.getDirectDescendentsOf(src_id, cats, items); + llinfos << "copying " << items->count() << " items" << llendl; for (LLInventoryModel::item_array_t::const_iterator iter = items->begin(); iter != items->end(); ++iter) @@ -1142,6 +1144,7 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL case LLAssetType::AT_BODYPART: case LLAssetType::AT_GESTURE: { + llinfos << "copying inventory item " << item->getName() << llendl; copy_inventory_item(gAgent.getID(), item->getPermissions().getOwner(), item->getUUID(), -- cgit v1.2.3 From 08381a276dbf0544692c44236b40f57ec111aefc Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Wed, 23 Jun 2010 15:30:48 +0300 Subject: EXT-7755 ADDITIONAL FIX Fixed issues with wrong title after an outfit from the Inventory is worn, "Wear..." menu items state is made consistent with "Wear" button. * Empty string is replaced with "Changing outfits" while changing COF; * Fixed title to show "No Outfit" after an outfit from the Inventory is worn; * Fixed bug with visible indicator after an empty folder is DnD from the Inventory "Clothing" * Updated context and Gear "Wear..." menu items to take into account "isCOFChangeInProgress" state in on_enable callbacks Reviewed by Neal Orman at https://codereview.productengine.com/secondlife/r/625/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 3947be49bb..f088a620d6 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1697,9 +1697,10 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category, void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append) { - gAgentWearables.notifyLoadingStarted(); if(!category) return; + gAgentWearables.notifyLoadingStarted(); + llinfos << "wearInventoryCategory( " << category->getName() << " )" << llendl; -- cgit v1.2.3 From 887b2858d4d180d3679f1eb39fd37be5a551615e Mon Sep 17 00:00:00 2001 From: Sergei Litovchuk Date: Fri, 11 Jun 2010 20:02:42 +0300 Subject: EXT-7779 FIXED Changed wearing panel from inventory panel to a flat list similar to My Outfits view. - Added common interface for My Outfits and Wearing tabs. - Changed LLPanelOutfitsInventory to use common interface for My Outfits and Wearing tabs. - Removed dependency on outfits side panel from inventory bridge context menus. - Removed unused LLShowCreatedOutfit class from llagentwearables.cpp. - Restored opening newly created outfit in My Outfits tab. - Fixed worn items indication for Wearing tab items. Revieved by Neal Orman at https://codereview.productengine.com/secondlife/r/604/. --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index f088a620d6..597076503d 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -45,7 +45,7 @@ #include "llinventoryobserver.h" #include "llnotificationsutil.h" #include "lloutfitobserver.h" -#include "llpaneloutfitsinventory.h" +#include "lloutfitslist.h" #include "llselectmgr.h" #include "llsidepanelappearance.h" #include "llsidetray.h" @@ -2306,18 +2306,11 @@ public: { LLSideTray::getInstance()->showPanel("panel_outfits_inventory", key); } - LLPanelOutfitsInventory *outfit_panel = - dynamic_cast(LLSideTray::getInstance()->getPanel("panel_outfits_inventory")); - if (outfit_panel) + LLOutfitsList *outfits_list = + dynamic_cast(LLSideTray::getInstance()->getPanel("outfitslist_tab")); + if (outfits_list) { - outfit_panel->getRootFolder()->clearSelection(); - outfit_panel->getRootFolder()->setSelectionByID(mFolderID, TRUE); - } - - LLAccordionCtrlTab* tab_outfits = outfit_panel ? outfit_panel->findChild("tab_outfits") : 0; - if (tab_outfits && !tab_outfits->getDisplayChildren()) - { - tab_outfits->changeOpenClose(tab_outfits->getDisplayChildren()); + outfits_list->setSelectedOutfitByUUID(mFolderID); } LLAppearanceMgr::getInstance()->updateIsDirty(); -- cgit v1.2.3 From 32283ca3397965ed28ad23492db362355a3dbef5 Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Thu, 24 Jun 2010 11:53:26 +0300 Subject: EXT-7777 FIXED reverted changes to show loading indicator for "Wear/Attach" action. Because it was too hard to fix EXT-7949 having so extremly lack of time. Proper fix for EXT-7949 requires changes in different places of the code calling add/removeCOFItemLink(). Reviewed by Neal Orman at https://codereview.productengine.com/secondlife/r/644/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 597076503d..ce022ac840 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -935,7 +935,9 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up // That means subscribers will be notified that loading is done after first item in a batch is worn. // (loading indicator disappears for example before all selected items are worn) // Have not fix this issue for 2.1 because of stability reason. EXT-7777. - gAgentWearables.notifyLoadingStarted(); + + // Disabled for now because it is *not* acceptable to call updateAppearanceFromCOF() multiple times +// gAgentWearables.notifyLoadingStarted(); LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear); if (!item_to_wear) return false; @@ -2540,7 +2542,8 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id) { // we have to pass do_update = true to call LLAppearanceMgr::updateAppearanceFromCOF. // it will trigger gAgentWariables.notifyLoadingFinished() - LLAppearanceMgr::addCOFItemLink(item_id, true); // Add COF link for item. + // But it is not acceptable solution. See EXT-7777 + LLAppearanceMgr::addCOFItemLink(item_id, false); // Add COF link for item. } else { @@ -2570,7 +2573,7 @@ void LLAppearanceMgr::linkRegisteredAttachments() ++it) { LLUUID item_id = *it; - addCOFItemLink(item_id, true); + addCOFItemLink(item_id, false); } mRegisteredAttachments.clear(); } -- cgit v1.2.3 From 5a39e173b06698fd9e07d524e7044a41e86bdfbb Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 28 Jun 2010 17:26:19 -0400 Subject: EXT-8063 WIP - last-ditch filtering of item counts in updateAppearanceFromCOF --- indra/newview/llappearancemgr.cpp | 71 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 4 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index ce022ac840..8a3b4cb028 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1537,16 +1537,79 @@ bool sort_by_description(const LLInventoryItem* item1, const LLInventoryItem* it return item1->LLInventoryItem::getDescription() < item2->LLInventoryItem::getDescription(); } -void LLAppearanceMgr::updateAppearanceFromCOF() +void item_array_diff(LLInventoryModel::item_array_t& full_list, + LLInventoryModel::item_array_t& keep_list, + LLInventoryModel::item_array_t& kill_list) + { - //checking integrity of the COF in terms of ordering of wearables, - //checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state) - updateClothingOrderingInfo(); + for (LLInventoryModel::item_array_t::iterator it = full_list.begin(); + it != full_list.end(); + ++it) + { + LLViewerInventoryItem *item = *it; + if (keep_list.find(item) < 0) // Why on earth does LLDynamicArray need to redefine find()? + { + kill_list.push_back(item); + } + } +} +void LLAppearanceMgr::enforceItemCountLimits() +{ + S32 purge_count = 0; + + LLInventoryModel::item_array_t body_items; + getDescendentsOfAssetType(getCOF(), body_items, LLAssetType::AT_BODYPART, false); + LLInventoryModel::item_array_t curr_body_items = body_items; + removeDuplicateItems(body_items); + filterWearableItems(body_items, 1); + LLInventoryModel::item_array_t kill_body_items; + item_array_diff(curr_body_items,body_items,kill_body_items); + for (LLInventoryModel::item_array_t::iterator it = kill_body_items.begin(); + it != kill_body_items.end(); + ++it) + { + LLViewerInventoryItem *item = *it; + llinfos << "purging dup body part " << item->getName() << llendl; + gInventory.purgeObject(item->getUUID()); + purge_count++; + } + + LLInventoryModel::item_array_t wear_items; + getDescendentsOfAssetType(getCOF(), wear_items, LLAssetType::AT_CLOTHING, false); + LLInventoryModel::item_array_t curr_wear_items = wear_items; + removeDuplicateItems(wear_items); + filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE); + LLInventoryModel::item_array_t kill_wear_items; + item_array_diff(curr_wear_items,wear_items,kill_wear_items); + for (LLInventoryModel::item_array_t::iterator it = kill_wear_items.begin(); + it != kill_wear_items.end(); + ++it) + { + LLViewerInventoryItem *item = *it; + llinfos << "purging excess clothing item " << item->getName() << llendl; + gInventory.purgeObject(item->getUUID()); + purge_count++; + } + + if (purge_count>0) + { + gInventory.notifyObservers(); + } +} + +void LLAppearanceMgr::updateAppearanceFromCOF() +{ // update dirty flag to see if the state of the COF matches // the saved outfit stored as a folder link llinfos << "starting" << llendl; + //checking integrity of the COF in terms of ordering of wearables, + //checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state) + updateClothingOrderingInfo(); + + enforceItemCountLimits(); + updateIsDirty(); dumpCat(getCOF(),"COF, start"); -- cgit v1.2.3 From b81adf898cbe770e1579da5b1618330aac27c671 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 29 Jun 2010 11:59:40 -0400 Subject: EXT-8063 FIX, EXT-7986 FIX - enforce wearable counts in updateApperanceFromCOF() if UI lets any improper state through --- indra/newview/llappearancemgr.cpp | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 8a3b4cb028..ddbec25c04 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1598,18 +1598,44 @@ void LLAppearanceMgr::enforceItemCountLimits() } } +class BoolSetter +{ +public: + BoolSetter(bool& var): + mVar(var) + { + mVar = true; + } + ~BoolSetter() + { + mVar = false; + } +private: + bool& mVar; +}; + void LLAppearanceMgr::updateAppearanceFromCOF() { - // update dirty flag to see if the state of the COF matches - // the saved outfit stored as a folder link + if (mIsInUpdateAppearanceFromCOF) + { + llwarns << "Called updateAppearanceFromCOF inside updateAppearanceFromCOF, skipping" << llendl; + return; + } + + BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF); + llinfos << "starting" << llendl; //checking integrity of the COF in terms of ordering of wearables, //checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state) updateClothingOrderingInfo(); + // Remove duplicate or excess wearables. Should normally be enforced at the UI level, but + // this should catch anything that gets through. enforceItemCountLimits(); + // update dirty flag to see if the state of the COF matches + // the saved outfit stored as a folder link updateIsDirty(); dumpCat(getCOF(),"COF, start"); @@ -2556,7 +2582,8 @@ void LLAppearanceMgr::dumpItemArray(const LLInventoryModel::item_array_t& items, LLAppearanceMgr::LLAppearanceMgr(): mAttachmentInvLinkEnabled(false), - mOutfitIsDirty(false) + mOutfitIsDirty(false), + mIsInUpdateAppearanceFromCOF(false) { LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); -- cgit v1.2.3 From 1c26bb6668e2011315f647359daf56a991c57261 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Wed, 30 Jun 2010 10:20:42 -0400 Subject: EXT-8115 FIX outfits saved under 2.0 load with "unsaved changes" Added code to save order information to outfits on loading / reverting them. Order information is updated not only in COF, but also in base outfit folder. This is only safe to do when we are explicitly loading a saved outfit, as the COF may have deviated from the saved outfit. This will also help fix order discrepencies in saved outfits that have been manually modified through inventory operations. Fix will only be effective after server 1.40 has rolled out. Tested results on Aditi to verify effectiveness. Code Reviewed by Seraph --- indra/newview/llappearancemgr.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index ce022ac840..853369b7c8 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -188,8 +188,9 @@ public: }; -LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(): - mFireCount(0) +LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering): + mFireCount(0), + mUpdateBaseOrder(update_base_outfit_ordering) { } @@ -199,7 +200,7 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy() if (!LLApp::isExiting()) { - LLAppearanceMgr::instance().updateAppearanceFromCOF(); + LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder); } } @@ -1417,7 +1418,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) // Create links to new COF contents. llinfos << "creating LLUpdateAppearanceOnDestroy" << llendl; - LLPointer link_waiter = new LLUpdateAppearanceOnDestroy; + LLPointer link_waiter = new LLUpdateAppearanceOnDestroy(!append); #ifndef LL_RELEASE_FOR_DOWNLOAD llinfos << "Linking body items" << llendl; @@ -1537,11 +1538,11 @@ bool sort_by_description(const LLInventoryItem* item1, const LLInventoryItem* it return item1->LLInventoryItem::getDescription() < item2->LLInventoryItem::getDescription(); } -void LLAppearanceMgr::updateAppearanceFromCOF() +void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) { //checking integrity of the COF in terms of ordering of wearables, //checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state) - updateClothingOrderingInfo(); + updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering); // update dirty flag to see if the state of the COF matches // the saved outfit stored as a folder link @@ -2244,11 +2245,19 @@ struct WearablesOrderComparator U32 mControlSize; }; -void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id) +void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base_outfit_ordering) { if (cat_id.isNull()) { cat_id = getCOF(); + if (update_base_outfit_ordering) + { + const LLUUID base_outfit_id = getBaseOutfitUUID(); + if (base_outfit_id.notNull()) + { + updateClothingOrderingInfo(base_outfit_id,false); + } + } } // COF is processed if cat_id is not specified @@ -2281,6 +2290,7 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id) item->setComplete(TRUE); item->updateServer(FALSE); gInventory.updateItem(item); + inventory_changed = true; } } -- cgit v1.2.3 From 1c05b8cc3269531f781f1e97260868509b757327 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 30 Jun 2010 11:42:16 -0400 Subject: Cleanup - moved small utility class --- indra/newview/llappearancemgr.cpp | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index ddbec25c04..547dfd7006 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -55,6 +55,25 @@ #include "llviewerregion.h" #include "llwearablelist.h" +// RAII thingy to guarantee that a variable gets reset when the Setter +// goes out of scope. More general utility would be handy - TODO: +// check boost. +class BoolSetter +{ +public: + BoolSetter(bool& var): + mVar(var) + { + mVar = true; + } + ~BoolSetter() + { + mVar = false; + } +private: + bool& mVar; +}; + char ORDER_NUMBER_SEPARATOR('@'); class LLOutfitUnLockTimer: public LLEventTimer @@ -1598,22 +1617,6 @@ void LLAppearanceMgr::enforceItemCountLimits() } } -class BoolSetter -{ -public: - BoolSetter(bool& var): - mVar(var) - { - mVar = true; - } - ~BoolSetter() - { - mVar = false; - } -private: - bool& mVar; -}; - void LLAppearanceMgr::updateAppearanceFromCOF() { if (mIsInUpdateAppearanceFromCOF) -- cgit v1.2.3 From 5cda3ccad729f21dee0ea5517be4dcd8304943fe Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 1 Jul 2010 14:08:25 -0400 Subject: EXT-8194 FIX - added textures for default avatar wearables and attachments --- indra/newview/llappearancemgr.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 547dfd7006..d666347a22 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1657,6 +1657,9 @@ void LLAppearanceMgr::updateAppearanceFromCOF() remove_non_link_items(obj_items); remove_non_link_items(gest_items); + dumpItemArray(wear_items,"asset_dump: wear_item"); + dumpItemArray(obj_items,"asset_dump: obj_item"); + if(!wear_items.count()) { LLNotificationsUtil::add("CouldNotPutOnOutfit"); @@ -2574,11 +2577,16 @@ void LLAppearanceMgr::dumpCat(const LLUUID& cat_id, const std::string& msg) void LLAppearanceMgr::dumpItemArray(const LLInventoryModel::item_array_t& items, const std::string& msg) { - llinfos << msg << llendl; for (S32 i=0; igetName() << llendl; + LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL; + LLUUID asset_id; + if (linked_item) + { + asset_id = linked_item->getAssetUUID(); + } + llinfos << msg << " " << i <<" " << item->getName() << " " << asset_id.asString() << llendl; } llinfos << llendl; } -- cgit v1.2.3 From e78f96b2fbf7a535b7bc5fe4a0338f354cdae7ed Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Fri, 2 Jul 2010 15:55:49 -0400 Subject: EXT-8213 FIX users cannot replace their shape if it does not load Removed checking for wearables loaded on replacing or adding individual items. After reviewing the code in depth, we believe this is safe to do, particularly since we allow the user to replace their outfit from the same state. Filed a followup issue for later investigation EXT-8231 Code reviewed by Vir and Seraph --- indra/newview/llappearancemgr.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index b5ad5c7a11..8ef3fa200b 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -991,14 +991,8 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up } } case LLAssetType::AT_BODYPART: - // Don't wear anything until initial wearables are loaded, can - // destroy clothing items. - if (!gAgentWearables.areWearablesLoaded()) - { - LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded"); - return false; - } - + // TODO: investigate wearables may not be loaded at this point EXT-8231 + // Remove the existing wearables of the same type. // Remove existing body parts anyway because we must not be able to wear e.g. two skins. if (item_to_wear->getType() == LLAssetType::AT_BODYPART) -- cgit v1.2.3 From 1ff353452174c37c600d7de650348ab30f91b86c Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Mon, 5 Jul 2010 12:17:54 +0100 Subject: CID-499 Checker: FORWARD_NULL Function: LLAppearanceMgr::dumpItemArray(const LLDynamicArray, (int)32> &, const std::basic_string, std::allocator>&) File: /indra/newview/llappearancemgr.cpp --- indra/newview/llappearancemgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 8ef3fa200b..17efc28a6a 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2590,7 +2590,7 @@ void LLAppearanceMgr::dumpItemArray(const LLInventoryModel::item_array_t& items, { asset_id = linked_item->getAssetUUID(); } - llinfos << msg << " " << i <<" " << item->getName() << " " << asset_id.asString() << llendl; + llinfos << msg << " " << i <<" " << (item ? item->getName() : "(nullitem)") << " " << asset_id.asString() << llendl; } llinfos << llendl; } -- cgit v1.2.3 From 9d96da4b94c875b8f32e9893f37142ba07b0c453 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Tue, 6 Jul 2010 12:44:43 -0400 Subject: EXT-8249 FIX coverity fix - eliminating fallthrough for switch statement Code reviewed by Seraph --- indra/newview/llappearancemgr.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 17efc28a6a..f8cff42412 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -989,16 +989,15 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up { removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1), false); } + addCOFItemLink(item_to_wear, do_update); } + break; case LLAssetType::AT_BODYPART: // TODO: investigate wearables may not be loaded at this point EXT-8231 // Remove the existing wearables of the same type. // Remove existing body parts anyway because we must not be able to wear e.g. two skins. - if (item_to_wear->getType() == LLAssetType::AT_BODYPART) - { - removeCOFLinksOfType(item_to_wear->getWearableType(), false); - } + removeCOFLinksOfType(item_to_wear->getWearableType(), false); addCOFItemLink(item_to_wear, do_update); break; -- cgit v1.2.3 From d68b8ce26936b239443b309b797d3d345a560d41 Mon Sep 17 00:00:00 2001 From: Alexei Arabadji Date: Wed, 7 Jul 2010 18:35:14 +0300 Subject: EXT-8154 FIXED Forced removing garbage items from COF. reviewed by Neal Orman at https://codereview.productengine.com/secondlife/r/687/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index f8cff42412..2c097bdbb1 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2489,6 +2489,19 @@ void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove) } default: break; } + + // *HACK: Force to remove garbage from COF. + // Unworn links or objects can't be processed by existed removing functionality + // since it is not designed for such cases. As example attachment object can't be removed + // since sever don't sends message _PREHASH_KillObject in that case. + // Also we can't check is link was successfully removed from COF since in case + // deleting attachment link removing performs asynchronously in process_kill_object callback. + LLViewerInventoryItem* item = gInventory.getItem(id_to_remove); + if (item != NULL) + { + gInventory.purgeObject(id_to_remove); + gInventory.notifyObservers(); + } } bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_body) -- cgit v1.2.3 From 3ca975740f9a113708509249bb6f3d2b559e17a8 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 7 Jul 2010 16:13:20 -0400 Subject: EXT-8234 FIX - reduced log spam quite a bit; rest is arguably still useful for diagnosing the not-uncommon problems encountered during outfit changes --- indra/newview/llappearancemgr.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index f8cff42412..b4638f0a0b 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -403,7 +403,10 @@ void LLWearableHoldingPattern::checkMissingWearables() for (S32 type = 0; type < LLWearableType::WT_COUNT; ++type) { - llinfos << "type " << type << " requested " << requested_by_type[type] << " found " << found_by_type[type] << llendl; + if (requested_by_type[type] > found_by_type[type]) + { + llwarns << "got fewer wearables than requested, type " << type << ": requested " << requested_by_type[type] << ", found " << found_by_type[type] << llendl; + } if (found_by_type[type] > 0) continue; if ( @@ -670,12 +673,15 @@ bool LLWearableHoldingPattern::pollMissingWearables() bool timed_out = isTimedOut(); bool missing_completed = isMissingCompleted(); bool done = timed_out || missing_completed; - - llinfos << "polling missing wearables, waiting for items " << mTypesToRecover.size() - << " links " << mTypesToLink.size() - << " wearables, timed out " << timed_out - << " elapsed " << mWaitTime.getElapsedTimeF32() - << " done " << done << llendl; + + if (!done) + { + llinfos << "polling missing wearables, waiting for items " << mTypesToRecover.size() + << " links " << mTypesToLink.size() + << " wearables, timed out " << timed_out + << " elapsed " << mWaitTime.getElapsedTimeF32() + << " done " << done << llendl; + } if (done) { @@ -795,12 +801,8 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) } mResolved += 1; // just counting callbacks, not successes. - llinfos << "onWearableAssetFetch, resolved count " << mResolved << " of requested " << getFoundList().size() << llendl; - if (wearable) - { - llinfos << "wearable found, type " << wearable->getType() << " asset " << wearable->getAssetID() << llendl; - } - else + llinfos << "resolved " << mResolved << "/" << getFoundList().size() << llendl; + if (!wearable) { llwarns << "no wearable found" << llendl; } @@ -1635,7 +1637,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) // the saved outfit stored as a folder link updateIsDirty(); - dumpCat(getCOF(),"COF, start"); + //dumpCat(getCOF(),"COF, start"); bool follow_folder_links = true; LLUUID current_outfit_id = getCOF(); @@ -1718,7 +1720,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) { LLFoundData& found = *it; - llinfos << "waiting for onWearableAssetFetch callback, asset " << found.mAssetID.asString() << llendl; + lldebugs << "waiting for onWearableAssetFetch callback, asset " << found.mAssetID.asString() << llendl; // Fetch the wearables about to be worn. LLWearableList::instance().getAsset(found.mAssetID, -- cgit v1.2.3 From e50692ef4b8102291dbc668b4de64e8c511fcfab Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Wed, 7 Jul 2010 17:03:43 -0400 Subject: SNOW-704 EXT-8267 FIX Crash on login for invalid inventory wearable type data Used to assert that the inventory's stored wearable type data matched the asset's stored wearable type, leading to a crash when these did not line up. Converted the assert to a check with llwarns for when this happens. code reviewed by vir --- indra/newview/llappearancemgr.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index f8cff42412..d8403d54f2 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -830,10 +830,14 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) LLFoundData& data = *iter; if(wearable->getAssetID() == data.mAssetID) { - data.mWearable = wearable; // Failing this means inventory or asset server are corrupted in a way we don't handle. - llassert((data.mWearableType < LLWearableType::WT_COUNT) && (wearable->getType() == data.mWearableType)); - break; + if ((data.mWearableType >= LLWearableType::WT_COUNT) || (wearable->getType() != data.mWearableType)) + { + llwarns << "recovered wearable but type invalid. inventory wearable type: " << data.mWearableType << " asset wearable type: " << wearable->getType() << llendl; + break; + } + + data.mWearable = wearable; } } } -- cgit v1.2.3 From bfb66a8b9422d9a86c728e8865b6fb7f936f1521 Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Thu, 8 Jul 2010 14:13:26 -0700 Subject: Fix for EXT-8151 Made LLPanelOutfitEdit::onPlusBtnClicked() iterate over all selected items and wear each one. Also made it create one LLUpdateAppearanceOnDestroy and pass it to all calls to wearItemOnAvatar. Add optional callback argument (as LLPointer) to wearItemOnAvatar, addCOFItemLink, LLDeferredCOFLinkObserver Reviewed by Nyx at http://codereview.lindenlab.com/2482033 --- indra/newview/llappearancemgr.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 862c68ecda..f4dbac5c0e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -951,7 +951,7 @@ const LLUUID LLAppearanceMgr::getBaseOutfitUUID() return outfit_cat->getUUID(); } -bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_update, bool replace) +bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_update, bool replace, LLPointer cb) { if (item_id_to_wear.isNull()) return false; @@ -1005,7 +1005,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up // Remove existing body parts anyway because we must not be able to wear e.g. two skins. removeCOFLinksOfType(item_to_wear->getWearableType(), false); - addCOFItemLink(item_to_wear, do_update); + addCOFItemLink(item_to_wear, do_update, cb); break; case LLAssetType::AT_OBJECT: rez_attachment(item_to_wear, NULL); @@ -1959,9 +1959,10 @@ bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventor class LLDeferredCOFLinkObserver: public LLInventoryObserver { public: - LLDeferredCOFLinkObserver(const LLUUID& item_id, bool do_update): + LLDeferredCOFLinkObserver(const LLUUID& item_id, bool do_update, LLPointer cb = NULL): mItemID(item_id), - mDoUpdate(do_update) + mDoUpdate(do_update), + mCallback(cb) { } @@ -1975,7 +1976,7 @@ public: if (item) { gInventory.removeObserver(this); - LLAppearanceMgr::instance().addCOFItemLink(item,mDoUpdate); + LLAppearanceMgr::instance().addCOFItemLink(item,mDoUpdate,mCallback); delete this; } } @@ -1983,26 +1984,27 @@ public: private: const LLUUID mItemID; bool mDoUpdate; + LLPointer mCallback; }; // BAP - note that this runs asynchronously if the item is not already loaded from inventory. // Dangerous if caller assumes link will exist after calling the function. -void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id, bool do_update ) +void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id, bool do_update, LLPointer cb) { const LLInventoryItem *item = gInventory.getItem(item_id); if (!item) { - LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, do_update); + LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, do_update, cb); gInventory.addObserver(observer); } else { - addCOFItemLink(item, do_update); + addCOFItemLink(item, do_update, cb); } } -void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update ) +void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update, LLPointer cb) { const LLViewerInventoryItem *vitem = dynamic_cast(item); if (!vitem) @@ -2063,7 +2065,10 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update } else { - LLPointer cb = do_update ? new ModifiedCOFCallback : 0; + if(do_update && cb.isNull()) + { + cb = new ModifiedCOFCallback; + } const std::string description = vitem->getIsLinkType() ? vitem->getDescription() : ""; link_inventory_item( gAgent.getID(), vitem->getLinkedUUID(), -- cgit v1.2.3 From 6f2118432d2753ef46df9c15a78267127191e110 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Thu, 8 Jul 2010 17:53:32 -0400 Subject: EXT-8279 FIX original items being deleted when removed from COF Replacing logic with call to removeCOFItemLinks, which should do appropriate checking to determine that item is in the COF and is actually a link. Code reviewed by Seraph --- indra/newview/llappearancemgr.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 862c68ecda..6aa2d19c12 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2502,12 +2502,7 @@ void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove) // since sever don't sends message _PREHASH_KillObject in that case. // Also we can't check is link was successfully removed from COF since in case // deleting attachment link removing performs asynchronously in process_kill_object callback. - LLViewerInventoryItem* item = gInventory.getItem(id_to_remove); - if (item != NULL) - { - gInventory.purgeObject(id_to_remove); - gInventory.notifyObservers(); - } + removeCOFItemLinks(id_to_remove,false); } bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_body) -- cgit v1.2.3 From f790036002a49176066ec346e4068dc05aa88357 Mon Sep 17 00:00:00 2001 From: Sergei Litovchuk Date: Sat, 10 Jul 2010 00:34:36 +0300 Subject: EXT-8190 PARTIAL FIX Fixed loading indicator infinite spins upon pressing 'Save' for outfit with non-link items. - Added inventory collector functor to select items by their actual type. - Fixed outfit "dirtiness" calculation so only link items are checked. Reviewed by Neal Orman at https://codereview.productengine.com/secondlife/r/728/. --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 43f6be42b6..562401cd89 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2179,17 +2179,19 @@ void LLAppearanceMgr::updateIsDirty() } else { + LLIsOfAssetType collector = LLIsOfAssetType(LLAssetType::AT_LINK); + LLInventoryModel::cat_array_t cof_cats; LLInventoryModel::item_array_t cof_items; - gInventory.collectDescendents(cof, cof_cats, cof_items, - LLInventoryModel::EXCLUDE_TRASH); + gInventory.collectDescendentsIf(cof, cof_cats, cof_items, + LLInventoryModel::EXCLUDE_TRASH, collector); LLInventoryModel::cat_array_t outfit_cats; LLInventoryModel::item_array_t outfit_items; - gInventory.collectDescendents(base_outfit, outfit_cats, outfit_items, - LLInventoryModel::EXCLUDE_TRASH); + gInventory.collectDescendentsIf(base_outfit, outfit_cats, outfit_items, + LLInventoryModel::EXCLUDE_TRASH, collector); - if(outfit_items.count() != cof_items.count() -1) + if(outfit_items.count() != cof_items.count()) { // Current outfit folder should have one more item than the outfit folder. // this one item is the link back to the outfit folder itself. @@ -2197,16 +2199,6 @@ void LLAppearanceMgr::updateIsDirty() return; } - //getting rid of base outfit folder link to simplify comparison - for (LLInventoryModel::item_array_t::iterator it = cof_items.begin(); it != cof_items.end(); ++it) - { - if (*it == base_outfit_item) - { - cof_items.erase(it); - break; - } - } - //"dirty" - also means a difference in linked UUIDs and/or a difference in wearables order (links' descriptions) std::sort(cof_items.begin(), cof_items.end(), sort_by_linked_uuid); std::sort(outfit_items.begin(), outfit_items.end(), sort_by_linked_uuid); -- cgit v1.2.3 From 2630252a9fb7e1bc884386546d9ba13da36b008c Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Mon, 12 Jul 2010 16:22:48 -0400 Subject: EXT-8151 FIX multi-selection breakage Original patch merged poorly with a coverity cleanup, resulting in us not passing the callback on to the proper functions for clothing (we did for bodyparts). Added the callback and wearing clothing works again! Code reviewed by Monroe --- indra/newview/llappearancemgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 43f6be42b6..df048fef02 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -995,7 +995,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up { removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1), false); } - addCOFItemLink(item_to_wear, do_update); + addCOFItemLink(item_to_wear, do_update, cb); } break; case LLAssetType::AT_BODYPART: -- cgit v1.2.3 From 5d85dad85f07ea23b3a2892276d8ac591a966864 Mon Sep 17 00:00:00 2001 From: Dessie Linden Date: Thu, 15 Jul 2010 12:31:08 -0700 Subject: Reverted changeset 2bb10eae42bf --- indra/newview/llappearancemgr.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index a7d90ab8d3..43f6be42b6 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -995,7 +995,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up { removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1), false); } - addCOFItemLink(item_to_wear, do_update, cb); + addCOFItemLink(item_to_wear, do_update); } break; case LLAssetType::AT_BODYPART: @@ -2179,19 +2179,17 @@ void LLAppearanceMgr::updateIsDirty() } else { - LLIsOfAssetType collector = LLIsOfAssetType(LLAssetType::AT_LINK); - LLInventoryModel::cat_array_t cof_cats; LLInventoryModel::item_array_t cof_items; - gInventory.collectDescendentsIf(cof, cof_cats, cof_items, - LLInventoryModel::EXCLUDE_TRASH, collector); + gInventory.collectDescendents(cof, cof_cats, cof_items, + LLInventoryModel::EXCLUDE_TRASH); LLInventoryModel::cat_array_t outfit_cats; LLInventoryModel::item_array_t outfit_items; - gInventory.collectDescendentsIf(base_outfit, outfit_cats, outfit_items, - LLInventoryModel::EXCLUDE_TRASH, collector); + gInventory.collectDescendents(base_outfit, outfit_cats, outfit_items, + LLInventoryModel::EXCLUDE_TRASH); - if(outfit_items.count() != cof_items.count()) + if(outfit_items.count() != cof_items.count() -1) { // Current outfit folder should have one more item than the outfit folder. // this one item is the link back to the outfit folder itself. @@ -2199,6 +2197,16 @@ void LLAppearanceMgr::updateIsDirty() return; } + //getting rid of base outfit folder link to simplify comparison + for (LLInventoryModel::item_array_t::iterator it = cof_items.begin(); it != cof_items.end(); ++it) + { + if (*it == base_outfit_item) + { + cof_items.erase(it); + break; + } + } + //"dirty" - also means a difference in linked UUIDs and/or a difference in wearables order (links' descriptions) std::sort(cof_items.begin(), cof_items.end(), sort_by_linked_uuid); std::sort(outfit_items.begin(), outfit_items.end(), sort_by_linked_uuid); -- cgit v1.2.3 From 1dae91d7354aef57625e3508b23a4bb21de242e8 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 19 Jul 2010 17:15:32 -0400 Subject: EXT-8360 WIP - propagating COF item name changes various places --- indra/newview/llappearancemgr.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index a7d90ab8d3..d2449abf08 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2209,6 +2209,7 @@ void LLAppearanceMgr::updateIsDirty() LLViewerInventoryItem *item2 = outfit_items.get(i); if (item1->getLinkedUUID() != item2->getLinkedUUID() || + item1->getName() != item2->getName() || item1->LLInventoryItem::getDescription() != item2->LLInventoryItem::getDescription()) { mOutfitIsDirty = true; -- cgit v1.2.3 From c3973a4895a5827a5a95dd15e99813bc32e11993 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 21 Jul 2010 15:28:28 -0400 Subject: EXT-8135 FIX - use LLUpdateAppearanceOnDestroy callback to postpone appearance update until all links are created --- indra/newview/llappearancemgr.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index d2449abf08..d6ac6e1e5e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2726,3 +2726,15 @@ BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const return FALSE; */ } + +void wear_multiple(const uuid_vec_t& ids, bool replace) +{ + LLPointer cb = new LLUpdateAppearanceOnDestroy; + + uuid_vec_t::const_iterator it; + for (it = ids.begin(); it != ids.end(); ++it) + { + LLAppearanceMgr::instance().wearItemOnAvatar(*it,false,replace,cb); + } +} + -- cgit v1.2.3 From 35837f2d382120088572ec87006238c79973e493 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 22 Jul 2010 11:11:22 -0400 Subject: EXT-8153 FIX - modified replace logic when wearing multiple items --- indra/newview/llappearancemgr.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index d6ac6e1e5e..5e0d49ac12 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2731,10 +2731,14 @@ void wear_multiple(const uuid_vec_t& ids, bool replace) { LLPointer cb = new LLUpdateAppearanceOnDestroy; + bool first = true; uuid_vec_t::const_iterator it; for (it = ids.begin(); it != ids.end(); ++it) { - LLAppearanceMgr::instance().wearItemOnAvatar(*it,false,replace,cb); + // if replace is requested, the first item worn will replace the current top + // item, and others will be added. + LLAppearanceMgr::instance().wearItemOnAvatar(*it,false,first && replace,cb); + first = false; } } -- cgit v1.2.3 From ee40479c3d55aa9a4dd82b3c96df8936f5ef8550 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 23 Jul 2010 16:22:20 -0400 Subject: Removed a bunch of templates and inlining through the miracle of boost::function --- indra/newview/llappearancemgr.cpp | 179 +++++++++++++++++++++++++++++++++++++- 1 file changed, 176 insertions(+), 3 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 5e0d49ac12..c04c2e271f 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1801,9 +1801,9 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool llinfos << "wearInventoryCategory( " << category->getName() << " )" << llendl; - callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal, - &LLAppearanceMgr::instance(), - category->getUUID(), copy, append)); + callAfterCategoryFetch(category->getUUID(), boost::bind(&LLAppearanceMgr::wearCategoryFinal, + &LLAppearanceMgr::instance(), + category->getUUID(), copy, append)); } void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append) @@ -2727,6 +2727,179 @@ BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const */ } +// Shim class to allow arbitrary boost::bind +// expressions to be run as one-time idle callbacks. +// +// TODO: rework idle function spec to take a boost::function in the first place. +class OnIdleCallbackOneTime +{ +public: + OnIdleCallbackOneTime(nullary_func_t callable): + mCallable(callable) + { + } + static void onIdle(void *data) + { + gIdleCallbacks.deleteFunction(onIdle, data); + OnIdleCallbackOneTime* self = reinterpret_cast(data); + self->call(); + delete self; + } + void call() + { + mCallable(); + } +private: + nullary_func_t mCallable; +}; + +void doOnIdleOneTime(nullary_func_t callable) +{ + OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable); + gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor); +} + +// Shim class to allow generic boost functions to be run as +// recurring idle callbacks. Callable should return true when done, +// false to continue getting called. +// +// TODO: rework idle function spec to take a boost::function in the first place. +class OnIdleCallbackRepeating +{ +public: + OnIdleCallbackRepeating(bool_func_t callable): + mCallable(callable) + { + } + // Will keep getting called until the callable returns true. + static void onIdle(void *data) + { + OnIdleCallbackRepeating* self = reinterpret_cast(data); + bool done = self->call(); + if (done) + { + gIdleCallbacks.deleteFunction(onIdle, data); + delete self; + } + } + bool call() + { + return mCallable(); + } +private: + bool_func_t mCallable; +}; + +void doOnIdleRepeating(bool_func_t callable) +{ + OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable); + gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor); +} + +class CallAfterCategoryFetchStage2: public LLInventoryFetchItemsObserver +{ +public: + CallAfterCategoryFetchStage2(const uuid_vec_t& ids, + nullary_func_t callable) : + LLInventoryFetchItemsObserver(ids), + mCallable(callable) + { + } + ~CallAfterCategoryFetchStage2() + { + } + virtual void done() + { + llinfos << this << " done with incomplete " << mIncomplete.size() + << " complete " << mComplete.size() << " calling callable" << llendl; + + gInventory.removeObserver(this); + doOnIdleOneTime(mCallable); + delete this; + } +protected: + nullary_func_t mCallable; +}; + +class CallAfterCategoryFetchStage1: public LLInventoryFetchDescendentsObserver +{ +public: + CallAfterCategoryFetchStage1(const LLUUID& cat_id, nullary_func_t callable) : + LLInventoryFetchDescendentsObserver(cat_id), + mCallable(callable) + { + } + ~CallAfterCategoryFetchStage1() + { + } + virtual void done() + { + // What we do here is get the complete information on the items in + // the library, and set up an observer that will wait for that to + // happen. + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(mComplete.front(), + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH); + S32 count = item_array.count(); + if(!count) + { + llwarns << "Nothing fetched in category " << mComplete.front() + << llendl; + //dec_busy_count(); + gInventory.removeObserver(this); + + // lets notify observers that loading is finished. + gAgentWearables.notifyLoadingFinished(); + delete this; + return; + } + + llinfos << "stage1 got " << item_array.count() << " items, passing to stage2 " << llendl; + uuid_vec_t ids; + for(S32 i = 0; i < count; ++i) + { + ids.push_back(item_array.get(i)->getUUID()); + } + + gInventory.removeObserver(this); + + // do the fetch + CallAfterCategoryFetchStage2 *stage2 = new CallAfterCategoryFetchStage2(ids, mCallable); + stage2->startFetch(); + if(stage2->isFinished()) + { + // everything is already here - call done. + stage2->done(); + } + else + { + // it's all on it's way - add an observer, and the inventory + // will call done for us when everything is here. + gInventory.addObserver(stage2); + } + delete this; + } +protected: + nullary_func_t mCallable; +}; + +void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb) +{ + CallAfterCategoryFetchStage1 *stage1 = new CallAfterCategoryFetchStage1(cat_id, cb); + stage1->startFetch(); + if (stage1->isFinished()) + { + stage1->done(); + } + else + { + gInventory.addObserver(stage1); + } +} + void wear_multiple(const uuid_vec_t& ids, bool replace) { LLPointer cb = new LLUpdateAppearanceOnDestroy; -- cgit v1.2.3 From 2e9671a8a8ec0a8897945c96aa62c77ad245abac Mon Sep 17 00:00:00 2001 From: Alexei Arabadji Date: Mon, 26 Jul 2010 10:33:43 +0300 Subject: EXT-8329 FIXED Provided disabling 'Wear Item' button after item was worn. Details: 1 Updated condition is item can be worn considering situation when item is copied in COF but is not worn. 2 Avoided code duplication in method LLOutfitsList::canWearSelected() reviewed by Vadim Savchuk and Neal Orman at https://codereview.productengine.com/secondlife/r/785/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 5e0d49ac12..ee0c77ef53 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2699,6 +2699,21 @@ BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const return gInventory.isObjectDescendentOf(obj_id, getCOF()); } +// static +bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLLinkedItemIDMatches find_links(gInventory.getLinkedItemID(obj_id)); + gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + find_links); + + return !items.empty(); +} + BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const { if (!getIsInCOF(obj_id)) return FALSE; -- cgit v1.2.3 From 75980159451eb4f80c1ac03ec4b9d8d488279840 Mon Sep 17 00:00:00 2001 From: Vadim Savchuk Date: Tue, 27 Jul 2010 22:34:34 +0300 Subject: EXT-8491 FIXED Crash in LLAppearanceMgr::addCOFItemLink(). Reason: When you click on a clothing link in COF, LLAppearanceMgr::wearItemOnAvatar() removes all COF links of the clicked wearable type -- thus invalidating all previously obtained LLViewerInventoryItems for those links -- and then passes such an invalid item (item_to_wear) to addCOFItemLink() which of course crashes. Fix: 1. Handle this case in wearItemOnAvatar(): don't try wearing COF items. 2. Disable the Wear button in the inventory SP when a COF item is selected. 3. Fixed get_can_item_be_worn() to return FALSE for items which are in COF or have links in COF. Reviewed by Nyx at https://codereview.productengine.com/secondlife/r/811/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index b64007aa75..78edcb3e25 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -983,6 +983,10 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up LLNotificationsUtil::add("CannotWearTrash"); return false; } + else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), LLAppearanceMgr::instance().getCOF())) // EXT-84911 + { + return false; + } switch (item_to_wear->getType()) { -- cgit v1.2.3 From 15247f086989a43881d79c1ee5416bb00721eb68 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 27 Jul 2010 14:22:14 -0700 Subject: Backed out changeset: 58571b4e704b --- indra/newview/llappearancemgr.cpp | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 43f6be42b6..a7d90ab8d3 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -995,7 +995,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up { removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1), false); } - addCOFItemLink(item_to_wear, do_update); + addCOFItemLink(item_to_wear, do_update, cb); } break; case LLAssetType::AT_BODYPART: @@ -2179,17 +2179,19 @@ void LLAppearanceMgr::updateIsDirty() } else { + LLIsOfAssetType collector = LLIsOfAssetType(LLAssetType::AT_LINK); + LLInventoryModel::cat_array_t cof_cats; LLInventoryModel::item_array_t cof_items; - gInventory.collectDescendents(cof, cof_cats, cof_items, - LLInventoryModel::EXCLUDE_TRASH); + gInventory.collectDescendentsIf(cof, cof_cats, cof_items, + LLInventoryModel::EXCLUDE_TRASH, collector); LLInventoryModel::cat_array_t outfit_cats; LLInventoryModel::item_array_t outfit_items; - gInventory.collectDescendents(base_outfit, outfit_cats, outfit_items, - LLInventoryModel::EXCLUDE_TRASH); + gInventory.collectDescendentsIf(base_outfit, outfit_cats, outfit_items, + LLInventoryModel::EXCLUDE_TRASH, collector); - if(outfit_items.count() != cof_items.count() -1) + if(outfit_items.count() != cof_items.count()) { // Current outfit folder should have one more item than the outfit folder. // this one item is the link back to the outfit folder itself. @@ -2197,16 +2199,6 @@ void LLAppearanceMgr::updateIsDirty() return; } - //getting rid of base outfit folder link to simplify comparison - for (LLInventoryModel::item_array_t::iterator it = cof_items.begin(); it != cof_items.end(); ++it) - { - if (*it == base_outfit_item) - { - cof_items.erase(it); - break; - } - } - //"dirty" - also means a difference in linked UUIDs and/or a difference in wearables order (links' descriptions) std::sort(cof_items.begin(), cof_items.end(), sort_by_linked_uuid); std::sort(outfit_items.begin(), outfit_items.end(), sort_by_linked_uuid); -- cgit v1.2.3 From 4b00b988445ae562b2bc203479d7fd42ce5891d8 Mon Sep 17 00:00:00 2001 From: Vadim Savchuk Date: Tue, 3 Aug 2010 23:28:51 +0300 Subject: EXT-8534 FIXED Fixed the 'Wear' in My Outfits being disabled for outfits consisting of body parts only. Changed the condition to enable the "Wear" button in My Outfits and the corresponding item in the outfit context menu. They now get enabled for any outfit that isn't the base outfit and contains non-worn wearables. By the way, did a minor cleanup: moved an LLAgentWearables.isCOFChangeInProgress() call to LLAppearanceMgr::getCanAddToCOF() to avoid code duplication. Reviewed by Sergey Litovchuk at https://codereview.productengine.com/secondlife/r/832/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') 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; -- cgit v1.2.3 From 62466c070490c173296a95ff792b6d9ac64777e6 Mon Sep 17 00:00:00 2001 From: Vadim Savchuk Date: Fri, 6 Aug 2010 17:14:01 +0300 Subject: EXT-8577 WIP Context menu items for multi-attachments. Done: - 1. Dropped the obsolete "MultipleAttachments" setting. - 2. Added an "Add" item to the following attachment-related context menus: * My Appearance (ex-My Outfits) context menu. * Edit Outfit -> Add More context menu. * Object in-world context menu. * Inventory context menu. * Object inspector gear menu. - 3. Modified "Attach To / Attach To HUD" to perform the "add" instead of "replace" action. TODO: - Ability to attach multiple objects at once from the Add More panel (bulk attach). - Make sure there's no memleak when you click Wear/Attach in the in-world object context menu and the callback isn't invoked (because e.g. avatar fails to get close enough to the object). Issues: 0. I'm not sure whether LLAgentWearables::userAttachMultipleAttachments() should replace attachments or add them. Assumed the former. 1. I couldn't verify that adding objects from the object inspector menu works because I either could wear an object or see its inspector, not both. 2. > 1. Right-click on an object in your inventory and select "Wear". > VERIFY: Attaches the object and replaces whatever's there; asks for > confirmation before replacing an existing object. I think this is impossible to implement because we don't know in advance what point the object will be attached to, so we can't display a confirmation dialog. Reviewed by Seraph at https://codereview.productengine.com/secondlife/r/843/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 296a580106..cecb2ee6ad 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1012,7 +1012,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up addCOFItemLink(item_to_wear, do_update, cb); break; case LLAssetType::AT_OBJECT: - rez_attachment(item_to_wear, NULL); + rez_attachment(item_to_wear, NULL, replace); break; default: return false;; } -- 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(-) (limited to 'indra/newview/llappearancemgr.cpp') 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 6c1796c105054bf52f879ab7060a2f53f896d44d Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 12 Aug 2010 11:00:39 -0400 Subject: DEV-52580 WIP: disallow multiple links to the same attachment in updateAppearanceFromCOF() --- indra/newview/llappearancemgr.cpp | 80 ++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 35 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 2729053390..5a076845da 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1608,46 +1608,56 @@ void item_array_diff(LLInventoryModel::item_array_t& full_list, } } -void LLAppearanceMgr::enforceItemCountLimits() +S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id, + LLAssetType::EType type, + S32 max_items, + LLInventoryModel::item_array_t& items_to_kill) { - S32 purge_count = 0; - - LLInventoryModel::item_array_t body_items; - getDescendentsOfAssetType(getCOF(), body_items, LLAssetType::AT_BODYPART, false); - LLInventoryModel::item_array_t curr_body_items = body_items; - removeDuplicateItems(body_items); - filterWearableItems(body_items, 1); - LLInventoryModel::item_array_t kill_body_items; - item_array_diff(curr_body_items,body_items,kill_body_items); - for (LLInventoryModel::item_array_t::iterator it = kill_body_items.begin(); - it != kill_body_items.end(); - ++it) + S32 to_kill_count = 0; + + LLInventoryModel::item_array_t items; + getDescendentsOfAssetType(cat_id, items, type, false); + LLInventoryModel::item_array_t curr_items = items; + removeDuplicateItems(items); + if (max_items > 0) { - LLViewerInventoryItem *item = *it; - llinfos << "purging dup body part " << item->getName() << llendl; - gInventory.purgeObject(item->getUUID()); - purge_count++; + filterWearableItems(items, max_items); } - - LLInventoryModel::item_array_t wear_items; - getDescendentsOfAssetType(getCOF(), wear_items, LLAssetType::AT_CLOTHING, false); - LLInventoryModel::item_array_t curr_wear_items = wear_items; - removeDuplicateItems(wear_items); - filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE); - LLInventoryModel::item_array_t kill_wear_items; - item_array_diff(curr_wear_items,wear_items,kill_wear_items); - for (LLInventoryModel::item_array_t::iterator it = kill_wear_items.begin(); - it != kill_wear_items.end(); + LLInventoryModel::item_array_t kill_items; + item_array_diff(curr_items,items,kill_items); + for (LLInventoryModel::item_array_t::iterator it = kill_items.begin(); + it != kill_items.end(); ++it) { - LLViewerInventoryItem *item = *it; - llinfos << "purging excess clothing item " << item->getName() << llendl; - gInventory.purgeObject(item->getUUID()); - purge_count++; + items_to_kill.push_back(*it); + to_kill_count++; } + return to_kill_count; +} + + +void LLAppearanceMgr::enforceItemRestrictions() +{ + S32 purge_count = 0; + LLInventoryModel::item_array_t items_to_kill; - if (purge_count>0) + purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_BODYPART, + 1, items_to_kill); + purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_CLOTHING, + LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill); + purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_OBJECT, + -1, items_to_kill); + + if (items_to_kill.size()>0) { + for (LLInventoryModel::item_array_t::iterator it = items_to_kill.begin(); + it != items_to_kill.end(); + ++it) + { + LLViewerInventoryItem *item = *it; + llinfos << "purging duplicate or excess item " << item->getName() << llendl; + gInventory.purgeObject(item->getUUID()); + } gInventory.notifyObservers(); } } @@ -1670,7 +1680,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) // Remove duplicate or excess wearables. Should normally be enforced at the UI level, but // this should catch anything that gets through. - enforceItemCountLimits(); + enforceItemRestrictions(); // update dirty flag to see if the state of the COF matches // the saved outfit stored as a folder link @@ -2741,8 +2751,8 @@ bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id) LLInventoryModel::item_array_t items; LLLinkedItemIDMatches find_links(gInventory.getLinkedItemID(obj_id)); gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), - cats, - items, + cats, + items, LLInventoryModel::EXCLUDE_TRASH, find_links); -- cgit v1.2.3 From 06b0d72efa96b6a0ed665f7cd46f358c48929e7b Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Fri, 13 Aug 2010 07:24:57 -0400 Subject: Change license from GPL to LGPL (version 2.1) --- indra/newview/llappearancemgr.cpp | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 2729053390..04a5bcc256 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2,31 +2,25 @@ * @file llappearancemgr.cpp * @brief Manager for initiating appearance changes on the viewer * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -- 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 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') 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. -- 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 --------------- 1 file changed, 15 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') 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()); -- cgit v1.2.3 From 98cc2365034a93c69704daa69efb389799cc9627 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Tue, 24 Aug 2010 18:44:39 +0100 Subject: Backed out changeset a62bf7c0af21 Backing out this merge that I pushed (prematurely) to the wrong place. --- indra/newview/llappearancemgr.cpp | 147 ++++++++++++++++++++++---------------- 1 file changed, 86 insertions(+), 61 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 94286fd799..04a5bcc256 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1006,7 +1006,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up addCOFItemLink(item_to_wear, do_update, cb); break; case LLAssetType::AT_OBJECT: - rez_attachment(item_to_wear, NULL, replace); + rez_attachment(item_to_wear, NULL); break; default: return false;; } @@ -1299,8 +1299,16 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) return false; } - // Check whether the outfit contains the full set of body parts (shape+skin+hair+eyes). - return getCanMakeFolderIntoOutfit(outfit_cat_id); + // 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) @@ -1594,56 +1602,46 @@ void item_array_diff(LLInventoryModel::item_array_t& full_list, } } -S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id, - LLAssetType::EType type, - S32 max_items, - LLInventoryModel::item_array_t& items_to_kill) +void LLAppearanceMgr::enforceItemCountLimits() { - S32 to_kill_count = 0; - - LLInventoryModel::item_array_t items; - getDescendentsOfAssetType(cat_id, items, type, false); - LLInventoryModel::item_array_t curr_items = items; - removeDuplicateItems(items); - if (max_items > 0) + S32 purge_count = 0; + + LLInventoryModel::item_array_t body_items; + getDescendentsOfAssetType(getCOF(), body_items, LLAssetType::AT_BODYPART, false); + LLInventoryModel::item_array_t curr_body_items = body_items; + removeDuplicateItems(body_items); + filterWearableItems(body_items, 1); + LLInventoryModel::item_array_t kill_body_items; + item_array_diff(curr_body_items,body_items,kill_body_items); + for (LLInventoryModel::item_array_t::iterator it = kill_body_items.begin(); + it != kill_body_items.end(); + ++it) { - filterWearableItems(items, max_items); + LLViewerInventoryItem *item = *it; + llinfos << "purging dup body part " << item->getName() << llendl; + gInventory.purgeObject(item->getUUID()); + purge_count++; } - LLInventoryModel::item_array_t kill_items; - item_array_diff(curr_items,items,kill_items); - for (LLInventoryModel::item_array_t::iterator it = kill_items.begin(); - it != kill_items.end(); + + LLInventoryModel::item_array_t wear_items; + getDescendentsOfAssetType(getCOF(), wear_items, LLAssetType::AT_CLOTHING, false); + LLInventoryModel::item_array_t curr_wear_items = wear_items; + removeDuplicateItems(wear_items); + filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE); + LLInventoryModel::item_array_t kill_wear_items; + item_array_diff(curr_wear_items,wear_items,kill_wear_items); + for (LLInventoryModel::item_array_t::iterator it = kill_wear_items.begin(); + it != kill_wear_items.end(); ++it) { - items_to_kill.push_back(*it); - to_kill_count++; + LLViewerInventoryItem *item = *it; + llinfos << "purging excess clothing item " << item->getName() << llendl; + gInventory.purgeObject(item->getUUID()); + purge_count++; } - return to_kill_count; -} - - -void LLAppearanceMgr::enforceItemRestrictions() -{ - S32 purge_count = 0; - LLInventoryModel::item_array_t items_to_kill; - purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_BODYPART, - 1, items_to_kill); - purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_CLOTHING, - LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill); - purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_OBJECT, - -1, items_to_kill); - - if (items_to_kill.size()>0) + if (purge_count>0) { - for (LLInventoryModel::item_array_t::iterator it = items_to_kill.begin(); - it != items_to_kill.end(); - ++it) - { - LLViewerInventoryItem *item = *it; - llinfos << "purging duplicate or excess item " << item->getName() << llendl; - gInventory.purgeObject(item->getUUID()); - } gInventory.notifyObservers(); } } @@ -1666,7 +1664,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) // Remove duplicate or excess wearables. Should normally be enforced at the UI level, but // this should catch anything that gets through. - enforceItemRestrictions(); + enforceItemCountLimits(); // update dirty flag to see if the state of the COF matches // the saved outfit stored as a folder link @@ -1832,9 +1830,9 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool llinfos << "wearInventoryCategory( " << category->getName() << " )" << llendl; - callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal, - &LLAppearanceMgr::instance(), - category->getUUID(), copy, append)); + callAfterCategoryFetch(category->getUUID(), boost::bind(&LLAppearanceMgr::wearCategoryFinal, + &LLAppearanceMgr::instance(), + category->getUUID(), copy, append)); } void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append) @@ -2500,17 +2498,29 @@ 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)) + 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) { - //*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; + LLSelectMgr::getInstance()->remove(found_obj); + }; + } + default: break; } // *HACK: Force to remove garbage from COF. @@ -2650,6 +2660,7 @@ 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; @@ -2669,6 +2680,7 @@ 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) @@ -2686,6 +2698,7 @@ 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) @@ -2698,6 +2711,18 @@ 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()); @@ -2710,8 +2735,8 @@ bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id) LLInventoryModel::item_array_t items; LLLinkedItemIDMatches find_links(gInventory.getLinkedItemID(obj_id)); gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), - cats, - items, + cats, + items, LLInventoryModel::EXCLUDE_TRASH, find_links); -- cgit v1.2.3