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.cpp166
1 files changed, 119 insertions, 47 deletions
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 545c5b845b..e5796f8e63 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -39,7 +39,6 @@
#include "llagentwearablesfetch.h"
#include "llappearancemgr.h"
#include "llcallbacklist.h"
-#include "llfloatercustomize.h"
#include "llfolderview.h"
#include "llgesturemgr.h"
#include "llinventorybridge.h"
@@ -49,6 +48,7 @@
#include "llmd5.h"
#include "llnotificationsutil.h"
#include "llpaneloutfitsinventory.h"
+#include "llsidepanelappearance.h"
#include "llsidetray.h"
#include "lltexlayer.h"
#include "llviewerregion.h"
@@ -539,9 +539,15 @@ void LLAgentWearables::setWearableName(const LLUUID& item_id, const std::string&
BOOL LLAgentWearables::isWearableModifiable(LLWearableType::EType type, U32 index) const
{
LLUUID item_id = getWearableItemID(type, index);
- if (!item_id.isNull())
+ return item_id.notNull() ? isWearableModifiable(item_id) : FALSE;
+}
+
+BOOL LLAgentWearables::isWearableModifiable(const LLUUID& item_id) const
+{
+ const LLUUID& linked_id = gInventory.getLinkedItemID(item_id);
+ if (linked_id.notNull())
{
- LLInventoryItem* item = gInventory.getItem(item_id);
+ LLInventoryItem* item = gInventory.getItem(linked_id);
if (item && item->getPermissions().allowModifyBy(gAgent.getID(),
gAgent.getGroupID()))
{
@@ -595,12 +601,30 @@ LLInventoryItem* LLAgentWearables::getWearableInventoryItem(LLWearableType::ETyp
const LLWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) const
{
+ const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);
for (S32 i=0; i < LLWearableType::WT_COUNT; i++)
{
for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++)
{
const LLWearable * curr_wearable = getWearable((LLWearableType::EType)i, j);
- if (curr_wearable && (curr_wearable->getItemID() == item_id))
+ if (curr_wearable && (curr_wearable->getItemID() == base_item_id))
+ {
+ return curr_wearable;
+ }
+ }
+ }
+ return NULL;
+}
+
+LLWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id)
+{
+ const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);
+ for (S32 i=0; i < LLWearableType::WT_COUNT; i++)
+ {
+ for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++)
+ {
+ LLWearable * curr_wearable = getWearable((LLWearableType::EType)i, j);
+ if (curr_wearable && (curr_wearable->getItemID() == base_item_id))
{
return curr_wearable;
}
@@ -694,16 +718,16 @@ U32 LLAgentWearables::pushWearable(const LLWearableType::EType type, LLWearable
{
// no null wearables please!
llwarns << "Null wearable sent for type " << type << llendl;
- return MAX_WEARABLES_PER_TYPE;
+ return MAX_CLOTHING_PER_TYPE;
}
- if (type < LLWearableType::WT_COUNT || mWearableDatas[type].size() < MAX_WEARABLES_PER_TYPE)
+ if (type < LLWearableType::WT_COUNT || mWearableDatas[type].size() < MAX_CLOTHING_PER_TYPE)
{
mWearableDatas[type].push_back(wearable);
wearableUpdated(wearable);
checkWearableAgainstInventory(wearable);
return mWearableDatas[type].size()-1;
}
- return MAX_WEARABLES_PER_TYPE;
+ return MAX_CLOTHING_PER_TYPE;
}
void LLAgentWearables::wearableUpdated(LLWearable *wearable)
@@ -740,7 +764,7 @@ void LLAgentWearables::popWearable(LLWearable *wearable)
U32 index = getWearableIndex(wearable);
LLWearableType::EType type = wearable->getType();
- if (index < MAX_WEARABLES_PER_TYPE && index < getWearableCount(type))
+ if (index < MAX_CLOTHING_PER_TYPE && index < getWearableCount(type))
{
popWearable(type, index);
}
@@ -761,7 +785,7 @@ U32 LLAgentWearables::getWearableIndex(LLWearable *wearable)
{
if (wearable == NULL)
{
- return MAX_WEARABLES_PER_TYPE;
+ return MAX_CLOTHING_PER_TYPE;
}
const LLWearableType::EType type = wearable->getType();
@@ -769,7 +793,7 @@ U32 LLAgentWearables::getWearableIndex(LLWearable *wearable)
if (wearable_iter == mWearableDatas.end())
{
llwarns << "tried to get wearable index with an invalid type!" << llendl;
- return MAX_WEARABLES_PER_TYPE;
+ return MAX_CLOTHING_PER_TYPE;
}
const wearableentry_vec_t& wearable_vec = wearable_iter->second;
for(U32 index = 0; index < wearable_vec.size(); index++)
@@ -780,7 +804,7 @@ U32 LLAgentWearables::getWearableIndex(LLWearable *wearable)
}
}
- return MAX_WEARABLES_PER_TYPE;
+ return MAX_CLOTHING_PER_TYPE;
}
const LLWearable* LLAgentWearables::getWearable(const LLWearableType::EType type, U32 index) const
@@ -812,6 +836,16 @@ LLWearable* LLAgentWearables::getTopWearable(const LLWearableType::EType type)
return getWearable(type, count-1);
}
+LLWearable* LLAgentWearables::getBottomWearable(const LLWearableType::EType type)
+{
+ if (getWearableCount(type) == 0)
+ {
+ return NULL;
+ }
+
+ return getWearable(type, 0);
+}
+
U32 LLAgentWearables::getWearableCount(const LLWearableType::EType type) const
{
wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type);
@@ -860,12 +894,7 @@ const LLUUID LLAgentWearables::getWearableAssetID(LLWearableType::EType type, U3
BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id) const
{
- const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);
- if (getWearableFromItemID(base_item_id) != NULL)
- {
- return TRUE;
- }
- return FALSE;
+ return getWearableFromItemID(item_id) != NULL;
}
// MULTI-WEARABLE: DEPRECATED (see backwards compatibility)
@@ -1565,37 +1594,18 @@ void LLAgentWearables::queryWearableCache()
S32 num_queries = 0;
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
{
- const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
- LLMD5 hash;
- bool hash_computed = false;
- for (U8 i=0; i < baked_dict->mWearables.size(); i++)
- {
- const LLWearableType::EType baked_type = baked_dict->mWearables[i];
- const U32 num_wearables = getWearableCount(baked_type);
- for (U32 index = 0; index < num_wearables; ++index)
- {
- const LLWearable* wearable = getWearable(baked_type,index);
- if (wearable)
- {
- LLUUID asset_id = wearable->getAssetID();
- hash.update((const unsigned char*)asset_id.mData, UUID_BYTES);
- hash_computed = true;
- }
- }
- }
- hash.finalize();
- if (hash_computed)
+ LLUUID hash_id = computeBakedTextureHash((EBakedTextureIndex) baked_index);
+ if (hash_id.notNull())
{
- LLUUID hash_id;
- hash.raw_digest(hash_id.mData);
- hash_id ^= baked_dict->mWearablesHashID;
num_queries++;
// *NOTE: make sure at least one request gets packed
+ ETextureIndex te_index = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index);
+
//llinfos << "Requesting texture for hash " << hash << " in baked texture slot " << baked_index << llendl;
gMessageSystem->nextBlockFast(_PREHASH_WearableData);
gMessageSystem->addUUIDFast(_PREHASH_ID, hash_id);
- gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)baked_index);
+ gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)te_index);
}
gAgentQueryManager.mActiveCacheQueries[baked_index] = gAgentQueryManager.mWearablesCacheQueryID;
@@ -1607,6 +1617,39 @@ void LLAgentWearables::queryWearableCache()
gAgentQueryManager.mWearablesCacheQueryID++;
}
+LLUUID LLAgentWearables::computeBakedTextureHash(LLVOAvatarDefines::EBakedTextureIndex index)
+{
+ LLUUID hash_id;
+ bool hash_computed = false;
+ LLMD5 hash;
+
+ const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(index);
+
+ for (U8 i=0; i < baked_dict->mWearables.size(); i++)
+ {
+ const LLWearableType::EType baked_type = baked_dict->mWearables[i];
+ const U32 num_wearables = getWearableCount(baked_type);
+ for (U32 index = 0; index < num_wearables; ++index)
+ {
+ const LLWearable* wearable = getWearable(baked_type,index);
+ if (wearable)
+ {
+ LLUUID asset_id = wearable->getAssetID();
+ hash.update((const unsigned char*)asset_id.mData, UUID_BYTES);
+ hash_computed = true;
+ }
+ }
+ }
+ if (hash_computed)
+ {
+ hash.update((const unsigned char*)baked_dict->mWearablesHashID.mData, UUID_BYTES);
+ hash.finalize();
+ hash.raw_digest(hash_id.mData);
+ }
+
+ return hash_id;
+}
+
// User has picked "remove from avatar" from a menu.
// static
void LLAgentWearables::userRemoveWearable(const LLWearableType::EType &type, const U32 &index)
@@ -1632,14 +1675,12 @@ void LLAgentWearables::userRemoveWearablesOfType(const LLWearableType::EType &ty
void LLAgentWearables::userRemoveAllClothes()
{
// We have to do this up front to avoid having to deal with the case of multiple wearables being dirty.
- if (gFloaterCustomize)
- {
- gFloaterCustomize->askToSaveIfDirty(userRemoveAllClothesStep2);
- }
- else
+ if (gAgentCamera.cameraCustomizeAvatar())
{
- userRemoveAllClothesStep2(TRUE);
+ // switching to outfit editor should automagically save any currently edited wearable
+ LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_outfit"));
}
+ userRemoveAllClothesStep2(TRUE);
}
// static
@@ -1848,6 +1889,20 @@ void LLAgentWearables::checkWearablesLoaded() const
#endif
}
+// Returns false if the given wearable is already topmost/bottommost
+// (depending on closer_to_body parameter).
+bool LLAgentWearables::canMoveWearable(const LLUUID& item_id, bool closer_to_body)
+{
+ const LLWearable* wearable = getWearableFromItemID(item_id);
+ if (!wearable) return false;
+
+ LLWearableType::EType wtype = wearable->getType();
+ const LLWearable* marginal_wearable = closer_to_body ? getBottomWearable(wtype) : getTopWearable(wtype);
+ if (!marginal_wearable) return false;
+
+ return wearable != marginal_wearable;
+}
+
BOOL LLAgentWearables::areWearablesLoaded() const
{
checkWearablesLoaded();
@@ -1918,6 +1973,23 @@ bool LLAgentWearables::moveWearable(const LLViewerInventoryItem* item, bool clos
return false;
}
+// static
+void LLAgentWearables::editWearable(const LLUUID& item_id)
+{
+ LLViewerInventoryItem* item;
+ LLWearable* wearable;
+
+ if ((item = gInventory.getLinkedItem(item_id)) &&
+ (wearable = gAgentWearables.getWearableFromAssetID(item->getAssetUUID())) &&
+ gAgentWearables.isWearableModifiable(item->getUUID()) &&
+ item->isFinished())
+ {
+ LLPanel* panel = LLSideTray::getInstance()->showPanel("panel_outfit_edit", LLSD());
+ // copied from LLPanelOutfitEdit::onEditWearableClicked()
+ LLSidepanelAppearance::editWearable(wearable, panel->getParent());
+ }
+}
+
void LLAgentWearables::updateServer()
{
sendAgentWearablesUpdate();