Initial AISv3 merge. New HTTP messages not plugged in yet.
This commit is contained in:
@@ -94,7 +94,7 @@ void LLWearableData::setWearable(const LLWearableType::EType type, U32 index, LL
|
||||
}
|
||||
}
|
||||
|
||||
U32 LLWearableData::pushWearable(const LLWearableType::EType type,
|
||||
void LLWearableData::pushWearable(const LLWearableType::EType type,
|
||||
LLWearable *wearable,
|
||||
bool trigger_updated /* = true */)
|
||||
{
|
||||
@@ -102,38 +102,19 @@ U32 LLWearableData::pushWearable(const LLWearableType::EType type,
|
||||
{
|
||||
// no null wearables please!
|
||||
LL_WARNS() << "Null wearable sent for type " << type << LL_ENDL;
|
||||
return MAX_CLOTHING_PER_TYPE;
|
||||
}
|
||||
// [RLVa:KB] - Checked: 2010-06-08 (RLVa-1.2.0g) | Added: RLVa-1.2.0g
|
||||
if ( (type < LLWearableType::WT_COUNT) && (mWearableDatas[type].size() < MAX_CLOTHING_PER_TYPE) )
|
||||
if (canAddWearable(type))
|
||||
{
|
||||
// Don't add the same wearable twice
|
||||
U32 idxWearable = getWearableIndex(wearable);
|
||||
llassert(MAX_CLOTHING_PER_TYPE == idxWearable); // pushWearable() on an already added wearable is a bug *somewhere*
|
||||
if (MAX_CLOTHING_PER_TYPE == idxWearable)
|
||||
{
|
||||
mWearableDatas[type].push_back(wearable);
|
||||
idxWearable = mWearableDatas[type].size() - 1;
|
||||
}
|
||||
// [RLVa:KB] - Checked: 2010-06-08 (RLVa-1.2.0g) | Added: RLVa-1.2.0g
|
||||
if (std::find(mWearableDatas[type].begin(), mWearableDatas[type].end(), wearable) == mWearableDatas[type].end())
|
||||
// [/RLVa:KB]
|
||||
mWearableDatas[type].push_back(wearable);
|
||||
if (trigger_updated)
|
||||
{
|
||||
const BOOL removed = FALSE;
|
||||
wearableUpdated(wearable, removed);
|
||||
}
|
||||
return idxWearable;
|
||||
}
|
||||
// [/RLVa:KB]
|
||||
// if (type < LLWearableType::WT_COUNT || mWearableDatas[type].size() < MAX_CLOTHING_PER_TYPE)
|
||||
// {
|
||||
// mWearableDatas[type].push_back(wearable);
|
||||
// if (trigger_updated)
|
||||
// {
|
||||
// const BOOL removed = FALSE;
|
||||
// wearableUpdated(wearable, removed);
|
||||
// }
|
||||
// return mWearableDatas[type].size()-1;
|
||||
// }
|
||||
return MAX_CLOTHING_PER_TYPE;
|
||||
}
|
||||
|
||||
// virtual
|
||||
@@ -146,7 +127,7 @@ void LLWearableData::wearableUpdated(LLWearable *wearable, BOOL removed)
|
||||
}
|
||||
}
|
||||
|
||||
void LLWearableData::popWearable(LLWearable *wearable)
|
||||
void LLWearableData::eraseWearable(LLWearable *wearable)
|
||||
{
|
||||
if (wearable == NULL)
|
||||
{
|
||||
@@ -154,18 +135,17 @@ void LLWearableData::popWearable(LLWearable *wearable)
|
||||
return;
|
||||
}
|
||||
|
||||
U32 index = getWearableIndex(wearable);
|
||||
const LLWearableType::EType type = wearable->getType();
|
||||
|
||||
if (index < MAX_CLOTHING_PER_TYPE && index < getWearableCount(type))
|
||||
U32 index;
|
||||
if (getWearableIndex(wearable,index))
|
||||
{
|
||||
popWearable(type, index);
|
||||
eraseWearable(type, index);
|
||||
}
|
||||
}
|
||||
|
||||
void LLWearableData::popWearable(const LLWearableType::EType type, U32 index)
|
||||
void LLWearableData::eraseWearable(const LLWearableType::EType type, U32 index)
|
||||
{
|
||||
//llassert_always(index == 0);
|
||||
LLWearable *wearable = getWearable(type, index);
|
||||
if (wearable)
|
||||
{
|
||||
@@ -225,11 +205,11 @@ void LLWearableData::pullCrossWearableValues(const LLWearableType::EType type)
|
||||
}
|
||||
|
||||
|
||||
U32 LLWearableData::getWearableIndex(const LLWearable *wearable) const
|
||||
BOOL LLWearableData::getWearableIndex(const LLWearable *wearable, U32& index_found) const
|
||||
{
|
||||
if (wearable == NULL)
|
||||
{
|
||||
return MAX_CLOTHING_PER_TYPE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const LLWearableType::EType type = wearable->getType();
|
||||
@@ -237,18 +217,50 @@ U32 LLWearableData::getWearableIndex(const LLWearable *wearable) const
|
||||
if (wearable_iter == mWearableDatas.end())
|
||||
{
|
||||
LL_WARNS() << "tried to get wearable index with an invalid type!" << LL_ENDL;
|
||||
return MAX_CLOTHING_PER_TYPE;
|
||||
return FALSE;
|
||||
}
|
||||
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;
|
||||
index_found = index;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return MAX_CLOTHING_PER_TYPE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
U32 LLWearableData::getClothingLayerCount() const
|
||||
{
|
||||
U32 count = 0;
|
||||
for (S32 i = 0; i < LLWearableType::WT_COUNT; i++)
|
||||
{
|
||||
LLWearableType::EType type = (LLWearableType::EType)i;
|
||||
if (LLWearableType::getAssetType(type)==LLAssetType::AT_CLOTHING)
|
||||
{
|
||||
count += getWearableCount(type);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
BOOL LLWearableData::canAddWearable(const LLWearableType::EType type) const
|
||||
{
|
||||
LLAssetType::EType a_type = LLWearableType::getAssetType(type);
|
||||
if (a_type==LLAssetType::AT_CLOTHING)
|
||||
{
|
||||
return (getClothingLayerCount() < MAX_CLOTHING_LAYERS);
|
||||
}
|
||||
else if (a_type==LLAssetType::AT_BODYPART)
|
||||
{
|
||||
return (getWearableCount(type) < 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLWearableData::isOnTop(LLWearable* wearable) const
|
||||
|
||||
@@ -61,11 +61,13 @@ public:
|
||||
const LLWearable* getBottomWearable(const LLWearableType::EType type) const;
|
||||
U32 getWearableCount(const LLWearableType::EType type) const;
|
||||
U32 getWearableCount(const U32 tex_index) const;
|
||||
U32 getWearableIndex(const LLWearable *wearable) const;
|
||||
BOOL getWearableIndex(const LLWearable *wearable, U32& index) const;
|
||||
U32 getClothingLayerCount() const;
|
||||
BOOL canAddWearable(const LLWearableType::EType type) const;
|
||||
|
||||
BOOL isOnTop(LLWearable* wearable) const;
|
||||
|
||||
static const U32 MAX_CLOTHING_PER_TYPE = 5;
|
||||
static const U32 MAX_CLOTHING_LAYERS = 60;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Setters
|
||||
@@ -73,11 +75,11 @@ public:
|
||||
protected:
|
||||
// Low-level data structure setter - public access is via setWearableItem, etc.
|
||||
void setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable);
|
||||
U32 pushWearable(const LLWearableType::EType type, LLWearable *wearable,
|
||||
void pushWearable(const LLWearableType::EType type, LLWearable *wearable,
|
||||
bool trigger_updated = true);
|
||||
virtual void wearableUpdated(LLWearable *wearable, BOOL removed);
|
||||
void popWearable(LLWearable *wearable);
|
||||
void popWearable(const LLWearableType::EType type, U32 index);
|
||||
void eraseWearable(LLWearable *wearable);
|
||||
void eraseWearable(const LLWearableType::EType type, U32 index);
|
||||
void clearWearableType(const LLWearableType::EType type);
|
||||
bool swapWearables(const LLWearableType::EType type, U32 index_a, U32 index_b);
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ static const std::string INV_DESC_LABEL("desc");
|
||||
static const std::string INV_PERMISSIONS_LABEL("permissions");
|
||||
static const std::string INV_SHADOW_ID_LABEL("shadow_id");
|
||||
static const std::string INV_ASSET_ID_LABEL("asset_id");
|
||||
static const std::string INV_LINKED_ID_LABEL("linked_id");
|
||||
static const std::string INV_SALE_INFO_LABEL("sale_info");
|
||||
static const std::string INV_FLAGS_LABEL("flags");
|
||||
static const std::string INV_CREATION_DATE_LABEL("created_at");
|
||||
@@ -77,13 +78,15 @@ LLInventoryObject::LLInventoryObject(const LLUUID& uuid,
|
||||
mUUID(uuid),
|
||||
mParentUUID(parent_uuid),
|
||||
mType(type),
|
||||
mName(name)
|
||||
mName(name),
|
||||
mCreationDate(0)
|
||||
{
|
||||
correctInventoryName(mName);
|
||||
}
|
||||
|
||||
LLInventoryObject::LLInventoryObject() :
|
||||
mType(LLAssetType::AT_NONE)
|
||||
mType(LLAssetType::AT_NONE),
|
||||
mCreationDate(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -249,13 +252,6 @@ BOOL LLInventoryObject::exportLegacyStream(std::ostream& output_stream, BOOL) co
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void LLInventoryObject::removeFromServer()
|
||||
{
|
||||
// don't do nothin'
|
||||
LL_WARNS() << "LLInventoryObject::removeFromServer() called. Doesn't do anything." << LL_ENDL;
|
||||
}
|
||||
|
||||
void LLInventoryObject::updateParentOnServer(BOOL) const
|
||||
{
|
||||
// don't do nothin'
|
||||
@@ -277,6 +273,25 @@ void LLInventoryObject::correctInventoryName(std::string& name)
|
||||
LLStringUtil::truncate(name, DB_INV_ITEM_NAME_STR_LEN);
|
||||
}
|
||||
|
||||
time_t LLInventoryObject::getCreationDate() const
|
||||
{
|
||||
return mCreationDate;
|
||||
}
|
||||
|
||||
void LLInventoryObject::setCreationDate(time_t creation_date_utc)
|
||||
{
|
||||
mCreationDate = creation_date_utc;
|
||||
}
|
||||
|
||||
const std::string& LLInventoryItem::getDescription() const
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
const std::string& LLInventoryItem::getActualDescription() const
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Class LLInventoryItem
|
||||
@@ -299,9 +314,9 @@ LLInventoryItem::LLInventoryItem(const LLUUID& uuid,
|
||||
mDescription(desc),
|
||||
mSaleInfo(sale_info),
|
||||
mInventoryType(inv_type),
|
||||
mFlags(flags),
|
||||
mCreationDate(creation_date_utc)
|
||||
mFlags(flags)
|
||||
{
|
||||
mCreationDate = creation_date_utc;
|
||||
LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
|
||||
LLStringUtil::replaceChar(mDescription, '|', ' ');
|
||||
mPermissions.initMasks(inv_type);
|
||||
@@ -314,9 +329,9 @@ LLInventoryItem::LLInventoryItem() :
|
||||
mDescription(),
|
||||
mSaleInfo(),
|
||||
mInventoryType(LLInventoryType::IT_NONE),
|
||||
mFlags(0),
|
||||
mCreationDate(0)
|
||||
mFlags(0)
|
||||
{
|
||||
mCreationDate = (time_t)0;
|
||||
}
|
||||
|
||||
LLInventoryItem::LLInventoryItem(const LLInventoryItem* other) :
|
||||
@@ -376,21 +391,6 @@ void LLInventoryItem::setAssetUUID(const LLUUID& asset_id)
|
||||
}
|
||||
|
||||
|
||||
const std::string& LLInventoryItem::getDescription() const
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
const std::string& LLInventoryItem::getActualDescription() const
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
time_t LLInventoryItem::getCreationDate() const
|
||||
{
|
||||
return mCreationDate;
|
||||
}
|
||||
|
||||
U32 LLInventoryItem::getCRC32() const
|
||||
{
|
||||
// *FIX: Not a real crc - more of a checksum.
|
||||
@@ -447,11 +447,6 @@ void LLInventoryItem::setFlags(U32 flags)
|
||||
mFlags = flags;
|
||||
}
|
||||
|
||||
void LLInventoryItem::setCreationDate(time_t creation_date_utc)
|
||||
{
|
||||
mCreationDate = creation_date_utc;
|
||||
}
|
||||
|
||||
// Currently only used in the Viewer to handle calling cards
|
||||
// where the creator is actually used to store the target.
|
||||
void LLInventoryItem::setCreator(const LLUUID& creator)
|
||||
@@ -513,6 +508,12 @@ U32 LLInventoryItem::getFlags() const
|
||||
return mFlags;
|
||||
}
|
||||
|
||||
time_t LLInventoryItem::getCreationDate() const
|
||||
{
|
||||
return mCreationDate;
|
||||
}
|
||||
|
||||
|
||||
// virtual
|
||||
void LLInventoryItem::packMessage(LLMessageSystem* msg) const
|
||||
{
|
||||
@@ -1047,11 +1048,17 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
|
||||
|
||||
LLFastTimer::DeclareTimer FTM_INVENTORY_SD_DESERIALIZE("Inventory SD Deserialize");
|
||||
|
||||
bool LLInventoryItem::fromLLSD(const LLSD& sd)
|
||||
bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
|
||||
{
|
||||
|
||||
LLFastTimer _(FTM_INVENTORY_SD_DESERIALIZE);
|
||||
mInventoryType = LLInventoryType::IT_NONE;
|
||||
mAssetUUID.setNull();
|
||||
if (is_new)
|
||||
{
|
||||
// If we're adding LLSD to an existing object, need avoid
|
||||
// clobbering these fields.
|
||||
mInventoryType = LLInventoryType::IT_NONE;
|
||||
mAssetUUID.setNull();
|
||||
}
|
||||
std::string w;
|
||||
|
||||
w = INV_ITEM_ID_LABEL;
|
||||
@@ -1108,6 +1115,11 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd)
|
||||
{
|
||||
mAssetUUID = sd[w];
|
||||
}
|
||||
w = INV_LINKED_ID_LABEL;
|
||||
if (sd.has(w))
|
||||
{
|
||||
mAssetUUID = sd[w];
|
||||
}
|
||||
w = INV_ASSET_TYPE_LABEL;
|
||||
if (sd.has(w))
|
||||
{
|
||||
|
||||
@@ -73,6 +73,7 @@ public:
|
||||
virtual LLAssetType::EType getType() const;
|
||||
LLAssetType::EType getActualType() const; // bypasses indirection for linked items
|
||||
BOOL getIsLinkType() const;
|
||||
virtual time_t getCreationDate() const;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Mutators
|
||||
@@ -83,6 +84,7 @@ public:
|
||||
virtual void rename(const std::string& new_name);
|
||||
void setParent(const LLUUID& new_parent);
|
||||
void setType(LLAssetType::EType type);
|
||||
virtual void setCreationDate(time_t creation_date_utc); // only stored for items
|
||||
|
||||
// [RLVa:KB] - Checked: 2014-01-07 (RLVa-1.4.10)
|
||||
// in place correction for inventory name string
|
||||
@@ -103,7 +105,6 @@ public:
|
||||
virtual BOOL importLegacyStream(std::istream& input_stream);
|
||||
virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const;
|
||||
|
||||
virtual void removeFromServer();
|
||||
virtual void updateParentOnServer(BOOL) const;
|
||||
virtual void updateServer(BOOL) const;
|
||||
|
||||
@@ -115,6 +116,7 @@ protected:
|
||||
LLUUID mParentUUID; // Parent category. Root categories have LLUUID::NULL.
|
||||
LLAssetType::EType mType;
|
||||
std::string mName;
|
||||
time_t mCreationDate; // seconds from 1/1/1970, UTC
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -180,7 +182,6 @@ public:
|
||||
void setPermissions(const LLPermissions& perm);
|
||||
void setInventoryType(LLInventoryType::EType inv_type);
|
||||
void setFlags(U32 flags);
|
||||
void setCreationDate(time_t creation_date_utc);
|
||||
void setCreator(const LLUUID& creator); // only used for calling cards
|
||||
|
||||
// Check for changes in permissions masks and sale info
|
||||
@@ -214,7 +215,7 @@ public:
|
||||
void unpackBinaryBucket(U8* bin_bucket, S32 bin_bucket_size);
|
||||
LLSD asLLSD() const;
|
||||
void asLLSD( LLSD& sd ) const;
|
||||
bool fromLLSD(const LLSD& sd);
|
||||
bool fromLLSD(const LLSD& sd, bool is_new = true);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Member Variables
|
||||
@@ -226,7 +227,6 @@ protected:
|
||||
LLSaleInfo mSaleInfo;
|
||||
LLInventoryType::EType mInventoryType;
|
||||
U32 mFlags;
|
||||
time_t mCreationDate; // seconds from 1/1/1970, UTC
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -535,7 +535,7 @@ void LLPermissions::packMessage(LLMessageSystem* msg) const
|
||||
msg->addBOOLFast(_PREHASH_GroupOwned, (BOOL)mIsGroupOwned);
|
||||
}
|
||||
|
||||
void LLPermissions::unpackMessage(LLSD perms)
|
||||
void LLPermissions::unpackMessage(const LLSD& perms)
|
||||
{
|
||||
mCreator = perms["creator-id"];
|
||||
mOwner = perms["owner-id"];
|
||||
|
||||
@@ -319,7 +319,7 @@ public:
|
||||
//
|
||||
|
||||
LLSD packMessage() const;
|
||||
void unpackMessage(LLSD perms);
|
||||
void unpackMessage(const LLSD& perms);
|
||||
|
||||
// For messaging system support
|
||||
void packMessage(LLMessageSystem* msg) const;
|
||||
|
||||
@@ -236,7 +236,7 @@ void LLSaleInfo::packMessage(LLMessageSystem* msg) const
|
||||
//msg->addU32Fast(_PREHASH_NextOwnerMask, mNextOwnerPermMask);
|
||||
}
|
||||
|
||||
void LLSaleInfo::unpackMessage(LLSD sales)
|
||||
void LLSaleInfo::unpackMessage(const LLSD& sales)
|
||||
{
|
||||
U8 sale_type = (U8)sales["sale-type"].asInteger();
|
||||
mSaleType = static_cast<EForSale>(sale_type);
|
||||
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
BOOL importStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask);
|
||||
|
||||
LLSD packMessage() const;
|
||||
void unpackMessage(LLSD sales);
|
||||
void unpackMessage(const LLSD& sales);
|
||||
|
||||
// message serialization
|
||||
void packMessage(LLMessageSystem* msg) const;
|
||||
|
||||
@@ -80,7 +80,7 @@ typedef boost::intrusive_ptr<AICurlPrivate::RefCountedThreadSafePerService> AIPe
|
||||
|
||||
enum AICapabilityType { // {Capabilities} [Responders]
|
||||
cap_texture = 0, // GetTexture [HTTPGetResponder]
|
||||
cap_inventory = 1, // { FetchInventory2, FetchLib2 } [LLInventoryModel::fetchInventoryResponder], { FetchInventoryDescendents2, FetchLibDescendents2 } [LLInventoryModelFetchDescendentsResponder]
|
||||
cap_inventory = 1, // { FetchInventory2, FetchLib2 } [LLInventoryModel::FetchItemHttpHandler], { FetchInventoryDescendents2, FetchLibDescendents2 } [GItemHttpHandler]
|
||||
cap_mesh = 2, // GetMesh [LLMeshSkinInfoResponder, LLMeshDecompositionResponder, LLMeshPhysicsShapeResponder, LLMeshHeaderResponder, LLMeshLODResponder]
|
||||
cap_other = 3, // All other capabilities
|
||||
|
||||
|
||||
@@ -917,7 +917,7 @@ P(emeraldDicDownloader);
|
||||
P(environmentApplyResponder);
|
||||
P(environmentRequestResponder);
|
||||
P2(eventPollResponder, reply_60s);
|
||||
P(fetchInventoryResponder);
|
||||
P(FetchItemHttpHandler);
|
||||
P(fetchScriptLimitsAttachmentInfoResponder);
|
||||
P(fetchScriptLimitsRegionDetailsResponder);
|
||||
P(fetchScriptLimitsRegionInfoResponder);
|
||||
@@ -930,8 +930,8 @@ P(homeLocationResponder);
|
||||
P2(HTTPGetResponder, reply_15s);
|
||||
P(iamHere);
|
||||
P(iamHereVoice);
|
||||
P2(inventoryModelFetchDescendentsResponder, transfer_300s);
|
||||
P(inventoryModelFetchItemResponder);
|
||||
P2(BGFolderHttpHandler, transfer_300s);
|
||||
P(BGItemHttpHandler);
|
||||
P(lcl_responder);
|
||||
P(mapLayerResponder);
|
||||
P(materialsResponder);
|
||||
@@ -951,6 +951,7 @@ P(productInfoRequestResponder);
|
||||
P(regionResponder);
|
||||
P(remoteParcelRequestResponder);
|
||||
P(requestAgentUpdateAppearance);
|
||||
P2(incrementCofVersionResponder_timeouts, transfer_30s_connect_10s);
|
||||
P(responderIgnore);
|
||||
P(setDisplayNameResponder);
|
||||
P2(simulatorFeaturesReceived, transfer_22s_connect_10s);
|
||||
|
||||
@@ -110,7 +110,7 @@ class LLSDInjector : public Injector
|
||||
class RawInjector : public Injector
|
||||
{
|
||||
public:
|
||||
RawInjector(char const* data, U32 size) : mData(data), mSize(size) { }
|
||||
RawInjector(U8 const* data, U32 size) : mData(data), mSize(size) { }
|
||||
/*virtual*/ ~RawInjector() { delete [] mData; }
|
||||
|
||||
/*virtual*/ char const* contentType(void) const { return "application/octet-stream"; }
|
||||
@@ -118,12 +118,12 @@ class RawInjector : public Injector
|
||||
/*virtual*/ U32 get_body(LLChannelDescriptors const& channels, buffer_ptr_t& buffer)
|
||||
{
|
||||
LLBufferStream ostream(channels, buffer.get());
|
||||
ostream.write(mData, mSize);
|
||||
ostream.write((const char*)mData, mSize);
|
||||
ostream << std::flush; // Always flush a LLBufferStream when done writing to it.
|
||||
return mSize;
|
||||
}
|
||||
|
||||
char const* mData;
|
||||
U8 const* mData;
|
||||
U32 mSize;
|
||||
};
|
||||
|
||||
@@ -722,7 +722,7 @@ void LLHTTPClient::put(std::string const& url, LLSD const& body, ResponderPtr re
|
||||
request(url, HTTP_PUT, new LLSDInjector(body), responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug), no_keep_alive, no_does_authentication, no_allow_compressed_reply);
|
||||
}
|
||||
|
||||
void LLHTTPClient::putRaw(const std::string& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
|
||||
void LLHTTPClient::putRaw(const std::string& url, const U8* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
|
||||
{
|
||||
request(url, HTTP_PUT, new RawInjector(data, size), responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug), no_keep_alive, no_does_authentication, no_allow_compressed_reply);
|
||||
}
|
||||
@@ -753,7 +753,7 @@ void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC
|
||||
request(url, HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, does_authentication, no_allow_compressed_reply);
|
||||
}
|
||||
|
||||
void LLHTTPClient::postRaw(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
|
||||
void LLHTTPClient::postRaw(std::string const& url, U8 const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
|
||||
{
|
||||
request(url, HTTP_POST, new RawInjector(data, size), responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
|
||||
}
|
||||
|
||||
@@ -491,8 +491,8 @@ public:
|
||||
static void put(std::string const& url, LLSD const& body, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
|
||||
{ AIHTTPHeaders headers; put(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
|
||||
|
||||
static void putRaw(const std::string& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
|
||||
static void putRaw(const std::string& url, const char* data, S32 size, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
|
||||
static void putRaw(const std::string& url, const U8* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
|
||||
static void putRaw(const std::string& url, const U8* data, S32 size, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
|
||||
{ AIHTTPHeaders headers; putRaw(url, data, size, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
|
||||
|
||||
static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
|
||||
@@ -517,8 +517,8 @@ public:
|
||||
{ AIHTTPHeaders headers; postXMLRPC(url, method, value, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
|
||||
|
||||
/** Takes ownership of data and deletes it when sent */
|
||||
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
|
||||
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
|
||||
static void postRaw(std::string const& url, const U8* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
|
||||
static void postRaw(std::string const& url, const U8* data, S32 size, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
|
||||
{ AIHTTPHeaders headers; postRaw(url, data, size, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
|
||||
|
||||
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
|
||||
|
||||
@@ -82,5 +82,24 @@ protected:
|
||||
std::string mRegisteredName;
|
||||
};
|
||||
|
||||
class LLBindMemberListener : public LLOldEvents::LLSimpleListener
|
||||
{
|
||||
public:
|
||||
typedef boost::function<void(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)> event_callback_t;
|
||||
template <typename T>
|
||||
LLBindMemberListener(T *pointer, const std::string& register_name, event_callback_t cb)
|
||||
{
|
||||
pointer->registerEventListener(register_name, this);
|
||||
mCallback = cb;
|
||||
}
|
||||
|
||||
// This is what you have to override to handle this event
|
||||
virtual bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
mCallback(event, userdata);
|
||||
return true;
|
||||
}
|
||||
event_callback_t mCallback;
|
||||
};
|
||||
|
||||
#endif // LL_LLMEMBERLISTENER_H
|
||||
|
||||
@@ -296,6 +296,7 @@ set(viewer_SOURCE_FILES
|
||||
llgroupnotify.cpp
|
||||
llhomelocationresponder.cpp
|
||||
llhoverview.cpp
|
||||
llhttpretrypolicy.cpp
|
||||
llhudeffect.cpp
|
||||
llhudeffectbeam.cpp
|
||||
llhudeffectlookat.cpp
|
||||
@@ -824,6 +825,7 @@ set(viewer_HEADER_FILES
|
||||
llgroupactions.h
|
||||
llgroupmgr.h
|
||||
llgroupnotify.h
|
||||
llhttpretrypolicy.h
|
||||
llhomelocationresponder.h
|
||||
llhoverview.h
|
||||
llhudeffect.h
|
||||
|
||||
@@ -7383,7 +7383,7 @@
|
||||
|
||||
<param
|
||||
id="868"
|
||||
group="0"
|
||||
group="3"
|
||||
wearable="shirt"
|
||||
edit_group="shirt"
|
||||
edit_group_order="8"
|
||||
@@ -8473,7 +8473,7 @@
|
||||
|
||||
<param
|
||||
id="869"
|
||||
group="0"
|
||||
group="3"
|
||||
wearable="pants"
|
||||
edit_group="pants"
|
||||
edit_group_order="6"
|
||||
@@ -9391,7 +9391,7 @@
|
||||
|
||||
<param
|
||||
id="163"
|
||||
group="0"
|
||||
group="3"
|
||||
wearable="skin"
|
||||
edit_group="skin_facedetail"
|
||||
edit_group_order="3"
|
||||
@@ -11449,7 +11449,7 @@
|
||||
|
||||
<param
|
||||
id="877"
|
||||
group="0"
|
||||
group="3"
|
||||
name="Jacket Wrinkles"
|
||||
label="Jacket Wrinkles"
|
||||
wearable="jacket"
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "llinventoryfunctions.h"
|
||||
#include "llinventoryobserver.h"
|
||||
#include "llinventorypanel.h"
|
||||
#include "lllocaltextureobject.h"
|
||||
#include "llpanelmaininventory.h"
|
||||
#include "llmd5.h"
|
||||
#include "llnotificationsutil.h"
|
||||
@@ -97,7 +98,7 @@ void wear_and_edit_cb(const LLUUID& inv_item)
|
||||
gAgentWearables.requestEditingWearable(inv_item);
|
||||
|
||||
// Wear it.
|
||||
LLAppearanceMgr::instance().wearItemOnAvatar(inv_item);
|
||||
LLAppearanceMgr::instance().wearItemOnAvatar(inv_item,true);
|
||||
}
|
||||
|
||||
void wear_cb(const LLUUID& inv_item)
|
||||
@@ -232,8 +233,11 @@ void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar)
|
||||
llassert(avatar);
|
||||
if (avatar)
|
||||
{
|
||||
avatar->outputRezTiming("Sending wearables request");
|
||||
sendAgentWearablesRequest();
|
||||
if(!gHippoGridManager->getConnectedGrid()->isSecondLife())
|
||||
{
|
||||
avatar->outputRezTiming("Sending wearables request");
|
||||
sendAgentWearablesRequest();
|
||||
}
|
||||
setAvatarAppearance(avatar);
|
||||
}
|
||||
}
|
||||
@@ -260,7 +264,7 @@ LLAgentWearables::sendAgentWearablesUpdateCallback::~sendAgentWearablesUpdateCal
|
||||
* @param wearable The wearable data.
|
||||
* @param todo Bitmask of actions to take on completion.
|
||||
*/
|
||||
LLAgentWearables::addWearableToAgentInventoryCallback::addWearableToAgentInventoryCallback(
|
||||
LLAgentWearables::AddWearableToAgentInventoryCallback::AddWearableToAgentInventoryCallback(
|
||||
LLPointer<LLRefCount> cb, LLWearableType::EType type, U32 index, LLViewerWearable* wearable, U32 todo, const std::string description) :
|
||||
mType(type),
|
||||
mIndex(index),
|
||||
@@ -272,7 +276,7 @@ LLAgentWearables::addWearableToAgentInventoryCallback::addWearableToAgentInvento
|
||||
LL_INFOS() << "constructor" << LL_ENDL;
|
||||
}
|
||||
|
||||
void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& inv_item)
|
||||
void LLAgentWearables::AddWearableToAgentInventoryCallback::fire(const LLUUID& inv_item)
|
||||
{
|
||||
if (mTodo & CALL_CREATESTANDARDDONE)
|
||||
{
|
||||
@@ -307,7 +311,8 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i
|
||||
}
|
||||
if (mTodo & CALL_WEARITEM)
|
||||
{
|
||||
LLAppearanceMgr::instance().addCOFItemLink(inv_item, true, NULL, mDescription);
|
||||
LLAppearanceMgr::instance().addCOFItemLink(inv_item,
|
||||
new LLUpdateAppearanceAndEditWearableOnDestroy(inv_item), mDescription);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,7 +346,7 @@ void LLAgentWearables::addWearabletoAgentInventoryDone(const LLWearableType::ETy
|
||||
gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
|
||||
|
||||
LLViewerInventoryItem* item = gInventory.getItem(item_id);
|
||||
if(item && wearable)
|
||||
if (item && wearable)
|
||||
{
|
||||
// We're changing the asset id, so we both need to set it
|
||||
// locally via setAssetUUID() and via setTransactionID() which
|
||||
@@ -367,12 +372,12 @@ void LLAgentWearables::sendAgentWearablesUpdate()
|
||||
if (wearable->getItemID().isNull())
|
||||
{
|
||||
LLPointer<LLInventoryCallback> cb =
|
||||
new addWearableToAgentInventoryCallback(
|
||||
new AddWearableToAgentInventoryCallback(
|
||||
LLPointer<LLRefCount>(NULL),
|
||||
(LLWearableType::EType)type,
|
||||
index,
|
||||
wearable,
|
||||
addWearableToAgentInventoryCallback::CALL_NONE);
|
||||
AddWearableToAgentInventoryCallback::CALL_NONE);
|
||||
addWearableToAgentInventory(cb, wearable);
|
||||
}
|
||||
else
|
||||
@@ -470,23 +475,18 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32
|
||||
item->getFlags(),
|
||||
item->getCreationDate());
|
||||
template_item->setTransactionID(new_wearable->getTransactionID());
|
||||
template_item->updateServer(FALSE);
|
||||
gInventory.updateItem(template_item);
|
||||
if (name_changed)
|
||||
{
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
update_inventory_item(template_item, gAgentAvatarp->mEndCustomizeCallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add a new inventory item (shouldn't ever happen here)
|
||||
U32 todo = addWearableToAgentInventoryCallback::CALL_NONE;
|
||||
U32 todo = AddWearableToAgentInventoryCallback::CALL_NONE;
|
||||
if (send_update)
|
||||
{
|
||||
todo |= addWearableToAgentInventoryCallback::CALL_UPDATE;
|
||||
todo |= AddWearableToAgentInventoryCallback::CALL_UPDATE;
|
||||
}
|
||||
LLPointer<LLInventoryCallback> cb =
|
||||
new addWearableToAgentInventoryCallback(
|
||||
new AddWearableToAgentInventoryCallback(
|
||||
LLPointer<LLRefCount>(NULL),
|
||||
type,
|
||||
index,
|
||||
@@ -539,12 +539,12 @@ LLViewerWearable* LLAgentWearables::saveWearableAs(const LLWearableType::EType t
|
||||
trunc_description);
|
||||
|
||||
LLPointer<LLInventoryCallback> cb =
|
||||
new addWearableToAgentInventoryCallback(
|
||||
new AddWearableToAgentInventoryCallback(
|
||||
LLPointer<LLRefCount>(NULL),
|
||||
type,
|
||||
index,
|
||||
new_wearable,
|
||||
addWearableToAgentInventoryCallback::CALL_WEARITEM,
|
||||
AddWearableToAgentInventoryCallback::CALL_WEARITEM,
|
||||
trunc_description
|
||||
);
|
||||
LLUUID category_id;
|
||||
@@ -826,10 +826,13 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed)
|
||||
// the versions themselves are compatible. This code can be removed before release.
|
||||
if( wearable->getDefinitionVersion() == 24 )
|
||||
{
|
||||
wearable->setDefinitionVersion(22);
|
||||
U32 index = getWearableIndex(wearable);
|
||||
saveWearable(wearable->getType(),index,TRUE);
|
||||
U32 index;
|
||||
if (getWearableIndex(wearable,index))
|
||||
{
|
||||
LL_INFOS() << "forcing wearable type " << wearable->getType() << " to version 22 from 24" << LL_ENDL;
|
||||
wearable->setDefinitionVersion(22);
|
||||
saveWearable(wearable->getType(),index,TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
//Needed as wearable 'save' process is a mess and fires superfluous updateScrollingPanelList calls
|
||||
@@ -881,11 +884,13 @@ void LLAgentWearables::getWearableItemIDs(LLWearableType::EType eType, uuid_vec_
|
||||
if (mWearableDatas.end() != itWearableType)
|
||||
{
|
||||
for (wearableentry_vec_t::const_iterator itWearable = itWearableType->second.begin();
|
||||
itWearable != itWearableType->second.end(); ++itWearable)
|
||||
itWearable != itWearableType->second.end(); ++itWearable)
|
||||
{
|
||||
LLViewerWearable* wearable = dynamic_cast<LLViewerWearable*>(*itWearable);
|
||||
if(wearable)
|
||||
idItems.push_back(wearable->getItemID());
|
||||
const LLViewerWearable* pWearable = dynamic_cast<LLViewerWearable*>(*itWearable);
|
||||
if (pWearable)
|
||||
{
|
||||
idItems.push_back(pWearable->getItemID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1033,12 +1038,12 @@ void LLAgentWearables::recoverMissingWearable(const LLWearableType::EType type,
|
||||
// destory content.) JC
|
||||
const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
|
||||
LLPointer<LLInventoryCallback> cb =
|
||||
new addWearableToAgentInventoryCallback(
|
||||
new AddWearableToAgentInventoryCallback(
|
||||
LLPointer<LLRefCount>(NULL),
|
||||
type,
|
||||
index,
|
||||
new_wearable,
|
||||
addWearableToAgentInventoryCallback::CALL_RECOVERDONE);
|
||||
AddWearableToAgentInventoryCallback::CALL_RECOVERDONE);
|
||||
addWearableToAgentInventory( cb, new_wearable, lost_and_found_id, TRUE);
|
||||
}
|
||||
|
||||
@@ -1081,7 +1086,7 @@ public:
|
||||
/* virtual */ void fire(const LLUUID& inv_item)
|
||||
{
|
||||
LL_INFOS() << "One item created " << inv_item.asString() << LL_ENDL;
|
||||
LLViewerInventoryItem *item = gInventory.getItem(inv_item);
|
||||
LLConstPointer<LLInventoryObject> item = gInventory.getItem(inv_item);
|
||||
mItemsToLink.push_back(item);
|
||||
updatePendingWearable(inv_item);
|
||||
}
|
||||
@@ -1089,9 +1094,9 @@ public:
|
||||
{
|
||||
LL_INFOS() << "All items created" << LL_ENDL;
|
||||
LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
|
||||
LLAppearanceMgr::instance().linkAll(LLAppearanceMgr::instance().getCOF(),
|
||||
mItemsToLink,
|
||||
link_waiter);
|
||||
link_inventory_array(LLAppearanceMgr::instance().getCOF(),
|
||||
mItemsToLink,
|
||||
link_waiter);
|
||||
}
|
||||
void addPendingWearable(LLViewerWearable *wearable)
|
||||
{
|
||||
@@ -1140,7 +1145,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
LLInventoryModel::item_array_t mItemsToLink;
|
||||
LLInventoryObject::const_object_list_t mItemsToLink;
|
||||
std::vector<LLViewerWearable*> mWearablesAwaitingItems;
|
||||
};
|
||||
|
||||
@@ -1195,6 +1200,39 @@ void LLAgentWearables::createStandardWearables()
|
||||
}
|
||||
}
|
||||
|
||||
// We no longer need this message in the current viewer, but send
|
||||
// it for now to maintain compatibility with release viewers. Can
|
||||
// remove this function once the SH-3455 changesets are universally deployed.
|
||||
void LLAgentWearables::sendDummyAgentWearablesUpdate()
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "sendAgentWearablesUpdate()" << LL_ENDL;
|
||||
|
||||
// Send the AgentIsNowWearing
|
||||
gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing);
|
||||
|
||||
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
|
||||
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
|
||||
// Send 4 standardized nonsense item ids (same as returned by the modified sim, not that it especially matters).
|
||||
gMessageSystem->nextBlockFast(_PREHASH_WearableData);
|
||||
gMessageSystem->addU8Fast(_PREHASH_WearableType, U8(1));
|
||||
gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID("db5a4e5f-9da3-44c8-992d-1181c5795498"));
|
||||
|
||||
gMessageSystem->nextBlockFast(_PREHASH_WearableData);
|
||||
gMessageSystem->addU8Fast(_PREHASH_WearableType, U8(2));
|
||||
gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID("6969c7cc-f72f-4a76-a19b-c293cce8ce4f"));
|
||||
|
||||
gMessageSystem->nextBlockFast(_PREHASH_WearableData);
|
||||
gMessageSystem->addU8Fast(_PREHASH_WearableType, U8(3));
|
||||
gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID("7999702b-b291-48f9-8903-c91dfb828408"));
|
||||
|
||||
gMessageSystem->nextBlockFast(_PREHASH_WearableData);
|
||||
gMessageSystem->addU8Fast(_PREHASH_WearableType, U8(4));
|
||||
gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID("566cb59e-ef60-41d7-bfa6-e0f293fbea40"));
|
||||
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
void LLAgentWearables::createStandardWearablesDone(S32 type, U32 index)
|
||||
{
|
||||
LL_INFOS() << "type " << type << " index " << index << LL_ENDL;
|
||||
@@ -1335,7 +1373,7 @@ void LLAgentWearables::removeWearableFinal( LLWearableType::EType type, bool do_
|
||||
//queryWearableCache(); // moved below
|
||||
if (old_wearable)
|
||||
{
|
||||
popWearable(old_wearable);
|
||||
eraseWearable(old_wearable);
|
||||
old_wearable->removeFromAvatar(TRUE);
|
||||
}
|
||||
}
|
||||
@@ -1352,7 +1390,7 @@ void LLAgentWearables::removeWearableFinal( LLWearableType::EType type, bool do_
|
||||
|
||||
if (old_wearable)
|
||||
{
|
||||
popWearable(old_wearable);
|
||||
eraseWearable(old_wearable);
|
||||
old_wearable->removeFromAvatar(TRUE);
|
||||
}
|
||||
}
|
||||
@@ -1366,30 +1404,92 @@ void LLAgentWearables::removeWearableFinal( LLWearableType::EType type, bool do_
|
||||
|
||||
// Assumes existing wearables are not dirty.
|
||||
void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& items,
|
||||
const std::vector< LLViewerWearable* >& wearables,
|
||||
BOOL remove)
|
||||
const std::vector< LLViewerWearable* >& wearables)
|
||||
{
|
||||
LL_INFOS() << "setWearableOutfit() start" << LL_ENDL;
|
||||
|
||||
// TODO: Removed check for ensuring that teens don't remove undershirt and underwear. Handle later
|
||||
if (remove)
|
||||
{
|
||||
// note: shirt is the first non-body part wearable item. Update if wearable order changes.
|
||||
// This loop should remove all clothing, but not any body parts
|
||||
for (S32 type = 0; type < (S32)LLWearableType::WT_COUNT; type++)
|
||||
{
|
||||
if (LLWearableType::getAssetType((LLWearableType::EType)type) == LLAssetType::AT_CLOTHING)
|
||||
{
|
||||
removeWearable((LLWearableType::EType)type, true, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
S32 count = wearables.size();
|
||||
llassert(items.size() == count);
|
||||
|
||||
S32 i;
|
||||
for (i = 0; i < count; i++)
|
||||
// Check for whether outfit already matches the one requested
|
||||
S32 matched = 0, mismatched = 0;
|
||||
const S32 arr_size = LLWearableType::WT_COUNT;
|
||||
S32 type_counts[arr_size];
|
||||
std::fill(type_counts,type_counts+arr_size,0);
|
||||
for (S32 i = 0; i < count; i++)
|
||||
{
|
||||
LLViewerWearable* new_wearable = wearables[i];
|
||||
LLPointer<LLInventoryItem> new_item = items[i];
|
||||
|
||||
const LLWearableType::EType type = new_wearable->getType();
|
||||
if (type < 0 || type>=LLWearableType::WT_COUNT)
|
||||
{
|
||||
LL_WARNS() << "invalid type " << type << LL_ENDL;
|
||||
mismatched++;
|
||||
continue;
|
||||
}
|
||||
S32 index = type_counts[type];
|
||||
type_counts[type]++;
|
||||
|
||||
LLViewerWearable *curr_wearable = dynamic_cast<LLViewerWearable*>(getWearable(type,index));
|
||||
if (!new_wearable || !curr_wearable ||
|
||||
new_wearable->getAssetID() != curr_wearable->getAssetID())
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "mismatch, type " << type << " index " << index
|
||||
<< " names " << (curr_wearable ? curr_wearable->getName() : "NONE") << ","
|
||||
<< " names " << (new_wearable ? new_wearable->getName() : "NONE") << LL_ENDL;
|
||||
mismatched++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't care about this case - ordering of wearables with the same asset id has no effect.
|
||||
// Causes the two-alphas error case in MAINT-4158.
|
||||
// We should actually disallow wearing two wearables with the same asset id.
|
||||
#if 0
|
||||
if (curr_wearable->getName() != new_item->getName() ||
|
||||
curr_wearable->getItemID() != new_item->getUUID())
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "mismatch on name or inventory id, names "
|
||||
<< curr_wearable->getName() << " vs " << new_item->getName()
|
||||
<< " item ids " << curr_wearable->getItemID() << " vs " << new_item->getUUID()
|
||||
<< LL_ENDL;
|
||||
mismatched++;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
// If we got here, everything matches.
|
||||
matched++;
|
||||
}
|
||||
LL_DEBUGS("Avatar") << "matched " << matched << " mismatched " << mismatched << LL_ENDL;
|
||||
for (S32 j=0; j<LLWearableType::WT_COUNT; j++)
|
||||
{
|
||||
LLWearableType::EType type = (LLWearableType::EType) j;
|
||||
if (getWearableCount(type) != type_counts[j])
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "count mismatch for type " << j << " current " << getWearableCount(j) << " requested " << type_counts[j] << LL_ENDL;
|
||||
mismatched++;
|
||||
}
|
||||
}
|
||||
if (mismatched == 0)
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "no changes, bailing out" << LL_ENDL;
|
||||
mCOFChangeInProgress = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// TODO: Removed check for ensuring that teens don't remove undershirt and underwear. Handle later
|
||||
// note: shirt is the first non-body part wearable item. Update if wearable order changes.
|
||||
// This loop should remove all clothing, but not any body parts
|
||||
for (S32 j = 0; j < (S32)LLWearableType::WT_COUNT; j++)
|
||||
{
|
||||
if (LLWearableType::getAssetType((LLWearableType::EType)j) == LLAssetType::AT_CLOTHING)
|
||||
{
|
||||
removeWearable((LLWearableType::EType)j, true, 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (S32 i = 0; i < count; i++)
|
||||
{
|
||||
LLViewerWearable* new_wearable = wearables[i];
|
||||
LLPointer<LLInventoryItem> new_item = items[i];
|
||||
@@ -1422,6 +1522,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
|
||||
if (isAgentAvatarValid())
|
||||
{
|
||||
gAgentAvatarp->setCompositeUpdatesEnabled(TRUE);
|
||||
gAgentAvatarp->writeWearablesToAvatar();
|
||||
gAgentAvatarp->updateVisualParams();
|
||||
|
||||
// If we have not yet declouded, we may want to use
|
||||
@@ -1442,7 +1543,6 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
|
||||
if (!mInitialWearablesLoaded)
|
||||
{
|
||||
mInitialWearablesLoaded = true;
|
||||
mInitialWearablesLoadedSignal();
|
||||
}
|
||||
// [/SL:KB]
|
||||
notifyLoadingFinished();
|
||||
@@ -1511,7 +1611,13 @@ bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD&
|
||||
{
|
||||
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
|
||||
LLInventoryItem* new_item = gInventory.getItem( notification["payload"]["item_id"].asUUID());
|
||||
U32 index = gAgentWearables.getWearableIndex(wearable);
|
||||
U32 index;
|
||||
if (!gAgentWearables.getWearableIndex(wearable,index))
|
||||
{
|
||||
LL_WARNS() << "Wearable not found" << LL_ENDL;
|
||||
delete wearable;
|
||||
return false;
|
||||
}
|
||||
if( !new_item )
|
||||
{
|
||||
delete wearable;
|
||||
@@ -1550,11 +1656,11 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWeara
|
||||
if (do_append && getWearableItemID(type,0).notNull())
|
||||
{
|
||||
new_wearable->setItemID(new_item->getUUID());
|
||||
/*mWearableDatas[type].push_back(new_wearable);
|
||||
checkWearableAgainstInventory(new_wearable);*/
|
||||
pushWearable(type,new_wearable); //To call LLAgentWearables::wearableUpdated
|
||||
const bool trigger_updated = false;
|
||||
pushWearable(type, new_wearable, trigger_updated);
|
||||
LL_INFOS() << "Added additional wearable for type " << type
|
||||
<< " size is now " << getWearableCount(type) << LL_ENDL;
|
||||
checkWearableAgainstInventory(new_wearable);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1653,33 +1759,12 @@ void LLAgentWearables::invalidateBakedTextureHash(LLMD5& hash) const
|
||||
}
|
||||
}
|
||||
|
||||
// User has picked "remove from avatar" from a menu.
|
||||
// static
|
||||
//void LLAgentWearables::userRemoveWearable(const LLWearableType::EType &type, const U32 &index)
|
||||
//{
|
||||
// if (!(type==LLWearableType::WT_SHAPE || type==LLWearableType::WT_SKIN || type==LLWearableType::WT_HAIR || type==LLWearableType::WT_EYES)) //&&
|
||||
// //!((!gAgent.isTeen()) && (type==LLWearableType::WT_UNDERPANTS || type==LLWearableType::WT_UNDERSHIRT)))
|
||||
// {
|
||||
// gAgentWearables.removeWearable(type,false,index);
|
||||
// }
|
||||
//}
|
||||
|
||||
//static
|
||||
//void LLAgentWearables::userRemoveWearablesOfType(const LLWearableType::EType &type)
|
||||
//{
|
||||
// if (!(type==LLWearableType::WT_SHAPE || type==LLWearableType::WT_SKIN || type==LLWearableType::WT_HAIR || type==LLWearableType::WT_EYES)) //&&
|
||||
// //!((!gAgent.isTeen()) && (type==LLWearableType::WT_UNDERPANTS || type==LLWearableType::WT_UNDERSHIRT)))
|
||||
// {
|
||||
// gAgentWearables.removeWearable(type,true,0);
|
||||
// }
|
||||
//}
|
||||
|
||||
// Combines userRemoveAllAttachments() and userAttachMultipleAttachments() logic to
|
||||
// get attachments into desired state with minimal number of adds/removes.
|
||||
//void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array)
|
||||
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-22 (Catznip-2.2)
|
||||
void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array, bool attach_only)
|
||||
// [/SL:KB]
|
||||
/// Given a desired set of attachments, find what objects need to be
|
||||
// removed, and what additional inventory items need to be added.
|
||||
void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array_t& obj_item_array,
|
||||
llvo_vec_t& objects_to_remove,
|
||||
llvo_vec_t& objects_to_retain,
|
||||
LLInventoryModel::item_array_t& items_to_add)
|
||||
{
|
||||
// Possible cases:
|
||||
// already wearing but not in request set -> take off.
|
||||
@@ -1691,10 +1776,12 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj
|
||||
std::set<LLUUID> requested_item_ids;
|
||||
std::set<LLUUID> current_item_ids;
|
||||
for (S32 i=0; i<obj_item_array.size(); i++)
|
||||
requested_item_ids.insert(obj_item_array[i].get()->getLinkedUUID());
|
||||
|
||||
{
|
||||
const LLUUID & requested_id = obj_item_array[i].get()->getLinkedUUID();
|
||||
//LL_INFOS() << "Requested attachment id " << requested_id << LL_ENDL;
|
||||
requested_item_ids.insert(requested_id);
|
||||
}
|
||||
// Build up list of objects to be removed and items currently attached.
|
||||
llvo_vec_t objects_to_remove;
|
||||
for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
|
||||
iter != gAgentAvatarp->mAttachmentPoints.end();)
|
||||
{
|
||||
@@ -1708,22 +1795,33 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj
|
||||
if (objectp)
|
||||
{
|
||||
LLUUID object_item_id = objectp->getAttachmentItemID();
|
||||
|
||||
bool remove_attachment = true;
|
||||
if (requested_item_ids.find(object_item_id) != requested_item_ids.end())
|
||||
{
|
||||
// Object currently worn, was requested.
|
||||
{ // Object currently worn, was requested to keep it
|
||||
// Flag as currently worn so we won't have to add it again.
|
||||
current_item_ids.insert(object_item_id);
|
||||
remove_attachment = false;
|
||||
}
|
||||
else if (objectp->isTempAttachment())
|
||||
{ // Check if we should keep this temp attachment
|
||||
remove_attachment = LLAppearanceMgr::instance().shouldRemoveTempAttachment(objectp->getID());
|
||||
}
|
||||
|
||||
if (remove_attachment)
|
||||
{
|
||||
// LL_INFOS() << "found object to remove, id " << objectp->getID() << ", item " << objectp->getAttachmentItemID() << LL_ENDL;
|
||||
objects_to_remove.push_back(objectp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// object currently worn, not requested.
|
||||
objects_to_remove.push_back(objectp);
|
||||
// LL_INFOS() << "found object to keep, id " << objectp->getID() << ", item " << objectp->getAttachmentItemID() << LL_ENDL;
|
||||
current_item_ids.insert(object_item_id);
|
||||
objects_to_retain.push_back(objectp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLInventoryModel::item_array_t items_to_add;
|
||||
for (LLInventoryModel::item_array_t::iterator it = obj_item_array.begin();
|
||||
it != obj_item_array.end();
|
||||
++it)
|
||||
@@ -1742,18 +1840,6 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj
|
||||
// S32 remove_count = objects_to_remove.size();
|
||||
// S32 add_count = items_to_add.size();
|
||||
// LL_INFOS() << "remove " << remove_count << " add " << add_count << LL_ENDL;
|
||||
|
||||
// Remove everything in objects_to_remove
|
||||
// userRemoveMultipleAttachments(objects_to_remove);
|
||||
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-22 (Catznip-2.2)
|
||||
if (!attach_only)
|
||||
{
|
||||
userRemoveMultipleAttachments(objects_to_remove);
|
||||
}
|
||||
// [/SL:KB]
|
||||
|
||||
// Add everything in items_to_add
|
||||
userAttachMultipleAttachments(items_to_add);
|
||||
}
|
||||
|
||||
void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remove)
|
||||
@@ -1821,7 +1907,7 @@ void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_arra
|
||||
const LLInventoryItem* pItem = obj_item_array.at(idxItem).get();
|
||||
if (!gRlvAttachmentLocks.canAttach(pItem))
|
||||
{
|
||||
obj_item_array.erase(obj_item_array.begin() + idxItem);
|
||||
obj_item_array.erase( obj_item_array.begin() + idxItem );
|
||||
RLV_ASSERT(false);
|
||||
}
|
||||
}
|
||||
@@ -1938,7 +2024,7 @@ bool LLAgentWearables::canWearableBeRemoved(const LLViewerWearable* wearable) co
|
||||
return !(((type == LLWearableType::WT_SHAPE) || (type == LLWearableType::WT_SKIN) || (type == LLWearableType::WT_HAIR) || (type == LLWearableType::WT_EYES))
|
||||
&& (getWearableCount(type) <= 1) );
|
||||
}
|
||||
void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL upload_bake)
|
||||
void LLAgentWearables::animateAllWearableParams(F32 delta, bool upload_bake)
|
||||
{
|
||||
for( S32 type = 0; type < LLWearableType::WT_COUNT; ++type )
|
||||
{
|
||||
@@ -2012,7 +2098,16 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con
|
||||
LLViewerWearable* wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp);
|
||||
LLAssetType::EType asset_type = wearable->getAssetType();
|
||||
LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
|
||||
LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(wear ? wear_and_edit_cb : wear_cb);
|
||||
LLPointer<LLInventoryCallback> cb;
|
||||
if(wear)
|
||||
{
|
||||
cb = new LLBoostFuncInventoryCallback(wear_and_edit_cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
cb = new LLBoostFuncInventoryCallback(wear_cb);
|
||||
}
|
||||
|
||||
LLUUID folder_id;
|
||||
|
||||
if (parent_id.notNull())
|
||||
@@ -2031,8 +2126,7 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con
|
||||
wearable->getTransactionID(),
|
||||
wearable->getName(),
|
||||
wearable->getDescription(),
|
||||
asset_type,
|
||||
inv_type,
|
||||
asset_type, inv_type,
|
||||
wearable->getType(),
|
||||
LLFloaterPerms::getNextOwnerPerms("Wearables"),
|
||||
cb);
|
||||
@@ -2118,13 +2212,6 @@ boost::signals2::connection LLAgentWearables::addLoadedCallback(loaded_callback_
|
||||
return mLoadedSignal.connect(cb);
|
||||
}
|
||||
|
||||
// [SL:KB] - Patch: Appearance-InitialWearablesLoadedCallback | Checked: 2010-08-14 (Catznip-2.1)
|
||||
boost::signals2::connection LLAgentWearables::addInitialWearablesLoadedCallback(loaded_callback_t cb)
|
||||
{
|
||||
return mInitialWearablesLoadedSignal.connect(cb);
|
||||
}
|
||||
// [/SL:KB]
|
||||
|
||||
bool LLAgentWearables::changeInProgress() const
|
||||
{
|
||||
return mCOFChangeInProgress;
|
||||
@@ -2133,6 +2220,7 @@ bool LLAgentWearables::changeInProgress() const
|
||||
void LLAgentWearables::notifyLoadingStarted()
|
||||
{
|
||||
mCOFChangeInProgress = true;
|
||||
mCOFChangeTimer.reset();
|
||||
mLoadingStartedSignal();
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ public:
|
||||
bool areInitalWearablesLoaded() const { return mInitialWearablesLoaded; }
|
||||
// [/SL:KB]
|
||||
bool isCOFChangeInProgress() const { return mCOFChangeInProgress; }
|
||||
F32 getCOFChangeTime() const { return mCOFChangeTimer.getElapsedTimeF32(); }
|
||||
void updateWearablesLoaded();
|
||||
void checkWearablesLoaded() const;
|
||||
bool canMoveWearable(const LLUUID& item_id, bool closer_to_body) const;
|
||||
@@ -87,7 +88,7 @@ public:
|
||||
// Note: False for shape, skin, eyes, and hair, unless you have MORE than 1.
|
||||
bool canWearableBeRemoved(const LLViewerWearable* wearable) const;
|
||||
|
||||
void animateAllWearableParams(F32 delta, BOOL upload_bake);
|
||||
void animateAllWearableParams(F32 delta, bool upload_bake = false);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Accessors
|
||||
@@ -114,7 +115,7 @@ private:
|
||||
/*virtual*/void wearableUpdated(LLWearable *wearable, BOOL removed);
|
||||
public:
|
||||
// void setWearableItem(LLInventoryItem* new_item, LLViewerWearable* wearable, bool do_append = false);
|
||||
void setWearableOutfit(const LLInventoryItem::item_array_t& items, const std::vector< LLViewerWearable* >& wearables, BOOL remove);
|
||||
void setWearableOutfit(const LLInventoryItem::item_array_t& items, const std::vector< LLViewerWearable* >& wearables);
|
||||
void setWearableName(const LLUUID& item_id, const std::string& new_name);
|
||||
void nameOrDescriptionChanged(LLUUID const& item_id);
|
||||
// *TODO: Move this into llappearance/LLWearableData ?
|
||||
@@ -198,6 +199,11 @@ public:
|
||||
void saveAllWearables();
|
||||
void revertWearable(const LLWearableType::EType type, const U32 index);
|
||||
|
||||
// We no longer need this message in the current viewer, but send
|
||||
// it for now to maintain compatibility with release viewers. Can
|
||||
// remove this function once the SH-3455 changesets are universally deployed.
|
||||
void sendDummyAgentWearablesUpdate();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Static UI hooks
|
||||
//--------------------------------------------------------------------
|
||||
@@ -207,11 +213,10 @@ public:
|
||||
|
||||
typedef std::vector<LLViewerObject*> llvo_vec_t;
|
||||
|
||||
// static void userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array);
|
||||
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-22 (Catznip-3.0.0a) | Added: Catznip-2.2.0a
|
||||
// Not the best way to go about this but other attempts changed far too much LL code to be a viable solution
|
||||
static void userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array, bool fAttachOnly = false);
|
||||
// [/SL:KB]
|
||||
static void findAttachmentsAddRemoveInfo(LLInventoryModel::item_array_t& obj_item_array,
|
||||
llvo_vec_t& objects_to_remove,
|
||||
llvo_vec_t& objects_to_retain,
|
||||
LLInventoryModel::item_array_t& items_to_add);
|
||||
static void userRemoveMultipleAttachments(llvo_vec_t& llvo_array);
|
||||
static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array);
|
||||
|
||||
@@ -229,9 +234,6 @@ public:
|
||||
typedef boost::function<void()> loaded_callback_t;
|
||||
typedef boost::signals2::signal<void()> loaded_signal_t;
|
||||
boost::signals2::connection addLoadedCallback(loaded_callback_t cb);
|
||||
// [SL:KB] - Patch: Appearance-InitialWearablesLoadedCallback | Checked: 2010-08-14 (Catznip-3.0.0a) | Added: Catznip-2.1.1d
|
||||
boost::signals2::connection addInitialWearablesLoadedCallback(loaded_callback_t cb);
|
||||
// [/SL:KB]
|
||||
|
||||
bool changeInProgress() const;
|
||||
void notifyLoadingStarted();
|
||||
@@ -240,9 +242,6 @@ public:
|
||||
private:
|
||||
loading_started_signal_t mLoadingStartedSignal; // should be called before wearables are changed
|
||||
loaded_signal_t mLoadedSignal; // emitted when all agent wearables get loaded
|
||||
// [SL:KB] - Patch: Appearance-InitialWearablesLoadedCallback | Checked: 2010-08-14 (Catznip-3.0.0a) | Added: Catznip-2.1.1d
|
||||
loaded_signal_t mInitialWearablesLoadedSignal; // emitted once when the initial wearables are loaded
|
||||
// [/SL:KB]
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Member variables
|
||||
@@ -259,6 +258,7 @@ private:
|
||||
* True if agent's outfit is being changed now.
|
||||
*/
|
||||
BOOL mCOFChangeInProgress;
|
||||
LLTimer mCOFChangeTimer;
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// Support classes
|
||||
@@ -275,7 +275,7 @@ private:
|
||||
~sendAgentWearablesUpdateCallback();
|
||||
};
|
||||
|
||||
class addWearableToAgentInventoryCallback : public LLInventoryCallback
|
||||
class AddWearableToAgentInventoryCallback : public LLInventoryCallback
|
||||
{
|
||||
public:
|
||||
enum ETodo
|
||||
@@ -288,7 +288,7 @@ private:
|
||||
CALL_WEARITEM = 16
|
||||
};
|
||||
|
||||
addWearableToAgentInventoryCallback(LLPointer<LLRefCount> cb,
|
||||
AddWearableToAgentInventoryCallback(LLPointer<LLRefCount> cb,
|
||||
LLWearableType::EType type,
|
||||
U32 index,
|
||||
LLViewerWearable* wearable,
|
||||
|
||||
@@ -239,7 +239,7 @@ public:
|
||||
void doneIdle()
|
||||
{
|
||||
// NOTE: the code above makes the assumption that COF is empty which won't be the case the way it's used now
|
||||
LLInventoryModel::item_array_t initial_items;
|
||||
LLInventoryObject::const_object_list_t initial_items;
|
||||
for (uuid_vec_t::iterator itItem = mIDs.begin(); itItem != mIDs.end(); ++itItem)
|
||||
{
|
||||
LLViewerInventoryItem* pItem = gInventory.getItem(*itItem);
|
||||
@@ -415,7 +415,7 @@ void LLLibraryOutfitsFetch::folderDone()
|
||||
}
|
||||
|
||||
mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
|
||||
mLibraryClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true);
|
||||
mLibraryClothingID = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_CLOTHING, false);
|
||||
|
||||
// If Library->Clothing->Initial Outfits exists, use that.
|
||||
LLNameCategoryCollector matchFolderFunctor("Initial Outfits");
|
||||
@@ -666,13 +666,9 @@ void LLLibraryOutfitsFetch::contentsDone()
|
||||
wearable_iter != wearable_array.end();
|
||||
++wearable_iter)
|
||||
{
|
||||
const LLViewerInventoryItem *item = wearable_iter->get();
|
||||
link_inventory_item(gAgent.getID(),
|
||||
item->getLinkedUUID(),
|
||||
new_outfit_folder_id,
|
||||
item->getName(),
|
||||
item->getDescription(),
|
||||
LLAssetType::AT_LINK,
|
||||
LLConstPointer<LLInventoryObject> item = wearable_iter->get();
|
||||
link_inventory_object(new_outfit_folder_id,
|
||||
item,
|
||||
order_myoutfits_on_destroy);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,7 +40,7 @@ class LLWearable;
|
||||
class LLWearableHoldingPattern;
|
||||
class LLInventoryCallback;
|
||||
class LLOutfitUnLockTimer;
|
||||
class LLCallAfterInventoryLinkMgr;
|
||||
class RequestAgentUpdateAppearanceResponder;
|
||||
|
||||
class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
|
||||
{
|
||||
@@ -52,9 +52,11 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
|
||||
public:
|
||||
typedef std::vector<LLInventoryModel::item_array_t> wearables_by_type_t;
|
||||
|
||||
void updateAppearanceFromCOF(bool update_base_outfit_ordering = false);
|
||||
void updateAppearanceFromCOF(bool enforce_item_restrictions = true,
|
||||
bool enforce_ordering = true,
|
||||
nullary_func_t post_update_func = no_op);
|
||||
// [SL:KB] - Patch: Appearance-MixedViewers | Checked: 2010-04-02 (Catznip-3.0.0a) | Added: Catznip-2.0.0a
|
||||
void updateAppearanceFromInitialWearables(LLInventoryModel::item_array_t& initial_items);
|
||||
void updateAppearanceFromInitialWearables(LLInventoryObject::const_object_list_t& initial_items);
|
||||
// [/SL:KB]
|
||||
bool needToSaveCOF();
|
||||
void updateCOF(const LLUUID& category, bool append = false);
|
||||
@@ -74,18 +76,24 @@ public:
|
||||
void addCategoryToCurrentOutfit(const LLUUID& cat_id);
|
||||
S32 findExcessOrDuplicateItems(const LLUUID& cat_id,
|
||||
LLAssetType::EType type,
|
||||
S32 max_items,
|
||||
LLInventoryModel::item_array_t& items_to_kill);
|
||||
void enforceItemRestrictions();
|
||||
S32 max_items_per_type,
|
||||
S32 max_items_total,
|
||||
LLInventoryObject::object_list_t& items_to_kill);
|
||||
void findAllExcessOrDuplicateItems(const LLUUID& cat_id,
|
||||
LLInventoryObject::object_list_t& items_to_kill);
|
||||
void enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
S32 getActiveCopyOperations() const;
|
||||
|
||||
// Replace category contents with copied links via the slam_inventory_folder
|
||||
// command (single inventory operation where supported)
|
||||
void slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
|
||||
bool include_folder_links, LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
// Copy all items and the src category itself.
|
||||
void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
void copyItems(const LLUUID& dst_id, LLInventoryModel::item_array_t* items, LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
// Return whether this folder contains minimal contents suitable for making a full outfit.
|
||||
BOOL getCanMakeFolderIntoOutfit(const LLUUID& folder_id);
|
||||
|
||||
@@ -101,21 +109,20 @@ public:
|
||||
// Determine whether we can replace current outfit with the given one.
|
||||
bool getCanReplaceCOF(const LLUUID& outfit_cat_id);
|
||||
|
||||
// Can we add all referenced items to the avatar?
|
||||
bool canAddWearables(const uuid_vec_t& item_ids);
|
||||
|
||||
// Copy all items in a category.
|
||||
void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
void copyItems(const LLUUID& dst_id, LLInventoryModel::item_array_t* items, LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
// Find the Current Outfit folder.
|
||||
const LLUUID getCOF() const;
|
||||
S32 getCOFVersion() const;
|
||||
|
||||
S32 mLastUpdateRequestCOFVersion;
|
||||
S32 getLastUpdateRequestCOFVersion() const;
|
||||
|
||||
// COF version of last appearance message received for self av.
|
||||
S32 mLastAppearanceUpdateCOFVersion;
|
||||
S32 getLastAppearanceUpdateCOFVersion() const;
|
||||
void setLastAppearanceUpdateCOFVersion(S32 new_val);
|
||||
// Debugging - get truncated LLSD summary of COF contents.
|
||||
LLSD dumpCOF() const;
|
||||
|
||||
// Finds the folder link to the currently worn outfit
|
||||
const LLViewerInventoryItem *getBaseOutfitLink();
|
||||
@@ -124,17 +131,24 @@ public:
|
||||
// find the UUID of the currently worn outfit (Base Outfit)
|
||||
const LLUUID getBaseOutfitUUID();
|
||||
|
||||
void wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear,
|
||||
bool do_update,
|
||||
bool replace,
|
||||
LLPointer<LLInventoryCallback> cb = NULL);
|
||||
|
||||
// Wear/attach an item (from a user's inventory) on the agent
|
||||
bool wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update = true, bool replace = false, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
void wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update, bool replace = false,
|
||||
LLPointer<LLInventoryCallback> cb = NULL);
|
||||
|
||||
// Update the displayed outfit name in UI.
|
||||
void updatePanelOutfitName(const std::string& name);
|
||||
|
||||
void purgeBaseOutfitLink(const LLUUID& category);
|
||||
void purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
void createBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> link_waiter);
|
||||
|
||||
void updateAgentWearables(LLWearableHoldingPattern* holder, bool append);
|
||||
void updateAgentWearables(LLWearableHoldingPattern* holder);
|
||||
|
||||
S32 countActiveHoldingPatterns();
|
||||
// For debugging - could be moved elsewhere.
|
||||
void dumpCat(const LLUUID& cat_id, const std::string& msg);
|
||||
void dumpItemArray(const LLInventoryModel::item_array_t& items, const std::string& msg);
|
||||
@@ -144,25 +158,23 @@ public:
|
||||
void registerAttachment(const LLUUID& item_id);
|
||||
void setAttachmentInvLinkEnable(bool val);
|
||||
|
||||
// utility function for bulk linking.
|
||||
void linkAll(const LLUUID& category,
|
||||
LLInventoryModel::item_array_t& items,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
// Add COF link to individual item.
|
||||
void addCOFItemLink(const LLUUID& item_id, bool do_update = true, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
|
||||
void addCOFItemLink(const LLInventoryItem *item, bool do_update = true, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
|
||||
void addCOFItemLink(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
|
||||
void addCOFItemLink(const LLInventoryItem *item, LLPointer<LLInventoryCallback> cb = NULL, const std::string description = "");
|
||||
|
||||
// Find COF entries referencing the given item.
|
||||
LLInventoryModel::item_array_t findCOFItemLinks(const LLUUID& item_id);
|
||||
bool isLinkedInCOF(const LLUUID& item_id);
|
||||
|
||||
// Remove COF entries
|
||||
void removeCOFItemLinks(const LLUUID& item_id);
|
||||
void removeCOFLinksOfType(LLWearableType::EType type);
|
||||
void removeCOFItemLinks(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
void removeCOFLinksOfType(LLWearableType::EType type, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
void removeAllClothesFromAvatar();
|
||||
void removeAllAttachmentsFromAvatar();
|
||||
|
||||
// Special handling of temp attachments, which are not in the COF
|
||||
bool shouldRemoveTempAttachment(const LLUUID& item_id);
|
||||
|
||||
//has the current outfit changed since it was loaded?
|
||||
bool isOutfitDirty() { return mOutfitIsDirty; }
|
||||
|
||||
@@ -173,12 +185,11 @@ public:
|
||||
// should only be necessary to do on initial login.
|
||||
void updateIsDirty();
|
||||
|
||||
void setOutfitLocked(bool locked);
|
||||
|
||||
// Called when self avatar is first fully visible.
|
||||
void onFirstFullyVisible();
|
||||
|
||||
// Create initial outfits from library.
|
||||
void autopopulateOutfits();
|
||||
|
||||
// Copy initial gestures from library.
|
||||
void copyLibraryGestures();
|
||||
|
||||
@@ -192,6 +203,10 @@ public:
|
||||
void removeItemsFromAvatar(const uuid_vec_t& item_ids);
|
||||
void removeItemFromAvatar(const LLUUID& item_id);
|
||||
|
||||
|
||||
void onOutfitFolderCreated(const LLUUID& folder_id, bool show_panel);
|
||||
void onOutfitFolderCreatedAndClothingOrdered(const LLUUID& folder_id, bool show_panel);
|
||||
|
||||
private:
|
||||
LLUUID makeNewOutfitCore(const std::string& new_folder_name, bool show_panel/*=true*/, LLInventoryModel::item_array_t* items = NULL);
|
||||
public:
|
||||
@@ -206,15 +221,29 @@ public:
|
||||
//Divvy items into arrays by wearable type
|
||||
static void divvyWearablesByType(const LLInventoryModel::item_array_t& items, wearables_by_type_t& items_by_type);
|
||||
|
||||
typedef std::map<LLUUID,std::string> desc_map_t;
|
||||
|
||||
void getWearableOrderingDescUpdates(LLInventoryModel::item_array_t& wear_items, desc_map_t& desc_map);
|
||||
|
||||
//Check ordering information on wearables stored in links' descriptions and update if it is invalid
|
||||
// COF is processed if cat_id is not specified
|
||||
void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null, bool update_base_outfit_ordering = false);
|
||||
bool validateClothingOrderingInfo(LLUUID cat_id = LLUUID::null);
|
||||
|
||||
void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null,
|
||||
LLPointer<LLInventoryCallback> cb = NULL);
|
||||
|
||||
bool isOutfitLocked() { return mOutfitLocked; }
|
||||
|
||||
bool isInUpdateAppearanceFromCOF() { return mIsInUpdateAppearanceFromCOF; }
|
||||
|
||||
void requestServerAppearanceUpdate(LLHTTPClient::ResponderPtr responder_ptr = NULL);
|
||||
void requestServerAppearanceUpdate();
|
||||
|
||||
void incrementCofVersion(LLHTTPClient::ResponderPtr responder_ptr = NULL);
|
||||
|
||||
U32 getNumAttachmentsInCOF();
|
||||
|
||||
// *HACK Remove this after server side texture baking is deployed on all sims.
|
||||
void incrementCofVersionLegacy();
|
||||
|
||||
void setAppearanceServiceURL(const std::string& url) { mAppearanceServiceURL = url; }
|
||||
std::string getAppearanceServiceURL() const;
|
||||
@@ -229,51 +258,47 @@ protected:
|
||||
|
||||
private:
|
||||
|
||||
void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type);
|
||||
void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type, S32 max_total);
|
||||
|
||||
void getDescendentsOfAssetType(const LLUUID& category,
|
||||
LLInventoryModel::item_array_t& items,
|
||||
LLAssetType::EType type,
|
||||
bool follow_folder_links);
|
||||
bool follow_folder_links = false);
|
||||
|
||||
void getUserDescendents(const LLUUID& category,
|
||||
LLInventoryModel::item_array_t& wear_items,
|
||||
LLInventoryModel::item_array_t& obj_items,
|
||||
LLInventoryModel::item_array_t& gest_items,
|
||||
bool follow_folder_links);
|
||||
bool follow_folder_links = false);
|
||||
|
||||
void purgeCategory(const LLUUID& category, bool keep_outfit_links);
|
||||
|
||||
static void onOutfitRename(const LLSD& notification, const LLSD& response);
|
||||
|
||||
void setOutfitLocked(bool locked);
|
||||
|
||||
// [SL:KB] - Checked: 2010-04-24 (RLVa-1.2.0f) | Added: RLVa-1.2.0f
|
||||
void purgeItems(const LLInventoryModel::item_array_t& items);
|
||||
void purgeItemsOfType(LLAssetType::EType asset_type);
|
||||
void syncCOF(const LLInventoryModel::item_array_t& items,
|
||||
LLInventoryModel::item_array_t& items_to_add, LLInventoryModel::item_array_t& items_to_remove);
|
||||
// [/SL:KB]
|
||||
|
||||
bool mAttachmentInvLinkEnabled;
|
||||
bool mOutfitIsDirty;
|
||||
bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls.
|
||||
|
||||
boost::intrusive_ptr<RequestAgentUpdateAppearanceResponder> mAppearanceResponder;
|
||||
|
||||
/**
|
||||
* Lock for blocking operations on outfit until server reply or timeout exceed
|
||||
* to avoid unsynchronized outfit state or performing duplicate operations.
|
||||
*/
|
||||
bool mOutfitLocked;
|
||||
|
||||
boost::scoped_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer;
|
||||
std::auto_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer;
|
||||
|
||||
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-18 (Catznip-3.0.0a) | Modified: Catznip-2.1.2e
|
||||
public:
|
||||
void linkPendingAttachments();
|
||||
void onRegisterAttachmentComplete(const LLUUID& idItem);
|
||||
private:
|
||||
uuid_vec_t mPendingAttachLinks;
|
||||
// [/SL:KB]
|
||||
// Set of temp attachment UUIDs that should be removed
|
||||
typedef std::set<LLUUID> doomed_temp_attachments_t;
|
||||
doomed_temp_attachments_t mDoomedTempAttachmentIDs;
|
||||
|
||||
void addDoomedTempAttachment(const LLUUID& id_to_remove);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Item-specific convenience functions
|
||||
@@ -292,27 +317,31 @@ public:
|
||||
class LLUpdateAppearanceOnDestroy: public LLInventoryCallback
|
||||
{
|
||||
public:
|
||||
LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false);
|
||||
LLUpdateAppearanceOnDestroy(bool enforce_item_restrictions = true,
|
||||
bool enforce_ordering = true,
|
||||
nullary_func_t post_update_func = no_op);
|
||||
virtual ~LLUpdateAppearanceOnDestroy();
|
||||
/* virtual */ void fire(const LLUUID& inv_item);
|
||||
|
||||
private:
|
||||
U32 mFireCount;
|
||||
bool mUpdateBaseOrder;
|
||||
bool mEnforceItemRestrictions;
|
||||
bool mEnforceOrdering;
|
||||
nullary_func_t mPostUpdateFunc;
|
||||
};
|
||||
|
||||
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-08-31 (Catznip-3.0.0a) | Added: Catznip-2.1.2a
|
||||
class LLRegisterAttachmentCallback : public LLInventoryCallback
|
||||
class LLUpdateAppearanceAndEditWearableOnDestroy: public LLInventoryCallback
|
||||
{
|
||||
public:
|
||||
/*virtual*/ void fire(const LLUUID& idItem)
|
||||
{
|
||||
LLAppearanceMgr::instance().onRegisterAttachmentComplete(idItem);
|
||||
}
|
||||
};
|
||||
// [/SL:KB]
|
||||
LLUpdateAppearanceAndEditWearableOnDestroy(const LLUUID& item_id);
|
||||
|
||||
#define SUPPORT_ENSEMBLES 0
|
||||
/* virtual */ void fire(const LLUUID& item_id) {}
|
||||
|
||||
~LLUpdateAppearanceAndEditWearableOnDestroy();
|
||||
|
||||
private:
|
||||
LLUUID mItemID;
|
||||
};
|
||||
|
||||
LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name);
|
||||
|
||||
|
||||
@@ -1623,6 +1623,8 @@ bool LLAppViewer::cleanup()
|
||||
|
||||
LLAvatarAppearance::cleanupClass();
|
||||
|
||||
LLAvatarAppearance::cleanupClass();
|
||||
|
||||
LLPostProcess::cleanupClass();
|
||||
|
||||
LLTracker::cleanupInstance();
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
LLAssetUploadChainResponder(const LLSD& post_data,
|
||||
const std::string& file_name,
|
||||
const LLUUID& queue_id,
|
||||
char* data,
|
||||
U8* data,
|
||||
U32 data_size,
|
||||
std::string script_name,
|
||||
LLAssetUploadQueueSupplier *supplier) :
|
||||
@@ -129,7 +129,9 @@ public:
|
||||
for(LLSD::array_const_iterator line = compile_errors.beginArray();
|
||||
line < compile_errors.endArray(); line++)
|
||||
{
|
||||
mSupplier->log(line->asString());
|
||||
std::string str = line->asString();
|
||||
str.erase(std::remove(str.begin(), str.end(), '\n'), str.end());
|
||||
mSupplier->log(str);
|
||||
LL_INFOS() << content["errors"] << LL_ENDL;
|
||||
}
|
||||
}
|
||||
@@ -139,7 +141,7 @@ public:
|
||||
/*virtual*/ char const* getName(void) const { return "LLAssetUploadChainResponder"; }
|
||||
|
||||
LLAssetUploadQueueSupplier *mSupplier;
|
||||
char* mData;
|
||||
U8* mData;
|
||||
U32 mDataSize;
|
||||
std::string mScriptName;
|
||||
};
|
||||
@@ -190,7 +192,7 @@ void LLAssetUploadQueue::queue(const std::string& filename,
|
||||
BOOL is_running,
|
||||
BOOL is_target_mono,
|
||||
const LLUUID& queue_id,
|
||||
char* script_data,
|
||||
U8* script_data,
|
||||
U32 data_size,
|
||||
std::string script_name)
|
||||
{
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
BOOL is_running,
|
||||
BOOL is_target_mono,
|
||||
const LLUUID& queue_id,
|
||||
char* data,
|
||||
U8* data,
|
||||
U32 data_size,
|
||||
std::string script_name);
|
||||
|
||||
@@ -72,7 +72,7 @@ private:
|
||||
BOOL mIsRunning;
|
||||
BOOL mIsTargetMono;
|
||||
LLUUID mQueueId;
|
||||
char* mData;
|
||||
U8* mData;
|
||||
U32 mDataSize;
|
||||
std::string mScriptName;
|
||||
};
|
||||
|
||||
@@ -416,8 +416,8 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
|
||||
{
|
||||
// Read script source in to buffer.
|
||||
U32 script_size = file.getSize();
|
||||
char* script_data = new char[script_size];
|
||||
file.read((U8*)script_data, script_size);
|
||||
U8* script_data = new U8[script_size];
|
||||
file.read(script_data, script_size);
|
||||
|
||||
queue->mUploadQueue->queue(filename, data->mTaskId,
|
||||
data->mItemId, is_running, queue->mMono, queue->getID(),
|
||||
|
||||
@@ -753,15 +753,11 @@ void LLFloaterCustomize::saveCurrentWearables()
|
||||
if (link_item)
|
||||
{
|
||||
// Create new link
|
||||
link_inventory_item( gAgent.getID(),
|
||||
link_item->getLinkedUUID(),
|
||||
link_inventory_object(
|
||||
LLAppearanceMgr::instance().getCOF(),
|
||||
link_item->getName(),
|
||||
description,
|
||||
LLAssetType::AT_LINK,
|
||||
NULL);
|
||||
link_item, NULL);
|
||||
// Remove old link
|
||||
gInventory.purgeObject(link_item->getUUID());
|
||||
remove_inventory_object(link_item->getUUID(), NULL);
|
||||
}
|
||||
}
|
||||
gAgentWearables.saveWearable( cur, i );
|
||||
|
||||
@@ -352,15 +352,6 @@ void LLFloaterLandmark::onBtnDelete()
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the item entirely
|
||||
/*
|
||||
item->removeFromServer();
|
||||
gInventory.deleteObject(item->getUUID());
|
||||
gInventory.notifyObservers();
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
void LLFloaterLandmark::onBtnRename()
|
||||
|
||||
@@ -129,7 +129,7 @@ void LLFloaterOpenObject::dirty()
|
||||
|
||||
|
||||
|
||||
void LLFloaterOpenObject::moveToInventory(bool wear)
|
||||
void LLFloaterOpenObject::moveToInventory(bool wear, bool replace)
|
||||
{
|
||||
if (mObjectSelection->getRootObjectCount() != 1)
|
||||
{
|
||||
@@ -157,40 +157,34 @@ void LLFloaterOpenObject::moveToInventory(bool wear)
|
||||
parent_category_id = gInventory.getRootFolderID();
|
||||
}
|
||||
|
||||
LLCategoryCreate* cat_data = new LLCategoryCreate(object_id, wear);
|
||||
|
||||
inventory_func_type func = boost::bind(LLFloaterOpenObject::callbackCreateInventoryCategory,_1,object_id,wear,replace);
|
||||
LLUUID category_id = gInventory.createNewCategory(parent_category_id,
|
||||
LLFolderType::FT_NONE,
|
||||
name,
|
||||
callbackCreateInventoryCategory,
|
||||
(void*)cat_data);
|
||||
LLFolderType::FT_NONE,
|
||||
name,
|
||||
func);
|
||||
|
||||
//If we get a null category ID, we are using a capability in createNewCategory and we will
|
||||
//handle the following in the callbackCreateInventoryCategory routine.
|
||||
if ( category_id.notNull() )
|
||||
{
|
||||
LLSD result;
|
||||
result["folder_id"] = category_id;
|
||||
//Reduce redundant code by just calling the callback. Dur.
|
||||
callbackCreateInventoryCategory(result,cat_data);
|
||||
callbackCreateInventoryCategory(category_id, object_id, wear);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLSD& result, void* data)
|
||||
void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLUUID& category_id, LLUUID object_id, bool wear, bool replace)
|
||||
{
|
||||
LLCategoryCreate* cat_data = (LLCategoryCreate*)data;
|
||||
|
||||
LLUUID category_id = result["folder_id"].asUUID();
|
||||
LLCatAndWear* wear_data = new LLCatAndWear;
|
||||
|
||||
wear_data->mCatID = category_id;
|
||||
wear_data->mWear = cat_data->mWear;
|
||||
wear_data->mWear = wear;
|
||||
wear_data->mFolderResponded = true;
|
||||
wear_data->mReplace = replace;
|
||||
|
||||
// Copy and/or move the items into the newly created folder.
|
||||
// Ignore any "you're going to break this item" messages.
|
||||
BOOL success = move_inv_category_world_to_agent(cat_data->mObjectID, category_id, TRUE,
|
||||
BOOL success = move_inv_category_world_to_agent(object_id, category_id, TRUE,
|
||||
callbackMoveInventory,
|
||||
(void*)wear_data);
|
||||
if (!success)
|
||||
@@ -200,7 +194,6 @@ void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLSD& result, vo
|
||||
|
||||
LLNotificationsUtil::add("OpenObjectCannotCopy");
|
||||
}
|
||||
delete cat_data;
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -64,6 +64,7 @@ public:
|
||||
LLUUID mCatID;
|
||||
bool mWear;
|
||||
bool mFolderResponded;
|
||||
bool mReplace;
|
||||
};
|
||||
|
||||
protected:
|
||||
@@ -73,11 +74,11 @@ protected:
|
||||
void refresh();
|
||||
void draw();
|
||||
|
||||
void moveToInventory(bool wear);
|
||||
void moveToInventory(bool wear, bool replace = false);
|
||||
|
||||
static void onClickMoveToInventory(void* data);
|
||||
static void onClickMoveAndWear(void* data);
|
||||
static void callbackCreateInventoryCategory(const LLSD& result, void* data);
|
||||
static void callbackCreateInventoryCategory(const LLUUID& category_id, LLUUID object_id, bool wear, bool replace = false);
|
||||
static void callbackMoveInventory(S32 result, void* data);
|
||||
static void* createPanelInventory(void* data);
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item)
|
||||
|
||||
// Default constructor
|
||||
LLFolderView::LLFolderView( const std::string& name,
|
||||
const LLRect& rect, const LLUUID& source_id, LLPanel* parent_panel, LLFolderViewEventListener* listener ) :
|
||||
const LLRect& rect, const LLUUID& source_id, LLPanel* parent_panel, LLFolderViewEventListener* listener, LLFolderViewGroupedItemModel* group_model ) :
|
||||
#if LL_WINDOWS
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4355 ) // warning C4355: 'this' : used in base member initializer list
|
||||
@@ -211,7 +211,8 @@ LLFolderView::LLFolderView( const std::string& name,
|
||||
mUseEllipses(FALSE),
|
||||
mDraggingOverItem(NULL),
|
||||
mStatusTextBox(NULL),
|
||||
mSearchType(1)
|
||||
mSearchType(1),
|
||||
mGroupedItemModel(group_model)
|
||||
{
|
||||
LLPanel* panel = parent_panel;
|
||||
mParentPanel = panel->getHandle();
|
||||
@@ -2362,6 +2363,14 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu)
|
||||
flags = 0x0;
|
||||
}
|
||||
|
||||
// This adds a check for restrictions based on the entire
|
||||
// selection set - for example, any one wearable may not push you
|
||||
// over the limit, but all wearables together still might.
|
||||
if (getFolderViewGroupedItemModel())
|
||||
{
|
||||
getFolderViewGroupedItemModel()->groupFilterContextMenu(mSelectedItems, *menu);
|
||||
}
|
||||
|
||||
addNoOptions(menu);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "llviewertexture.h"
|
||||
|
||||
class LLFolderViewEventListener;
|
||||
class LLFolderViewGroupedItemModel;
|
||||
class LLFolderViewFolder;
|
||||
class LLFolderViewItem;
|
||||
class LLInventoryModel;
|
||||
@@ -77,13 +78,19 @@ public:
|
||||
|
||||
|
||||
LLFolderView( const std::string& name, const LLRect& rect,
|
||||
const LLUUID& source_id, LLPanel *parent_view, LLFolderViewEventListener* listener );
|
||||
const LLUUID& source_id, LLPanel *parent_view, LLFolderViewEventListener* listener, LLFolderViewGroupedItemModel* group_model = NULL );
|
||||
|
||||
typedef folder_view_item_deque selected_items_t;
|
||||
|
||||
virtual ~LLFolderView( void );
|
||||
|
||||
virtual BOOL canFocusChildren() const;
|
||||
|
||||
virtual LLFolderView* getRoot() { return this; }
|
||||
|
||||
LLFolderViewGroupedItemModel* getFolderViewGroupedItemModel() { return mGroupedItemModel; }
|
||||
const LLFolderViewGroupedItemModel* getFolderViewGroupedItemModel() const { return mGroupedItemModel; }
|
||||
|
||||
// FolderViews default to sort by name. This will change that,
|
||||
// and resort the items if necessary.
|
||||
void setSortOrder(U32 order);
|
||||
@@ -321,6 +328,8 @@ protected:
|
||||
|
||||
LLHandle<LLPanel> mParentPanel;
|
||||
|
||||
LLFolderViewGroupedItemModel* mGroupedItemModel;
|
||||
|
||||
/**
|
||||
* Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll.
|
||||
* NOTE: For now it's used only to cut LLFolderViewItem::mLabel text for Landmarks in Places Panel.
|
||||
|
||||
@@ -355,7 +355,7 @@ protected:
|
||||
LLUIImagePtr icon_open,
|
||||
LLUIImagePtr icon_link,
|
||||
LLFolderView* root,
|
||||
LLFolderViewEventListener* listener );
|
||||
LLFolderViewEventListener* listener);
|
||||
|
||||
friend class LLBuildNewViewsScheduler;
|
||||
friend class LLPanelObjectInventory;
|
||||
@@ -572,4 +572,12 @@ public:
|
||||
virtual void operator()(LLFolderViewEventListener* listener) = 0;
|
||||
};
|
||||
|
||||
typedef std::deque<LLFolderViewItem*> folder_view_item_deque;
|
||||
|
||||
class LLFolderViewGroupedItemModel : public LLRefCount
|
||||
{
|
||||
public:
|
||||
virtual void groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu) = 0;
|
||||
};
|
||||
|
||||
#endif // LLFOLDERVIEWITEM_H
|
||||
|
||||
155
indra/newview/llhttpretrypolicy.cpp
Normal file
155
indra/newview/llhttpretrypolicy.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* @file llhttpretrypolicy.h
|
||||
* @brief Header for a retry policy class intended for use with http responders.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llhttpretrypolicy.h"
|
||||
#include "llhttpstatuscodes.h"
|
||||
#include "aihttpheaders.h"
|
||||
|
||||
// for curl_getdate() (apparently parsing RFC 1123 dates is hard)
|
||||
#include <curl/curl.h>
|
||||
|
||||
// Parses 'Retry-After' header contents and returns seconds until retry should occur.
|
||||
bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait)
|
||||
{
|
||||
// *TODO: This needs testing! Not in use yet.
|
||||
// Examples of Retry-After headers:
|
||||
// Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
|
||||
// Retry-After: 120
|
||||
|
||||
// Check for number of seconds version, first:
|
||||
char* end = 0;
|
||||
// Parse as double
|
||||
double seconds = std::strtod(retry_after.c_str(), &end);
|
||||
if (end != 0 && *end == 0)
|
||||
{
|
||||
// Successful parse
|
||||
seconds_to_wait = (F32)seconds;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse rfc1123 date.
|
||||
time_t date = curl_getdate(retry_after.c_str(), NULL);
|
||||
if (-1 == date) return false;
|
||||
|
||||
seconds_to_wait = (F64)date - LLTimer::getTotalSeconds();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries, bool retry_on_4xx):
|
||||
mMinDelay(min_delay),
|
||||
mMaxDelay(max_delay),
|
||||
mBackoffFactor(backoff_factor),
|
||||
mMaxRetries(max_retries),
|
||||
mRetryOn4xx(retry_on_4xx)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void LLAdaptiveRetryPolicy::init()
|
||||
{
|
||||
mDelay = mMinDelay;
|
||||
mRetryCount = 0;
|
||||
mShouldRetry = true;
|
||||
}
|
||||
|
||||
void LLAdaptiveRetryPolicy::reset()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
bool LLAdaptiveRetryPolicy::getRetryAfter(const AIHTTPReceivedHeaders& headers, F32& retry_header_time)
|
||||
{
|
||||
AIHTTPReceivedHeaders::range_type results;
|
||||
return headers.getValues("retry-after", results) && getSecondsUntilRetryAfter(results.first->second, retry_header_time);
|
||||
}
|
||||
|
||||
void LLAdaptiveRetryPolicy::onSuccess()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void LLAdaptiveRetryPolicy::onFailure(S32 status, const AIHTTPReceivedHeaders& headers)
|
||||
{
|
||||
F32 retry_header_time;
|
||||
bool has_retry_header_time = getRetryAfter(headers,retry_header_time);
|
||||
onFailureCommon(status, has_retry_header_time, retry_header_time);
|
||||
}
|
||||
|
||||
|
||||
void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time)
|
||||
{
|
||||
if (!mShouldRetry)
|
||||
{
|
||||
LL_INFOS() << "keep on failing" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
if (mRetryCount > 0)
|
||||
{
|
||||
mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay);
|
||||
}
|
||||
// Honor server Retry-After header.
|
||||
// Status 503 may ask us to wait for a certain amount of time before retrying.
|
||||
F32 wait_time = mDelay;
|
||||
if (has_retry_header_time)
|
||||
{
|
||||
wait_time = retry_header_time;
|
||||
}
|
||||
|
||||
if (mRetryCount>=mMaxRetries)
|
||||
{
|
||||
LL_INFOS() << "Too many retries " << mRetryCount << ", will not retry" << LL_ENDL;
|
||||
mShouldRetry = false;
|
||||
}
|
||||
|
||||
if (!mRetryOn4xx && !(status == HTTP_INTERNAL_ERROR_OTHER || ((500 <= status) && (status < 600))))
|
||||
{
|
||||
LL_INFOS() << "Non-server error " << status << ", will not retry" << LL_ENDL;
|
||||
mShouldRetry = false;
|
||||
}
|
||||
if (mShouldRetry)
|
||||
{
|
||||
LL_INFOS() << "Retry count " << mRetryCount << " should retry after " << wait_time << LL_ENDL;
|
||||
mRetryTimer.reset();
|
||||
mRetryTimer.setTimerExpirySec(wait_time);
|
||||
}
|
||||
mRetryCount++;
|
||||
}
|
||||
|
||||
|
||||
bool LLAdaptiveRetryPolicy::shouldRetry(F32& seconds_to_wait) const
|
||||
{
|
||||
if (mRetryCount == 0)
|
||||
{
|
||||
// Called shouldRetry before any failure.
|
||||
seconds_to_wait = F32_MAX;
|
||||
return false;
|
||||
}
|
||||
seconds_to_wait = mShouldRetry ? (F32) mRetryTimer.getRemainingTimeF32() : F32_MAX;
|
||||
return mShouldRetry;
|
||||
}
|
||||
88
indra/newview/llhttpretrypolicy.h
Normal file
88
indra/newview/llhttpretrypolicy.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* @file file llhttpretrypolicy.h
|
||||
* @brief declarations for http retry policy class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_RETRYPOLICY_H
|
||||
#define LL_RETRYPOLICY_H
|
||||
|
||||
#include "lltimer.h"
|
||||
#include "llthread.h"
|
||||
|
||||
class AIHTTPReceivedHeaders;
|
||||
|
||||
// This is intended for use with HTTP Clients/Responders, but is not
|
||||
// specifically coupled with those classes.
|
||||
class LLHTTPRetryPolicy: public LLThreadSafeRefCount
|
||||
{
|
||||
public:
|
||||
LLHTTPRetryPolicy() {}
|
||||
|
||||
virtual ~LLHTTPRetryPolicy() {}
|
||||
// Call after a sucess to reset retry state.
|
||||
|
||||
virtual void onSuccess() = 0;
|
||||
// Call once after an HTTP failure to update state.
|
||||
virtual void onFailure(S32 status, const AIHTTPReceivedHeaders& headers) = 0;
|
||||
|
||||
virtual bool shouldRetry(F32& seconds_to_wait) const = 0;
|
||||
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
|
||||
// Very general policy with geometric back-off after failures,
|
||||
// up to a maximum delay, and maximum number of retries.
|
||||
class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy
|
||||
{
|
||||
public:
|
||||
LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries, bool retry_on_4xx = false);
|
||||
|
||||
// virtual
|
||||
void onSuccess();
|
||||
|
||||
void reset();
|
||||
|
||||
// virtual
|
||||
void onFailure(S32 status, const AIHTTPReceivedHeaders& headers);
|
||||
// virtual
|
||||
bool shouldRetry(F32& seconds_to_wait) const;
|
||||
|
||||
protected:
|
||||
void init();
|
||||
bool getRetryAfter(const AIHTTPReceivedHeaders& headers, F32& retry_header_time);
|
||||
void onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time);
|
||||
|
||||
private:
|
||||
F32 mMinDelay; // delay never less than this value
|
||||
F32 mMaxDelay; // delay never exceeds this value
|
||||
F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay.
|
||||
U32 mMaxRetries; // maximum number of times shouldRetry will return true.
|
||||
F32 mDelay; // current delay.
|
||||
U32 mRetryCount; // number of times shouldRetry has been called.
|
||||
LLTimer mRetryTimer; // time until next retry.
|
||||
bool mShouldRetry; // Becomes false after too many retries, or the wrong sort of status received, etc.
|
||||
bool mRetryOn4xx; // Normally only retry on 5xx server errors.
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -71,6 +71,8 @@ typedef LLMemberListener<LLInventoryPanel> inventory_panel_listener_t;
|
||||
|
||||
bool LLInventoryAction::doToSelected(LLFolderView* folder, std::string action)
|
||||
{
|
||||
if (!folder)
|
||||
return true;
|
||||
LLInventoryModel* model = &gInventory;
|
||||
if ("rename" == action)
|
||||
{
|
||||
@@ -133,43 +135,7 @@ bool LLInventoryAction::doToSelected(LLFolderView* folder, std::string action)
|
||||
return true;
|
||||
}
|
||||
|
||||
class LLDoToSelectedPanel : public object_inventory_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
LLPanelObjectInventory *panel = mPtr;
|
||||
LLFolderView* folder = panel->getRootFolder();
|
||||
if(!folder) return true;
|
||||
|
||||
return LLInventoryAction::doToSelected(folder, userdata.asString());
|
||||
}
|
||||
};
|
||||
|
||||
class LLDoToSelectedFloater : public inventory_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
LLInventoryPanel *panel = mPtr->getPanel();
|
||||
LLFolderView* folder = panel->getRootFolder();
|
||||
if(!folder) return true;
|
||||
|
||||
return LLInventoryAction::doToSelected(folder, userdata.asString());
|
||||
}
|
||||
};
|
||||
|
||||
class LLDoToSelected : public inventory_panel_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
LLInventoryPanel *panel = mPtr;
|
||||
LLFolderView* folder = panel->getRootFolder();
|
||||
if(!folder) return true;
|
||||
|
||||
return LLInventoryAction::doToSelected(folder, userdata.asString());
|
||||
}
|
||||
};
|
||||
|
||||
class LLNewWindow : public inventory_listener_t
|
||||
struct LLNewWindow : public inventory_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
@@ -190,105 +156,10 @@ class LLNewWindow : public inventory_listener_t
|
||||
}
|
||||
};
|
||||
|
||||
class LLShowFilters : public inventory_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
mPtr->toggleFindOptions();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class LLResetFilter : public inventory_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
mPtr->resetFilters();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class LLCloseAllFolders : public inventory_panel_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
mPtr->closeAllFolders();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class LLCloseAllFoldersFloater : public inventory_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
mPtr->getPanel()->closeAllFolders();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class LLEmptyTrash : public inventory_panel_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
LLInventoryModel* model = mPtr->getModel();
|
||||
if(!model) return false;
|
||||
LLNotificationsUtil::add("ConfirmEmptyTrash", LLSD(), LLSD(), boost::bind(&LLEmptyTrash::callback_empty_trash, this, _1, _2));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool callback_empty_trash(const LLSD& notification, const LLSD& response)
|
||||
{
|
||||
S32 option = LLNotification::getSelectedOption(notification, response);
|
||||
if (option == 0) // YES
|
||||
{
|
||||
LLInventoryModel* model = mPtr->getModel();
|
||||
LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
model->purgeDescendentsOf(trash_id);
|
||||
model->notifyObservers();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class LLEmptyLostAndFound : public inventory_panel_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
LLInventoryModel* model = mPtr->getModel();
|
||||
if(!model) return false;
|
||||
LLNotificationsUtil::add("ConfirmEmptyLostAndFound", LLSD(), LLSD(), boost::bind(&LLEmptyLostAndFound::callback_empty_lost_and_found, this, _1, _2));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool callback_empty_lost_and_found(const LLSD& notification, const LLSD& response)
|
||||
{
|
||||
S32 option = LLNotification::getSelectedOption(notification, response);
|
||||
if (option == 0) // YES
|
||||
{
|
||||
LLInventoryModel* model = mPtr->getModel();
|
||||
LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
|
||||
model->purgeDescendentsOf(lost_and_found_id);
|
||||
model->notifyObservers();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class LLEmptyTrashFloater : public inventory_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
LLInventoryModel* model = mPtr->getPanel()->getModel();
|
||||
if(!model) return false;
|
||||
LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
model->purgeDescendentsOf(trash_id);
|
||||
model->notifyObservers();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void do_create(LLInventoryModel *model, LLInventoryPanel *ptr, std::string type, LLFolderBridge *self = NULL)
|
||||
void do_create(LLInventoryModel *model, LLInventoryPanel *ptr, const LLSD& sdtype, LLFolderBridge *self = NULL)
|
||||
{
|
||||
const std::string& type = sdtype.asString();
|
||||
LL_INFOS() << "self=0x" << std::hex << self << std::dec << LL_ENDL;
|
||||
if ("category" == type)
|
||||
{
|
||||
LLUUID category;
|
||||
@@ -343,31 +214,7 @@ void do_create(LLInventoryModel *model, LLInventoryPanel *ptr, std::string type,
|
||||
ptr->getRootFolder()->setNeedsAutoRename(TRUE);
|
||||
}
|
||||
|
||||
class LLDoCreate : public inventory_panel_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
LLInventoryModel* model = mPtr->getModel();
|
||||
if(!model) return false;
|
||||
std::string type = userdata.asString();
|
||||
do_create(model, mPtr, type, LLFolderBridge::sSelf.get());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class LLDoCreateFloater : public inventory_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
LLInventoryModel* model = mPtr->getPanel()->getModel();
|
||||
if(!model) return false;
|
||||
std::string type = userdata.asString();
|
||||
do_create(model, mPtr->getPanel(), type);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class LLSetSortBy : public inventory_listener_t
|
||||
struct LLSetSortBy : public inventory_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
@@ -426,20 +273,7 @@ class LLSetSortBy : public inventory_listener_t
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class LLRefreshInvModel : public inventory_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
LLInventoryModel* model = mPtr->getPanel()->getModel();
|
||||
if(!model) return false;
|
||||
model->empty();
|
||||
LLInventoryModelBackgroundFetch::instance().start();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class LLSetSearchType : public inventory_listener_t
|
||||
struct LLSetSearchType : public inventory_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
@@ -451,7 +285,7 @@ class LLSetSearchType : public inventory_listener_t
|
||||
}
|
||||
};
|
||||
|
||||
class LLBeginIMSession : public inventory_panel_listener_t
|
||||
struct LLBeginIMSession : public inventory_panel_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
@@ -572,7 +406,7 @@ class LLBeginIMSession : public inventory_panel_listener_t
|
||||
}
|
||||
};
|
||||
|
||||
class LLAttachObject : public inventory_panel_listener_t
|
||||
struct LLAttachObject : public inventory_panel_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
@@ -628,42 +462,30 @@ class LLAttachObject : public inventory_panel_listener_t
|
||||
|
||||
void init_object_inventory_panel_actions(LLPanelObjectInventory *panel)
|
||||
{
|
||||
(new LLDoToSelectedPanel())->registerListener(panel, "Inventory.DoToSelected");
|
||||
(new LLBindMemberListener(panel, "Inventory.DoToSelected", boost::bind(&LLInventoryAction::doToSelected, boost::bind(&LLPanelObjectInventory::getRootFolder, panel), _2)));
|
||||
}
|
||||
|
||||
void init_inventory_actions(LLInventoryView *floater)
|
||||
{
|
||||
(new LLDoToSelectedFloater())->registerListener(floater, "Inventory.DoToSelected");
|
||||
(new LLDoToSelectedFloater())->registerListener(floater, "Inventory.DoToSelected");
|
||||
(new LLCloseAllFoldersFloater())->registerListener(floater, "Inventory.CloseAllFolders");
|
||||
(new LLEmptyTrashFloater())->registerListener(floater, "Inventory.EmptyTrash");
|
||||
(new LLDoCreateFloater())->registerListener(floater, "Inventory.DoCreate");
|
||||
|
||||
(new LLBindMemberListener(floater, "Inventory.DoToSelected", boost::bind(&LLInventoryAction::doToSelected, boost::bind(&LLInventoryView::getRootFolder, floater), _2)));
|
||||
(new LLBindMemberListener(floater, "Inventory.CloseAllFolders", boost::bind(&LLInventoryPanel::closeAllFolders, boost::bind(&LLInventoryView::getPanel, floater))));
|
||||
(new LLBindMemberListener(floater, "Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "", LLFolderType::FT_TRASH)));
|
||||
(new LLBindMemberListener(floater, "Inventory.DoCreate", boost::bind(&do_create, &gInventory, boost::bind(&LLInventoryView::getPanel, floater), _2, (LLFolderBridge*)0)));
|
||||
(new LLNewWindow())->registerListener(floater, "Inventory.NewWindow");
|
||||
(new LLShowFilters())->registerListener(floater, "Inventory.ShowFilters");
|
||||
(new LLResetFilter())->registerListener(floater, "Inventory.ResetFilter");
|
||||
(new LLBindMemberListener(floater, "Inventory.ShowFilters", boost::bind(&LLInventoryView::toggleFindOptions, floater)));
|
||||
(new LLBindMemberListener(floater, "Inventory.ResetFilter", boost::bind(&LLInventoryView::resetFilters, floater)));
|
||||
(new LLSetSortBy())->registerListener(floater, "Inventory.SetSortBy");
|
||||
|
||||
(new LLSetSearchType())->registerListener(floater, "Inventory.SetSearchType");
|
||||
}
|
||||
|
||||
class LLShare : public inventory_panel_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
LLAvatarActions::shareWithAvatars(mPtr);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void init_inventory_panel_actions(LLInventoryPanel *panel)
|
||||
{
|
||||
(new LLDoToSelected())->registerListener(panel, "Inventory.DoToSelected");
|
||||
(new LLBindMemberListener(panel, "Inventory.DoToSelected", boost::bind(&LLInventoryAction::doToSelected, boost::bind(&LLInventoryPanel::getRootFolder, panel), _2)));
|
||||
(new LLAttachObject())->registerListener(panel, "Inventory.AttachObject");
|
||||
(new LLCloseAllFolders())->registerListener(panel, "Inventory.CloseAllFolders");
|
||||
(new LLEmptyTrash())->registerListener(panel, "Inventory.EmptyTrash");
|
||||
(new LLEmptyLostAndFound())->registerListener(panel, "Inventory.EmptyLostAndFound");
|
||||
(new LLDoCreate())->registerListener(panel, "Inventory.DoCreate");
|
||||
(new LLBindMemberListener(panel, "Inventory.CloseAllFolders", boost::bind(&LLInventoryPanel::closeAllFolders, panel)));
|
||||
(new LLBindMemberListener(panel, "Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH)));
|
||||
(new LLBindMemberListener(panel, "Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)));
|
||||
(new LLBindMemberListener(panel, "Inventory.DoCreate", boost::bind(&do_create, &gInventory, panel, _2, boost::bind(&LLHandle<LLFolderBridge>::get, boost::cref(LLFolderBridge::sSelf)))));
|
||||
(new LLBeginIMSession())->registerListener(panel, "Inventory.BeginIMSession");
|
||||
(new LLShare())->registerListener(panel, "Inventory.Share");
|
||||
(new LLBindMemberListener(panel, "Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, panel)));
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "llcallingcard.h"
|
||||
#include "llfloaterproperties.h"
|
||||
#include "llfolderview.h"
|
||||
#include "llfoldervieweventlistener.h"
|
||||
#include "llinventorymodel.h"
|
||||
#include "llinventoryobserver.h"
|
||||
@@ -77,7 +78,7 @@ public:
|
||||
// LLInvFVBridge functionality
|
||||
//--------------------------------------------------------------------
|
||||
virtual const LLUUID& getUUID() const { return mUUID; }
|
||||
virtual void clearDisplayName() {}
|
||||
virtual void clearDisplayName() { mDisplayName.clear(); }
|
||||
virtual const std::string& getPrefix() { return LLStringUtil::null; }
|
||||
virtual void restoreItem() {}
|
||||
virtual void restoreToWorld() {}
|
||||
@@ -87,9 +88,11 @@ public:
|
||||
//--------------------------------------------------------------------
|
||||
virtual const std::string& getName() const;
|
||||
virtual const std::string& getDisplayName() const;
|
||||
|
||||
virtual PermissionMask getPermissionMask() const;
|
||||
virtual LLFolderType::EType getPreferredType() const;
|
||||
virtual time_t getCreationDate() const;
|
||||
virtual void setCreationDate(time_t creation_date_utc);
|
||||
virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; }
|
||||
virtual std::string getLabelSuffix() const { return LLStringUtil::null; }
|
||||
virtual void openItem() {}
|
||||
@@ -102,6 +105,7 @@ public:
|
||||
virtual BOOL isItemMovable() const;
|
||||
virtual BOOL isItemInTrash() const;
|
||||
virtual BOOL isLink() const;
|
||||
virtual BOOL isLibraryItem() const;
|
||||
//virtual BOOL removeItem() = 0;
|
||||
virtual void removeBatch(std::vector<LLFolderViewEventListener*>& batch);
|
||||
virtual void move(LLFolderViewEventListener* new_parent_bridge) {}
|
||||
@@ -148,7 +152,6 @@ protected:
|
||||
BOOL isAgentInventory() const; // false if lost or in the inventory library
|
||||
BOOL isCOFFolder() const; // true if COF or descendant of
|
||||
BOOL isInboxFolder() const; // true if COF or descendant of marketplace inbox
|
||||
BOOL isOutboxFolder() const; // true if COF or descendant of marketplace outbox
|
||||
BOOL isOutboxFolderDirectParent() const;
|
||||
const LLUUID getOutboxFolder() const;
|
||||
|
||||
@@ -162,13 +165,18 @@ protected:
|
||||
const LLUUID& new_parent,
|
||||
BOOL restamp);
|
||||
void removeBatchNoCheck(std::vector<LLFolderViewEventListener*>& batch);
|
||||
public:
|
||||
BOOL isOutboxFolder() const; // true if COF or descendant of marketplace outbox
|
||||
protected:
|
||||
LLHandle<LLInventoryPanel> mInventoryPanel;
|
||||
LLFolderView* mRoot;
|
||||
const LLUUID mUUID; // item id
|
||||
LLInventoryType::EType mInvType;
|
||||
bool mIsLink;
|
||||
mutable std::string mDisplayName;
|
||||
|
||||
void purgeItem(LLInventoryModel *model, const LLUUID &uuid);
|
||||
virtual void buildDisplayName() const {}
|
||||
};
|
||||
|
||||
class AIFilePicker;
|
||||
@@ -206,7 +214,6 @@ public:
|
||||
virtual void restoreToWorld();
|
||||
virtual void gotoItem();
|
||||
virtual LLUIImagePtr getIcon() const;
|
||||
virtual const std::string& getDisplayName() const;
|
||||
virtual std::string getLabelSuffix() const;
|
||||
virtual LLFontGL::StyleFlags getLabelStyle() const;
|
||||
virtual PermissionMask getPermissionMask() const;
|
||||
@@ -217,19 +224,15 @@ public:
|
||||
virtual BOOL isItemCopyable() const;
|
||||
virtual bool hasChildren() const { return FALSE; }
|
||||
virtual BOOL isUpToDate() const { return TRUE; }
|
||||
|
||||
virtual LLUIImagePtr getIconOverlay() const;
|
||||
static void showFloaterImagePreview(LLInventoryItem* item, AIFilePicker* filepicker);
|
||||
|
||||
/*virtual*/ void clearDisplayName() { mDisplayName.clear(); }
|
||||
|
||||
LLViewerInventoryItem* getItem() const;
|
||||
|
||||
protected:
|
||||
BOOL confirmRemoveItem(const LLSD& notification, const LLSD& response);
|
||||
virtual BOOL isItemPermissive() const;
|
||||
static void buildDisplayName(LLInventoryItem* item, std::string& name);
|
||||
|
||||
mutable std::string mDisplayName;
|
||||
virtual void buildDisplayName() const;
|
||||
};
|
||||
|
||||
class LLFolderBridge : public LLInvFVBridge
|
||||
@@ -246,6 +249,8 @@ public:
|
||||
BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop);
|
||||
BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop);
|
||||
|
||||
virtual void buildDisplayName() const;
|
||||
|
||||
virtual void performAction(LLInventoryModel* model, std::string action);
|
||||
virtual void openItem();
|
||||
virtual void closeItem();
|
||||
@@ -256,6 +261,8 @@ public:
|
||||
virtual LLFolderType::EType getPreferredType() const;
|
||||
virtual LLUIImagePtr getIcon() const;
|
||||
virtual LLUIImagePtr getIconOpen() const;
|
||||
virtual LLUIImagePtr getIconOverlay() const;
|
||||
|
||||
static LLUIImagePtr getIcon(LLFolderType::EType preferred_type);
|
||||
|
||||
virtual BOOL renameItem(const std::string& new_name);
|
||||
@@ -285,8 +292,8 @@ public:
|
||||
LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; }
|
||||
|
||||
protected:
|
||||
void buildContextMenuBaseOptions(U32 flags);
|
||||
void buildContextMenuFolderOptions(U32 flags);
|
||||
void buildContextMenuOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items);
|
||||
void buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Menu callbacks
|
||||
@@ -315,8 +322,6 @@ protected:
|
||||
void modifyOutfit(BOOL append);
|
||||
void determineFolderType();
|
||||
|
||||
menuentry_vec_t getMenuItems() { return mItems; } // returns a copy of current menu items
|
||||
|
||||
void dropToFavorites(LLInventoryItem* inv_item);
|
||||
void dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit);
|
||||
|
||||
@@ -331,8 +336,6 @@ private:
|
||||
|
||||
bool mCallingCards;
|
||||
bool mWearables;
|
||||
menuentry_vec_t mItems;
|
||||
menuentry_vec_t mDisabledItems;
|
||||
LLRootHandle<LLFolderBridge> mHandle;
|
||||
};
|
||||
|
||||
@@ -365,6 +368,7 @@ public:
|
||||
virtual void openItem();
|
||||
virtual void previewItem();
|
||||
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
|
||||
virtual void performAction(LLInventoryModel* model, std::string action);
|
||||
static void openSoundPreview(void*);
|
||||
};
|
||||
|
||||
@@ -660,4 +664,11 @@ void hide_context_entries(LLMenuGL& menu,
|
||||
const menuentry_vec_t &entries_to_show,
|
||||
const menuentry_vec_t &disabled_entries);
|
||||
|
||||
class LLFolderViewGroupedItemBridge: public LLFolderViewGroupedItemModel
|
||||
{
|
||||
public:
|
||||
LLFolderViewGroupedItemBridge();
|
||||
virtual void groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu);
|
||||
};
|
||||
|
||||
#endif // LL_LLINVENTORYBRIDGE_H
|
||||
|
||||
@@ -154,12 +154,9 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s
|
||||
return;
|
||||
}
|
||||
|
||||
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
|
||||
new_cat->rename(new_name);
|
||||
new_cat->updateServer(FALSE);
|
||||
model->updateCategory(new_cat);
|
||||
|
||||
model->notifyObservers();
|
||||
LLSD updates;
|
||||
updates["name"] = new_name;
|
||||
update_inventory_category(cat_id, updates, NULL);
|
||||
}
|
||||
|
||||
void copy_inventory_category(LLInventoryModel* model,
|
||||
@@ -740,6 +737,13 @@ bool LLIsOfAssetType::operator()(LLInventoryCategory* cat, LLInventoryItem* item
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool LLIsValidItemLink::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
|
||||
{
|
||||
LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
|
||||
if (!vitem) return false;
|
||||
return (vitem->getActualType() == LLAssetType::AT_LINK && !vitem->getIsBrokenLink());
|
||||
}
|
||||
|
||||
bool LLIsTypeWithPermissions::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
|
||||
{
|
||||
if(mType == LLAssetType::AT_CATEGORY)
|
||||
|
||||
@@ -186,6 +186,13 @@ protected:
|
||||
LLAssetType::EType mType;
|
||||
};
|
||||
|
||||
class LLIsValidItemLink : public LLInventoryCollectFunctor
|
||||
{
|
||||
public:
|
||||
virtual bool operator()(LLInventoryCategory* cat,
|
||||
LLInventoryItem* item);
|
||||
};
|
||||
|
||||
class LLIsTypeWithPermissions : public LLInventoryCollectFunctor
|
||||
{
|
||||
public:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,32 +27,28 @@
|
||||
#ifndef LL_LLINVENTORYMODEL_H
|
||||
#define LL_LLINVENTORYMODEL_H
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "llassettype.h"
|
||||
#include "llfoldertype.h"
|
||||
#include "llframetimer.h"
|
||||
#include "llhttpclient.h"
|
||||
#include "lluuid.h"
|
||||
#include "llpermissionsflags.h"
|
||||
#include "llviewerinventory.h"
|
||||
#include "llstring.h"
|
||||
|
||||
#include "llmd5.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class AIHTTPTimeoutPolicy;
|
||||
extern AIHTTPTimeoutPolicy fetchInventoryResponder_timeout;
|
||||
extern AIHTTPTimeoutPolicy FetchItemHttpHandler_timeout;
|
||||
|
||||
class LLInventoryObserver;
|
||||
class LLInventoryObject;
|
||||
class LLInventoryItem;
|
||||
class LLInventoryCategory;
|
||||
class LLViewerInventoryItem;
|
||||
class LLViewerInventoryCategory;
|
||||
class LLViewerInventoryItem;
|
||||
class LLViewerInventoryCategory;
|
||||
class LLMessageSystem;
|
||||
class LLInventoryCollectFunctor;
|
||||
|
||||
@@ -82,15 +78,17 @@ public:
|
||||
typedef std::vector<LLPointer<LLViewerInventoryItem> > item_array_t;
|
||||
typedef std::set<LLUUID> changed_items_t;
|
||||
|
||||
class fetchInventoryResponder : public LLHTTPClient::ResponderWithResult
|
||||
class FetchItemHttpHandler : public LLHTTPClient::ResponderWithResult
|
||||
{
|
||||
public:
|
||||
fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {};
|
||||
LOG_CLASS(FetchItemHttpHandler);
|
||||
|
||||
FetchItemHttpHandler(const LLSD& request_sd) : mRequestSD(request_sd) {};
|
||||
/*virtual*/ void httpSuccess(void);
|
||||
/*virtual*/ void httpFailure(void);
|
||||
/*virtual*/ AICapabilityType capability_type(void) const { return cap_inventory; }
|
||||
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return fetchInventoryResponder_timeout; }
|
||||
/*virtual*/ char const* getName(void) const { return "fetchInventoryResponder"; }
|
||||
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return FetchItemHttpHandler_timeout; }
|
||||
/*virtual*/ char const* getName(void) const { return "FetchItemHttpHandler"; }
|
||||
protected:
|
||||
LLSD mRequestSD;
|
||||
};
|
||||
@@ -146,6 +144,8 @@ public:
|
||||
// during authentication. Returns true if everything parsed.
|
||||
bool loadSkeleton(const LLSD& options, const LLUUID& owner_id);
|
||||
void buildParentChildMap(); // brute force method to rebuild the entire parent-child relations
|
||||
void createCommonSystemCategories();
|
||||
|
||||
// Call on logout to save a terse representation.
|
||||
void cache(const LLUUID& parent_folder_id, const LLUUID& agent_id);
|
||||
private:
|
||||
@@ -164,6 +164,15 @@ private:
|
||||
parent_cat_map_t mParentChildCategoryTree;
|
||||
parent_item_map_t mParentChildItemTree;
|
||||
|
||||
// Track links to items and categories. We do not store item or
|
||||
// category pointers here, because broken links are also supported.
|
||||
typedef std::multimap<LLUUID, LLUUID> backlink_mmap_t;
|
||||
backlink_mmap_t mBacklinkMMap; // key = target_id: ID of item, values = link_ids: IDs of item or folder links referencing it.
|
||||
// For internal use only
|
||||
bool hasBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id) const;
|
||||
void addBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id);
|
||||
void removeBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Login
|
||||
//--------------------------------------------------------------------
|
||||
@@ -215,6 +224,9 @@ public:
|
||||
EXCLUDE_TRASH = FALSE,
|
||||
INCLUDE_TRASH = TRUE
|
||||
};
|
||||
// Simpler existence test if matches don't actually need to be collected.
|
||||
bool hasMatchingDirectDescendent(const LLUUID& cat_id,
|
||||
LLInventoryCollectFunctor& filter, bool follow_folder_links = false);
|
||||
void collectDescendents(const LLUUID& id,
|
||||
cat_array_t& categories,
|
||||
item_array_t& items,
|
||||
@@ -228,25 +240,35 @@ public:
|
||||
|
||||
// Collect all items in inventory that are linked to item_id.
|
||||
// Assumes item_id is itself not a linked item.
|
||||
item_array_t collectLinkedItems(const LLUUID& item_id,
|
||||
item_array_t collectLinksTo(const LLUUID& item_id,
|
||||
const LLUUID& start_folder_id = LLUUID::null);
|
||||
|
||||
|
||||
// Check if one object has a parent chain up to the category specified by UUID.
|
||||
BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id, const BOOL break_on_recursion=FALSE) const;
|
||||
|
||||
// Follow parent chain to the top.
|
||||
bool getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Find
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
const LLUUID findCategoryUUIDForTypeInRoot(
|
||||
LLFolderType::EType preferred_type,
|
||||
bool create_folder,
|
||||
const LLUUID& root_id);
|
||||
|
||||
// Returns the uuid of the category that specifies 'type' as what it
|
||||
// defaults to containing. The category is not necessarily only for that type.
|
||||
// NOTE: If create_folder is true, this will create a new inventory category
|
||||
// on the fly if one does not exist. *NOTE: if find_in_library is true it
|
||||
// will search in the user's library folder instead of "My Inventory"
|
||||
const LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type,
|
||||
bool create_folder = true,
|
||||
bool find_in_library = false);
|
||||
bool create_folder = true);
|
||||
// will search in the user's library folder instead of "My Inventory"
|
||||
const LLUUID findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type,
|
||||
bool create_folder = true);
|
||||
|
||||
// Get whatever special folder this object is a child of, if any.
|
||||
const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const;
|
||||
@@ -308,7 +330,7 @@ public:
|
||||
// NOTE: In usage, you will want to perform cache accounting
|
||||
// operations in LLInventoryModel::accountForUpdate() or
|
||||
// LLViewerInventoryItem::updateServer() before calling this method.
|
||||
U32 updateItem(const LLViewerInventoryItem* item);
|
||||
U32 updateItem(const LLViewerInventoryItem* item, U32 mask = 0);
|
||||
|
||||
// Change an existing item with the matching id or add
|
||||
// the category. No notifcation will be sent to observers. This
|
||||
@@ -317,7 +339,7 @@ public:
|
||||
// NOTE: In usage, you will want to perform cache accounting
|
||||
// operations in accountForUpdate() or LLViewerInventoryCategory::
|
||||
// updateServer() before calling this method.
|
||||
void updateCategory(const LLViewerInventoryCategory* cat);
|
||||
void updateCategory(const LLViewerInventoryCategory* cat, U32 mask = 0);
|
||||
|
||||
// Move the specified object id to the specified category and
|
||||
// update the internal structures. No cache accounting,
|
||||
@@ -338,11 +360,27 @@ public:
|
||||
// Delete
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
// Update model after an item is confirmed as removed from
|
||||
// server. Works for categories or items.
|
||||
void onObjectDeletedFromServer(const LLUUID& item_id,
|
||||
bool fix_broken_links = true,
|
||||
bool update_parent_version = true,
|
||||
bool do_notify_observers = true);
|
||||
|
||||
// Update model after all descendents removed from server.
|
||||
void onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links = true);
|
||||
|
||||
// Update model after an existing item gets updated on server.
|
||||
void onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version);
|
||||
|
||||
// Update model after an existing category gets updated on server.
|
||||
void onCategoryUpdated(const LLUUID& cat_id, const LLSD& updates);
|
||||
|
||||
// Delete a particular inventory object by ID. Will purge one
|
||||
// object from the internal data structures, maintaining a
|
||||
// consistent internal state. No cache accounting, observer
|
||||
// notification, or server update is performed.
|
||||
void deleteObject(const LLUUID& id);
|
||||
void deleteObject(const LLUUID& id, bool fix_broken_links = true, bool do_notify_observers = true);
|
||||
/// move Item item_id to Trash
|
||||
void removeItem(const LLUUID& item_id);
|
||||
/// move Category category_id to Trash
|
||||
@@ -350,17 +388,6 @@ public:
|
||||
/// removeItem() or removeCategory(), whichever is appropriate
|
||||
void removeObject(const LLUUID& object_id);
|
||||
|
||||
// Delete a particular inventory object by ID, and delete it from
|
||||
// the server. Also updates linked items.
|
||||
void purgeObject(const LLUUID& id);
|
||||
|
||||
// Collects and purges the descendants of the id
|
||||
// provided. If the category is not found, no action is
|
||||
// taken. This method goes through the long winded process of
|
||||
// removing server representation of folders and items while doing
|
||||
// cache accounting in a fairly efficient manner. This method does
|
||||
// not notify observers (though maybe it should...)
|
||||
void purgeDescendentsOf(const LLUUID& id);
|
||||
protected:
|
||||
void updateLinkedObjectsFromPurge(const LLUUID& baseobj_id);
|
||||
|
||||
@@ -398,9 +425,8 @@ public:
|
||||
LLUUID createNewCategory(const LLUUID& parent_id,
|
||||
LLFolderType::EType preferred_type,
|
||||
const std::string& name,
|
||||
void (*callback)(const LLSD&, void*) = NULL,
|
||||
void* user_data = NULL);
|
||||
public:
|
||||
boost::optional<inventory_func_type> callback = boost::optional<inventory_func_type>());
|
||||
protected:
|
||||
// Internal methods that add inventory and make sure that all of
|
||||
// the internal data structures are consistent. These methods
|
||||
// should be passed pointers of newly created objects, and the
|
||||
@@ -476,6 +502,7 @@ public:
|
||||
// inventory. The next notify will include that notification.
|
||||
void addChangedMask(U32 mask, const LLUUID& referent);
|
||||
const changed_items_t& getChangedIDs() const { return mChangedItemIDs; }
|
||||
const changed_items_t& getAddedIDs() const { return mAddedItemIDs; }
|
||||
protected:
|
||||
// Updates all linked items pointing to this id.
|
||||
void addChangedMaskForLinks(const LLUUID& object_id, U32 mask);
|
||||
@@ -486,6 +513,8 @@ private:
|
||||
// Variables used to track what has changed since the last notify.
|
||||
U32 mModifyMask;
|
||||
changed_items_t mChangedItemIDs;
|
||||
changed_items_t mAddedItemIDs;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Observers
|
||||
@@ -547,7 +576,7 @@ public:
|
||||
static void processMoveInventoryItem(LLMessageSystem* msg, void**);
|
||||
static void processFetchInventoryReply(LLMessageSystem* msg, void**);
|
||||
protected:
|
||||
bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting);
|
||||
bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting, U32 mask = 0x0);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Locks
|
||||
@@ -564,10 +593,12 @@ private:
|
||||
std::map<LLUUID, bool> mCategoryLock;
|
||||
std::map<LLUUID, bool> mItemLock;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Debugging
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
// *NOTE: DEBUG functionality
|
||||
void dumpInventory() const;
|
||||
bool validate() const;
|
||||
|
||||
/** Miscellaneous
|
||||
** **
|
||||
|
||||
@@ -40,23 +40,112 @@
|
||||
#include "hippogridmanager.h"
|
||||
|
||||
class AIHTTPTimeoutPolicy;
|
||||
extern AIHTTPTimeoutPolicy inventoryModelFetchDescendentsResponder_timeout;
|
||||
extern AIHTTPTimeoutPolicy inventoryModelFetchItemResponder_timeout;
|
||||
extern AIHTTPTimeoutPolicy BGItemHttpHandler_timeout;
|
||||
extern AIHTTPTimeoutPolicy BGFolderHttpHandler_timeout;
|
||||
|
||||
const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f;
|
||||
const S32 MAX_FETCH_RETRIES = 10;
|
||||
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Class <anonymous>::BGItemHttpHandler
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// Http request handler class for single inventory item requests.
|
||||
//
|
||||
// We'll use a handler-per-request pattern here rather than
|
||||
// a shared handler. Mainly convenient as this was converted
|
||||
// from a Responder class model.
|
||||
//
|
||||
// Derives from and is identical to the normal FetchItemHttpHandler
|
||||
// except that: 1) it uses the background request object which is
|
||||
// updated more slowly than the foreground and 2) keeps a count of
|
||||
// active requests on the LLInventoryModelBackgroundFetch object
|
||||
// to indicate outstanding operations are in-flight.
|
||||
//
|
||||
class BGItemHttpHandler : public LLInventoryModel::FetchItemHttpHandler
|
||||
{
|
||||
LOG_CLASS(BGItemHttpHandler);
|
||||
|
||||
public:
|
||||
BGItemHttpHandler(const LLSD & request_sd)
|
||||
: LLInventoryModel::FetchItemHttpHandler(request_sd)
|
||||
{
|
||||
LLInventoryModelBackgroundFetch::instance().incrFetchCount(1);
|
||||
}
|
||||
|
||||
virtual ~BGItemHttpHandler()
|
||||
{
|
||||
LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
|
||||
}
|
||||
|
||||
/*virtual*/ AICapabilityType capability_type(void) const { return cap_inventory; }
|
||||
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return BGItemHttpHandler_timeout; }
|
||||
/*virtual*/ char const* getName(void) const { return "BGItemHttpHandler"; }
|
||||
protected:
|
||||
BGItemHttpHandler(const BGItemHttpHandler &); // Not defined
|
||||
void operator=(const BGItemHttpHandler &); // Not defined
|
||||
};
|
||||
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Class <anonymous>::BGFolderHttpHandler
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
// Http request handler class for folders.
|
||||
//
|
||||
// Handler for FetchInventoryDescendents2 and FetchLibDescendents2
|
||||
// caps requests for folders.
|
||||
//
|
||||
class BGFolderHttpHandler : public LLHTTPClient::ResponderWithResult
|
||||
{
|
||||
LOG_CLASS(BGFolderHttpHandler);
|
||||
|
||||
public:
|
||||
BGFolderHttpHandler(const LLSD & request_sd, const uuid_vec_t & recursive_cats)
|
||||
: LLHTTPClient::ResponderWithResult(),
|
||||
mRequestSD(request_sd),
|
||||
mRecursiveCatUUIDs(recursive_cats)
|
||||
{
|
||||
LLInventoryModelBackgroundFetch::instance().incrFetchCount(1);
|
||||
}
|
||||
|
||||
virtual ~BGFolderHttpHandler()
|
||||
{
|
||||
LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
|
||||
}
|
||||
|
||||
/*virtual*/ AICapabilityType capability_type(void) const { return cap_inventory; }
|
||||
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return BGFolderHttpHandler_timeout; }
|
||||
/*virtual*/ char const* getName(void) const { return "BGFolderHttpHandler"; }
|
||||
|
||||
protected:
|
||||
BGFolderHttpHandler(const BGFolderHttpHandler &); // Not defined
|
||||
void operator=(const BGFolderHttpHandler &); // Not defined
|
||||
BOOL getIsRecursive(const LLUUID& cat_id) const;
|
||||
private:
|
||||
/*virtual*/ void httpSuccess(void);
|
||||
/*virtual*/ void httpFailure(void);
|
||||
LLSD mRequestSD;
|
||||
uuid_vec_t mRecursiveCatUUIDs; // hack for storing away which cat fetches are recursive
|
||||
};
|
||||
|
||||
|
||||
const char * const LOG_INV("Inventory");
|
||||
|
||||
|
||||
LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch() :
|
||||
mBackgroundFetchActive(FALSE),
|
||||
mFolderFetchActive(false),
|
||||
mFetchCount(0),
|
||||
mAllFoldersFetched(FALSE),
|
||||
mRecursiveInventoryFetchStarted(FALSE),
|
||||
mRecursiveLibraryFetchStarted(FALSE),
|
||||
mNumFetchRetries(0),
|
||||
mMinTimeBetweenFetches(0.3f),
|
||||
mMaxTimeBetweenFetches(10.f),
|
||||
mTimelyFetchPending(FALSE),
|
||||
mFetchCount(0)
|
||||
mTimelyFetchPending(FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -109,12 +198,24 @@ BOOL LLInventoryModelBackgroundFetch::folderFetchActive() const
|
||||
return mFolderFetchActive;
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::addRequestAtFront(const LLUUID & id, BOOL recursive, bool is_category)
|
||||
{
|
||||
mFetchQueue.push_front(FetchQueueInfo(id, recursive, is_category));
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::addRequestAtBack(const LLUUID & id, BOOL recursive, bool is_category)
|
||||
{
|
||||
mFetchQueue.push_back(FetchQueueInfo(id, recursive, is_category));
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive)
|
||||
{
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(id);
|
||||
if (cat || (id.isNull() && !isEverythingFetched()))
|
||||
{ // it's a folder, do a bulk fetch
|
||||
LL_DEBUGS("InventoryFetch") << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL;
|
||||
LLViewerInventoryCategory * cat(gInventory.getCategory(id));
|
||||
|
||||
if (cat || (id.isNull() && ! isEverythingFetched()))
|
||||
{
|
||||
// it's a folder, do a bulk fetch
|
||||
LL_DEBUGS(LOG_INV) << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL;
|
||||
|
||||
mFolderFetchActive = true;
|
||||
if (id.isNull())
|
||||
@@ -181,11 +282,13 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched()
|
||||
mAllFoldersFetched = TRUE;
|
||||
}
|
||||
mFolderFetchActive = false;
|
||||
|
||||
if (mBackgroundFetchActive)
|
||||
{
|
||||
gIdleCallbacks.deleteFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
mBackgroundFetchActive = FALSE;
|
||||
}
|
||||
mBackgroundFetchActive = false;
|
||||
LL_INFOS(LOG_INV) << "Inventory background fetch completed" << LL_ENDL;
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *)
|
||||
@@ -385,241 +488,41 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
|
||||
}
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::incrFetchCount(S16 fetching)
|
||||
void LLInventoryModelBackgroundFetch::incrFetchCount(S32 fetching)
|
||||
{
|
||||
mFetchCount += fetching;
|
||||
if (mFetchCount < 0)
|
||||
{
|
||||
LL_WARNS_ONCE(LOG_INV) << "Inventory fetch count fell below zero (0)." << LL_ENDL;
|
||||
mFetchCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInventoryResponder
|
||||
{
|
||||
public:
|
||||
LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {};
|
||||
/*virtual*/ void httpSuccess(void);
|
||||
/*virtual*/ void httpFailure(void);
|
||||
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return inventoryModelFetchItemResponder_timeout; }
|
||||
/*virtual*/ char const* getName(void) const { return "LLInventoryModelFetchItemResponder"; }
|
||||
};
|
||||
|
||||
void LLInventoryModelFetchItemResponder::httpSuccess(void)
|
||||
{
|
||||
LLInventoryModel::fetchInventoryResponder::httpSuccess();
|
||||
LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
|
||||
}
|
||||
|
||||
void LLInventoryModelFetchItemResponder::httpFailure(void)
|
||||
{
|
||||
LLInventoryModel::fetchInventoryResponder::httpFailure();
|
||||
LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
|
||||
}
|
||||
|
||||
class LLInventoryModelFetchDescendentsResponder : public LLHTTPClient::ResponderWithResult
|
||||
{
|
||||
public:
|
||||
LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd, uuid_vec_t recursive_cats) :
|
||||
mRequestSD(request_sd),
|
||||
mRecursiveCatUUIDs(recursive_cats)
|
||||
{};
|
||||
/*virtual*/ void httpSuccess(void);
|
||||
/*virtual*/ void httpFailure(void);
|
||||
/*virtual*/ AICapabilityType capability_type(void) const { return cap_inventory; }
|
||||
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return inventoryModelFetchDescendentsResponder_timeout; }
|
||||
/*virtual*/ char const* getName(void) const { return "LLInventoryModelFetchDescendentsResponder"; }
|
||||
|
||||
protected:
|
||||
BOOL getIsRecursive(const LLUUID& cat_id) const;
|
||||
private:
|
||||
LLSD mRequestSD;
|
||||
uuid_vec_t mRecursiveCatUUIDs; // hack for storing away which cat fetches are recursive
|
||||
};
|
||||
|
||||
// If we get back a normal response, handle it here.
|
||||
void LLInventoryModelFetchDescendentsResponder::httpSuccess(void)
|
||||
{
|
||||
LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance();
|
||||
if (mContent.has("folders"))
|
||||
{
|
||||
|
||||
for(LLSD::array_const_iterator folder_it = mContent["folders"].beginArray();
|
||||
folder_it != mContent["folders"].endArray();
|
||||
++folder_it)
|
||||
{
|
||||
LLSD folder_sd = *folder_it;
|
||||
|
||||
|
||||
//LLUUID agent_id = folder_sd["agent_id"];
|
||||
|
||||
//if(agent_id != gAgent.getID()) //This should never happen.
|
||||
//{
|
||||
// LL_WARNS() << "Got a UpdateInventoryItem for the wrong agent."
|
||||
// << LL_ENDL;
|
||||
// break;
|
||||
//}
|
||||
|
||||
LLUUID parent_id = folder_sd["folder_id"];
|
||||
LLUUID owner_id = folder_sd["owner_id"];
|
||||
S32 version = (S32)folder_sd["version"].asInteger();
|
||||
S32 descendents = (S32)folder_sd["descendents"].asInteger();
|
||||
LLPointer<LLViewerInventoryCategory> tcategory = new LLViewerInventoryCategory(owner_id);
|
||||
|
||||
if (parent_id.isNull())
|
||||
{
|
||||
LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
|
||||
for(LLSD::array_const_iterator item_it = folder_sd["items"].beginArray();
|
||||
item_it != folder_sd["items"].endArray();
|
||||
++item_it)
|
||||
{
|
||||
LLUUID lost_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
|
||||
if (lost_uuid.notNull())
|
||||
{
|
||||
LLSD item = *item_it;
|
||||
titem->unpackMessage(item);
|
||||
|
||||
LLInventoryModel::update_list_t update;
|
||||
LLInventoryModel::LLCategoryUpdate new_folder(lost_uuid, 1);
|
||||
update.push_back(new_folder);
|
||||
gInventory.accountForUpdate(update);
|
||||
|
||||
titem->setParent(lost_uuid);
|
||||
titem->updateParentOnServer(FALSE);
|
||||
gInventory.updateItem(titem);
|
||||
gInventory.notifyObservers();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLViewerInventoryCategory* pcat = gInventory.getCategory(parent_id);
|
||||
if (!pcat)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for(LLSD::array_const_iterator category_it = folder_sd["categories"].beginArray();
|
||||
category_it != folder_sd["categories"].endArray();
|
||||
++category_it)
|
||||
{
|
||||
LLSD category = *category_it;
|
||||
tcategory->fromLLSD(category);
|
||||
|
||||
const BOOL recursive = getIsRecursive(tcategory->getUUID());
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
fetcher->mFetchQueue.push_back(LLInventoryModelBackgroundFetch::FetchQueueInfo(tcategory->getUUID(), recursive));
|
||||
}
|
||||
else if ( !gInventory.isCategoryComplete(tcategory->getUUID()) )
|
||||
{
|
||||
gInventory.updateCategory(tcategory);
|
||||
}
|
||||
|
||||
}
|
||||
LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
|
||||
for(LLSD::array_const_iterator item_it = folder_sd["items"].beginArray();
|
||||
item_it != folder_sd["items"].endArray();
|
||||
++item_it)
|
||||
{
|
||||
LLSD item = *item_it;
|
||||
titem->unpackMessage(item);
|
||||
|
||||
gInventory.updateItem(titem);
|
||||
}
|
||||
|
||||
// set version and descendentcount according to message.
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(parent_id);
|
||||
if(cat)
|
||||
{
|
||||
cat->setVersion(version);
|
||||
cat->setDescendentCount(descendents);
|
||||
cat->determineFolderType();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (mContent.has("bad_folders"))
|
||||
{
|
||||
for(LLSD::array_const_iterator folder_it = mContent["bad_folders"].beginArray();
|
||||
folder_it != mContent["bad_folders"].endArray();
|
||||
++folder_it)
|
||||
{
|
||||
LLSD folder_sd = *folder_it;
|
||||
|
||||
//These folders failed on the dataserver. We probably don't want to retry them.
|
||||
LL_INFOS() << "Folder " << folder_sd["folder_id"].asString()
|
||||
<< "Error: " << folder_sd["error"].asString() << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
fetcher->incrFetchCount(-1);
|
||||
|
||||
if (fetcher->isBulkFetchProcessingComplete())
|
||||
{
|
||||
LL_INFOS() << "Inventory fetch completed" << LL_ENDL;
|
||||
fetcher->setAllFoldersFetched();
|
||||
}
|
||||
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
|
||||
//If we get back an error (not found, etc...), handle it here
|
||||
void LLInventoryModelFetchDescendentsResponder::httpFailure(void)
|
||||
{
|
||||
LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance();
|
||||
|
||||
LL_INFOS() << "LLInventoryModelFetchDescendentsResponder::error "
|
||||
<< mStatus << ": " << mReason << LL_ENDL;
|
||||
|
||||
fetcher->incrFetchCount(-1);
|
||||
|
||||
if (is_internal_http_error_that_warrants_a_retry(mStatus)) // timed out
|
||||
{
|
||||
for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray();
|
||||
folder_it != mRequestSD["folders"].endArray();
|
||||
++folder_it)
|
||||
{
|
||||
LLSD folder_sd = *folder_it;
|
||||
LLUUID folder_id = folder_sd["folder_id"];
|
||||
const BOOL recursive = getIsRecursive(folder_id);
|
||||
fetcher->mFetchQueue.push_front(LLInventoryModelBackgroundFetch::FetchQueueInfo(folder_id, recursive));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fetcher->isBulkFetchProcessingComplete())
|
||||
{
|
||||
fetcher->setAllFoldersFetched();
|
||||
}
|
||||
}
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
|
||||
BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat_id) const
|
||||
{
|
||||
return (std::find(mRecursiveCatUUIDs.begin(),mRecursiveCatUUIDs.end(), cat_id) != mRecursiveCatUUIDs.end());
|
||||
}
|
||||
|
||||
// Bundle up a bunch of requests to send all at once.
|
||||
void LLInventoryModelBackgroundFetch::bulkFetch()
|
||||
{
|
||||
//Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped.
|
||||
//If there are items in mFetchQueue, we want to check the time since the last bulkFetch was
|
||||
//sent. If it exceeds our retry time, go ahead and fire off another batch.
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (gDisconnected || !region) return;
|
||||
LLViewerRegion * region(gAgent.getRegion());
|
||||
if (! region || gDisconnected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// *TODO: These values could be tweaked at runtime to effect
|
||||
// a fast/slow fetch throttle. Once login is complete and the scene
|
||||
U32 const max_batch_size = 5;
|
||||
|
||||
U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER) & 0x1;
|
||||
|
||||
U32 item_count(0);
|
||||
U32 folder_count(0);
|
||||
|
||||
const U32 sort_order(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER) & 0x1);
|
||||
|
||||
uuid_vec_t recursive_cats;
|
||||
|
||||
U32 folder_count=0;
|
||||
U32 folder_lib_count=0;
|
||||
U32 item_count=0;
|
||||
U32 item_lib_count=0;
|
||||
|
||||
// This function can do up to four requests at once.
|
||||
@@ -633,15 +536,26 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
|
||||
LLSD item_request_body;
|
||||
LLSD item_request_body_lib;
|
||||
|
||||
while (!mFetchQueue.empty())
|
||||
while (! mFetchQueue.empty())
|
||||
{
|
||||
const FetchQueueInfo& fetch_info = mFetchQueue.front();
|
||||
const FetchQueueInfo & fetch_info(mFetchQueue.front());
|
||||
if (fetch_info.mIsCategory)
|
||||
{
|
||||
const LLUUID &cat_id = fetch_info.mUUID;
|
||||
if (!cat_id.isNull())
|
||||
const LLUUID & cat_id(fetch_info.mUUID);
|
||||
if (cat_id.isNull()) //DEV-17797
|
||||
{
|
||||
const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
|
||||
LLSD folder_sd;
|
||||
folder_sd["folder_id"] = LLUUID::null.asString();
|
||||
folder_sd["owner_id"] = gAgent.getID();
|
||||
folder_sd["sort_order"] = LLSD::Integer(sort_order);
|
||||
folder_sd["fetch_folders"] = LLSD::Boolean(FALSE);
|
||||
folder_sd["fetch_items"] = LLSD::Boolean(TRUE);
|
||||
folder_request_body["folders"].append(folder_sd);
|
||||
folder_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id));
|
||||
|
||||
if (cat)
|
||||
{
|
||||
@@ -650,9 +564,9 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
|
||||
LLSD folder_sd;
|
||||
folder_sd["folder_id"] = cat->getUUID();
|
||||
folder_sd["owner_id"] = cat->getOwnerID();
|
||||
folder_sd["sort_order"] = (LLSD::Integer)sort_order;
|
||||
folder_sd["fetch_folders"] = TRUE; //(LLSD::Boolean)sFullFetchStarted;
|
||||
folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
|
||||
folder_sd["sort_order"] = LLSD::Integer(sort_order);
|
||||
folder_sd["fetch_folders"] = LLSD::Boolean(TRUE); //(LLSD::Boolean)sFullFetchStarted;
|
||||
folder_sd["fetch_items"] = LLSD::Boolean(TRUE);
|
||||
|
||||
if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
|
||||
{
|
||||
@@ -680,8 +594,8 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
|
||||
// May already have this folder, but append child folders to list.
|
||||
if (fetch_info.mRecursive)
|
||||
{
|
||||
LLInventoryModel::cat_array_t* categories;
|
||||
LLInventoryModel::item_array_t* items;
|
||||
LLInventoryModel::cat_array_t * categories(NULL);
|
||||
LLInventoryModel::item_array_t * items(NULL);
|
||||
gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items);
|
||||
for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
|
||||
it != categories->end();
|
||||
@@ -691,13 +605,16 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fetch_info.mRecursive)
|
||||
recursive_cats.push_back(cat_id);
|
||||
}
|
||||
if (fetch_info.mRecursive)
|
||||
{
|
||||
recursive_cats.push_back(cat_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLViewerInventoryItem* itemp = gInventory.getItem(fetch_info.mUUID);
|
||||
LLViewerInventoryItem * itemp(gInventory.getItem(fetch_info.mUUID));
|
||||
|
||||
if (itemp)
|
||||
{
|
||||
LLSD item_sd;
|
||||
@@ -735,39 +652,62 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
|
||||
{
|
||||
if (folder_count)
|
||||
{
|
||||
std::string url = region->getCapability("FetchInventoryDescendents2");
|
||||
llassert(!url.empty());
|
||||
++mFetchCount;
|
||||
LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats);
|
||||
LLHTTPClient::post_approved(url, folder_request_body, fetcher, approved_folder);
|
||||
if (folder_request_body["folders"].size())
|
||||
{
|
||||
const std::string url(region->getCapability("FetchInventoryDescendents2"));
|
||||
|
||||
if (! url.empty())
|
||||
{
|
||||
BGFolderHttpHandler * handler(new BGFolderHttpHandler(folder_request_body, recursive_cats));
|
||||
LLHTTPClient::post_approved(url, folder_request_body, handler, approved_folder);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (folder_lib_count)
|
||||
{
|
||||
std::string url = gAgent.getRegion()->getCapability("FetchLibDescendents2");
|
||||
llassert(!url.empty());
|
||||
++mFetchCount;
|
||||
LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats);
|
||||
LLHTTPClient::post_approved(url, folder_request_body_lib, fetcher, approved_folder_lib);
|
||||
if (folder_request_body_lib["folders"].size())
|
||||
{
|
||||
const std::string url(region->getCapability("FetchLibDescendents2"));
|
||||
|
||||
if (! url.empty())
|
||||
{
|
||||
BGFolderHttpHandler * handler(new BGFolderHttpHandler(folder_request_body_lib, recursive_cats));
|
||||
LLHTTPClient::post_approved(url, folder_request_body_lib, handler, approved_folder_lib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (item_count)
|
||||
{
|
||||
std::string url = region->getCapability("FetchInventory2");
|
||||
llassert(!url.empty());
|
||||
++mFetchCount;
|
||||
LLSD body;
|
||||
body["agent_id"] = gAgent.getID();
|
||||
body["items"] = item_request_body;
|
||||
LLHTTPClient::post_approved(url, body, new LLInventoryModelFetchItemResponder(body), approved_item);
|
||||
if (item_request_body.size())
|
||||
{
|
||||
const std::string url(region->getCapability("FetchInventory2"));
|
||||
|
||||
if (! url.empty())
|
||||
{
|
||||
LLSD body;
|
||||
body["agent_id"] = gAgent.getID();
|
||||
body["items"] = item_request_body;
|
||||
BGItemHttpHandler * handler(new BGItemHttpHandler(body));
|
||||
LLHTTPClient::post_approved(url, body, handler, approved_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (item_lib_count)
|
||||
{
|
||||
std::string url = region->getCapability("FetchLib2");
|
||||
llassert(!url.empty());
|
||||
++mFetchCount;
|
||||
LLSD body;
|
||||
body["agent_id"] = gAgent.getID();
|
||||
body["items"] = item_request_body_lib;
|
||||
LLHTTPClient::post_approved(url, body, new LLInventoryModelFetchItemResponder(body), approved_item_lib);
|
||||
if (item_request_body_lib.size())
|
||||
{
|
||||
const std::string url(region->getCapability("FetchLib2"));
|
||||
|
||||
if (! url.empty())
|
||||
{
|
||||
LLSD body;
|
||||
body["agent_id"] = gAgent.getID();
|
||||
body["items"] = item_request_body_lib;
|
||||
BGItemHttpHandler * handler(new BGItemHttpHandler(body));
|
||||
LLHTTPClient::post_approved(url, body, handler, approved_item_lib);
|
||||
}
|
||||
}
|
||||
}
|
||||
mFetchTimer.reset();
|
||||
}
|
||||
@@ -781,7 +721,8 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
|
||||
bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const
|
||||
{
|
||||
for (fetch_queue_t::const_iterator it = mFetchQueue.begin();
|
||||
it != mFetchQueue.end(); ++it)
|
||||
it != mFetchQueue.end();
|
||||
++it)
|
||||
{
|
||||
const LLUUID& fetch_id = (*it).mUUID;
|
||||
if (gInventory.isObjectDescendentOf(fetch_id, cat_id))
|
||||
@@ -789,4 +730,175 @@ bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LL
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// If we get back a normal response, handle it here.
|
||||
void BGFolderHttpHandler::httpSuccess(void)
|
||||
{
|
||||
LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance();
|
||||
const LLSD& content = mContent;
|
||||
// in response as an application-level error.
|
||||
|
||||
// Instead, we assume success and attempt to extract information.
|
||||
if (content.has("folders"))
|
||||
{
|
||||
LLSD folders(content["folders"]);
|
||||
|
||||
for (LLSD::array_const_iterator folder_it = folders.beginArray();
|
||||
folder_it != folders.endArray();
|
||||
++folder_it)
|
||||
{
|
||||
LLSD folder_sd(*folder_it);
|
||||
|
||||
//LLUUID agent_id = folder_sd["agent_id"];
|
||||
|
||||
//if(agent_id != gAgent.getID()) //This should never happen.
|
||||
//{
|
||||
// LL_WARNS(LOG_INV) << "Got a UpdateInventoryItem for the wrong agent."
|
||||
// << LL_ENDL;
|
||||
// break;
|
||||
//}
|
||||
|
||||
LLUUID parent_id(folder_sd["folder_id"].asUUID());
|
||||
LLUUID owner_id(folder_sd["owner_id"].asUUID());
|
||||
S32 version(folder_sd["version"].asInteger());
|
||||
S32 descendents(folder_sd["descendents"].asInteger());
|
||||
LLPointer<LLViewerInventoryCategory> tcategory = new LLViewerInventoryCategory(owner_id);
|
||||
|
||||
if (parent_id.isNull())
|
||||
{
|
||||
LLSD items(folder_sd["items"]);
|
||||
LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
|
||||
|
||||
for (LLSD::array_const_iterator item_it = items.beginArray();
|
||||
item_it != items.endArray();
|
||||
++item_it)
|
||||
{
|
||||
const LLUUID lost_uuid(gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
|
||||
|
||||
if (lost_uuid.notNull())
|
||||
{
|
||||
LLSD item(*item_it);
|
||||
|
||||
titem->unpackMessage(item);
|
||||
|
||||
LLInventoryModel::update_list_t update;
|
||||
LLInventoryModel::LLCategoryUpdate new_folder(lost_uuid, 1);
|
||||
update.push_back(new_folder);
|
||||
gInventory.accountForUpdate(update);
|
||||
|
||||
titem->setParent(lost_uuid);
|
||||
titem->updateParentOnServer(FALSE);
|
||||
gInventory.updateItem(titem);
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLViewerInventoryCategory * pcat(gInventory.getCategory(parent_id));
|
||||
if (! pcat)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LLSD categories(folder_sd["categories"]);
|
||||
for (LLSD::array_const_iterator category_it = categories.beginArray();
|
||||
category_it != categories.endArray();
|
||||
++category_it)
|
||||
{
|
||||
LLSD category(*category_it);
|
||||
tcategory->fromLLSD(category);
|
||||
|
||||
const bool recursive(getIsRecursive(tcategory->getUUID()));
|
||||
if (recursive)
|
||||
{
|
||||
fetcher->addRequestAtBack(tcategory->getUUID(), recursive, true);
|
||||
}
|
||||
else if (! gInventory.isCategoryComplete(tcategory->getUUID()))
|
||||
{
|
||||
gInventory.updateCategory(tcategory);
|
||||
}
|
||||
}
|
||||
|
||||
LLSD items(folder_sd["items"]);
|
||||
LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
|
||||
for (LLSD::array_const_iterator item_it = items.beginArray();
|
||||
item_it != items.endArray();
|
||||
++item_it)
|
||||
{
|
||||
LLSD item(*item_it);
|
||||
titem->unpackMessage(item);
|
||||
|
||||
gInventory.updateItem(titem);
|
||||
}
|
||||
|
||||
// Set version and descendentcount according to message.
|
||||
LLViewerInventoryCategory * cat(gInventory.getCategory(parent_id));
|
||||
if (cat)
|
||||
{
|
||||
cat->setVersion(version);
|
||||
cat->setDescendentCount(descendents);
|
||||
cat->determineFolderType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (content.has("bad_folders"))
|
||||
{
|
||||
LLSD bad_folders(content["bad_folders"]);
|
||||
for (LLSD::array_const_iterator folder_it = bad_folders.beginArray();
|
||||
folder_it != bad_folders.endArray();
|
||||
++folder_it)
|
||||
{
|
||||
// *TODO: Stop copying data [ed: this isn't copying data]
|
||||
LLSD folder_sd(*folder_it);
|
||||
|
||||
// These folders failed on the dataserver. We probably don't want to retry them.
|
||||
LL_WARNS(LOG_INV) << "Folder " << folder_sd["folder_id"].asString()
|
||||
<< "Error: " << folder_sd["error"].asString() << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
if (fetcher->isBulkFetchProcessingComplete())
|
||||
{
|
||||
LL_INFOS() << "Inventory fetch completed" << LL_ENDL;
|
||||
fetcher->setAllFoldersFetched();
|
||||
}
|
||||
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
|
||||
//If we get back an error (not found, etc...), handle it here
|
||||
void BGFolderHttpHandler::httpFailure(void)
|
||||
{
|
||||
LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance();
|
||||
|
||||
LL_INFOS() << "BGFolderHttpHandler::error "
|
||||
<< mStatus << ": " << mReason << LL_ENDL;
|
||||
|
||||
if (is_internal_http_error_that_warrants_a_retry(mStatus)) // timed out
|
||||
{
|
||||
for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray();
|
||||
folder_it != mRequestSD["folders"].endArray();
|
||||
++folder_it)
|
||||
{
|
||||
LLSD folder_sd(*folder_it);
|
||||
LLUUID folder_id(folder_sd["folder_id"].asUUID());
|
||||
const BOOL recursive = getIsRecursive(folder_id);
|
||||
fetcher->addRequestAtFront(folder_id, recursive, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fetcher->isBulkFetchProcessingComplete())
|
||||
{
|
||||
fetcher->setAllFoldersFetched();
|
||||
}
|
||||
}
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
|
||||
BOOL BGFolderHttpHandler::getIsRecursive(const LLUUID& cat_id) const
|
||||
{
|
||||
return (std::find(mRecursiveCatUUIDs.begin(),mRecursiveCatUUIDs.end(), cat_id) != mRecursiveCatUUIDs.end());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,8 +39,6 @@
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
class LLInventoryModelBackgroundFetch : public LLSingleton<LLInventoryModelBackgroundFetch>
|
||||
{
|
||||
friend class LLInventoryModelFetchDescendentsResponder;
|
||||
|
||||
public:
|
||||
LLInventoryModelBackgroundFetch();
|
||||
~LLInventoryModelBackgroundFetch();
|
||||
@@ -61,16 +59,22 @@ public:
|
||||
bool inventoryFetchInProgress() const;
|
||||
|
||||
void findLostItems();
|
||||
void incrFetchCount(S16 fetching);
|
||||
protected:
|
||||
void incrFetchCount(S32 fetching);
|
||||
|
||||
bool isBulkFetchProcessingComplete() const;
|
||||
void setAllFoldersFetched();
|
||||
|
||||
void addRequestAtFront(const LLUUID & id, BOOL recursive, bool is_category);
|
||||
void addRequestAtBack(const LLUUID & id, BOOL recursive, bool is_category);
|
||||
|
||||
protected:
|
||||
void bulkFetch();
|
||||
|
||||
void backgroundFetch();
|
||||
static void backgroundFetchCB(void*); // background fetch idle function
|
||||
|
||||
void setAllFoldersFetched();
|
||||
bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const;
|
||||
|
||||
private:
|
||||
BOOL mRecursiveInventoryFetchStarted;
|
||||
BOOL mRecursiveLibraryFetchStarted;
|
||||
@@ -78,7 +82,7 @@ private:
|
||||
|
||||
BOOL mBackgroundFetchActive; // TRUE if LLInventoryModelBackgroundFetch::backgroundFetchCB is being called from idle().
|
||||
bool mFolderFetchActive;
|
||||
S16 mFetchCount;
|
||||
S32 mFetchCount;
|
||||
BOOL mTimelyFetchPending;
|
||||
S32 mNumFetchRetries;
|
||||
|
||||
@@ -90,8 +94,10 @@ private:
|
||||
|
||||
struct FetchQueueInfo
|
||||
{
|
||||
FetchQueueInfo(const LLUUID& id, BOOL recursive, bool is_category = true) :
|
||||
mUUID(id), mRecursive(recursive), mIsCategory(is_category)
|
||||
FetchQueueInfo(const LLUUID& id, BOOL recursive, bool is_category = true)
|
||||
: mUUID(id),
|
||||
mIsCategory(is_category),
|
||||
mRecursive(recursive)
|
||||
{}
|
||||
LLUUID mUUID;
|
||||
bool mIsCategory;
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "llagent.h"
|
||||
#include "llagentwearables.h"
|
||||
#include "llfloater.h"
|
||||
#include "llfolderview.h"
|
||||
#include "llfocusmgr.h"
|
||||
#include "llinventorybridge.h"
|
||||
#include "llinventoryfunctions.h"
|
||||
@@ -237,7 +238,7 @@ void fetch_items_from_llsd(const LLSD& items_llsd)
|
||||
if (!url.empty())
|
||||
{
|
||||
body[i]["agent_id"] = gAgent.getID();
|
||||
LLHTTPClient::post(url, body[i], new LLInventoryModel::fetchInventoryResponder(body[i]));
|
||||
LLHTTPClient::post(url, body[i], new LLInventoryModel::FetchItemHttpHandler(body[i]));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -464,42 +465,13 @@ void LLInventoryFetchComboObserver::startFetch()
|
||||
mFetchItems->startFetch();
|
||||
mFetchDescendents->startFetch();
|
||||
}
|
||||
|
||||
void LLInventoryExistenceObserver::watchItem(const LLUUID& id)
|
||||
{
|
||||
if (id.notNull())
|
||||
{
|
||||
mMIA.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
void LLInventoryExistenceObserver::changed(U32 mask)
|
||||
{
|
||||
// scan through the incomplete items and move or erase them as
|
||||
// appropriate.
|
||||
if (!mMIA.empty())
|
||||
{
|
||||
for (uuid_vec_t::iterator it = mMIA.begin(); it < mMIA.end(); )
|
||||
{
|
||||
LLViewerInventoryItem* item = gInventory.getItem(*it);
|
||||
if (!item)
|
||||
{
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
mExist.push_back(*it);
|
||||
it = mMIA.erase(it);
|
||||
}
|
||||
if (mMIA.empty())
|
||||
{
|
||||
done();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See comment preceding LLInventoryAddedObserver::changed() for some
|
||||
// concerns that also apply to this observer.
|
||||
void LLInventoryAddItemByAssetObserver::changed(U32 mask)
|
||||
{
|
||||
if(!(mask & LLInventoryObserver::ADD))
|
||||
if(!(mask & LLInventoryObserver::ADD) ||
|
||||
!(mask & LLInventoryObserver::CREATE) ||
|
||||
!(mask & LLInventoryObserver::UPDATE_CREATE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -510,20 +482,12 @@ void LLInventoryAddItemByAssetObserver::changed(U32 mask)
|
||||
return;
|
||||
}
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
if (!(msg->getMessageName() && (0 == strcmp(msg->getMessageName(), "UpdateCreateInventoryItem"))))
|
||||
const uuid_set_t& added = gInventory.getAddedIDs();
|
||||
for (uuid_set_t::iterator it = added.begin(); it != added.end(); ++it)
|
||||
{
|
||||
// this is not our message
|
||||
return; // to prevent a crash. EXT-7921;
|
||||
}
|
||||
|
||||
LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem;
|
||||
S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
|
||||
for(S32 i = 0; i < num_blocks; ++i)
|
||||
{
|
||||
item->unpackMessage(msg, _PREHASH_InventoryData, i);
|
||||
LLInventoryItem *item = gInventory.getItem(*it);
|
||||
const LLUUID& asset_uuid = item->getAssetUUID();
|
||||
if (item->getUUID().notNull() && asset_uuid.notNull())
|
||||
if (item && item->getUUID().notNull() && asset_uuid.notNull())
|
||||
{
|
||||
if (isAssetWatched(asset_uuid))
|
||||
{
|
||||
@@ -535,8 +499,8 @@ void LLInventoryAddItemByAssetObserver::changed(U32 mask)
|
||||
|
||||
if (mAddedItems.size() == mWatchedAssets.size())
|
||||
{
|
||||
done();
|
||||
LL_DEBUGS("Inventory_Move") << "All watched items are added & processed." << LL_ENDL;
|
||||
done();
|
||||
mAddedItems.clear();
|
||||
|
||||
// Unable to clean watched items here due to somebody can require to check them in current frame.
|
||||
@@ -566,41 +530,28 @@ bool LLInventoryAddItemByAssetObserver::isAssetWatched( const LLUUID& asset_id )
|
||||
return std::find(mWatchedAssets.begin(), mWatchedAssets.end(), asset_id) != mWatchedAssets.end();
|
||||
}
|
||||
|
||||
// This observer used to explicitly check for whether it was being
|
||||
// called as a result of an UpdateCreateInventoryItem message. It has
|
||||
// now been decoupled enough that it's not actually checking the
|
||||
// message system, but now we have the special UPDATE_CREATE flag
|
||||
// being used for the same purpose. Fixing this, as we would need to
|
||||
// do to get rid of the message, is somewhat subtle because there's no
|
||||
// particular obvious criterion for when creating a new item should
|
||||
// trigger this observer and when it shouldn't. For example, creating
|
||||
// a new notecard with new->notecard causes a preview window to pop up
|
||||
// via the derived class LLOpenTaskOffer, but creating a new notecard
|
||||
// by copy and paste does not, solely because one goes through
|
||||
// UpdateCreateInventoryItem and the other doesn't.
|
||||
void LLInventoryAddedObserver::changed(U32 mask)
|
||||
{
|
||||
if (!(mask & LLInventoryObserver::ADD))
|
||||
if (!(mask & LLInventoryObserver::ADD) ||
|
||||
!(mask & LLInventoryObserver::CREATE) ||
|
||||
!(mask & LLInventoryObserver::UPDATE_CREATE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// *HACK: If this was in response to a packet off
|
||||
// the network, figure out which item was updated.
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
|
||||
std::string msg_name = msg->getMessageName();
|
||||
if (msg_name.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We only want newly created inventory items. JC
|
||||
if ( msg_name != "UpdateCreateInventoryItem")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
|
||||
S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
|
||||
for (S32 i = 0; i < num_blocks; ++i)
|
||||
{
|
||||
titem->unpackMessage(msg, _PREHASH_InventoryData, i);
|
||||
if (!(titem->getUUID().isNull()))
|
||||
{
|
||||
//we don't do anything with null keys
|
||||
mAdded.push_back(titem->getUUID());
|
||||
}
|
||||
}
|
||||
if (!mAdded.empty())
|
||||
if (!gInventory.getAddedIDs().empty())
|
||||
{
|
||||
done();
|
||||
}
|
||||
@@ -633,58 +584,6 @@ void LLInventoryCategoryAddedObserver::changed(U32 mask)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LLInventoryTransactionObserver::LLInventoryTransactionObserver(const LLTransactionID& transaction_id) :
|
||||
mTransactionID(transaction_id)
|
||||
{
|
||||
}
|
||||
|
||||
void LLInventoryTransactionObserver::changed(U32 mask)
|
||||
{
|
||||
if (mask & LLInventoryObserver::ADD)
|
||||
{
|
||||
// This could be it - see if we are processing a bulk update
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
if (msg->getMessageName()
|
||||
&& (0 == strcmp(msg->getMessageName(), "BulkUpdateInventory")))
|
||||
{
|
||||
// we have a match for the message - now check the
|
||||
// transaction id.
|
||||
LLUUID id;
|
||||
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, id);
|
||||
if (id == mTransactionID)
|
||||
{
|
||||
// woo hoo, we found it
|
||||
uuid_vec_t folders;
|
||||
uuid_vec_t items;
|
||||
S32 count;
|
||||
count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
|
||||
S32 i;
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, id, i);
|
||||
if (id.notNull())
|
||||
{
|
||||
folders.push_back(id);
|
||||
}
|
||||
}
|
||||
count = msg->getNumberOfBlocksFast(_PREHASH_ItemData);
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
msg->getUUIDFast(_PREHASH_ItemData, _PREHASH_ItemID, id, i);
|
||||
if (id.notNull())
|
||||
{
|
||||
items.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
// call the derived class the implements this method.
|
||||
done(folders, items);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLInventoryCategoriesObserver::changed(U32 mask)
|
||||
{
|
||||
if (!mCategoryMap.size())
|
||||
@@ -833,3 +732,23 @@ LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData(
|
||||
{
|
||||
mItemNameHash.finalize();
|
||||
}
|
||||
|
||||
void LLScrollOnRenameObserver::changed(U32 mask)
|
||||
{
|
||||
if (mask & LLInventoryObserver::LABEL)
|
||||
{
|
||||
const uuid_set_t& changed_item_ids = gInventory.getChangedIDs();
|
||||
for (uuid_set_t::const_iterator it = changed_item_ids.begin(); it != changed_item_ids.end(); ++it)
|
||||
{
|
||||
const LLUUID& id = *it;
|
||||
if (id == mUUID)
|
||||
{
|
||||
mView->scrollToShowSelection();
|
||||
|
||||
gInventory.removeObserver(this);
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,10 @@ public:
|
||||
GESTURE = 64,
|
||||
REBUILD = 128, // Item UI changed (e.g. item type different)
|
||||
SORT = 256, // Folder needs to be resorted.
|
||||
DESCRIPTION = 0x10000, // Singu extension to keep track of description changes.
|
||||
CREATE = 512, // With ADD, item has just been created.
|
||||
// unfortunately a particular message is still associated with some unique semantics.
|
||||
UPDATE_CREATE = 1024, // With ADD, item added via UpdateCreateInventoryItem
|
||||
DESCRIPTION = 2048, // Singu extension to keep track of description changes.
|
||||
ALL = 0xffffffff
|
||||
};
|
||||
LLInventoryObserver();
|
||||
@@ -152,25 +155,6 @@ protected:
|
||||
LLInventoryFetchDescendentsObserver *mFetchDescendents;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLInventoryExistenceObserver
|
||||
//
|
||||
// Used as a base class for doing something when all the
|
||||
// observed item ids exist in the inventory somewhere.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
class LLInventoryExistenceObserver : public LLInventoryObserver
|
||||
{
|
||||
public:
|
||||
LLInventoryExistenceObserver() {}
|
||||
/*virtual*/ void changed(U32 mask);
|
||||
|
||||
void watchItem(const LLUUID& id);
|
||||
protected:
|
||||
virtual void done() = 0;
|
||||
uuid_vec_t mExist;
|
||||
uuid_vec_t mMIA;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLInventoryMovedObserver
|
||||
//
|
||||
@@ -210,13 +194,11 @@ private:
|
||||
class LLInventoryAddedObserver : public LLInventoryObserver
|
||||
{
|
||||
public:
|
||||
LLInventoryAddedObserver() : mAdded() {}
|
||||
LLInventoryAddedObserver() {}
|
||||
/*virtual*/ void changed(U32 mask);
|
||||
|
||||
protected:
|
||||
virtual void done() = 0;
|
||||
|
||||
uuid_vec_t mAdded;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -241,25 +223,6 @@ protected:
|
||||
cat_vec_t mAddedCategories;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLInventoryTransactionObserver
|
||||
//
|
||||
// Base class for doing something when an inventory transaction completes.
|
||||
// NOTE: This class is not quite complete. Avoid using unless you fix up its
|
||||
// functionality gaps.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
class LLInventoryTransactionObserver : public LLInventoryObserver
|
||||
{
|
||||
public:
|
||||
LLInventoryTransactionObserver(const LLTransactionID& transaction_id);
|
||||
/*virtual*/ void changed(U32 mask);
|
||||
|
||||
protected:
|
||||
virtual void done(const uuid_vec_t& folders, const uuid_vec_t& items) = 0;
|
||||
|
||||
LLTransactionID mTransactionID;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLInventoryCompletionObserver
|
||||
//
|
||||
@@ -326,4 +289,23 @@ protected:
|
||||
|
||||
category_map_t mCategoryMap;
|
||||
};
|
||||
|
||||
class LLFolderView;
|
||||
|
||||
// Force a FolderView to scroll after an item in the corresponding view has been renamed.
|
||||
class LLScrollOnRenameObserver: public LLInventoryObserver
|
||||
{
|
||||
public:
|
||||
LLFolderView *mView;
|
||||
LLUUID mUUID;
|
||||
|
||||
LLScrollOnRenameObserver(const LLUUID& uuid, LLFolderView *view):
|
||||
mUUID(uuid),
|
||||
mView(view)
|
||||
{
|
||||
}
|
||||
/* virtual */ void changed(U32 mask);
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_LLINVENTORYOBSERVERS_H
|
||||
|
||||
@@ -145,7 +145,8 @@ LLInventoryPanel::LLInventoryPanel(const std::string& name,
|
||||
mInventory(inventory),
|
||||
mAllowMultiSelect(allow_multi_select),
|
||||
mViewsInitialized(false),
|
||||
mInvFVBridgeBuilder(NULL)
|
||||
mInvFVBridgeBuilder(NULL),
|
||||
mGroupedItemBridge(new LLFolderViewGroupedItemBridge)
|
||||
{
|
||||
mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER;
|
||||
|
||||
@@ -172,7 +173,7 @@ void LLInventoryPanel::buildFolderView()
|
||||
else
|
||||
{
|
||||
root_id = (preferred_type != LLFolderType::FT_NONE)
|
||||
? gInventory.findCategoryUUIDForType(preferred_type, false, false)
|
||||
? gInventory.findCategoryUUIDForType(preferred_type, false)
|
||||
: gInventory.getCategory(static_cast<LLUUID>(mStartFolder)) ? static_cast<LLUUID>(mStartFolder) // Singu Note: if start folder is an id of a folder, use it
|
||||
: LLUUID::null;
|
||||
}
|
||||
@@ -695,7 +696,8 @@ LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool u
|
||||
folder_rect,
|
||||
LLUUID::null,
|
||||
this,
|
||||
bridge);
|
||||
bridge,
|
||||
mGroupedItemBridge);
|
||||
ret->setAllowMultiSelect(mAllowMultiSelect);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ class LLTextBox;
|
||||
class LLIconCtrl;
|
||||
class LLSaveFolderState;
|
||||
class LLInvPanelComplObserver;
|
||||
class LLFolderViewGroupedItemBridge;
|
||||
|
||||
class LLInventoryPanel : public LLPanel
|
||||
{
|
||||
@@ -169,6 +170,7 @@ protected:
|
||||
LLHandle<LLFolderView> mFolderRoot;
|
||||
LLScrollContainer* mScroller;
|
||||
|
||||
LLPointer<LLFolderViewGroupedItemBridge> mGroupedItemBridge;
|
||||
/**
|
||||
* Pointer to LLInventoryFVBridgeBuilder.
|
||||
*
|
||||
|
||||
@@ -771,7 +771,8 @@ BOOL LLPanelEditWearable::postBuild()
|
||||
|
||||
if (mTab = findChild<LLTabContainer>("layer_tabs"))
|
||||
{
|
||||
for(U32 i = 1; i <= LLAgentWearables::MAX_CLOTHING_PER_TYPE; ++i)
|
||||
LL_COMPILE_TIME_MESSAGE("layer_tabs needs re-implemented");
|
||||
for(U32 i = 1; i <= 6/*LLAgentWearables::MAX_CLOTHING_PER_TYPE*/; ++i)
|
||||
{
|
||||
LLPanel* new_panel = new LLPanel(llformat("%i",i));
|
||||
mTab->addTabPanel(new_panel, llformat("Layer %i",i));
|
||||
@@ -1008,15 +1009,13 @@ void LLPanelEditWearable::refreshWearables(bool force_immediate)
|
||||
U32 index;
|
||||
if (mPendingWearable)
|
||||
{
|
||||
index = gAgentWearables.getWearableIndex(mPendingWearable);
|
||||
if (index == LLAgentWearables::MAX_CLOTHING_PER_TYPE)
|
||||
if (!gAgentWearables.getWearableIndex(mPendingWearable, index))
|
||||
return;
|
||||
mPendingWearable = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = gAgentWearables.getWearableIndex(getWearable());
|
||||
if (index == LLAgentWearables::MAX_CLOTHING_PER_TYPE)
|
||||
if (!gAgentWearables.getWearableIndex(mPendingWearable, index))
|
||||
{
|
||||
index = gAgentWearables.getWearableCount(mType);
|
||||
if (index)
|
||||
@@ -1026,7 +1025,8 @@ void LLPanelEditWearable::refreshWearables(bool force_immediate)
|
||||
|
||||
if (mTab)
|
||||
{
|
||||
for(U32 i = 0; i < LLAgentWearables::MAX_CLOTHING_PER_TYPE; ++i)
|
||||
LL_COMPILE_TIME_MESSAGE("layer_tabs needs re-implemented");
|
||||
for(U32 i = 0; i < 6/*LLAgentWearables::MAX_CLOTHING_PER_TYPE*/; ++i)
|
||||
{
|
||||
mTab->enableTabButton(i, i < gAgentWearables.getWearableCount(mType));
|
||||
}
|
||||
@@ -1168,10 +1168,13 @@ void LLPanelEditWearable::setNewImageID(ETextureIndex te_index, LLUUID const& uu
|
||||
}
|
||||
if (getWearable())
|
||||
{
|
||||
U32 index = gAgentWearables.getWearableIndex(getWearable());
|
||||
gAgentAvatarp->setLocalTexture(te_index, image, FALSE, index);
|
||||
LLVisualParamHint::requestHintUpdates();
|
||||
gAgentAvatarp->wearableUpdated(mType, FALSE);
|
||||
U32 index;
|
||||
if (gAgentWearables.getWearableIndex(getWearable(), index))
|
||||
{
|
||||
gAgentAvatarp->setLocalTexture(te_index, image, FALSE, index);
|
||||
LLVisualParamHint::requestHintUpdates();
|
||||
gAgentAvatarp->wearableUpdated(mType, FALSE);
|
||||
}
|
||||
}
|
||||
if (mType == LLWearableType::WT_ALPHA && image->getID() != IMG_INVISIBLE)
|
||||
{
|
||||
@@ -1230,7 +1233,8 @@ void LLPanelEditWearable::saveChanges(bool force_save_as, std::string new_name)
|
||||
return;
|
||||
}
|
||||
|
||||
U32 index = gAgentWearables.getWearableIndex(getWearable());
|
||||
U32 index;
|
||||
gAgentWearables.getWearableIndex(getWearable(), index);
|
||||
|
||||
// Find an existing link to this wearable's inventory item, if any, and its description field.
|
||||
LLInventoryItem *link_item = NULL;
|
||||
@@ -1271,15 +1275,11 @@ void LLPanelEditWearable::saveChanges(bool force_save_as, std::string new_name)
|
||||
if (link_item)
|
||||
{
|
||||
// Create new link
|
||||
link_inventory_item( gAgent.getID(),
|
||||
link_item->getLinkedUUID(),
|
||||
LLAppearanceMgr::instance().getCOF(),
|
||||
link_item->getName(),
|
||||
description,
|
||||
LLAssetType::AT_LINK,
|
||||
link_inventory_object( LLAppearanceMgr::instance().getCOF(),
|
||||
link_item,
|
||||
NULL);
|
||||
// Remove old link
|
||||
gInventory.purgeObject(link_item->getUUID());
|
||||
|
||||
remove_inventory_item(link_item, NULL);
|
||||
}
|
||||
gAgentWearables.saveWearable(mType, index, TRUE, new_name);
|
||||
}
|
||||
@@ -1543,9 +1543,12 @@ void LLPanelEditWearable::onInvisibilityCommit(LLUICtrl* ctrl, LLAvatarAppearanc
|
||||
mPreviousAlphaTexture[te] = lto->getID();
|
||||
|
||||
LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( IMG_INVISIBLE );
|
||||
U32 index = gAgentWearables.getWearableIndex(getWearable());
|
||||
gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
|
||||
gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE);
|
||||
U32 index;
|
||||
if (gAgentWearables.getWearableIndex(getWearable(), index))
|
||||
{
|
||||
gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
|
||||
gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1563,9 +1566,12 @@ void LLPanelEditWearable::onInvisibilityCommit(LLUICtrl* ctrl, LLAvatarAppearanc
|
||||
if (!image)
|
||||
return;
|
||||
|
||||
U32 index = gAgentWearables.getWearableIndex(getWearable());
|
||||
gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
|
||||
gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE);
|
||||
U32 index;
|
||||
if (gAgentWearables.getWearableIndex(getWearable(), index))
|
||||
{
|
||||
gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
|
||||
gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -903,6 +903,11 @@ void LLInventoryView::toggleFindOptions()
|
||||
}
|
||||
}
|
||||
|
||||
LLFolderView* LLInventoryView::getRootFolder() const
|
||||
{
|
||||
return mActivePanel ? (mActivePanel->getRootFolder()) : NULL;
|
||||
}
|
||||
|
||||
void LLInventoryView::setSelectCallback(const LLFolderView::signal_t::slot_type& cb)
|
||||
{
|
||||
getChild<LLInventoryPanel>("All Items")->setSelectCallback(cb);
|
||||
|
||||
@@ -87,6 +87,7 @@ public:
|
||||
LLInventoryPanel* getPanel() { return mActivePanel; }
|
||||
LLInventoryPanel* getActivePanel() { return mActivePanel; }
|
||||
const LLInventoryPanel* getActivePanel() const { return mActivePanel; }
|
||||
LLFolderView* getRootFolder() const;
|
||||
|
||||
const std::string& getFilterText() const { return mFilterText; }
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ void LLOutboxInventoryPanel::buildFolderView(/*const LLInventoryPanel::Params& p
|
||||
// Determine the root folder in case specified, and
|
||||
// build the views starting with that folder.
|
||||
|
||||
LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false);
|
||||
LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
|
||||
|
||||
if (root_id == LLUUID::null)
|
||||
{
|
||||
|
||||
@@ -495,13 +495,6 @@ void LLPreview::onDiscardBtn(void* data)
|
||||
self->mForceClose = TRUE;
|
||||
self->close();
|
||||
|
||||
// Delete the item entirely
|
||||
/*
|
||||
item->removeFromServer();
|
||||
gInventory.deleteObject(item->getUUID());
|
||||
gInventory.notifyObservers();
|
||||
*/
|
||||
|
||||
// Move the item to the trash
|
||||
LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
if (item->getParentUUID() != trash_id)
|
||||
|
||||
@@ -380,6 +380,13 @@ void update_texture_fetch()
|
||||
gTextureList.updateImages(0.10f);
|
||||
}
|
||||
|
||||
void set_flags_and_update_appearance()
|
||||
{
|
||||
LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true);
|
||||
LLAppearanceMgr::instance().updateAppearanceFromCOF(true, true, no_op);
|
||||
}
|
||||
|
||||
|
||||
void hooked_process_sound_trigger(LLMessageSystem *msg, void **)
|
||||
{
|
||||
process_sound_trigger(msg,NULL);
|
||||
@@ -2247,11 +2254,16 @@ bool idle_startup()
|
||||
// This method MUST be called before gInventory.findCategoryUUIDForType because of
|
||||
// gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap.
|
||||
gInventory.buildParentChildMap();
|
||||
display_startup();
|
||||
gInventory.createCommonSystemCategories();
|
||||
|
||||
/*llinfos << "Setting Inventory changed mask and notifying observers" << llendl;
|
||||
// It's debatable whether this flag is a good idea - sets all
|
||||
// bits, and in general it isn't true that inventory
|
||||
// initialization generates all types of changes. Maybe add an
|
||||
// INITIALIZE mask bit instead?
|
||||
gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
|
||||
gInventory.notifyObservers();*/
|
||||
gInventory.notifyObservers();
|
||||
|
||||
display_startup();
|
||||
|
||||
//all categories loaded. lets create "My Favorites" category
|
||||
gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true);
|
||||
@@ -2565,15 +2577,35 @@ bool idle_startup()
|
||||
// Start loading the wearables, textures, gestures
|
||||
LLStartUp::loadInitialOutfit( sInitialOutfit, sInitialOutfitGender );
|
||||
}
|
||||
// If not first login, we need to fetch COF contents and
|
||||
// compute appearance from that.
|
||||
if (isAgentAvatarValid() && !gAgent.isFirstLogin() && !gAgent.isGenderChosen())
|
||||
{
|
||||
gAgentWearables.notifyLoadingStarted();
|
||||
gAgent.setGenderChosen(TRUE);
|
||||
gAgentWearables.sendDummyAgentWearablesUpdate();
|
||||
callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(), set_flags_and_update_appearance);
|
||||
}
|
||||
|
||||
display_startup();
|
||||
|
||||
// wait precache-delay and for agent's avatar or a lot longer.
|
||||
if(((timeout_frac > 1.f) && isAgentAvatarValid())
|
||||
|| (timeout_frac > 3.f))
|
||||
if((timeout_frac > 1.f) && isAgentAvatarValid())
|
||||
{
|
||||
LLStartUp::setStartupState( STATE_WEARABLES_WAIT );
|
||||
}
|
||||
else if (timeout_frac > 10.f)
|
||||
{
|
||||
// If we exceed the wait above while isAgentAvatarValid is
|
||||
// not true yet, we will change startup state and
|
||||
// eventually (once avatar does get created) wind up at
|
||||
// the gender chooser. This should occur only in very
|
||||
// unusual circumstances, so set the timeout fairly high
|
||||
// to minimize mistaken hits here.
|
||||
LL_WARNS() << "Wait for valid avatar state exceeded "
|
||||
<< timeout.getElapsedTimeF32() << " will invoke gender chooser" << LL_ENDL;
|
||||
LLStartUp::setStartupState( STATE_WEARABLES_WAIT );
|
||||
}
|
||||
else
|
||||
{
|
||||
update_texture_fetch();
|
||||
@@ -4096,7 +4128,10 @@ bool process_login_success_response(std::string& password, U32& first_sim_size_x
|
||||
flag = login_flags["gendered"].asString();
|
||||
if(flag == "Y")
|
||||
{
|
||||
gAgent.setGenderChosen(TRUE);
|
||||
// We don't care about this flag anymore; now base whether
|
||||
// outfit is chosen on COF contents, initial outfit
|
||||
// requested and available, etc.
|
||||
//gAgent.setGenderChosen(TRUE);
|
||||
}
|
||||
|
||||
flag = login_flags["daylight_savings"].asString();
|
||||
|
||||
@@ -803,7 +803,7 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,
|
||||
if ( !handled )
|
||||
{
|
||||
// Disallow drag and drop to 3D from the outbox
|
||||
const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false);
|
||||
const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
|
||||
if (outbox_id.notNull())
|
||||
{
|
||||
for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -115,14 +115,13 @@ public:
|
||||
void cloneViewerItem(LLPointer<LLViewerInventoryItem>& newitem) const;
|
||||
|
||||
// virtual methods
|
||||
virtual void removeFromServer( void );
|
||||
virtual void updateParentOnServer(BOOL restamp) const;
|
||||
virtual void updateServer(BOOL is_new) const;
|
||||
void fetchFromServer(void) const;
|
||||
|
||||
//virtual void packMessage(LLMessageSystem* msg) const;
|
||||
virtual void packMessage(LLMessageSystem* msg) const;
|
||||
virtual BOOL unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0);
|
||||
virtual BOOL unpackMessage(LLSD item);
|
||||
virtual BOOL unpackMessage(const LLSD& item);
|
||||
virtual BOOL importFile(LLFILE* fp);
|
||||
virtual BOOL importLegacyStream(std::istream& input_stream);
|
||||
|
||||
@@ -137,7 +136,6 @@ public:
|
||||
void setComplete(BOOL complete) { mIsComplete = complete; }
|
||||
//void updateAssetOnServer() const;
|
||||
|
||||
virtual void packMessage(LLMessageSystem* msg) const;
|
||||
virtual void setTransactionID(const LLTransactionID& transaction_id);
|
||||
struct comparePointers
|
||||
{
|
||||
@@ -201,16 +199,17 @@ public:
|
||||
LLViewerInventoryCategory(const LLViewerInventoryCategory* other);
|
||||
void copyViewerCategory(const LLViewerInventoryCategory* other);
|
||||
|
||||
virtual void removeFromServer();
|
||||
virtual void updateParentOnServer(BOOL restamp_children) const;
|
||||
virtual void updateServer(BOOL is_new) const;
|
||||
|
||||
virtual void packMessage(LLMessageSystem* msg) const;
|
||||
|
||||
const LLUUID& getOwnerID() const { return mOwnerID; }
|
||||
|
||||
// Version handling
|
||||
enum { VERSION_UNKNOWN = -1, VERSION_INITIAL = 1 };
|
||||
S32 getVersion() const { return mVersion; }
|
||||
void setVersion(S32 version) { mVersion = version; }
|
||||
S32 getVersion() const;
|
||||
void setVersion(S32 version);
|
||||
|
||||
// Returns true if a fetch was issued.
|
||||
bool fetch();
|
||||
@@ -221,6 +220,8 @@ public:
|
||||
enum { DESCENDENT_COUNT_UNKNOWN = -1 };
|
||||
S32 getDescendentCount() const { return mDescendentCount; }
|
||||
void setDescendentCount(S32 descendents) { mDescendentCount = descendents; }
|
||||
// How many descendents do we currently have information for in the InventoryModel?
|
||||
S32 getViewerDescendentCount() const;
|
||||
|
||||
// file handling on the viewer. These are not meant for anything
|
||||
// other than caching.
|
||||
@@ -228,6 +229,8 @@ public:
|
||||
bool importFileLocal(LLFILE* fp);
|
||||
void determineFolderType();
|
||||
void changeType(LLFolderType::EType new_folder_type);
|
||||
virtual void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0);
|
||||
virtual BOOL unpackMessage(const LLSD& category);
|
||||
|
||||
private:
|
||||
friend class LLInventoryModel;
|
||||
@@ -250,7 +253,7 @@ class LLViewerJointAttachment;
|
||||
|
||||
//void rez_attachment_cb(const LLUUID& inv_item, LLViewerJointAttachment *attachmentp);
|
||||
// [SL:KB] - Patch: Appearance-DnDWear | Checked: 2010-09-28 (Catznip-3.0.0a) | Added: Catznip-2.2.0a
|
||||
void rez_attachment_cb(const LLUUID& inv_item, LLViewerJointAttachment *attachmentp, bool replace);
|
||||
void rez_attachment_cb(const LLUUID& inv_item, LLViewerJointAttachment *attachmentp, bool replace = false);
|
||||
// [/SL:KB]
|
||||
|
||||
void activate_gesture_cb(const LLUUID& inv_item);
|
||||
@@ -270,9 +273,11 @@ private:
|
||||
};
|
||||
|
||||
typedef boost::function<void(const LLUUID&)> inventory_func_type;
|
||||
void no_op_inventory_func(const LLUUID&); // A do-nothing inventory_func
|
||||
|
||||
typedef boost::function<void(const LLSD&)> llsd_func_type;
|
||||
typedef boost::function<void()> nullary_func_type;
|
||||
|
||||
void no_op_inventory_func(const LLUUID&); // A do-nothing inventory_func
|
||||
void no_op_llsd_func(const LLSD&); // likewise for LLSD
|
||||
void no_op(); // A do-nothing nullary func.
|
||||
|
||||
// Shim between inventory callback and boost function/callable
|
||||
@@ -280,7 +285,7 @@ class LLBoostFuncInventoryCallback: public LLInventoryCallback
|
||||
{
|
||||
public:
|
||||
|
||||
LLBoostFuncInventoryCallback(inventory_func_type fire_func,
|
||||
LLBoostFuncInventoryCallback(inventory_func_type fire_func = no_op_inventory_func,
|
||||
nullary_func_type destroy_func = no_op):
|
||||
mFireFunc(fire_func),
|
||||
mDestroyFunc(destroy_func)
|
||||
@@ -354,14 +359,16 @@ void copy_inventory_item(
|
||||
const std::string& new_name,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
void link_inventory_item(
|
||||
const LLUUID& agent_id,
|
||||
const LLUUID& item_id,
|
||||
const LLUUID& parent_id,
|
||||
const std::string& new_name,
|
||||
const std::string& new_description,
|
||||
const LLAssetType::EType asset_type,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
// utility functions for inventory linking.
|
||||
void link_inventory_object(const LLUUID& category,
|
||||
LLConstPointer<LLInventoryObject> baseobj,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
void link_inventory_object(const LLUUID& category,
|
||||
const LLUUID& id,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
void link_inventory_array(const LLUUID& category,
|
||||
LLInventoryObject::const_object_list_t& baseobj_array,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
void move_inventory_item(
|
||||
const LLUUID& agent_id,
|
||||
@@ -371,6 +378,46 @@ void move_inventory_item(
|
||||
const std::string& new_name,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
void update_inventory_item(
|
||||
LLViewerInventoryItem *update_item,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
void update_inventory_item(
|
||||
const LLUUID& item_id,
|
||||
const LLSD& updates,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
void update_inventory_category(
|
||||
const LLUUID& cat_id,
|
||||
const LLSD& updates,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
void remove_inventory_items(
|
||||
LLInventoryObject::object_list_t& items,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
void remove_inventory_item(
|
||||
LLPointer<LLInventoryObject> obj,
|
||||
LLPointer<LLInventoryCallback> cb,
|
||||
bool immediate_delete = false);
|
||||
|
||||
void remove_inventory_item(
|
||||
const LLUUID& item_id,
|
||||
LLPointer<LLInventoryCallback> cb,
|
||||
bool immediate_delete = false);
|
||||
|
||||
void remove_inventory_category(
|
||||
const LLUUID& cat_id,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
void remove_inventory_object(
|
||||
const LLUUID& object_id,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
void purge_descendents_of(
|
||||
const LLUUID& cat_id,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
const LLUUID get_folder_by_itemtype(const LLInventoryItem *src);
|
||||
|
||||
void copy_inventory_from_notecard(const LLUUID& destination_id,
|
||||
@@ -385,4 +432,11 @@ void menu_create_inventory_item(LLFolderView* root,
|
||||
const LLSD& userdata,
|
||||
const LLUUID& default_parent_uuid = LLUUID::null);
|
||||
|
||||
void slam_inventory_folder(const LLUUID& folder_id,
|
||||
const LLSD& contents,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
void remove_folder_contents(const LLUUID& folder_id, bool keep_outfit_links,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
#endif // LL_LLVIEWERINVENTORY_H
|
||||
|
||||
@@ -1483,7 +1483,7 @@ void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string
|
||||
|
||||
// postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here.
|
||||
size_t size = openid_token.size();
|
||||
char* data = new char[size];
|
||||
U8* data = new U8[size];
|
||||
memcpy(data, openid_token.data(), size);
|
||||
|
||||
LLHTTPClient::postRaw(
|
||||
|
||||
@@ -986,7 +986,12 @@ class LLOpenTaskOffer : public LLInventoryAddedObserver
|
||||
protected:
|
||||
/*virtual*/ void done()
|
||||
{
|
||||
for (uuid_vec_t::iterator it = mAdded.begin(); it != mAdded.end();)
|
||||
uuid_vec_t added;
|
||||
for(uuid_set_t::const_iterator it = gInventory.getAddedIDs().begin(); it != gInventory.getAddedIDs().end(); ++it)
|
||||
{
|
||||
added.push_back(*it);
|
||||
}
|
||||
for (uuid_vec_t::iterator it = added.begin(); it != added.end();)
|
||||
{
|
||||
const LLUUID& item_uuid = *it;
|
||||
bool was_moved = false;
|
||||
@@ -1008,13 +1013,12 @@ protected:
|
||||
|
||||
if (was_moved)
|
||||
{
|
||||
it = mAdded.erase(it);
|
||||
it = added.erase(it);
|
||||
}
|
||||
else ++it;
|
||||
}
|
||||
|
||||
open_inventory_offer(mAdded, "");
|
||||
mAdded.clear();
|
||||
open_inventory_offer(added, "");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1023,8 +1027,12 @@ class LLOpenTaskGroupOffer : public LLInventoryAddedObserver
|
||||
protected:
|
||||
/*virtual*/ void done()
|
||||
{
|
||||
open_inventory_offer(mAdded, "group_offer");
|
||||
mAdded.clear();
|
||||
uuid_vec_t added;
|
||||
for(uuid_set_t::const_iterator it = gInventory.getAddedIDs().begin(); it != gInventory.getAddedIDs().end(); ++it)
|
||||
{
|
||||
added.push_back(*it);
|
||||
}
|
||||
open_inventory_offer(added, "group_offer");
|
||||
gInventory.removeObserver(this);
|
||||
delete this;
|
||||
}
|
||||
@@ -1058,6 +1066,13 @@ void start_new_inventory_observer()
|
||||
gInventoryMoveObserver = new LLViewerInventoryMoveFromWorldObserver;
|
||||
gInventory.addObserver(gInventoryMoveObserver);
|
||||
}
|
||||
|
||||
if (!gNewInventoryHintObserver)
|
||||
{
|
||||
// Observer is deleted by gInventory
|
||||
gNewInventoryHintObserver = new LLNewInventoryHintObserver();
|
||||
gInventory.addObserver(gNewInventoryHintObserver);
|
||||
}
|
||||
}
|
||||
|
||||
class LLDiscardAgentOffer : public LLInventoryFetchItemsObserver
|
||||
|
||||
@@ -143,6 +143,7 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco
|
||||
{
|
||||
gAgentAvatarp = new LLVOAvatarSelf(id, pcode, regionp);
|
||||
gAgentAvatarp->initInstance();
|
||||
gAgentWearables.setAvatarObject(gAgentAvatarp);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2548,8 +2549,8 @@ void LLViewerObject::dirtyInventory()
|
||||
mInventory->clear(); // will deref and delete entries
|
||||
delete mInventory;
|
||||
mInventory = NULL;
|
||||
mInventoryDirty = TRUE;
|
||||
}
|
||||
mInventoryDirty = TRUE;
|
||||
}
|
||||
|
||||
void LLViewerObject::registerInventoryListener(LLVOInventoryListener* listener, void* user_data)
|
||||
@@ -2586,12 +2587,15 @@ void LLViewerObject::clearInventoryListeners()
|
||||
|
||||
void LLViewerObject::requestInventory()
|
||||
{
|
||||
mInventoryDirty = FALSE;
|
||||
if(mInventoryDirty && mInventory && !mInventoryCallbacks.empty())
|
||||
{
|
||||
mInventory->clear(); // will deref and delete entries
|
||||
delete mInventory;
|
||||
mInventory = NULL;
|
||||
mInventoryDirty = FALSE; //since we are going to request it now
|
||||
}
|
||||
if(mInventory)
|
||||
{
|
||||
//mInventory->clear() // will deref and delete it
|
||||
//delete mInventory;
|
||||
//mInventory = NULL;
|
||||
doInventoryCallback();
|
||||
}
|
||||
// throw away duplicate requests
|
||||
@@ -5897,6 +5901,11 @@ void LLViewerObject::resetChildrenPosition(const LLVector3& offset, BOOL simplif
|
||||
return ;
|
||||
}
|
||||
|
||||
// virtual
|
||||
BOOL LLViewerObject::isTempAttachment() const
|
||||
{
|
||||
return (mID.notNull() && (mID == mAttachmentItemID));
|
||||
}
|
||||
|
||||
// <edit>
|
||||
std::string LLViewerObject::getAttachmentPointName()
|
||||
|
||||
@@ -179,6 +179,7 @@ public:
|
||||
virtual BOOL isAttachment() const { return FALSE; }
|
||||
virtual LLVOAvatar* getAvatar() const; //get the avatar this object is attached to, or NULL if object is not an attachment
|
||||
virtual BOOL isHUDAttachment() const { return FALSE; }
|
||||
virtual BOOL isTempAttachment() const;
|
||||
virtual void updateRadius() {};
|
||||
virtual F32 getVObjRadius() const; // default implemenation is mDrawable->getRadius()
|
||||
|
||||
@@ -824,7 +825,7 @@ public:
|
||||
BOOL getLastUpdateCached() const;
|
||||
void setLastUpdateCached(BOOL last_update_cached);
|
||||
private:
|
||||
LLUUID mAttachmentItemID; // ItemID when item is in user inventory.
|
||||
LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory.
|
||||
EObjectUpdateType mLastUpdateType;
|
||||
BOOL mLastUpdateCached;
|
||||
};
|
||||
|
||||
@@ -385,7 +385,7 @@ void LLViewerWearable::writeToAvatar(LLAvatarAppearance *avatarp)
|
||||
|
||||
// Updates the user's avatar's appearance, replacing this wearables' parameters and textures with default values.
|
||||
// static
|
||||
void LLViewerWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload_bake )
|
||||
void LLViewerWearable::removeFromAvatar( LLWearableType::EType type, bool upload_bake )
|
||||
{
|
||||
if (!isAgentAvatarValid()) return;
|
||||
|
||||
@@ -507,7 +507,7 @@ void LLViewerWearable::revertValues()
|
||||
{
|
||||
panel->updateScrollingPanelList();
|
||||
}*/
|
||||
if( LLFloaterCustomize::instanceExists() && gAgentWearables.getWearableIndex(this)==0 )
|
||||
if (LLFloaterCustomize::instanceExists() && LLFloaterCustomize::getInstance()->getCurrentWearablePanel()->getWearable() == this)
|
||||
LLFloaterCustomize::getInstance()->updateScrollingPanelList();
|
||||
|
||||
}
|
||||
@@ -522,7 +522,7 @@ void LLViewerWearable::saveValues()
|
||||
panel->updateScrollingPanelList();
|
||||
}*/
|
||||
|
||||
if( LLFloaterCustomize::instanceExists() && gAgentWearables.getWearableIndex(this)==0)
|
||||
if (LLFloaterCustomize::instanceExists() && LLFloaterCustomize::getInstance()->getCurrentWearablePanel()->getWearable() == this)
|
||||
LLFloaterCustomize::getInstance()->updateScrollingPanelList();
|
||||
}
|
||||
|
||||
|
||||
@@ -63,8 +63,8 @@ public:
|
||||
BOOL isOldVersion() const;
|
||||
|
||||
/*virtual*/ void writeToAvatar(LLAvatarAppearance *avatarp);
|
||||
void removeFromAvatar( BOOL upload_bake ) { LLViewerWearable::removeFromAvatar( mType, upload_bake ); }
|
||||
static void removeFromAvatar( LLWearableType::EType type, BOOL upload_bake );
|
||||
void removeFromAvatar( bool upload_bake = false ) { LLViewerWearable::removeFromAvatar( mType, upload_bake ); }
|
||||
static void removeFromAvatar( LLWearableType::EType type, bool upload_bake = false);
|
||||
|
||||
/*virtual*/ EImportResult importStream( std::istream& input_stream, LLAvatarAppearance* avatarp );
|
||||
|
||||
|
||||
@@ -1078,6 +1078,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
||||
mIsEditingAppearance(FALSE),
|
||||
mUseLocalAppearance(FALSE),
|
||||
mUseServerBakes(FALSE), // FIXME DRANO consider using boost::optional, defaulting to unknown.
|
||||
mLastUpdateRequestCOFVersion(-1),
|
||||
mLastUpdateReceivedCOFVersion(-1),
|
||||
// <edit>
|
||||
mHasPhysicsParameters( false ),
|
||||
mIdleMinute(0),
|
||||
@@ -1144,6 +1146,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
||||
mRuthTimer.reset();
|
||||
mRuthDebugTimer.reset();
|
||||
mDebugExistenceTimer.reset();
|
||||
mLastAppearanceMessageTimer.reset();
|
||||
mPelvisOffset = LLVector3(0.0f,0.0f,0.0f);
|
||||
mLastPelvisToFoot = 0.0f;
|
||||
mPelvisFixup = 0.0f;
|
||||
@@ -3831,10 +3834,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
||||
mUseServerBakes, central_bake_version);
|
||||
std::string origin_string = bakedTextureOriginInfo();
|
||||
debug_line += " [" + origin_string + "]";
|
||||
const LLAppearanceMgr& appmgr(LLAppearanceMgr::instance());
|
||||
S32 curr_cof_version = appmgr.getCOFVersion();
|
||||
S32 last_request_cof_version = appmgr.getLastUpdateRequestCOFVersion();
|
||||
S32 last_received_cof_version = appmgr.getLastAppearanceUpdateCOFVersion();
|
||||
S32 curr_cof_version = LLAppearanceMgr::instance().getCOFVersion();
|
||||
S32 last_request_cof_version = mLastUpdateRequestCOFVersion;
|
||||
S32 last_received_cof_version = mLastUpdateReceivedCOFVersion;
|
||||
if (isSelf())
|
||||
{
|
||||
debug_line += llformat(" - cof: %d req: %d rcv:%d",
|
||||
@@ -3854,6 +3856,13 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
||||
debug_line += llformat(" %s", (mIsSitting ? "S" : "T"));
|
||||
debug_line += llformat("%s", (isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED) ? "G" : "-"));
|
||||
}
|
||||
F32 elapsed = mLastAppearanceMessageTimer.getElapsedTimeF32();
|
||||
static const char *elapsed_chars = "Xx*...";
|
||||
U32 bucket = U32(elapsed*2);
|
||||
if (bucket < strlen(elapsed_chars))
|
||||
{
|
||||
debug_line += llformat(" %c", elapsed_chars[bucket]);
|
||||
}
|
||||
addDebugText(debug_line);
|
||||
}
|
||||
if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked"))
|
||||
@@ -6350,7 +6359,7 @@ BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable)
|
||||
//-----------------------------------------------------------------------------
|
||||
// updateSexDependentLayerSets()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLVOAvatar::updateSexDependentLayerSets( BOOL upload_bake )
|
||||
void LLVOAvatar::updateSexDependentLayerSets( bool upload_bake )
|
||||
{
|
||||
invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
|
||||
invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, upload_bake );
|
||||
@@ -6958,6 +6967,29 @@ const std::string LLVOAvatar::getAttachedPointName(const LLUUID& inv_item_id)
|
||||
return LLStringUtil::null;
|
||||
}
|
||||
|
||||
LLViewerObject * LLVOAvatar::findAttachmentByID( const LLUUID & target_id ) const
|
||||
{
|
||||
for(attachment_map_t::const_iterator attachment_points_iter = mAttachmentPoints.begin();
|
||||
attachment_points_iter != gAgentAvatarp->mAttachmentPoints.end();
|
||||
++attachment_points_iter)
|
||||
{
|
||||
LLViewerJointAttachment* attachment = attachment_points_iter->second;
|
||||
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 &&
|
||||
attached_object->getID() == target_id)
|
||||
{
|
||||
return attached_object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result )
|
||||
{
|
||||
@@ -7936,7 +7968,8 @@ void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix,
|
||||
LLVisualParam* param = getFirstVisualParam();
|
||||
for (S32 i = 0; i < (S32)params_for_dump.size(); i++)
|
||||
{
|
||||
while( param && (param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
|
||||
while( param && ((param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) &&
|
||||
(param->getGroup() != VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE)) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
|
||||
{
|
||||
param = getNextVisualParam();
|
||||
}
|
||||
@@ -8017,7 +8050,8 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
|
||||
{
|
||||
for( S32 i = 0; i < num_blocks; i++ )
|
||||
{
|
||||
while( param && (param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
|
||||
while( param && ((param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) &&
|
||||
(param->getGroup() != VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE)) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
|
||||
{
|
||||
param = getNextVisualParam();
|
||||
}
|
||||
@@ -8038,7 +8072,8 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
|
||||
}
|
||||
}
|
||||
|
||||
const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
|
||||
const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE) +
|
||||
getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
|
||||
if (num_blocks != expected_tweakable_count)
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "Number of params in AvatarAppearance msg (" << num_blocks << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << "). Processing what we can. object: " << getID() << LL_ENDL;
|
||||
@@ -8114,6 +8149,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
|
||||
return;
|
||||
}
|
||||
|
||||
mLastAppearanceMessageTimer.reset();
|
||||
|
||||
ESex old_sex = getSex();
|
||||
|
||||
LLAppearanceMessageContents contents;
|
||||
@@ -8130,8 +8167,14 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
|
||||
return;
|
||||
}
|
||||
|
||||
if (appearance_version > 1)
|
||||
{
|
||||
LL_WARNS() << "unsupported appearance version " << appearance_version << ", discarding appearance message" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
S32 this_update_cof_version = contents.mCOFVersion;
|
||||
S32 last_update_request_cof_version = LLAppearanceMgr::instance().mLastUpdateRequestCOFVersion;
|
||||
S32 last_update_request_cof_version = mLastUpdateRequestCOFVersion;
|
||||
|
||||
// Only now that we have result of appearance_version can we decide whether to bail out.
|
||||
if( isSelf() )
|
||||
@@ -8140,8 +8183,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
|
||||
<< " last_update_request_cof_version " << last_update_request_cof_version
|
||||
<< " my_cof_version " << LLAppearanceMgr::instance().getCOFVersion() << LL_ENDL;
|
||||
|
||||
LLAppearanceMgr::instance().setLastAppearanceUpdateCOFVersion(this_update_cof_version);
|
||||
|
||||
if (getRegion() && (getRegion()->getCentralBakeVersion()==0))
|
||||
{
|
||||
LL_WARNS() << avString() << "Received AvatarAppearance message for self in non-server-bake region" << LL_ENDL;
|
||||
@@ -8189,8 +8230,16 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
|
||||
return;
|
||||
}
|
||||
|
||||
// No backsies zone - if we get here, the message should be valid and usable, will be processed.
|
||||
|
||||
setIsUsingServerBakes(appearance_version > 0);
|
||||
|
||||
// Note:
|
||||
// RequestAgentUpdateAppearanceResponder::onRequestRequested()
|
||||
// assumes that cof version is only updated with server-bake
|
||||
// appearance messages.
|
||||
mLastUpdateReceivedCOFVersion = this_update_cof_version;
|
||||
|
||||
applyParsedTEMessage(contents.mTEContents);
|
||||
|
||||
SHClientTagMgr::instance().updateAvatarTag(this);
|
||||
@@ -8267,7 +8316,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
|
||||
}
|
||||
}
|
||||
}
|
||||
const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
|
||||
const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE) +
|
||||
getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
|
||||
if (num_params != expected_tweakable_count)
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "Number of params in AvatarAppearance msg (" << num_params << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << "). Processing what we can. object: " << getID() << LL_ENDL;
|
||||
|
||||
@@ -654,7 +654,7 @@ private:
|
||||
public:
|
||||
void debugColorizeSubMeshes(U32 i, const LLColor4& color);
|
||||
virtual void updateMeshTextures();
|
||||
void updateSexDependentLayerSets(BOOL upload_bake);
|
||||
void updateSexDependentLayerSets(bool upload_bake = false);
|
||||
virtual void dirtyMesh(); // Dirty the avatar mesh
|
||||
void updateMeshData();
|
||||
protected:
|
||||
@@ -747,6 +747,8 @@ public:
|
||||
void cleanupAttachedMesh( LLViewerObject* pVO );
|
||||
static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj);
|
||||
/*virtual*/ BOOL isWearingWearableType(LLWearableType::EType type ) const;
|
||||
LLViewerObject * findAttachmentByID( const LLUUID & target_id ) const;
|
||||
|
||||
protected:
|
||||
LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object);
|
||||
void lazyAttach();
|
||||
@@ -1034,6 +1036,18 @@ public:
|
||||
protected:
|
||||
LLFrameTimer mRuthDebugTimer; // For tracking how long it takes for av to rez
|
||||
LLFrameTimer mDebugExistenceTimer; // Debugging for how long the avatar has been in memory.
|
||||
LLFrameTimer mLastAppearanceMessageTimer; // Time since last appearance message received.
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// COF monitoring
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
// COF version of last viewer-initiated appearance update request. For non-self avs, this will remain at default.
|
||||
S32 mLastUpdateRequestCOFVersion;
|
||||
|
||||
// COF version of last appearance message received for this av.
|
||||
S32 mLastUpdateReceivedCOFVersion;
|
||||
|
||||
/** Diagnostics
|
||||
** **
|
||||
|
||||
@@ -221,7 +221,7 @@ bool check_for_unsupported_baked_appearance()
|
||||
return true;
|
||||
|
||||
gAgentAvatarp->checkForUnsupportedServerBakeAppearance();
|
||||
return false;
|
||||
return LLApp::isExiting();
|
||||
}
|
||||
|
||||
void force_bake_all_textures()
|
||||
@@ -273,6 +273,7 @@ void LLVOAvatarSelf::initInstance()
|
||||
//doPeriodically(output_self_av_texture_diagnostics, 30.0);
|
||||
doPeriodically(update_avatar_rez_metrics, 5.0);
|
||||
doPeriodically(check_for_unsupported_baked_appearance, 120.0);
|
||||
doPeriodically(boost::bind(&LLVOAvatarSelf::checkStuckAppearance, this), 30.0);
|
||||
}
|
||||
|
||||
void LLVOAvatarSelf::setHoverIfRegionEnabled()
|
||||
@@ -283,7 +284,7 @@ void LLVOAvatarSelf::setHoverIfRegionEnabled()
|
||||
if (region->avatarHoverHeightEnabled())
|
||||
{
|
||||
F32 hover_z = gSavedPerAccountSettings.getF32("AvatarHoverOffsetZ");
|
||||
setHoverOffset(LLVector3(0.0, 0.0, llclamp(hover_z,MIN_HOVER_Z,MAX_HOVER_Z)));
|
||||
setHoverOffset(LLVector3(0.0, 0.0, llclamp(hover_z, MIN_HOVER_Z, MAX_HOVER_Z)));
|
||||
LL_INFOS("Avatar") << avString() << " set hover height from debug setting " << hover_z << LL_ENDL;
|
||||
}
|
||||
else
|
||||
@@ -297,11 +298,39 @@ void LLVOAvatarSelf::setHoverIfRegionEnabled()
|
||||
LL_INFOS("Avatar") << avString() << " region or simulator features not known, no change on hover" << LL_ENDL;
|
||||
if (region)
|
||||
{
|
||||
region->setSimulatorFeaturesReceivedCallback(boost::bind(&LLVOAvatarSelf::onSimulatorFeaturesReceived,this,_1));
|
||||
region->setSimulatorFeaturesReceivedCallback(boost::bind(&LLVOAvatarSelf::onSimulatorFeaturesReceived, this, _1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LLVOAvatarSelf::checkStuckAppearance()
|
||||
{
|
||||
if (!gAgentAvatarp->isUsingServerBakes())
|
||||
return false;
|
||||
const F32 CONDITIONAL_UNSTICK_INTERVAL = 300.0;
|
||||
const F32 UNCONDITIONAL_UNSTICK_INTERVAL = 600.0;
|
||||
|
||||
if (gAgentWearables.isCOFChangeInProgress())
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "checking for stuck appearance" << LL_ENDL;
|
||||
F32 change_time = gAgentWearables.getCOFChangeTime();
|
||||
LL_DEBUGS("Avatar") << "change in progress for " << change_time << " seconds" << LL_ENDL;
|
||||
S32 active_hp = LLAppearanceMgr::instance().countActiveHoldingPatterns();
|
||||
LL_DEBUGS("Avatar") << "active holding patterns " << active_hp << " seconds" << LL_ENDL;
|
||||
S32 active_copies = LLAppearanceMgr::instance().getActiveCopyOperations();
|
||||
LL_DEBUGS("Avatar") << "active copy operations " << active_copies << LL_ENDL;
|
||||
|
||||
if ((change_time > CONDITIONAL_UNSTICK_INTERVAL && active_copies == 0) ||
|
||||
(change_time > UNCONDITIONAL_UNSTICK_INTERVAL))
|
||||
{
|
||||
gAgentWearables.notifyLoadingFinished();
|
||||
}
|
||||
}
|
||||
|
||||
// Return false to continue running check periodically.
|
||||
return LLApp::isExiting();
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLVOAvatarSelf::markDead()
|
||||
{
|
||||
@@ -733,14 +762,9 @@ void LLVOAvatarSelf::updateVisualParams()
|
||||
LLVOAvatar::updateVisualParams();
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
void LLVOAvatarSelf::idleUpdateAppearanceAnimation()
|
||||
void LLVOAvatarSelf::writeWearablesToAvatar()
|
||||
{
|
||||
// Animate all top-level wearable visual parameters
|
||||
gAgentWearables.animateAllWearableParams(calcMorphAmount(), FALSE);
|
||||
|
||||
// apply wearable visual params to avatar
|
||||
for (U32 type = 0; type < LLWearableType::WT_COUNT; type++)
|
||||
for (U32 type = 0; type < LLWearableType::WT_COUNT; type++)
|
||||
{
|
||||
LLWearable *wearable = gAgentWearables.getTopWearable((LLWearableType::EType)type);
|
||||
if (wearable)
|
||||
@@ -749,6 +773,17 @@ void LLVOAvatarSelf::idleUpdateAppearanceAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
void LLVOAvatarSelf::idleUpdateAppearanceAnimation()
|
||||
{
|
||||
// Animate all top-level wearable visual parameters
|
||||
gAgentWearables.animateAllWearableParams(calcMorphAmount(), FALSE);
|
||||
|
||||
// Apply wearable visual params to avatar
|
||||
writeWearablesToAvatar();
|
||||
|
||||
//allow avatar to process updates
|
||||
LLVOAvatar::idleUpdateAppearanceAnimation();
|
||||
|
||||
@@ -779,12 +814,6 @@ void LLVOAvatarSelf::stopMotionFromSource(const LLUUID& source_id)
|
||||
}
|
||||
}
|
||||
|
||||
//virtual
|
||||
U32 LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, const EObjectUpdateType update_type, LLDataPacker *dp)
|
||||
{
|
||||
return LLVOAvatar::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);
|
||||
}
|
||||
|
||||
void LLVOAvatarSelf::setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index)
|
||||
{
|
||||
if (te >= TEX_NUM_INDICES)
|
||||
@@ -1630,8 +1659,8 @@ BOOL LLVOAvatarSelf::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex t
|
||||
return LLVOAvatar::isTextureVisible(type);
|
||||
}
|
||||
|
||||
U32 index = gAgentWearables.getWearableIndex(wearable);
|
||||
return isTextureVisible(type,index);
|
||||
U32 index;
|
||||
return gAgentWearables.getWearableIndex(wearable, index) && isTextureVisible(type, index);
|
||||
}
|
||||
|
||||
|
||||
@@ -3014,6 +3043,11 @@ void LLVOAvatarSelf::onCustomizeStart(bool disable_camera_switch)
|
||||
{
|
||||
if (isAgentAvatarValid())
|
||||
{
|
||||
if (!gAgentAvatarp->mEndCustomizeCallback.get())
|
||||
{
|
||||
gAgentAvatarp->mEndCustomizeCallback = new LLUpdateAppearanceOnDestroy;
|
||||
}
|
||||
|
||||
gAgentAvatarp->mIsEditingAppearance = true;
|
||||
gAgentAvatarp->mUseLocalAppearance = true;
|
||||
|
||||
@@ -3054,10 +3088,10 @@ void LLVOAvatarSelf::onCustomizeEnd(bool disable_camera_switch)
|
||||
gAgentCamera.resetView();
|
||||
}
|
||||
|
||||
if (gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion())
|
||||
{
|
||||
LLAppearanceMgr::instance().requestServerAppearanceUpdate();
|
||||
}
|
||||
// Dereferencing the previous callback will cause
|
||||
// updateAppearanceFromCOF to be called, whenever all refs
|
||||
// have resolved.
|
||||
gAgentAvatarp->mEndCustomizeCallback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "llvoavatar.h"
|
||||
|
||||
struct LocalTextureData;
|
||||
class LLInventoryCallback;
|
||||
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -102,17 +103,12 @@ public:
|
||||
/*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight, bool upload_bake = false );
|
||||
/*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight, bool upload_bake = false );
|
||||
/*virtual*/ void updateVisualParams();
|
||||
void writeWearablesToAvatar();
|
||||
/*virtual*/ void idleUpdateAppearanceAnimation();
|
||||
|
||||
/*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys,
|
||||
void **user_data,
|
||||
U32 block_num,
|
||||
const EObjectUpdateType update_type,
|
||||
LLDataPacker *dp);
|
||||
|
||||
private:
|
||||
// helper function. Passed in param is assumed to be in avatar's parameter list.
|
||||
BOOL setParamWeight(const LLViewerVisualParam *param, F32 weight, bool upload_bake = FALSE );
|
||||
BOOL setParamWeight(const LLViewerVisualParam *param, F32 weight, bool upload_bake = false );
|
||||
|
||||
|
||||
|
||||
@@ -140,6 +136,7 @@ public:
|
||||
public:
|
||||
/*virtual*/ BOOL updateCharacter(LLAgent &agent);
|
||||
/*virtual*/ void idleUpdateTractorBeam();
|
||||
bool checkStuckAppearance();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Loading state
|
||||
@@ -352,6 +349,7 @@ private:
|
||||
public:
|
||||
static void onCustomizeStart(bool disable_camera_switch = false);
|
||||
static void onCustomizeEnd(bool disable_camera_switch = false);
|
||||
LLPointer<LLInventoryCallback> mEndCustomizeCallback;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Visibility
|
||||
|
||||
@@ -290,7 +290,7 @@ void LLWebProfile::post(LLPointer<LLImageFormatted> image, const LLSD& config, c
|
||||
|
||||
size_t size = body_size + image->getDataSize() + footer_size;
|
||||
// postRaw() takes ownership of the buffer and releases it later.
|
||||
char* data = new char [size];
|
||||
U8* data = new U8 [size];
|
||||
memcpy(data, body.str().data(), body_size);
|
||||
// Insert the image data.
|
||||
memcpy(data + body_size, image->getData(), image->getDataSize());
|
||||
|
||||
@@ -406,7 +406,7 @@ void RlvRenameOnWearObserver::doneIdle()
|
||||
if (gInventory.isObjectDescendentOf(idAttachItem, pRlvRoot->getUUID()))
|
||||
items.push_back(gInventory.getItem(idAttachItem));
|
||||
else
|
||||
items = gInventory.collectLinkedItems(idAttachItem, pRlvRoot->getUUID());
|
||||
items = gInventory.collectLinksTo(idAttachItem, pRlvRoot->getUUID());
|
||||
if (items.empty())
|
||||
continue;
|
||||
|
||||
@@ -462,12 +462,12 @@ void RlvRenameOnWearObserver::doneIdle()
|
||||
else
|
||||
{
|
||||
// "No modify" item with a non-renameable parent: create a new folder named and move the item into it
|
||||
LLUUID idFolder = gInventory.createNewCategory(pFolder->getUUID(), LLFolderType::FT_NONE, strFolderName,
|
||||
&RlvRenameOnWearObserver::onCategoryCreate, new LLUUID(pItem->getUUID()));
|
||||
inventory_func_type func = boost::bind(&RlvRenameOnWearObserver::onCategoryCreate, this, _1, pItem->getUUID());
|
||||
LLUUID idFolder = gInventory.createNewCategory(pFolder->getUUID(), LLFolderType::FT_NONE, strFolderName, func);
|
||||
if (idFolder.notNull())
|
||||
{
|
||||
// Not using the new 'CreateInventoryCategory' cap so manually invoke the callback
|
||||
RlvRenameOnWearObserver::onCategoryCreate(LLSD().with("folder_id", idFolder), new LLUUID(pItem->getUUID()));
|
||||
RlvRenameOnWearObserver::onCategoryCreate(idFolder, pItem->getUUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -480,15 +480,10 @@ void RlvRenameOnWearObserver::doneIdle()
|
||||
}
|
||||
|
||||
// Checked: 2012-03-22 (RLVa-1.4.6) | Added: RLVa-1.4.6
|
||||
void RlvRenameOnWearObserver::onCategoryCreate(const LLSD& sdData, void* pParam)
|
||||
void RlvRenameOnWearObserver::onCategoryCreate(const LLUUID& folder_id, const LLUUID& item_id)
|
||||
{
|
||||
LLUUID idFolder = sdData["folder_id"].asUUID();
|
||||
LLUUID* pidItem = (LLUUID*)pParam;
|
||||
|
||||
if ( (idFolder.notNull()) && (pidItem) && (pidItem->notNull()) )
|
||||
move_inventory_item(gAgent.getID(), gAgent.getSessionID(), *pidItem, idFolder, std::string(), NULL);
|
||||
|
||||
delete pidItem;
|
||||
if (folder_id.notNull() && item_id.notNull())
|
||||
move_inventory_item(gAgent.getID(), gAgent.getSessionID(), item_id, folder_id, std::string(), NULL);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -516,13 +511,14 @@ bool RlvGiveToRLVOffer::createDestinationFolder(const std::string& strPath)
|
||||
const LLUUID& idRlvRoot = RlvInventory::instance().getSharedRootID();
|
||||
if (idRlvRoot.notNull())
|
||||
{
|
||||
onCategoryCreateCallback(LLSD().with("folder_id", idRlvRoot), this);
|
||||
onCategoryCreate(idRlvRoot);
|
||||
}
|
||||
else
|
||||
{
|
||||
const LLUUID idTemp = gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, RLV_ROOT_FOLDER, onCategoryCreateCallback, (void*)this);
|
||||
inventory_func_type func = boost::bind(&RlvGiveToRLVOffer::onCategoryCreate, this, _1);
|
||||
const LLUUID idTemp = gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, RLV_ROOT_FOLDER, func);
|
||||
if (idTemp.notNull())
|
||||
onCategoryCreateCallback(LLSD().with("folder_id", idTemp), this);
|
||||
onCategoryCreate(idTemp);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -532,40 +528,39 @@ bool RlvGiveToRLVOffer::createDestinationFolder(const std::string& strPath)
|
||||
}
|
||||
|
||||
// Checked: 2014-01-07 (RLVa-1.4.10)
|
||||
void RlvGiveToRLVOffer::onCategoryCreateCallback(const LLSD& sdData, void* pInstance)
|
||||
void RlvGiveToRLVOffer::onCategoryCreate(const LLUUID& folder_id)
|
||||
{
|
||||
RlvGiveToRLVOffer* pThis = (RlvGiveToRLVOffer*)pInstance;
|
||||
|
||||
LLUUID idFolder = sdData["folder_id"].asUUID();
|
||||
if (idFolder.isNull())
|
||||
if (folder_id.isNull())
|
||||
{
|
||||
// Problem encountered, abort move
|
||||
pThis->onDestinationCreated(LLUUID::null, LLStringUtil::null);
|
||||
onDestinationCreated(LLUUID::null, LLStringUtil::null);
|
||||
return;
|
||||
}
|
||||
|
||||
while (pThis->m_DestPath.size() > 1)
|
||||
LLUUID target_folder = folder_id;
|
||||
while (m_DestPath.size() > 1)
|
||||
{
|
||||
std::string strFolder = pThis->m_DestPath.front();
|
||||
pThis->m_DestPath.pop_front();
|
||||
std::string strFolder = m_DestPath.front();
|
||||
m_DestPath.pop_front();
|
||||
|
||||
const LLViewerInventoryCategory* pFolder = RlvInventory::instance().getSharedFolder(idFolder, strFolder, false);
|
||||
const LLViewerInventoryCategory* pFolder = RlvInventory::instance().getSharedFolder(folder_id, strFolder, false);
|
||||
if (pFolder)
|
||||
{
|
||||
idFolder = pFolder->getUUID();
|
||||
target_folder = pFolder->getUUID();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLInventoryObject::correctInventoryName(strFolder);
|
||||
const LLUUID idTemp = gInventory.createNewCategory(idFolder, LLFolderType::FT_NONE, strFolder, onCategoryCreateCallback, pInstance);
|
||||
inventory_func_type func = boost::bind(&RlvGiveToRLVOffer::onCategoryCreate, this, _1);
|
||||
const LLUUID idTemp = gInventory.createNewCategory(folder_id, LLFolderType::FT_NONE, strFolder, func);
|
||||
if (idTemp.notNull())
|
||||
onCategoryCreateCallback(LLSD().with("folder_id", idTemp), pInstance);
|
||||
onCategoryCreate(idTemp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Destination folder should exist at this point (we'll be deallocated when the function returns)
|
||||
pThis->onDestinationCreated(idFolder, pThis->m_DestPath.front());
|
||||
onDestinationCreated(target_folder, m_DestPath.front());
|
||||
}
|
||||
|
||||
// Checked: 2014-01-07 (RLVa-1.4.10)
|
||||
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
virtual void done();
|
||||
protected:
|
||||
void doneIdle();
|
||||
static void onCategoryCreate(const LLSD& sdData, void* pParam);
|
||||
void onCategoryCreate(const LLUUID& folder_id, const LLUUID& item_id);
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
@@ -129,7 +129,7 @@ protected:
|
||||
virtual void onDestinationCreated(const LLUUID& idFolder, const std::string& strName) = 0;
|
||||
void moveAndRename(const LLUUID& idFolder, const LLUUID& idDestination, const std::string& strName);
|
||||
private:
|
||||
static void onCategoryCreateCallback(const LLSD& sdData, void* pInstance);
|
||||
void onCategoryCreate(const LLUUID& folder_id);
|
||||
|
||||
private:
|
||||
std::list<std::string> m_DestPath;
|
||||
|
||||
@@ -1165,7 +1165,7 @@ bool RlvFolderLocks::getLockedItems(const LLUUID& idFolder, LLInventoryModel::it
|
||||
if (!fItemLocked)
|
||||
{
|
||||
LLInventoryModel::item_array_t itemLinks =
|
||||
gInventory.collectLinkedItems(pItem->getUUID(), RlvInventory::instance().getSharedRootID());
|
||||
gInventory.collectLinksTo(pItem->getUUID(), RlvInventory::instance().getSharedRootID());
|
||||
for (LLInventoryModel::item_array_t::iterator itItemLink = itemLinks.begin();
|
||||
(itItemLink < itemLinks.end()) && (!fItemLocked); ++itItemLink)
|
||||
{
|
||||
|
||||
@@ -533,7 +533,7 @@ inline ERlvWearMask RlvWearableLocks::canWear(LLWearableType::EType eType) const
|
||||
return (!isLockedWearableType(eType, RLV_LOCK_ADD))
|
||||
? ((!hasLockedWearable(eType))
|
||||
? RLV_WEAR
|
||||
: (gAgentWearables.getWearableCount(eType) < LLAgentWearables::MAX_CLOTHING_PER_TYPE) ? RLV_WEAR_ADD : RLV_WEAR_LOCKED)
|
||||
: (gAgentWearables.canAddWearable(eType)) ? RLV_WEAR_ADD : RLV_WEAR_LOCKED)
|
||||
: RLV_WEAR_LOCKED;
|
||||
}
|
||||
|
||||
|
||||
@@ -260,7 +260,7 @@
|
||||
<menu_item_separator name="Sound Separator" />
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Play" left="0" mouse_opaque="true"
|
||||
name="Sound Play" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="open" />
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="sound_play" />
|
||||
</menu_item_call>
|
||||
<menu_item_separator name="Landmark Separator" />
|
||||
<menu_item_call bottom_delta="-18" height="18" label="About Landmark" left="0"
|
||||
|
||||
Reference in New Issue
Block a user