diff options
Diffstat (limited to 'indra/newview/llagentwearables.cpp')
-rw-r--r-- | indra/newview/llagentwearables.cpp | 282 |
1 files changed, 211 insertions, 71 deletions
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index f4bc35002b..7b55282ee5 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -119,9 +119,9 @@ protected: void importedFolderDone(void); void contentsDone(void); enum ELibraryOutfitFetchStep mCurrFetchStep; - typedef std::vector< std::pair< LLUUID, std::string > > cloth_folder_vec_t; - cloth_folder_vec_t mLibraryClothingFolders; - cloth_folder_vec_t mImportedClothingFolders; + typedef std::vector<LLUUID> clothing_folder_vec_t; + clothing_folder_vec_t mLibraryClothingFolders; + clothing_folder_vec_t mImportedClothingFolders; bool mOutfitsPopulated; LLUUID mClothingID; LLUUID mLibraryClothingID; @@ -245,6 +245,7 @@ void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar) // wearables LLAgentWearables::createStandardWearablesAllDoneCallback::~createStandardWearablesAllDoneCallback() { + llinfos << "destructor - all done?" << llendl; gAgentWearables.createStandardWearablesAllDone(); } @@ -271,10 +272,16 @@ LLAgentWearables::addWearableToAgentInventoryCallback::addWearableToAgentInvento mTodo(todo), mCB(cb) { + llinfos << "constructor" << llendl; } void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& inv_item) { + if (mTodo & CALL_CREATESTANDARDDONE) + { + llinfos << "callback fired, inv_item " << inv_item.asString() << llendl; + } + if (inv_item.isNull()) return; @@ -286,6 +293,7 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i } if (mTodo & CALL_RECOVERDONE) { + LLAppearanceManager::instance().addCOFItemLink(inv_item,false); gAgentWearables.recoverMissingWearableDone(); } /* @@ -293,6 +301,7 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i */ if (mTodo & CALL_CREATESTANDARDDONE) { + LLAppearanceManager::instance().addCOFItemLink(inv_item,false); gAgentWearables.createStandardWearablesDone(mType, mIndex); } if (mTodo & CALL_MAKENEWOUTFITDONE) @@ -310,6 +319,8 @@ void LLAgentWearables::addWearabletoAgentInventoryDone(const S32 type, const LLUUID& item_id, LLWearable* wearable) { + llinfos << "type " << type << " index " << index << " item " << item_id.asString() << llendl; + if (item_id.isNull()) return; @@ -1038,7 +1049,7 @@ void LLAgentWearables::onInitialWearableAssetArrived(LLWearable* wearable, void* { return; } - + if (wearable) { llassert(type == wearable->getType()); @@ -1057,6 +1068,7 @@ void LLAgentWearables::onInitialWearableAssetArrived(LLWearable* wearable, void* // Somehow the asset doesn't exist in the database. gAgentWearables.recoverMissingWearable(type,index); } + gInventory.notifyObservers(); @@ -1138,6 +1150,80 @@ void LLAgentWearables::addLocalTextureObject(const EWearableType wearable_type, wearable->setLocalTextureObject(texture_type, lto); } +class OnWearableItemCreatedCB: public LLInventoryCallback +{ +public: + OnWearableItemCreatedCB(): + mWearablesAwaitingItems(WT_COUNT,NULL) + { + llinfos << "created callback" << llendl; + } + /* virtual */ void fire(const LLUUID& inv_item) + { + llinfos << "One item created " << inv_item.asString() << llendl; + LLViewerInventoryItem *item = gInventory.getItem(inv_item); + mItemsToLink.put(item); + updatePendingWearable(inv_item); + } + ~OnWearableItemCreatedCB() + { + llinfos << "All items created" << llendl; + LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy; + LLAppearanceManager::instance().linkAll(LLAppearanceManager::instance().getCOF(), + mItemsToLink, + link_waiter); + } + void addPendingWearable(LLWearable *wearable) + { + if (!wearable) + { + llwarns << "no wearable" << llendl; + return; + } + EWearableType type = wearable->getType(); + if (type<WT_COUNT) + { + mWearablesAwaitingItems[type] = wearable; + } + else + { + llwarns << "invalid type " << type << llendl; + } + } + void updatePendingWearable(const LLUUID& inv_item) + { + LLViewerInventoryItem *item = gInventory.getItem(inv_item); + if (!item) + { + llwarns << "no item found" << llendl; + return; + } + if (!item->isWearableType()) + { + llwarns << "non-wearable item found" << llendl; + return; + } + if (item && item->isWearableType()) + { + EWearableType type = item->getWearableType(); + if (type < WT_COUNT) + { + LLWearable *wearable = mWearablesAwaitingItems[type]; + if (wearable) + wearable->setItemID(inv_item); + } + else + { + llwarns << "invalid wearable type " << type << llendl; + } + } + } + +private: + LLInventoryModel::item_array_t mItemsToLink; + std::vector<LLWearable*> mWearablesAwaitingItems; +}; + void LLAgentWearables::createStandardWearables(BOOL female) { llwarns << "Creating Standard " << (female ? "female" : "male") @@ -1167,35 +1253,34 @@ void LLAgentWearables::createStandardWearables(BOOL female) FALSE //WT_SKIRT }; + LLPointer<LLInventoryCallback> cb = new OnWearableItemCreatedCB; for (S32 i=0; i < WT_COUNT; i++) { - bool once = false; - LLPointer<LLRefCount> donecb = NULL; if (create[i]) { - if (!once) - { - once = true; - donecb = new createStandardWearablesAllDoneCallback; - } llassert(getWearableCount((EWearableType)i) == 0); LLWearable* wearable = LLWearableList::instance().createNewWearable((EWearableType)i); - U32 index = pushWearable((EWearableType)i,wearable); + ((OnWearableItemCreatedCB*)(&(*cb)))->addPendingWearable(wearable); // no need to update here... - LLPointer<LLInventoryCallback> cb = - new addWearableToAgentInventoryCallback( - donecb, - i, - index, - wearable, - addWearableToAgentInventoryCallback::CALL_CREATESTANDARDDONE); - addWearableToAgentInventory(cb, wearable, LLUUID::null, FALSE); + LLUUID category_id = LLUUID::null; + create_inventory_item(gAgent.getID(), + gAgent.getSessionID(), + category_id, + wearable->getTransactionID(), + wearable->getName(), + wearable->getDescription(), + wearable->getAssetType(), + LLInventoryType::IT_WEARABLE, + wearable->getType(), + wearable->getPermissions().getMaskNextOwner(), + cb); } } } void LLAgentWearables::createStandardWearablesDone(S32 type, U32 index) { + llinfos << "type " << type << " index " << index << llendl; if (mAvatarObject) { mAvatarObject->updateVisualParams(); @@ -1206,6 +1291,8 @@ void LLAgentWearables::createStandardWearablesAllDone() { // ... because sendAgentWearablesUpdate will notify inventory // observers. + llinfos << "all done?" << llendl; + mWearablesLoaded = TRUE; checkWearablesLoaded(); @@ -1576,7 +1663,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it const LLDynamicArray< LLWearable* >& wearables, BOOL remove) { - lldebugs << "setWearableOutfit() start" << llendl; + llinfos << "setWearableOutfit() start" << llendl; BOOL wearables_to_remove[WT_COUNT]; wearables_to_remove[WT_SHAPE] = FALSE; @@ -2153,7 +2240,7 @@ void LLAgentWearables::updateServer() void LLAgentWearables::populateMyOutfitsFolder(void) { - llinfos << "starting outfit populate" << llendl; + llinfos << "starting outfit population" << llendl; LLLibraryOutfitsFetch* outfits = new LLLibraryOutfitsFetch(); @@ -2225,17 +2312,28 @@ void LLLibraryOutfitsFetch::folderDone(void) 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. if (cat_array.count() > 0 || wearable_array.count() > 0) { mOutfitsPopulated = true; return; } - + mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); mLibraryClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); - + + // If Library->Clothing->Initial Outfits exists, use that. + LLNameCategoryCollector matchFolderFunctor("Initial Outfits"); + 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(); + } + mCompleteFolders.clear(); // Get the complete information on the items in the inventory. @@ -2266,31 +2364,28 @@ void LLLibraryOutfitsFetch::outfitsDone(void) { const LLViewerInventoryCategory *cat = iter->get(); - // Get the names and id's of every outfit in the library, except for ruth and other "misc" outfits. - if (cat->getName() != "More Outfits" && cat->getName() != "Ruth") + // 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(std::make_pair(cat->getUUID(), cat->getName())); + mLibraryClothingFolders.push_back(cat->getUUID()); } } - - // Collect the contents of your Inventory Clothing folder cat_array.clear(); wearable_array.clear(); - gInventory.collectDescendents(mClothingID, cat_array, wearable_array, - LLInventoryModel::EXCLUDE_TRASH); // Check if you already have an "Imported Library Clothing" folder - for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); - iter != cat_array.end(); - ++iter) + LLNameCategoryCollector matchFolderFunctor(mImportedClothingName); + gInventory.collectDescendentsIf(mClothingID, + cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH, + matchFolderFunctor); + if (cat_array.size() > 0) { - const LLViewerInventoryCategory *cat = iter->get(); - if (cat->getName() == mImportedClothingName) - { - mImportedClothingID = cat->getUUID(); - } + const LLViewerInventoryCategory *cat = cat_array.get(0); + mImportedClothingID = cat->getUUID(); } mCompleteFolders.clear(); @@ -2328,31 +2423,59 @@ private: LLLibraryOutfitsFetch * mLibraryOutfitsFetcher; }; +// Copy the clothing folders from the library into the imported clothing folder void LLLibraryOutfitsFetch::libraryDone(void) { - // Copy the clothing folders from the library into the imported clothing folder if necessary. - if (mImportedClothingID == LLUUID::null) + if (mImportedClothingID != LLUUID::null) { - gInventory.removeObserver(this); - LLPointer<LLInventoryCallback> copy_waiter = new LLLibraryOutfitsCopyDone(this); - mImportedClothingID = gInventory.createNewCategory(mClothingID, - LLFolderType::FT_NONE, - mImportedClothingName); + // 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 (clothing_folder_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; + } - for (cloth_folder_vec_t::const_iterator iter = mLibraryClothingFolders.begin(); - iter != mLibraryClothingFolders.end(); - ++iter) + if (!LLAppearanceManager::getInstance()->getCanMakeFolderIntoOutfit(src_folder_id)) { - LLUUID folder_id = gInventory.createNewCategory(mImportedClothingID, - LLFolderType::FT_NONE, - iter->second); - LLAppearanceManager::getInstance()->shallowCopyCategoryContents(iter->first, folder_id, copy_waiter); + llinfos << "Skipping non-outfit folder name:" << cat->getName() << llendl; + continue; } - } - else - { - // Skip straight to fetching the contents of the imported folder - importedFolderFetch(); + + // 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()); + LLAppearanceManager::getInstance()->shallowCopyCategoryContents(src_folder_id, dst_folder_id, copy_waiter); } } @@ -2389,7 +2512,7 @@ void LLLibraryOutfitsFetch::importedFolderDone(void) // Get the name of every imported outfit folders.push_back(cat->getUUID()); - mImportedClothingFolders.push_back(std::make_pair(cat->getUUID(), cat->getName())); + mImportedClothingFolders.push_back(cat->getUUID()); } mCompleteFolders.clear(); @@ -2405,17 +2528,25 @@ void LLLibraryOutfitsFetch::contentsDone(void) LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; - for (cloth_folder_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin(); + for (clothing_folder_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; + } + // First, make a folder in the My Outfits directory. - LLUUID new_outfit_folder_id = gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, folder_iter->second); + 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_iter->first, cat_array, wearable_array, + gInventory.collectDescendents(folder_id, cat_array, wearable_array, LLInventoryModel::EXCLUDE_TRASH); for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin(); @@ -2485,7 +2616,7 @@ class LLFetchAndLinkObserver: public LLInventoryFetchObserver public: LLFetchAndLinkObserver(LLInventoryFetchObserver::item_ref_t& ids): m_ids(ids), - LLInventoryFetchObserver(true) + LLInventoryFetchObserver(true) // retry for missing items { } ~LLFetchAndLinkObserver() @@ -2494,7 +2625,9 @@ public: virtual void done() { gInventory.removeObserver(this); + // Link to all fetched items in COF. + LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy; for (LLInventoryFetchObserver::item_ref_t::iterator it = m_ids.begin(); it != m_ids.end(); ++it) @@ -2506,8 +2639,13 @@ public: llwarns << "fetch failed!" << llendl; continue; } - link_inventory_item(gAgent.getID(), item->getLinkedUUID(), LLAppearanceManager::instance().getCOF(), item->getName(), - LLAssetType::AT_LINK, LLPointer<LLInventoryCallback>(NULL)); + + link_inventory_item(gAgent.getID(), + item->getLinkedUUID(), + LLAppearanceManager::instance().getCOF(), + item->getName(), + LLAssetType::AT_LINK, + link_waiter); } } private: @@ -2530,11 +2668,13 @@ void LLInitialWearablesFetch::processWearablesMessage() #ifdef USE_CURRENT_OUTFIT_FOLDER ids.push_back(wearable_data->mItemID); #endif - // Fetch the wearables - LLWearableList::instance().getAsset(wearable_data->mAssetID, - LLStringUtil::null, - LLWearableDictionary::getAssetType(wearable_data->mType), - LLAgentWearables::onInitialWearableAssetArrived, (void*)(wearable_data)); +#if 0 +// // Fetch the wearables +// LLWearableList::instance().getAsset(wearable_data->mAssetID, +// LLStringUtil::null, +// LLWearableDictionary::getAssetType(wearable_data->mType), +// LLAgentWearables::onInitialWearableAssetArrived, (void*)(wearable_data)); +#endif } else { |