summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x[-rw-r--r--]indra/newview/llagentwearables.cpp18
-rwxr-xr-xindra/newview/llagentwearables.h6
-rwxr-xr-xindra/newview/llagentwearablesfetch.cpp394
-rwxr-xr-xindra/newview/llagentwearablesfetch.h41
-rwxr-xr-xindra/newview/llappearancemgr.cpp226
-rwxr-xr-xindra/newview/llappearancemgr.h31
-rwxr-xr-xindra/newview/llinventorybridge.cpp69
-rwxr-xr-xindra/newview/llviewerfoldertype.cpp6
8 files changed, 144 insertions, 647 deletions
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 80c8364223..8e60bf1c6d 100644..100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1861,24 +1861,6 @@ void LLAgentWearables::updateServer()
gAgent.sendAgentSetAppearance();
}
-void LLAgentWearables::populateMyOutfitsFolder(void)
-{
- llinfos << "starting outfit population" << llendl;
-
- const LLUUID& my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
- LLLibraryOutfitsFetch* outfits = new LLLibraryOutfitsFetch(my_outfits_id);
- outfits->mMyOutfitsID = my_outfits_id;
-
- // Get the complete information on the items in the inventory and
- // setup an observer that will wait for that to happen.
- gInventory.addObserver(outfits);
- outfits->startFetch();
- if (outfits->isFinished())
- {
- outfits->done();
- }
-}
-
boost::signals2::connection LLAgentWearables::addLoadingStartedCallback(loading_started_callback_t cb)
{
return mLoadingStartedSignal.connect(cb);
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 0adf545aab..b0ac988341 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -171,12 +171,6 @@ protected:
//--------------------------------------------------------------------
// Outfits
//--------------------------------------------------------------------
-public:
-
- // Should only be called if we *know* we've never done so before, since users may
- // not want the Library outfits to stay in their quick outfit selector and can delete them.
- void populateMyOutfitsFolder();
-
private:
void makeNewOutfitDone(S32 type, U32 index);
diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp
index 2d2d730396..014c610a5c 100755
--- a/indra/newview/llagentwearablesfetch.cpp
+++ b/indra/newview/llagentwearablesfetch.cpp
@@ -35,46 +35,6 @@
#include "llvoavatarself.h"
-void order_my_outfits_cb()
-{
- if (!LLApp::isRunning())
- {
- llwarns << "called during shutdown, skipping" << llendl;
- return;
- }
-
- const LLUUID& my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
- if (my_outfits_id.isNull()) return;
-
- LLInventoryModel::cat_array_t* cats;
- LLInventoryModel::item_array_t* items;
- gInventory.getDirectDescendentsOf(my_outfits_id, cats, items);
- if (!cats) return;
-
- //My Outfits should at least contain saved initial outfit and one another outfit
- if (cats->size() < 2)
- {
- llwarning("My Outfits category was not populated properly", 0);
- return;
- }
-
- llinfos << "Starting updating My Outfits with wearables ordering information" << llendl;
-
- for (LLInventoryModel::cat_array_t::iterator outfit_iter = cats->begin();
- outfit_iter != cats->end(); ++outfit_iter)
- {
- const LLUUID& cat_id = (*outfit_iter)->getUUID();
- if (cat_id.isNull()) continue;
-
- // saved initial outfit already contains wearables ordering information
- if (cat_id == LLAppearanceMgr::getInstance()->getBaseOutfitUUID()) continue;
-
- LLAppearanceMgr::getInstance()->updateClothingOrderingInfo(cat_id);
- }
-
- llinfos << "Finished updating My Outfits with wearables ordering information" << llendl;
-}
-
LLInitialWearablesFetch::LLInitialWearablesFetch(const LLUUID& cof_id) :
LLInventoryFetchDescendentsObserver(cof_id)
{
@@ -244,357 +204,3 @@ void LLInitialWearablesFetch::processWearablesMessage()
}
}
-LLLibraryOutfitsFetch::LLLibraryOutfitsFetch(const LLUUID& my_outfits_id) :
- LLInventoryFetchDescendentsObserver(my_outfits_id),
- mCurrFetchStep(LOFS_FOLDER),
- mOutfitsPopulated(false)
-{
- llinfos << "created" << llendl;
-
- mMyOutfitsID = LLUUID::null;
- mClothingID = LLUUID::null;
- mLibraryClothingID = LLUUID::null;
- mImportedClothingID = LLUUID::null;
- mImportedClothingName = "Imported Library Clothing";
-}
-
-LLLibraryOutfitsFetch::~LLLibraryOutfitsFetch()
-{
- llinfos << "destroyed" << llendl;
-}
-
-void LLLibraryOutfitsFetch::done()
-{
- llinfos << "start" << llendl;
-
- // Delay this until idle() routine, since it's a heavy operation and
- // we also can't have it run within notifyObservers.
- doOnIdleOneTime(boost::bind(&LLLibraryOutfitsFetch::doneIdle,this));
- gInventory.removeObserver(this); // Prevent doOnIdleOneTime from being added twice.
-}
-
-void LLLibraryOutfitsFetch::doneIdle()
-{
- llinfos << "start" << llendl;
-
- gInventory.addObserver(this); // Add this back in since it was taken out during ::done()
-
- switch (mCurrFetchStep)
- {
- case LOFS_FOLDER:
- folderDone();
- mCurrFetchStep = LOFS_OUTFITS;
- break;
- case LOFS_OUTFITS:
- outfitsDone();
- mCurrFetchStep = LOFS_LIBRARY;
- break;
- case LOFS_LIBRARY:
- libraryDone();
- mCurrFetchStep = LOFS_IMPORTED;
- break;
- case LOFS_IMPORTED:
- importedFolderDone();
- mCurrFetchStep = LOFS_CONTENTS;
- break;
- case LOFS_CONTENTS:
- contentsDone();
- break;
- default:
- llwarns << "Got invalid state for outfit fetch: " << mCurrFetchStep << llendl;
- mOutfitsPopulated = TRUE;
- break;
- }
-
- // We're completely done. Cleanup.
- if (mOutfitsPopulated)
- {
- gInventory.removeObserver(this);
- delete this;
- return;
- }
-}
-
-void LLLibraryOutfitsFetch::folderDone()
-{
- llinfos << "start" << llendl;
-
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t wearable_array;
- gInventory.collectDescendents(mMyOutfitsID, cat_array, wearable_array,
- LLInventoryModel::EXCLUDE_TRASH);
-
- // Early out if we already have items in My Outfits
- // except the case when My Outfits contains just initial outfit
- if (cat_array.count() > 1)
- {
- mOutfitsPopulated = true;
- return;
- }
-
- mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
- mLibraryClothingID = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_CLOTHING, false);
-
- // If Library->Clothing->Initial Outfits exists, use that.
- LLNameCategoryCollector matchFolderFunctor("Initial Outfits");
- cat_array.clear();
- gInventory.collectDescendentsIf(mLibraryClothingID,
- cat_array, wearable_array,
- LLInventoryModel::EXCLUDE_TRASH,
- matchFolderFunctor);
- if (cat_array.count() > 0)
- {
- const LLViewerInventoryCategory *cat = cat_array.get(0);
- mLibraryClothingID = cat->getUUID();
- }
-
- mComplete.clear();
-
- // Get the complete information on the items in the inventory.
- uuid_vec_t folders;
- folders.push_back(mClothingID);
- folders.push_back(mLibraryClothingID);
- setFetchIDs(folders);
- startFetch();
- if (isFinished())
- {
- done();
- }
-}
-
-void LLLibraryOutfitsFetch::outfitsDone()
-{
- llinfos << "start" << llendl;
-
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t wearable_array;
- uuid_vec_t folders;
-
- // Collect the contents of the Library's Clothing folder
- gInventory.collectDescendents(mLibraryClothingID, cat_array, wearable_array,
- LLInventoryModel::EXCLUDE_TRASH);
-
- llassert(cat_array.count() > 0);
- for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin();
- iter != cat_array.end();
- ++iter)
- {
- const LLViewerInventoryCategory *cat = iter->get();
-
- // Get the names and id's of every outfit in the library, skip "Ruth"
- // because it's a low quality legacy outfit
- if (cat->getName() != "Ruth")
- {
- // Get the name of every outfit in the library
- folders.push_back(cat->getUUID());
- mLibraryClothingFolders.push_back(cat->getUUID());
- }
- }
- cat_array.clear();
- wearable_array.clear();
-
- // Check if you already have an "Imported Library Clothing" folder
- LLNameCategoryCollector matchFolderFunctor(mImportedClothingName);
- gInventory.collectDescendentsIf(mClothingID,
- cat_array, wearable_array,
- LLInventoryModel::EXCLUDE_TRASH,
- matchFolderFunctor);
- if (cat_array.size() > 0)
- {
- const LLViewerInventoryCategory *cat = cat_array.get(0);
- mImportedClothingID = cat->getUUID();
- }
-
- mComplete.clear();
- setFetchIDs(folders);
- startFetch();
- if (isFinished())
- {
- done();
- }
-}
-
-class LLLibraryOutfitsCopyDone: public LLInventoryCallback
-{
-public:
- LLLibraryOutfitsCopyDone(LLLibraryOutfitsFetch * fetcher):
- mFireCount(0), mLibraryOutfitsFetcher(fetcher)
- {
- }
-
- virtual ~LLLibraryOutfitsCopyDone()
- {
- if (!LLApp::isExiting() && mLibraryOutfitsFetcher)
- {
- gInventory.addObserver(mLibraryOutfitsFetcher);
- mLibraryOutfitsFetcher->done();
- }
- }
-
- /* virtual */ void fire(const LLUUID& inv_item)
- {
- mFireCount++;
- }
-private:
- U32 mFireCount;
- LLLibraryOutfitsFetch * mLibraryOutfitsFetcher;
-};
-
-// Copy the clothing folders from the library into the imported clothing folder
-void LLLibraryOutfitsFetch::libraryDone()
-{
- llinfos << "start" << llendl;
-
- if (mImportedClothingID != LLUUID::null)
- {
- // Skip straight to fetching the contents of the imported folder
- importedFolderFetch();
- return;
- }
-
- // Remove observer; next autopopulation step will be triggered externally by LLLibraryOutfitsCopyDone.
- gInventory.removeObserver(this);
-
- LLPointer<LLInventoryCallback> copy_waiter = new LLLibraryOutfitsCopyDone(this);
- mImportedClothingID = gInventory.createNewCategory(mClothingID,
- LLFolderType::FT_NONE,
- mImportedClothingName);
- // Copy each folder from library into clothing unless it already exists.
- for (uuid_vec_t::const_iterator iter = mLibraryClothingFolders.begin();
- iter != mLibraryClothingFolders.end();
- ++iter)
- {
- const LLUUID& src_folder_id = (*iter); // Library clothing folder ID
- const LLViewerInventoryCategory *cat = gInventory.getCategory(src_folder_id);
- if (!cat)
- {
- llwarns << "Library folder import for uuid:" << src_folder_id << " failed to find folder." << llendl;
- continue;
- }
-
- if (!LLAppearanceMgr::getInstance()->getCanMakeFolderIntoOutfit(src_folder_id))
- {
- llinfos << "Skipping non-outfit folder name:" << cat->getName() << llendl;
- continue;
- }
-
- // Don't copy the category if it already exists.
- LLNameCategoryCollector matchFolderFunctor(cat->getName());
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t wearable_array;
- gInventory.collectDescendentsIf(mImportedClothingID,
- cat_array, wearable_array,
- LLInventoryModel::EXCLUDE_TRASH,
- matchFolderFunctor);
- if (cat_array.size() > 0)
- {
- continue;
- }
-
- LLUUID dst_folder_id = gInventory.createNewCategory(mImportedClothingID,
- LLFolderType::FT_NONE,
- cat->getName());
- LLAppearanceMgr::getInstance()->shallowCopyCategoryContents(src_folder_id, dst_folder_id, copy_waiter);
- }
-}
-
-void LLLibraryOutfitsFetch::importedFolderFetch()
-{
- llinfos << "start" << llendl;
-
- // Fetch the contents of the Imported Clothing Folder
- uuid_vec_t folders;
- folders.push_back(mImportedClothingID);
-
- mComplete.clear();
- setFetchIDs(folders);
- startFetch();
- if (isFinished())
- {
- done();
- }
-}
-
-void LLLibraryOutfitsFetch::importedFolderDone()
-{
- llinfos << "start" << llendl;
-
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t wearable_array;
- uuid_vec_t folders;
-
- // Collect the contents of the Imported Clothing folder
- gInventory.collectDescendents(mImportedClothingID, cat_array, wearable_array,
- LLInventoryModel::EXCLUDE_TRASH);
-
- for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin();
- iter != cat_array.end();
- ++iter)
- {
- const LLViewerInventoryCategory *cat = iter->get();
-
- // Get the name of every imported outfit
- folders.push_back(cat->getUUID());
- mImportedClothingFolders.push_back(cat->getUUID());
- }
-
- mComplete.clear();
- setFetchIDs(folders);
- startFetch();
- if (isFinished())
- {
- done();
- }
-}
-
-void LLLibraryOutfitsFetch::contentsDone()
-{
- llinfos << "start" << llendl;
-
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t wearable_array;
-
- LLPointer<LLInventoryCallback> order_myoutfits_on_destroy = new LLBoostFuncInventoryCallback(no_op_inventory_func, order_my_outfits_cb);
-
- for (uuid_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin();
- folder_iter != mImportedClothingFolders.end();
- ++folder_iter)
- {
- const LLUUID &folder_id = (*folder_iter);
- const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id);
- if (!cat)
- {
- llwarns << "Library folder import for uuid:" << folder_id << " failed to find folder." << llendl;
- continue;
- }
-
- //initial outfit should be already in My Outfits
- if (cat->getName() == LLStartUp::getInitialOutfitName()) continue;
-
- // First, make a folder in the My Outfits directory.
- LLUUID new_outfit_folder_id = gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, cat->getName());
-
- cat_array.clear();
- wearable_array.clear();
- // Collect the contents of each imported clothing folder, so we can create new outfit links for it
- gInventory.collectDescendents(folder_id, cat_array, wearable_array,
- LLInventoryModel::EXCLUDE_TRASH);
-
- for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin();
- wearable_iter != wearable_array.end();
- ++wearable_iter)
- {
- const LLViewerInventoryItem *item = wearable_iter->get();
- link_inventory_item(gAgent.getID(),
- item->getLinkedUUID(),
- new_outfit_folder_id,
- item->getName(),
- item->getDescription(),
- LLAssetType::AT_LINK,
- order_myoutfits_on_destroy);
- }
- }
-
- mOutfitsPopulated = true;
-}
-
diff --git a/indra/newview/llagentwearablesfetch.h b/indra/newview/llagentwearablesfetch.h
index bedc445c0e..81b03110ae 100755
--- a/indra/newview/llagentwearablesfetch.h
+++ b/indra/newview/llagentwearablesfetch.h
@@ -70,45 +70,4 @@ private:
initial_wearable_data_vec_t mAgentInitialWearables; // Wearables from the old agent wearables msg
};
-//--------------------------------------------------------------------
-// InitialWearablesFetch
-//
-// This grabs outfits from the Library and copies those over to the user's
-// outfits folder, typically during first-ever login.
-//--------------------------------------------------------------------
-class LLLibraryOutfitsFetch : public LLInventoryFetchDescendentsObserver
-{
-public:
- enum ELibraryOutfitFetchStep
- {
- LOFS_FOLDER = 0,
- LOFS_OUTFITS,
- LOFS_LIBRARY,
- LOFS_IMPORTED,
- LOFS_CONTENTS
- };
-
- LLLibraryOutfitsFetch(const LLUUID& my_outfits_id);
- ~LLLibraryOutfitsFetch();
-
- virtual void done();
- void doneIdle();
- LLUUID mMyOutfitsID;
- void importedFolderFetch();
-protected:
- void folderDone();
- void outfitsDone();
- void libraryDone();
- void importedFolderDone();
- void contentsDone();
- enum ELibraryOutfitFetchStep mCurrFetchStep;
- uuid_vec_t mLibraryClothingFolders;
- uuid_vec_t mImportedClothingFolders;
- bool mOutfitsPopulated;
- LLUUID mClothingID;
- LLUUID mLibraryClothingID;
- LLUUID mImportedClothingID;
- std::string mImportedClothingName;
-};
-
#endif // LL_AGENTWEARABLESINITIALFETCH_H
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 118f557c97..12c8c82af4 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -435,13 +435,11 @@ private:
S32 LLCallAfterInventoryCopyMgr::sInstanceCount = 0;
-LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering,
- bool enforce_item_restrictions,
+LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool enforce_item_restrictions,
bool enforce_ordering,
nullary_func_t post_update_func
):
mFireCount(0),
- mUpdateBaseOrder(update_base_outfit_ordering),
mEnforceItemRestrictions(enforce_item_restrictions),
mEnforceOrdering(enforce_ordering),
mPostUpdateFunc(post_update_func)
@@ -468,8 +466,7 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()
selfStopPhase("update_appearance_on_destroy");
- LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder,
- mEnforceItemRestrictions,
+ LLAppearanceMgr::instance().updateAppearanceFromCOF(mEnforceItemRestrictions,
mEnforceOrdering,
mPostUpdateFunc);
}
@@ -503,7 +500,7 @@ LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOn
if (!LLApp::isExiting())
{
LLAppearanceMgr::instance().updateAppearanceFromCOF(
- false,true,true,
+ true,true,
boost::bind(edit_wearable_and_customize_avatar, mItemID));
}
}
@@ -1450,7 +1447,7 @@ void LLAppearanceMgr::shallowCopyCategory(const LLUUID& src_id, const LLUUID& ds
gInventory.notifyObservers();
}
-void LLAppearanceMgr::copyCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
+void LLAppearanceMgr::slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
bool include_folder_links, LLPointer<LLInventoryCallback> cb)
{
LLInventoryModel::cat_array_t* cats;
@@ -1819,35 +1816,36 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
all_items += obj_items;
all_items += gest_items;
- // Will link all the above items.
- LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
-#if 0
- linkAll(cof,all_items,link_waiter);
+ // Find any wearables that need description set to enforce ordering.
+ desc_map_t desc_map;
+ getWearableOrderingDescUpdates(wear_items, desc_map);
- // Add link to outfit if category is an outfit.
- if (!append)
- {
- createBaseOutfitLink(category, link_waiter);
- }
-
- // Remove current COF contents. Have to do this after creating
- // the link_waiter so links can be followed for any items that get
- // carried over (e.g. keeping old shape if the new outfit does not
- // contain one)
-
- // even in the non-append case, createBaseOutfitLink() already
- // deletes the existing link, don't need to do it again here.
- bool keep_outfit_links = true;
- remove_folder_contents(cof, keep_outfit_links, link_waiter);
-#else
+ // Will link all the above items.
+ // link_waiter enforce flags are false because we've already fixed everything up in updateCOF().
+ LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(false,false);
LLSD contents = LLSD::emptyArray();
+
for (LLInventoryModel::item_array_t::const_iterator it = all_items.begin();
it != all_items.end(); ++it)
{
LLSD item_contents;
LLInventoryItem *item = *it;
+
+ std::string desc;
+ desc_map_t::const_iterator desc_iter = desc_map.find(item->getUUID());
+ if (desc_iter != desc_map.end())
+ {
+ desc = desc_iter->second;
+ LL_DEBUGS("Avatar") << item->getName() << " overriding desc to: " << desc
+ << " (was: " << item->getActualDescription() << ")" << llendl;
+ }
+ else
+ {
+ desc = item->getActualDescription();
+ }
+
item_contents["name"] = item->getName();
- item_contents["desc"] = item->getActualDescription();
+ item_contents["desc"] = desc;
item_contents["linked_id"] = item->getLinkedUUID();
item_contents["type"] = LLAssetType::AT_LINK;
contents.append(item_contents);
@@ -1868,7 +1866,6 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
dump_sequential_xml(gAgentAvatarp->getFullname() + "_slam_request", contents);
}
slam_inventory_folder(getCOF(), contents, link_waiter);
-#endif
LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL;
}
@@ -2035,8 +2032,7 @@ void LLAppearanceMgr::enforceCOFItemRestrictions(LLPointer<LLInventoryCallback>
}
}
-void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
- bool enforce_item_restrictions,
+void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
bool enforce_ordering,
nullary_func_t post_update_func)
{
@@ -2056,7 +2052,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
// enforce_item_restrictions to false so we don't get
// caught in a perpetual loop.
LLPointer<LLInventoryCallback> cb(
- new LLUpdateAppearanceOnDestroy(update_base_outfit_ordering, false, enforce_ordering, post_update_func));
+ new LLUpdateAppearanceOnDestroy(false, enforce_ordering, post_update_func));
enforceCOFItemRestrictions(cb);
return;
}
@@ -2070,11 +2066,13 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
// to wait for the update callbacks, then (finally!) call
// updateAppearanceFromCOF() with no additional COF munging needed.
LLPointer<LLInventoryCallback> cb(
- new LLUpdateAppearanceOnDestroy(false, false, false, post_update_func));
- updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering, cb);
+ new LLUpdateAppearanceOnDestroy(false, false, post_update_func));
+ updateClothingOrderingInfo(LLUUID::null, cb);
return;
}
+ llassert(validateClothingOrderingInfo());
+
BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF);
selfStartPhase("update_appearance_from_cof");
@@ -2817,23 +2815,6 @@ void LLAppearanceMgr::copyLibraryGestures()
}
}
-void LLAppearanceMgr::autopopulateOutfits()
-{
- // If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account)
- // then auto-populate outfits from the library into the My Outfits folder.
-
- LL_INFOS("Avatar") << self_av_string() << "avatar fully visible" << LL_ENDL;
-
- static bool check_populate_my_outfits = true;
- if (check_populate_my_outfits &&
- (LLInventoryModel::getIsFirstTimeInViewer2()
- || gSavedSettings.getBOOL("MyOutfitsAutofill")))
- {
- gAgentWearables.populateMyOutfitsFolder();
- }
- check_populate_my_outfits = false;
-}
-
// Handler for anything that's deferred until avatar de-clouds.
void LLAppearanceMgr::onFirstFullyVisible()
{
@@ -2841,10 +2822,6 @@ void LLAppearanceMgr::onFirstFullyVisible()
gAgentAvatarp->reportAvatarRezTime();
gAgentAvatarp->debugAvatarVisible();
- // The auto-populate is failing at the point of generating outfits
- // folders, so don't do the library copy until that is resolved.
- // autopopulateOutfits();
-
// If this is the first time we've ever logged in,
// then copy default gestures from the library.
if (gAgent.isFirstLogin()) {
@@ -2862,6 +2839,22 @@ void appearance_mgr_update_dirty_state()
}
}
+void update_base_outfit_after_ordering()
+{
+ LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance();
+
+ LLPointer<LLInventoryCallback> dirty_state_updater =
+ new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state);
+
+ //COF contains only links so we copy to the Base Outfit only links
+ const LLUUID base_outfit_id = app_mgr.getBaseOutfitUUID();
+ bool copy_folder_links = false;
+ app_mgr.slamCategoryLinks(app_mgr.getCOF(), base_outfit_id, copy_folder_links, dirty_state_updater);
+
+}
+
+// Save COF changes - update the contents of the current base outfit
+// to match the current COF. Fails if no current base outfit is set.
bool LLAppearanceMgr::updateBaseOutfit()
{
if (isOutfitLocked())
@@ -2871,25 +2864,19 @@ bool LLAppearanceMgr::updateBaseOutfit()
return false;
}
-
setOutfitLocked(true);
gAgentWearables.notifyLoadingStarted();
const LLUUID base_outfit_id = getBaseOutfitUUID();
- LL_DEBUGS("Avatar") << "updating base outfit to " << base_outfit_id << llendl;
if (base_outfit_id.isNull()) return false;
+ LL_DEBUGS("Avatar") << "saving cof to base outfit " << base_outfit_id << llendl;
- updateClothingOrderingInfo();
-
- // in a Base Outfit we do not remove items, only links
- remove_folder_contents(base_outfit_id, false, NULL);
-
- LLPointer<LLInventoryCallback> dirty_state_updater =
- new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state);
-
- //COF contains only links so we copy to the Base Outfit only links
- shallowCopyCategoryContents(getCOF(), base_outfit_id, dirty_state_updater);
+ LLPointer<LLInventoryCallback> cb =
+ new LLBoostFuncInventoryCallback(no_op_inventory_func, update_base_outfit_after_ordering);
+ // Really shouldn't be needed unless there's a race condition -
+ // updateAppearanceFromCOF() already calls updateClothingOrderingInfo.
+ updateClothingOrderingInfo(LLUUID::null, cb);
return true;
}
@@ -2937,12 +2924,6 @@ struct WearablesOrderComparator
bool operator()(const LLInventoryItem* item1, const LLInventoryItem* item2)
{
- if (!item1 || !item2)
- {
- llwarning("either item1 or item2 is NULL", 0);
- return true;
- }
-
const std::string& desc1 = item1->getActualDescription();
const std::string& desc2 = item2->getActualDescription();
@@ -2965,55 +2946,94 @@ struct WearablesOrderComparator
U32 mControlSize;
};
-void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id,
- bool update_base_outfit_ordering,
- LLPointer<LLInventoryCallback> cb)
+void LLAppearanceMgr::getWearableOrderingDescUpdates(LLInventoryModel::item_array_t& wear_items,
+ desc_map_t& desc_map)
{
- 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,cb);
- }
- }
- }
-
- // COF is processed if cat_id is not specified
- LLInventoryModel::item_array_t wear_items;
- getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING);
-
wearables_by_type_t items_by_type(LLWearableType::WT_COUNT);
divvyWearablesByType(wear_items, items_by_type);
for (U32 type = LLWearableType::WT_SHIRT; type < LLWearableType::WT_COUNT; type++)
{
-
U32 size = items_by_type[type].size();
if (!size) continue;
-
+
//sinking down invalid items which need reordering
std::sort(items_by_type[type].begin(), items_by_type[type].end(), WearablesOrderComparator((LLWearableType::EType) type));
-
+
//requesting updates only for those links which don't have "valid" descriptions
for (U32 i = 0; i < size; i++)
{
LLViewerInventoryItem* item = items_by_type[type][i];
if (!item) continue;
-
+
std::string new_order_str = build_order_string((LLWearableType::EType)type, i);
if (new_order_str == item->getActualDescription()) continue;
-
- LLSD updates;
- updates["desc"] = new_order_str;
- update_inventory_item(item->getUUID(),updates,cb);
+
+ desc_map[item->getUUID()] = new_order_str;
}
}
}
+bool LLAppearanceMgr::validateClothingOrderingInfo(LLUUID cat_id)
+{
+ // COF is processed if cat_id is not specified
+ if (cat_id.isNull())
+ {
+ cat_id = getCOF();
+ }
+
+ LLInventoryModel::item_array_t wear_items;
+ getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING);
+
+ // Identify items for which desc needs to change.
+ desc_map_t desc_map;
+ getWearableOrderingDescUpdates(wear_items, desc_map);
+
+ for (desc_map_t::const_iterator it = desc_map.begin();
+ it != desc_map.end(); ++it)
+ {
+ const LLUUID& item_id = it->first;
+ const std::string& new_order_str = it->second;
+ LLViewerInventoryItem *item = gInventory.getItem(item_id);
+ llwarns << "Order validation fails: " << item->getName()
+ << " needs to update desc to: " << new_order_str
+ << " (from: " << item->getActualDescription() << ")" << llendl;
+ }
+
+ return desc_map.size() == 0;
+}
+
+void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id,
+ LLPointer<LLInventoryCallback> cb)
+{
+ // COF is processed if cat_id is not specified
+ if (cat_id.isNull())
+ {
+ cat_id = getCOF();
+ }
+
+ LLInventoryModel::item_array_t wear_items;
+ getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING);
+
+ // Identify items for which desc needs to change.
+ desc_map_t desc_map;
+ getWearableOrderingDescUpdates(wear_items, desc_map);
+
+ for (desc_map_t::const_iterator it = desc_map.begin();
+ it != desc_map.end(); ++it)
+ {
+ LLSD updates;
+ const LLUUID& item_id = it->first;
+ const std::string& new_order_str = it->second;
+ LLViewerInventoryItem *item = gInventory.getItem(item_id);
+ LL_DEBUGS("Avatar") << item->getName() << " updating desc to: " << new_order_str
+ << " (was: " << item->getActualDescription() << ")" << llendl;
+ updates["desc"] = new_order_str;
+ update_inventory_item(item_id,updates,cb);
+ }
+
+}
+
class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder
{
LOG_CLASS(RequestAgentUpdateAppearanceResponder);
@@ -3428,7 +3448,7 @@ void LLAppearanceMgr::onOutfitFolderCreated(const LLUUID& folder_id, bool show_p
LLPointer<LLInventoryCallback> cb =
new LLBoostFuncInventoryCallback(no_op_inventory_func,
boost::bind(&LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered,this,folder_id,show_panel));
- updateClothingOrderingInfo(LLUUID::null, false, cb);
+ updateClothingOrderingInfo(LLUUID::null, cb);
}
void LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered(const LLUUID& folder_id, bool show_panel)
@@ -3437,7 +3457,7 @@ void LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered(const LLUUID& fold
new LLBoostFuncInventoryCallback(no_op_inventory_func,
boost::bind(show_created_outfit,folder_id,show_panel));
bool copy_folder_links = false;
- copyCategoryLinks(getCOF(), folder_id, copy_folder_links, cb);
+ slamCategoryLinks(getCOF(), folder_id, copy_folder_links, cb);
}
void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel)
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 4d7c536b3d..b2917cced4 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -49,8 +49,7 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
public:
typedef std::vector<LLInventoryModel::item_array_t> wearables_by_type_t;
- void updateAppearanceFromCOF(bool update_base_outfit_ordering = false,
- bool enforce_item_restrictions = true,
+ void updateAppearanceFromCOF(bool enforce_item_restrictions = true,
bool enforce_ordering = true,
nullary_func_t post_update_func = no_op);
bool needToSaveCOF();
@@ -74,10 +73,11 @@ public:
S32 getActiveCopyOperations() const;
- // Copy all links via the slam command (single inventory operation where supported)
- void copyCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
+ // Replace category contents with copied links via the slam_inventory_folder
+ // command (single inventory operation where supported)
+ void slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
bool include_folder_links, LLPointer<LLInventoryCallback> cb);
-
+
// Copy all items and the src category itself.
void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
LLPointer<LLInventoryCallback> cb);
@@ -173,9 +173,6 @@ public:
// Called when self avatar is first fully visible.
void onFirstFullyVisible();
- // Create initial outfits from library.
- void autopopulateOutfits();
-
// Copy initial gestures from library.
void copyLibraryGestures();
@@ -192,7 +189,8 @@ public:
void onOutfitFolderCreated(const LLUUID& folder_id, bool show_panel);
void onOutfitFolderCreatedAndClothingOrdered(const LLUUID& folder_id, bool show_panel);
- void makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel = true);
+
+ void makeNewOutfitLinks(const std::string& new_folder_name,bool show_panel = true);
bool moveWearable(LLViewerInventoryItem* item, bool closer_to_body);
@@ -201,10 +199,15 @@ public:
//Divvy items into arrays by wearable type
static void divvyWearablesByType(const LLInventoryModel::item_array_t& items, wearables_by_type_t& items_by_type);
+ typedef std::map<LLUUID,std::string> desc_map_t;
+
+ void getWearableOrderingDescUpdates(LLInventoryModel::item_array_t& wear_items, desc_map_t& desc_map);
+
//Check ordering information on wearables stored in links' descriptions and update if it is invalid
// COF is processed if cat_id is not specified
+ bool validateClothingOrderingInfo(LLUUID cat_id = LLUUID::null);
+
void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null,
- bool update_base_outfit_ordering = false,
LLPointer<LLInventoryCallback> cb = NULL);
bool isOutfitLocked() { return mOutfitLocked; }
@@ -277,8 +280,7 @@ public:
class LLUpdateAppearanceOnDestroy: public LLInventoryCallback
{
public:
- LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false,
- bool enforce_item_restrictions = true,
+ LLUpdateAppearanceOnDestroy(bool enforce_item_restrictions = true,
bool enforce_ordering = true,
nullary_func_t post_update_func = no_op);
virtual ~LLUpdateAppearanceOnDestroy();
@@ -286,7 +288,6 @@ public:
private:
U32 mFireCount;
- bool mUpdateBaseOrder;
bool mEnforceItemRestrictions;
bool mEnforceOrdering;
nullary_func_t mPostUpdateFunc;
@@ -305,10 +306,6 @@ private:
LLUUID mItemID;
};
-class
-
-#define SUPPORT_ENSEMBLES 0
-
LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name);
// Invoke a given callable after category contents are fully fetched.
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 89c56ab82c..cb3f40a5bb 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2416,49 +2416,13 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
}
- // if target is an outfit or current outfit folder we use link
- if (move_is_into_current_outfit || move_is_into_outfit)
+ // if target is current outfit folder we use link
+ if (move_is_into_current_outfit &&
+ inv_cat->getPreferredType() == LLFolderType::FT_NONE)
{
- if (inv_cat->getPreferredType() == LLFolderType::FT_NONE)
- {
- if (move_is_into_current_outfit)
- {
- // traverse category and add all contents to currently worn.
- BOOL append = true;
- LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append);
- }
- else
- {
- // Recursively create links in target outfit.
- LLInventoryModel::cat_array_t cats;
- LLInventoryModel::item_array_t items;
- model->collectDescendents(cat_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
- LLAppearanceMgr::instance().linkAll(mUUID,items,NULL);
- }
- }
- else
- {
-#if SUPPORT_ENSEMBLES
- // BAP - should skip if dup.
- if (move_is_into_current_outfit)
- {
- LLAppearanceMgr::instance().addEnsembleLink(inv_cat);
- }
- else
- {
- LLPointer<LLInventoryCallback> cb = NULL;
- const std::string empty_description = "";
- link_inventory_item(
- gAgent.getID(),
- cat_id,
- mUUID,
- inv_cat->getName(),
- empty_description,
- LLAssetType::AT_LINK_FOLDER,
- cb);
- }
-#endif
- }
+ // traverse category and add all contents to currently worn.
+ BOOL append = true;
+ LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append);
}
else if (move_is_into_outbox && !move_is_from_outbox)
{
@@ -2850,17 +2814,6 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
modifyOutfit(FALSE);
return;
}
-#if SUPPORT_ENSEMBLES
- else if ("wearasensemble" == action)
- {
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- LLViewerInventoryCategory* cat = getCategory();
- if(!cat) return;
- LLAppearanceMgr::instance().addEnsembleLink(cat,true);
- return;
- }
-#endif
else if ("addtooutfit" == action)
{
modifyOutfit(TRUE);
@@ -3382,16 +3335,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
items.push_back(std::string("New Clothes"));
items.push_back(std::string("New Body Parts"));
}
-#if SUPPORT_ENSEMBLES
- // Changing folder types is an unfinished unsupported feature
- // and can lead to unexpected behavior if enabled.
- items.push_back(std::string("Change Type"));
- const LLViewerInventoryCategory *cat = getCategory();
- if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
- {
- disabled_items.push_back(std::string("Change Type"));
- }
-#endif
getClipboardEntries(false, items, disabled_items, flags);
}
else
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index a179b61cff..4e028d2163 100755
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -139,14 +139,10 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "Inv_FolderOpen", "Inv_FolderClosed", FALSE, false, "default"));
-#if SUPPORT_ENSEMBLES
- initEnsemblesFromFile();
-#else
for (U32 type = (U32)LLFolderType::FT_ENSEMBLE_START; type <= (U32)LLFolderType::FT_ENSEMBLE_END; ++type)
{
addEntry((LLFolderType::EType)type, new ViewerFolderEntry("New Folder", "Inv_FolderOpen", "Inv_FolderClosed", FALSE, false));
- }
-#endif
+ }
}
bool LLViewerFolderDictionary::initEnsemblesFromFile()