Initial AISv3 merge. New HTTP messages not plugged in yet.

This commit is contained in:
Shyotl
2015-06-25 20:16:30 -05:00
parent 09f4528bfb
commit 9f10d9510d
71 changed files with 4962 additions and 3452 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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))
{

View File

@@ -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
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -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"];

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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();
}

View File

@@ -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,

View File

@@ -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

View File

@@ -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);

View File

@@ -1623,6 +1623,8 @@ bool LLAppViewer::cleanup()
LLAvatarAppearance::cleanupClass();
LLAvatarAppearance::cleanupClass();
LLPostProcess::cleanupClass();
LLTracker::cleanupInstance();

View File

@@ -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)
{

View File

@@ -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;
};

View File

@@ -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(),

View File

@@ -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 );

View File

@@ -352,15 +352,6 @@ void LLFloaterLandmark::onBtnDelete()
gInventory.notifyObservers();
}
}
// Delete the item entirely
/*
item->removeFromServer();
gInventory.deleteObject(item->getUUID());
gInventory.notifyObservers();
*/
}
void LLFloaterLandmark::onBtnRename()

View File

@@ -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

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -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

View 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;
}

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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
** **

View File

@@ -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());
}

View File

@@ -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;

View File

@@ -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;
}
}
}
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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.
*

View File

@@ -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);
}
}
}

View File

@@ -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);

View File

@@ -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; }

View File

@@ -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)
{

View File

@@ -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)

View File

@@ -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();

View File

@@ -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

View File

@@ -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

View File

@@ -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(

View File

@@ -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

View File

@@ -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()

View File

@@ -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;
};

View File

@@ -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();
}

View File

@@ -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 );

View File

@@ -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;

View File

@@ -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
** **

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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());

View File

@@ -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)

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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;
}

View File

@@ -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"