diff options
Diffstat (limited to 'indra/newview/llagentwearables.cpp')
-rw-r--r-- | indra/newview/llagentwearables.cpp | 300 |
1 files changed, 183 insertions, 117 deletions
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 2cfa8d2a54..34d2c00007 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -46,6 +46,7 @@ #include "llwearablelist.h" #include "llgesturemgr.h" #include "llappearancemgr.h" +#include "lltexlayer.h" #include <boost/scoped_ptr.hpp> @@ -65,11 +66,10 @@ public: struct InitialWearableData { EWearableType mType; - U32 mIndex; LLUUID mItemID; LLUUID mAssetID; - InitialWearableData(EWearableType type, U32 index, LLUUID itemID, LLUUID assetID) : - mType(type), mIndex(index), mItemID(itemID), mAssetID(assetID) { } + InitialWearableData(EWearableType type, LLUUID itemID, LLUUID assetID) : + mType(type), mItemID(itemID), mAssetID(assetID) { } }; typedef std::vector<InitialWearableData> initial_wearable_data_vec_t; @@ -139,11 +139,6 @@ LLAgentWearables::LLAgentWearables() : mWearablesLoaded(FALSE), mAvatarObject(NULL) { - // MULTI-WEARABLE: TODO remove null entries. - for (U32 i = 0; i < WT_COUNT; i++) - { - mWearableDatas[(EWearableType)i].push_back(NULL); - } } LLAgentWearables::~LLAgentWearables() @@ -237,10 +232,16 @@ void LLAgentWearables::addWearabletoAgentInventoryDone(const S32 type, { wearable->setItemID(item_id); } - setWearable((EWearableType)type,index,wearable); if (old_item_id.notNull()) + { gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id); + setWearable((EWearableType)type,index,wearable); + } + else + { + pushWearable((EWearableType)type,wearable); + } gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); LLViewerInventoryItem* item = gInventory.getItem(item_id); if (item && wearable) @@ -260,11 +261,11 @@ void LLAgentWearables::sendAgentWearablesUpdate() { // MULTI-WEARABLE: call i "type" or something. // First make sure that we have inventory items for each wearable - for (S32 i=0; i < WT_COUNT; ++i) + for (S32 type=0; type < WT_COUNT; ++type) { - for (U32 j=0; j < getWearableCount((EWearableType)i); j++) + for (U32 j=0; j < getWearableCount((EWearableType)type); ++j) { - LLWearable* wearable = getWearable((EWearableType)i,j); + LLWearable* wearable = getWearable((EWearableType)type,j); if (wearable) { if (wearable->getItemID().isNull()) @@ -272,7 +273,7 @@ void LLAgentWearables::sendAgentWearablesUpdate() LLPointer<LLInventoryCallback> cb = new addWearableToAgentInventoryCallback( LLPointer<LLRefCount>(NULL), - i, + type, j, wearable, addWearableToAgentInventoryCallback::CALL_NONE); @@ -299,15 +300,15 @@ void LLAgentWearables::sendAgentWearablesUpdate() lldebugs << "sendAgentWearablesUpdate()" << llendl; // MULTI-WEARABLE: update for multi-wearables after server-side support is in. - for (S32 i=0; i < WT_COUNT; ++i) + for (S32 type=0; type < WT_COUNT; ++type) { gMessageSystem->nextBlockFast(_PREHASH_WearableData); - U8 type_u8 = (U8)i; + U8 type_u8 = (U8)type; gMessageSystem->addU8Fast(_PREHASH_WearableType, type_u8); // MULTI-WEARABLE: TODO: hacked index to 0, needs to loop over all once messages support this. - LLWearable* wearable = getWearable((EWearableType)i, 0); + LLWearable* wearable = getWearable((EWearableType)type, 0); if (wearable) { //llinfos << "Sending wearable " << wearable->getName() << llendl; @@ -327,19 +328,18 @@ void LLAgentWearables::sendAgentWearablesUpdate() gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID::null); } - lldebugs << " " << LLWearableDictionary::getTypeLabel((EWearableType)i) << ": " << (wearable ? wearable->getAssetID() : LLUUID::null) << llendl; + lldebugs << " " << LLWearableDictionary::getTypeLabel((EWearableType)type) << ": " << (wearable ? wearable->getAssetID() : LLUUID::null) << llendl; } gAgent.sendReliableMessage(); } -// MULTI-WEARABLE: add index. void LLAgentWearables::saveWearable(const EWearableType type, const U32 index, BOOL send_update) { LLWearable* old_wearable = getWearable(type, index); if (old_wearable && (old_wearable->isDirty() || old_wearable->isOldVersion())) { LLUUID old_item_id = old_wearable->getItemID(); - LLWearable* new_wearable = LLWearableList::instance().createCopyFromAvatar(old_wearable); + LLWearable* new_wearable = LLWearableList::instance().createCopy(old_wearable); new_wearable->setItemID(old_item_id); // should this be in LLWearable::copyDataFrom()? setWearable(type,index,new_wearable); @@ -391,7 +391,6 @@ void LLAgentWearables::saveWearable(const EWearableType type, const U32 index, B } } -// MULTI-WEARABLE: add index void LLAgentWearables::saveWearableAs(const EWearableType type, const U32 index, const std::string& new_name, @@ -417,7 +416,7 @@ void LLAgentWearables::saveWearableAs(const EWearableType type, } std::string trunc_name(new_name); LLStringUtil::truncate(trunc_name, DB_INV_ITEM_NAME_STR_LEN); - LLWearable* new_wearable = LLWearableList::instance().createCopyFromAvatar( + LLWearable* new_wearable = LLWearableList::instance().createCopy( old_wearable, trunc_name); LLPointer<LLInventoryCallback> cb = @@ -451,10 +450,8 @@ void LLAgentWearables::saveWearableAs(const EWearableType type, void LLAgentWearables::revertWearable(const EWearableType type, const U32 index) { LLWearable* wearable = getWearable(type, index); - if (wearable) - { - wearable->writeToAvatar(TRUE); - } + wearable->revertValues(); + gAgent.sendAgentSetAppearance(); } @@ -604,13 +601,10 @@ void LLAgentWearables::sendAgentWearablesRequest() gAgent.sendReliableMessage(); } -// MULTI-WEARABLE: update for multiple items per type. -// Used to enable/disable menu items. // static BOOL LLAgentWearables::selfHasWearable(EWearableType type) { - // MULTI-WEARABLE: TODO could be getWearableCount > 0, once null entries have been eliminated. - return gAgentWearables.getWearable(type,0) != NULL; + return (gAgentWearables.getWearableCount(type) > 0); } LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index) @@ -633,6 +627,11 @@ LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index) void LLAgentWearables::setWearable(const EWearableType type, U32 index, LLWearable *wearable) { + if (!getWearable(type,index)) + { + pushWearable(type,wearable); + return; + } wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); if (wearable_iter == mWearableDatas.end()) { @@ -650,6 +649,59 @@ void LLAgentWearables::setWearable(const EWearableType type, U32 index, LLWearab } } +U32 LLAgentWearables::pushWearable(const EWearableType type, LLWearable *wearable) +{ + if (wearable == NULL) + { + // no null wearables please! + //TODO: insert llwarns + return MAX_WEARABLES_PER_TYPE; + } + if (type < WT_COUNT || mWearableDatas[type].size() < MAX_WEARABLES_PER_TYPE) + { + mWearableDatas[type].push_back(wearable); + return mWearableDatas[type].size()-1; + } + return MAX_WEARABLES_PER_TYPE; +} + +void LLAgentWearables::popWearable(const EWearableType type, LLWearable *wearable) +{ + U32 index = getWearableIndex(type, wearable); + if (index < MAX_WEARABLES_PER_TYPE && index < getWearableCount(type)) + { + popWearable(type, index); + } +} + +void LLAgentWearables::popWearable(const EWearableType type, U32 index) +{ + if (getWearable(type, index)) + { + mWearableDatas[type].erase(mWearableDatas[type].begin() + index); + } +} + +U32 LLAgentWearables::getWearableIndex(const EWearableType type, LLWearable *wearable) +{ + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + llwarns << "tried to get wearable index with an invalid type!" << llendl; + return MAX_WEARABLES_PER_TYPE; + } + const wearableentry_vec_t& wearable_vec = wearable_iter->second; + for(U32 index = 0; index < wearable_vec.size(); index++) + { + if (wearable_vec[index] == wearable) + { + return index; + } + } + + return MAX_WEARABLES_PER_TYPE; +} + const LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index) const { wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); @@ -668,7 +720,17 @@ const LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 in } } -//MULTI-WEARABLE: this will give wrong values until we get rid of the "always one empty object" scheme. +LLWearable* LLAgentWearables::getTopWearable(const EWearableType type) +{ + U32 count = getWearableCount(type); + if ( count == 0) + { + return NULL; + } + + return getWearable(type, count-1); +} + U32 LLAgentWearables::getWearableCount(const EWearableType type) const { wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); @@ -680,6 +742,13 @@ U32 LLAgentWearables::getWearableCount(const EWearableType type) const return wearable_vec.size(); } +U32 LLAgentWearables::getWearableCount(const U32 tex_index) const +{ + const EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType((LLVOAvatarDefines::ETextureIndex)tex_index); + return getWearableCount(wearable_type); +} + + BOOL LLAgentWearables::itemUpdatePending(const LLUUID& item_id) const { return mItemsAwaitingWearableUpdate.find(item_id) != mItemsAwaitingWearableUpdate.end(); @@ -798,7 +867,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs // 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. - LLInitialWearablesFetch::InitialWearableData wearable_data(type, 0, item_id, asset_id); // MULTI-WEARABLE: update + LLInitialWearablesFetch::InitialWearableData wearable_data(type, item_id, asset_id); // MULTI-WEARABLE: update outfit->mAgentInitialWearables.push_back(wearable_data); } @@ -832,7 +901,7 @@ void LLAgentWearables::onInitialWearableAssetArrived(LLWearable* wearable, void* { boost::scoped_ptr<LLInitialWearablesFetch::InitialWearableData> wear_data((LLInitialWearablesFetch::InitialWearableData*)userdata); const EWearableType type = wear_data->mType; - const U32 index = wear_data->mIndex; + U32 index = 0; LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); if (!avatar) @@ -843,22 +912,19 @@ 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); + index = gAgentWearables.pushWearable(type, wearable); gAgentWearables.mItemsAwaitingWearableUpdate.erase(wear_data->mItemID); // disable composites if initial textures are baked avatar->setupComposites(); - wearable->writeToAvatar(FALSE); avatar->setCompositeUpdatesEnabled(TRUE); gInventory.addChangedMask(LLInventoryObserver::LABEL, wearable->getItemID()); } else { // Somehow the asset doesn't exist in the database. - // MULTI-WEARABLE: assuming zeroth elt gAgentWearables.recoverMissingWearable(type,index); } @@ -898,7 +964,7 @@ void LLAgentWearables::recoverMissingWearable(const EWearableType type, U32 inde S32 type_s32 = (S32) type; setWearable(type,index,new_wearable); - new_wearable->writeToAvatar(TRUE); + //new_wearable->writeToAvatar(TRUE); // Add a new one in the lost and found folder. // (We used to overwrite the "not found" one, but that could potentially @@ -938,8 +1004,8 @@ void LLAgentWearables::addLocalTextureObject(const EWearableType wearable_type, { llerrs << "Tried to add local texture object to invalid wearable with type " << wearable_type << " and index " << wearable_index << llendl; } - - wearable->setLocalTextureObject(texture_type, new LLLocalTextureObject()); + LLLocalTextureObject* lto = new LLLocalTextureObject(); + wearable->setLocalTextureObject(texture_type, lto); } void LLAgentWearables::createStandardWearables(BOOL female) @@ -982,17 +1048,15 @@ void LLAgentWearables::createStandardWearables(BOOL female) once = true; donecb = new createStandardWearablesAllDoneCallback; } - // MULTI_WEARABLE: only elt 0, may be the right thing? - llassert(getWearable((EWearableType)i,0) == NULL); + llassert(getWearableCount((EWearableType)i) == 0); LLWearable* wearable = LLWearableList::instance().createNewWearable((EWearableType)i); - setWearable((EWearableType)i,0,wearable); + U32 index = pushWearable((EWearableType)i,wearable); // no need to update here... - // MULTI_WEARABLE: hardwired index = 0 here. LLPointer<LLInventoryCallback> cb = new addWearableToAgentInventoryCallback( donecb, i, - 0, + index, wearable, addWearableToAgentInventoryCallback::CALL_CREATESTANDARDDONE); addWearableToAgentInventory(cb, wearable, LLUUID::null, FALSE); @@ -1002,11 +1066,9 @@ void LLAgentWearables::createStandardWearables(BOOL female) void LLAgentWearables::createStandardWearablesDone(S32 type, U32 index) { - LLWearable* wearable = getWearable((EWearableType)type, index); - - if (wearable) + if (mAvatarObject) { - wearable->writeToAvatar(TRUE); + mAvatarObject->updateVisualParams(); } } @@ -1023,12 +1085,12 @@ void LLAgentWearables::createStandardWearablesAllDone() mAvatarObject->onFirstTEMessageReceived(); } +// MULTI-WEARABLE: Properly handle multiwearables later. void LLAgentWearables::getAllWearablesArray(LLDynamicArray<S32>& wearables) { for( S32 i = 0; i < WT_COUNT; ++i ) { - // MULTI-WEARABLE: Properly handle multiwearables later. - if (getWearable( (EWearableType) i, 0 ) != NULL) + if (getWearableCount( (EWearableType) i) != 0 ) { wearables.push_back(i); } @@ -1141,25 +1203,30 @@ void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name, 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; - if (!msg_started) + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) { - msg_started = TRUE; - msg->newMessage("CreateNewOutfitAttachments"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("HeaderData"); - msg->addUUID("NewFolderID", folder_id); + LLViewerObject *attached_object = (*attachment_iter); + if(!attached_object) continue; + const LLUUID& item_id = (*attachment_iter)->getItemID(); + if(item_id.isNull()) continue; + LLInventoryItem* item = gInventory.getItem(item_id); + if(!item) continue; + if(!msg_started) + { + msg_started = TRUE; + msg->newMessage("CreateNewOutfitAttachments"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->nextBlock("HeaderData"); + msg->addUUID("NewFolderID", folder_id); + } + msg->nextBlock("ObjectData"); + msg->addUUID("OldItemID", item_id); + msg->addUUID("OldFolderID", item->getParentUUID()); } - msg->nextBlock("ObjectData"); - msg->addUUID("OldItemID", item_id); - msg->addUUID("OldFolderID", item->getParentUUID()); } if (msg_started) @@ -1233,6 +1300,13 @@ void LLAgentWearables::addWearableToAgentInventory(LLPointer<LLInventoryCallback void LLAgentWearables::removeWearable(const EWearableType type, bool do_remove_all, U32 index) { + if ((gAgent.isTeen()) + && (type == WT_UNDERSHIRT || type == WT_UNDERPANTS)) + { + // Can't take off underclothing in simple UI mode or on PG accounts + // TODO: enable the removing of a single undershirt/underpants if multiple are worn. - Nyx + return; + } if (do_remove_all) { @@ -1240,16 +1314,8 @@ void LLAgentWearables::removeWearable(const EWearableType type, bool do_remove_a } else { -// MULTI_WEARABLE: handle vector changes from arbitrary removal. LLWearable* old_wearable = getWearable(type,index); - if ((gAgent.isTeen()) - && (type == WT_UNDERSHIRT || type == WT_UNDERPANTS)) - { - // Can't take off underclothing in simple UI mode or on PG accounts - return; - } - if (old_wearable) { if (old_wearable->isDirty()) @@ -1308,26 +1374,22 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem { LLWearable* old_wearable = getWearable(type,i); gInventory.addChangedMask(LLInventoryObserver::LABEL, getWearableItemID(type,i)); - setWearable(type,i,NULL); + popWearable(type,i); //queryWearableCache(); // moved below - // MULTI_WEARABLE: FIXME - currently we keep a null entry, so can't delete the last one. - if (i>0) - { - mWearableDatas[type].pop_back(); - } if (old_wearable) { old_wearable->removeFromAvatar(TRUE); } } + mWearableDatas[type].clear(); } else { LLWearable* old_wearable = getWearable(type, index); gInventory.addChangedMask(LLInventoryObserver::LABEL, getWearableItemID(type,index)); - setWearable(type,index,NULL); + popWearable(type, index); //queryWearableCache(); // moved below @@ -1335,16 +1397,6 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem { old_wearable->removeFromAvatar(TRUE); } - - // MULTI_WEARABLE: logic changes if null entries go away - if (getWearableCount(type)>1) - { - // Have to shrink the vector and clean up the item. - wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); - llassert_always(wearable_iter != mWearableDatas.end()); - wearableentry_vec_t& wearable_vec = wearable_iter->second; - wearable_vec.erase( wearable_vec.begin() + index ); - } } queryWearableCache(); @@ -1429,7 +1481,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it { wearables_being_removed.push_back(wearable); } - setWearable((EWearableType)i,0,NULL); + removeWearable((EWearableType)i,true,0); } } @@ -1450,9 +1502,9 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it } } - for (i = 0; i < count; i++) + if (mAvatarObject) { - wearables[i]->writeToAvatar(TRUE); + mAvatarObject->updateVisualParams(); } // Start rendering & update the server @@ -1578,7 +1630,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* n //llinfos << "LLVOAvatar::setWearableItem()" << llendl; queryWearableCache(); - new_wearable->writeToAvatar(TRUE); + //new_wearable->writeToAvatar(TRUE); updateServer(); } @@ -1612,13 +1664,16 @@ void LLAgentWearables::queryWearableCache() LLUUID hash; for (U8 i=0; i < baked_dict->mWearables.size(); i++) { - // EWearableType baked_type = gBakedWearableMap[baked_index][baked_num]; const EWearableType baked_type = baked_dict->mWearables[i]; - // MULTI_WEARABLE: assuming 0th - const LLWearable* wearable = getWearable(baked_type,0); - if (wearable) + // MULTI_WEARABLE: not order-dependent + const U32 num_wearables = getWearableCount(baked_type); + for (U32 index = 0; index < num_wearables; ++index) { - hash ^= wearable->getAssetID(); + const LLWearable* wearable = getWearable(baked_type,index); + if (wearable) + { + hash ^= wearable->getAssetID(); + } } } if (hash.notNull()) @@ -1672,7 +1727,6 @@ void LLAgentWearables::userRemoveAllClothes(void* userdata) } // static -// MULTI_WEARABLE: removing all here. void LLAgentWearables::userRemoveAllClothesStep2(BOOL proceed) { if (proceed) @@ -1717,20 +1771,25 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj { LLVOAvatar::attachment_map_t::iterator curiter = iter++; LLViewerJointAttachment* attachment = curiter->second; - LLViewerObject* objectp = attachment->getObject(); - if (objectp) + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) { - LLUUID object_item_id = attachment->getItemID(); - if (requested_item_ids.find(object_item_id) != requested_item_ids.end()) + LLViewerObject *objectp = (*attachment_iter); + if (objectp) { - // Object currently worn, was requested. - // Flag as currently worn so we won't have to add it again. - current_item_ids.insert(object_item_id); - } - else - { - // object currently worn, not requested. - objects_to_remove.push_back(objectp); + LLUUID object_item_id = objectp->getItemID(); + if (requested_item_ids.find(object_item_id) != requested_item_ids.end()) + { + // Object currently worn, was requested. + // Flag as currently worn so we won't have to add it again. + current_item_ids.insert(object_item_id); + } + else + { + // object currently worn, not requested. + objects_to_remove.push_back(objectp); + } } } } @@ -1806,9 +1865,16 @@ void LLAgentWearables::userRemoveAllAttachments() { LLVOAvatar::attachment_map_t::iterator curiter = iter++; LLViewerJointAttachment* attachment = curiter->second; - LLViewerObject* objectp = attachment->getObject(); - if (objectp) - objects_to_remove.push_back(objectp); + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject *attached_object = (*attachment_iter); + if (attached_object) + { + objects_to_remove.push_back(attached_object); + } + } } userRemoveMultipleAttachments(objects_to_remove); } |