diff options
Diffstat (limited to 'indra/newview/llagentwearables.cpp')
-rw-r--r-- | indra/newview/llagentwearables.cpp | 259 |
1 files changed, 225 insertions, 34 deletions
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 22875cbca2..4834b31bc7 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -37,6 +37,7 @@ #include "llfloatercustomize.h" #include "llfloaterinventory.h" +#include "llinventorybridge.h" #include "llinventorymodel.h" #include "llnotify.h" #include "llviewerregion.h" @@ -46,6 +47,9 @@ #include <boost/scoped_ptr.hpp> +// For viewer2.0 internal demo, don't use current outfit folder contents at all during initial startup. Will reenable +// this once we're sure this works completely. +// #define USE_CURRENT_OUTFIT_FOLDER LLAgentWearables gAgentWearables; @@ -662,13 +666,6 @@ BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id, BOOL include_linked_ return FALSE; } -struct InitialWearableData -{ - S32 mType; - U32 mIndex; - LLUUID mItemID; -}; - // MULTI-WEARABLE: update for multiple // static void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data) @@ -696,14 +693,18 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs return; } + // Get the UUID of the current outfit folder (will be created if it doesn't exist) + LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); + + LLOutfitFolderFetch* outfit = new LLOutfitFolderFetch(); + //lldebugs << "processAgentInitialWearablesUpdate()" << llendl; // Add wearables - LLUUID asset_id_array[WT_COUNT]; - LLUUID item_id_array[WT_COUNT]; // MULTI-WEARABLE: TODO: update once messages change. Currently use results to populate the zeroth element. gAgentWearables.mItemsAwaitingWearableUpdate.clear(); for (S32 i=0; i < num_wearables; i++) { + // Parse initial werables data from message system U8 type_u8 = 0; gMessageSystem->getU8Fast(_PREHASH_WearableData, _PREHASH_WearableType, type_u8, i); if (type_u8 >= WT_COUNT) @@ -711,10 +712,10 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs continue; } const EWearableType type = (EWearableType) type_u8; - + LLUUID item_id; gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_ItemID, item_id, i); - + LLUUID asset_id; gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_AssetID, asset_id, i); if (asset_id.isNull()) @@ -728,34 +729,77 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs { continue; } - - // MULTI-WEARABLE: extend arrays to index by type + index. - gAgentWearables.mItemsAwaitingWearableUpdate.insert(item_id); - item_id_array[type] = item_id; - asset_id_array[type] = asset_id; + + // MULTI-WEARABLE: TODO: update once messages change. Currently use results to populate the zeroth element. + + // Store initial wearables data until we know whether we have the current outfit folder or need to use the data. + InitialWearableData * temp_wearable_data = new InitialWearableData(type, 0, item_id, asset_id); // MULTI-WEARABLE: update + outfit->mAgentInitialWearables.push_back(temp_wearable_data); + } lldebugs << " " << LLWearableDictionary::getTypeLabel(type) << llendl; } + + // What we do here is get the complete information on the items in + // the inventory, and set up an observer that will wait for that to + // happen. + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + folders.push_back(current_outfit_id); + outfit->fetchDescendents(folders); + if(outfit->isEverythingComplete()) + { + // everything is already here - call done. + outfit->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(outfit); + } + } +} - // now that we have the asset ids...request the wearable assets - for (S32 i = 0; i < WT_COUNT; i++) +// static +void LLAgentWearables::fetchInitialWearables(initial_wearable_data_vec_t & current_outfit_links, initial_wearable_data_vec_t & message_wearables) +{ +#ifdef USE_CURRENT_OUTFIT_FOLDER + if (!current_outfit_links.empty()) + { + for (U8 i = 0; i < current_outfit_links.size(); ++i) { - // MULTI-WEARABLE: TODO: update once messages change. - // Currently use results to populate the zeroth element. - if (!item_id_array[i].isNull()) - { - InitialWearableData *wear_data = new InitialWearableData; - wear_data->mType = i; - wear_data->mIndex = 0; // MULTI-WEARABLE: update - wear_data->mItemID = item_id_array[i]; - LLWearableList::instance().getAsset(asset_id_array[i], - LLStringUtil::null, - LLWearableDictionary::getAssetType((EWearableType) i), - onInitialWearableAssetArrived, (void*)wear_data); - } + // Fetch the wearables in the current outfit folder + LLWearableList::instance().getAsset(current_outfit_links[i]->mAssetID, + LLStringUtil::null, + LLWearableDictionary::getAssetType(current_outfit_links[i]->mType), + onInitialWearableAssetArrived, (void*)(current_outfit_links[i])); + } + } + else +#endif + if (!message_wearables.empty()) // We have an empty current outfit folder, use the message data instead. + { + LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); + for (U8 i = 0; i < message_wearables.size(); ++i) + { + // Populate the current outfit folder with links to the wearables passed in the message +#ifdef USE_CURRENT_OUTFIT_FOLDER + std::string link_name = "WearableLink"; + link_inventory_item(gAgent.getID(), message_wearables[i]->mItemID, current_outfit_id, link_name, + LLAssetType::AT_LINK, LLPointer<LLInventoryCallback>(NULL)); +#endif + // Fetch the wearables + LLWearableList::instance().getAsset(message_wearables[i]->mAssetID, + LLStringUtil::null, + LLWearableDictionary::getAssetType(message_wearables[i]->mType), + onInitialWearableAssetArrived, (void*)(message_wearables[i])); } } + else + { + LL_WARNS("Wearables") << "No current outfit folder iterms found and no initial wearables fallback message received." << LL_ENDL; + } } // A single wearable that the avatar was wearing on start-up has arrived from the database. @@ -763,7 +807,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs void LLAgentWearables::onInitialWearableAssetArrived(LLWearable* wearable, void* userdata) { boost::scoped_ptr<InitialWearableData> wear_data((InitialWearableData*)userdata); - const EWearableType type = (EWearableType)wear_data->mType; + const EWearableType type = wear_data->mType; const U32 index = wear_data->mIndex; LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); @@ -775,10 +819,11 @@ void LLAgentWearables::onInitialWearableAssetArrived(LLWearable* wearable, void* if (wearable) { llassert(type == wearable->getType()); + // MULTI-WEARABLE: is this always zeroth element? Change sometime. wearable->setItemID(wear_data->mItemID); - gAgentWearables.setWearable(type,index,wearable); + gAgentWearables.setWearable(type, index, wearable); gAgentWearables.mItemsAwaitingWearableUpdate.erase(wear_data->mItemID); - + // disable composites if initial textures are baked avatar->setupComposites(); @@ -954,6 +999,8 @@ void LLAgentWearables::createStandardWearablesAllDone() mAvatarObject->onFirstTEMessageReceived(); } +// Note: wearables_to_include should be a list of EWearableType types +// attachments_to_include should be a list of attachment points void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name, const LLDynamicArray<S32>& wearables_to_include, const LLDynamicArray<S32>& attachments_to_include, @@ -1087,6 +1134,97 @@ void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name, } } +// Note: wearables_to_include should be a list of EWearableType types +// attachments_to_include should be a list of attachment points +void LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name, + const LLDynamicArray<S32>& wearables_to_include, + const LLDynamicArray<S32>& attachments_to_include, + BOOL rename_clothing) +{ + if (mAvatarObject.isNull()) + { + return; + } + + // First, make a folder in the Clothes directory. + LLUUID folder_id = gInventory.createNewCategory( + gInventory.findCategoryUUIDForType(LLAssetType::AT_MY_OUTFITS), + LLAssetType::AT_OUTFIT, + new_folder_name); + +// bool found_first_item = false; + + /////////////////// + // Wearables + + if (wearables_to_include.count()) + { + // Then, iterate though each of the wearables and save links to them in the folder. + S32 i; + S32 count = wearables_to_include.count(); + LLDynamicArray<LLUUID> delete_items; + LLPointer<LLRefCount> cbdone = NULL; + for (i = 0; i < count; ++i) + { + const S32 type = wearables_to_include[i]; + for (U32 j=0; j<getWearableCount((EWearableType)i); j++) + { + LLWearable* old_wearable = getWearable((EWearableType)type,j); + if (old_wearable) + { + std::string new_name; + if (rename_clothing) + { + new_name = new_folder_name; + new_name.append(" "); + new_name.append(old_wearable->getTypeLabel()); + LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN); + } + + LLViewerInventoryItem* item = gInventory.getItem(getWearableItemID((EWearableType) type, j)); + if (!item) continue; + LLPointer<LLInventoryCallback> cb = NULL; + link_inventory_item(gAgent.getID(), + item->getUUID(), + folder_id, + new_name, + LLAssetType::AT_LINK, + cb); + } + } + } + gInventory.notifyObservers(); + } + + + /////////////////// + // Attachments + + if (attachments_to_include.count()) + { + for (S32 i = 0; i < attachments_to_include.count(); i++) + { + S32 attachment_pt = attachments_to_include[i]; + LLViewerJointAttachment* attachment = get_if_there(mAvatarObject->mAttachmentPoints, attachment_pt, (LLViewerJointAttachment*)NULL); + if (!attachment) continue; + LLViewerObject* attached_object = attachment->getObject(); + if (!attached_object) continue; + const LLUUID& item_id = attachment->getItemID(); + if (item_id.isNull()) continue; + LLInventoryItem* item = gInventory.getItem(item_id); + if (!item) continue; + + LLPointer<LLInventoryCallback> cb = NULL; + link_inventory_item(gAgent.getID(), + item->getUUID(), + folder_id, + item->getName(), + LLAssetType::AT_LINK, + cb); + } + } +} + void LLAgentWearables::makeNewOutfitDone(S32 type, U32 index) { LLUUID first_item_id = getWearableItemID((EWearableType)type, index); @@ -1635,3 +1773,56 @@ void LLAgentWearables::updateServer() sendAgentWearablesUpdate(); gAgent.sendAgentSetAppearance(); } + +void LLAgentWearables::LLOutfitFolderFetch::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(mCompleteFolders.front(), + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH); + S32 count = item_array.count(); + LLAgentWearables::initial_wearable_data_vec_t current_outfit_links; + current_outfit_links.reserve(count); + + for(S32 i = 0; i < count; ++i) + { + // A bit of a hack since wearables database doesn't contain asset types... + // Perform indirection in case this assetID is in fact a link. This only works + // because of the assumption that all assetIDs and itemIDs are unique (i.e. + // no assetID is also used as an itemID elsewhere); therefore if the assetID + // exists as an itemID in the user's inventory, then this must be a link. + const LLInventoryItem *linked_item = gInventory.getItem(item_array.get(i)->getUUID()); + LLAssetType::EType asset_type = (LLAssetType::EType) 0; + if (linked_item) + { + asset_type = linked_item->getType(); + LLInventoryItem * base_item = gInventory.getItem(linked_item->getLinkedUUID()); + if (base_item) + { + EWearableType type = (EWearableType) (base_item->getFlags() & LLInventoryItem::II_FLAGS_WEARABLES_MASK); + // MULTI-WEARABLE: update + InitialWearableData * temp_wearable_data = new InitialWearableData(type, 0, linked_item->getLinkedUUID(), base_item->getAssetUUID()); + current_outfit_links.push_back(temp_wearable_data); + } + else + { + llwarns << "Null base_item in LLOutfitFolderFetch::done, linkedUUID is " << linked_item->getLinkedUUID().asString() << llendl; + } + } + else + { + llwarns << "Null linked_item in LLOutfitFolderFetch::done, UUID is " << item_array.get(i)->getUUID().asString() << llendl; + } + } + + gInventory.removeObserver(this); + LLAgentWearables::fetchInitialWearables(current_outfit_links, mAgentInitialWearables); + mAgentInitialWearables.clear(); + delete this; +} + |