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.cpp219
1 files changed, 134 insertions, 85 deletions
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 2cfa8d2a54..a26b799d3d 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_ATTACHMENTS_PER_TYPE;
+ }
+ if (type < WT_COUNT)
+ {
+ mWearableDatas[type].push_back(wearable);
+ return mWearableDatas[type].size()-1;
+ }
+ return MAX_ATTACHMENTS_PER_TYPE;
+}
+
+void LLAgentWearables::popWearable(const EWearableType type, LLWearable *wearable)
+{
+ U32 index = getWearableIndex(type, wearable);
+ if (index < MAX_ATTACHMENTS_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_ATTACHMENTS_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_ATTACHMENTS_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);
}
@@ -1233,6 +1295,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 +1309,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 +1369,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 +1392,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 +1476,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 +1497,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 +1625,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 +1659,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 +1722,6 @@ void LLAgentWearables::userRemoveAllClothes(void* userdata)
}
// static
-// MULTI_WEARABLE: removing all here.
void LLAgentWearables::userRemoveAllClothesStep2(BOOL proceed)
{
if (proceed)