summaryrefslogtreecommitdiff
path: root/indra/newview/llagentwearables.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llagentwearables.cpp')
-rw-r--r--indra/newview/llagentwearables.cpp144
1 files changed, 110 insertions, 34 deletions
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 6cb96d1336..475f34dc2b 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -62,7 +62,7 @@ class LLInitialWearablesFetch : public LLInventoryFetchDescendentsObserver
{
public:
LLInitialWearablesFetch() {}
- ~LLInitialWearablesFetch() {}
+ ~LLInitialWearablesFetch();
virtual void done();
struct InitialWearableData
@@ -84,7 +84,6 @@ public:
protected:
void processWearablesMessage();
void processContents();
- static void onIdle(void *userdata);
};
class LLLibraryOutfitsFetch : public LLInventoryFetchDescendentsObserver
@@ -654,11 +653,13 @@ LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index)
void LLAgentWearables::setWearable(const EWearableType type, U32 index, LLWearable *wearable)
{
- if (!getWearable(type,index))
+ LLWearable *old_wearable = getWearable(type,index);
+ if (!old_wearable)
{
pushWearable(type,wearable);
return;
}
+
wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type);
if (wearable_iter == mWearableDatas.end())
{
@@ -673,7 +674,8 @@ void LLAgentWearables::setWearable(const EWearableType type, U32 index, LLWearab
else
{
wearable_vec[index] = wearable;
- mAvatarObject->wearableUpdated(wearable->getType());
+ old_wearable->setLabelUpdated();
+ wearableUpdated(wearable);
}
}
@@ -688,12 +690,32 @@ U32 LLAgentWearables::pushWearable(const EWearableType type, LLWearable *wearabl
if (type < WT_COUNT || mWearableDatas[type].size() < MAX_WEARABLES_PER_TYPE)
{
mWearableDatas[type].push_back(wearable);
- mAvatarObject->wearableUpdated(wearable->getType());
+ wearableUpdated(wearable);
return mWearableDatas[type].size()-1;
}
return MAX_WEARABLES_PER_TYPE;
}
+void LLAgentWearables::wearableUpdated(LLWearable *wearable)
+{
+ mAvatarObject->wearableUpdated(wearable->getType());
+ wearable->setLabelUpdated();
+
+ // Hack pt 2. If the wearable we just loaded has definition version 24,
+ // then force a re-save of this wearable after slamming the version number to 22.
+ // This number was incorrectly incremented for internal builds before release, and
+ // this fix will ensure that the affected wearables are re-saved with the right version number.
+ // the versions themselves are compatible. This code can be removed before release.
+ if( wearable->getDefinitionVersion() == 24 )
+ {
+ wearable->setDefinitionVersion(22);
+ U32 index = getWearableIndex(wearable);
+ llinfos << "forcing werable type " << wearable->getType() << " to version 22 from 24" << llendl;
+ saveWearable(wearable->getType(),index,TRUE);
+ }
+
+}
+
void LLAgentWearables::popWearable(LLWearable *wearable)
{
if (wearable == NULL)
@@ -718,6 +740,7 @@ void LLAgentWearables::popWearable(const EWearableType type, U32 index)
{
mWearableDatas[type].erase(mWearableDatas[type].begin() + index);
mAvatarObject->wearableUpdated(wearable->getType());
+ wearable->setLabelUpdated();
}
}
@@ -1413,14 +1436,10 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem
for (S32 i=max_entry; i>=0; i--)
{
LLWearable* old_wearable = getWearable(type,i);
- const LLUUID &item_id = getWearableItemID(type,i);
- popWearable(type,i);
- gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
- LLAppearanceManager::instance().removeItemLinks(item_id,false);
-
//queryWearableCache(); // moved below
if (old_wearable)
{
+ popWearable(old_wearable);
old_wearable->removeFromAvatar(TRUE);
}
}
@@ -1429,16 +1448,11 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem
else
{
LLWearable* old_wearable = getWearable(type, index);
-
- const LLUUID &item_id = getWearableItemID(type,index);
- popWearable(type, index);
- gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
- LLAppearanceManager::instance().removeItemLinks(item_id,false);
-
//queryWearableCache(); // moved below
if (old_wearable)
{
+ popWearable(old_wearable);
old_wearable->removeFromAvatar(TRUE);
}
}
@@ -1500,7 +1514,6 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
continue;
}
- gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id);
// Assumes existing wearables are not dirty.
if (old_wearable->isDirty())
{
@@ -1509,9 +1522,9 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
}
}
- setWearable(type,0,new_wearable);
if (new_wearable)
new_wearable->setItemID(new_item->getUUID());
+ setWearable(type,0,new_wearable);
}
std::vector<LLWearable*> wearables_being_removed;
@@ -1534,7 +1547,6 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
gInventory.notifyObservers();
- queryWearableCache();
std::vector<LLWearable*>::iterator wearable_iter;
@@ -1557,6 +1569,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
// Start rendering & update the server
mWearablesLoaded = TRUE;
checkWearablesLoaded();
+ queryWearableCache();
updateServer();
lldebugs << "setWearableOutfit() end" << llendl;
@@ -2159,6 +2172,10 @@ void LLLibraryOutfitsFetch::contentsDone(void)
// to avoid gInventory.notifyObservers recursion.
//--------------------------------------------------------------------
+LLInitialWearablesFetch::~LLInitialWearablesFetch()
+{
+}
+
// virtual
void LLInitialWearablesFetch::done()
{
@@ -2166,15 +2183,7 @@ void LLInitialWearablesFetch::done()
// gInventory.notifyObservers. The results will be handled in the next
// idle tick instead.
gInventory.removeObserver(this);
- gIdleCallbacks.addFunction(onIdle, this);
-}
-
-// static
-void LLInitialWearablesFetch::onIdle(void *data)
-{
- gIdleCallbacks.deleteFunction(onIdle, data);
- LLInitialWearablesFetch *self = reinterpret_cast<LLInitialWearablesFetch*>(data);
- self->processContents();
+ doOnIdle(boost::bind(&LLInitialWearablesFetch::processContents,this));
}
void LLInitialWearablesFetch::processContents()
@@ -2194,17 +2203,50 @@ void LLInitialWearablesFetch::processContents()
else
{
processWearablesMessage();
- // Create links for attachments that may have arrived before the COF existed.
- LLAppearanceManager::instance().linkRegisteredAttachments();
}
delete this;
}
+class LLFetchAndLinkObserver: public LLInventoryFetchObserver
+{
+public:
+ LLFetchAndLinkObserver(LLInventoryFetchObserver::item_ref_t& ids):
+ m_ids(ids),
+ LLInventoryFetchObserver(true)
+ {
+ }
+ ~LLFetchAndLinkObserver()
+ {
+ }
+ virtual void done()
+ {
+ gInventory.removeObserver(this);
+ // Link to all fetched items in COF.
+ for (LLInventoryFetchObserver::item_ref_t::iterator it = m_ids.begin();
+ it != m_ids.end();
+ ++it)
+ {
+ LLUUID id = *it;
+ LLViewerInventoryItem *item = gInventory.getItem(*it);
+ if (!item)
+ {
+ llwarns << "fetch failed!" << llendl;
+ continue;
+ }
+ link_inventory_item(gAgent.getID(), item->getLinkedUUID(), LLAppearanceManager::instance().getCOF(), item->getName(),
+ LLAssetType::AT_LINK, LLPointer<LLInventoryCallback>(NULL));
+ }
+ }
+private:
+ LLInventoryFetchObserver::item_ref_t m_ids;
+};
+
void LLInitialWearablesFetch::processWearablesMessage()
{
if (!mAgentInitialWearables.empty()) // We have an empty current outfit folder, use the message data instead.
{
- const LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ const LLUUID current_outfit_id = LLAppearanceManager::instance().getCOF();
+ LLInventoryFetchObserver::item_ref_t ids;
for (U8 i = 0; i < mAgentInitialWearables.size(); ++i)
{
// Populate the current outfit folder with links to the wearables passed in the message
@@ -2213,9 +2255,7 @@ void LLInitialWearablesFetch::processWearablesMessage()
if (wearable_data->mAssetID.notNull())
{
#ifdef USE_CURRENT_OUTFIT_FOLDER
- const std::string link_name = "WearableLink"; // Unimportant what this is named, it isn't exposed.
- link_inventory_item(gAgent.getID(), wearable_data->mItemID, current_outfit_id, link_name,
- LLAssetType::AT_LINK, LLPointer<LLInventoryCallback>(NULL));
+ ids.push_back(wearable_data->mItemID);
#endif
// Fetch the wearables
LLWearableList::instance().getAsset(wearable_data->mAssetID,
@@ -2229,6 +2269,42 @@ void LLInitialWearablesFetch::processWearablesMessage()
<< wearable_data->mItemID << " assetID " << wearable_data->mAssetID << llendl;
}
}
+
+ // Add all current attachments to the requested items as well.
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( avatar )
+ {
+ for (LLVOAvatar::attachment_map_t::const_iterator iter = avatar->mAttachmentPoints.begin();
+ iter != avatar->mAttachmentPoints.end(); ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ if (!attachment) continue;
+ 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) continue;
+ const LLUUID& item_id = attached_object->getItemID();
+ if (item_id.isNull()) continue;
+ ids.push_back(item_id);
+ }
+ }
+ }
+
+ // Need to fetch the inventory items for ids, then create links to them after they arrive.
+ LLFetchAndLinkObserver *fetcher = new LLFetchAndLinkObserver(ids);
+ fetcher->fetchItems(ids);
+ // If no items to be fetched, done will never be triggered.
+ // TODO: Change LLInventoryFetchObserver::fetchItems to trigger done() on this condition.
+ if (fetcher->isEverythingComplete())
+ {
+ fetcher->done();
+ }
+ else
+ {
+ gInventory.addObserver(fetcher);
+ }
}
else
{