Conflicts:
	indra/newview/llagentwearables.cpp
	indra/newview/llagentwearables.h
This commit is contained in:
Siana Gearz
2011-10-13 04:27:20 +02:00
34 changed files with 1057 additions and 514 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -52,8 +52,6 @@ class LLInitialWearablesFetch;
class LLViewerObject;
class LLTexLayerTemplate;
typedef std::vector<LLViewerObject*> llvo_vec_t;
class LLAgentWearables : public LLInitClass<LLAgentWearables>
{
//--------------------------------------------------------------------
@@ -72,7 +70,7 @@ public:
// LLInitClass interface
static void initClass();
protected:
void createStandardWearablesDone(S32 index);
void createStandardWearablesDone(S32 type);
void createStandardWearablesAllDone();
//--------------------------------------------------------------------
@@ -85,7 +83,7 @@ public:
BOOL isWearableCopyable(LLWearableType::EType type) const;
BOOL areWearablesLoaded() const;
//void updateWearablesLoaded();
void updateWearablesLoaded();
//void checkWearablesLoaded() const;
//bool canMoveWearable(const LLUUID& item_id, bool closer_to_body);
@@ -101,24 +99,23 @@ public:
// Accessors
//--------------------------------------------------------------------
public:
const LLUUID& getWearableItemID(LLWearableType::EType type ) const;
//const LLUUID getWearableAssetID(LLWearableType::EType type, U32 index /*= 0*/) const;
const LLUUID getWearableItemID(LLWearableType::EType type ) const;
const LLUUID getWearableAssetID(LLWearableType::EType type) const;
const LLWearable* getWearableFromItemID(const LLUUID& item_id) const;
LLWearable* getWearableFromItemID(const LLUUID& item_id);
//LLWearable* getWearableFromAssetID(const LLUUID& asset_id);
LLWearable* getWearableFromAssetID(const LLUUID& asset_id);
LLInventoryItem* getWearableInventoryItem(LLWearableType::EType type);
static BOOL selfHasWearable( void* userdata ); // userdata is LLWearableType::EType
static BOOL selfHasWearable(LLWearableType::EType type);
LLWearable* getWearable( const LLWearableType::EType type );
const LLWearable* getWearable( const LLWearableType::EType type ) const;
//const LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const;
//LLWearable* getTopWearable(const LLWearableType::EType type);
//LLWearable* getBottomWearable(const LLWearableType::EType type);
//U32 getWearableCount(const LLWearableType::EType type) const;
//U32 getWearableCount(const U32 tex_index) const;
LLWearable* getTopWearable(const LLWearableType::EType type);
LLWearable* getBottomWearable(const LLWearableType::EType type);
U32 getWearableCount(const LLWearableType::EType type) const;
U32 getWearableCount(const U32 tex_index) const;
void copyWearableToInventory( LLWearableType::EType type );
static const U32 MAX_CLOTHING_PER_TYPE = 5;
static const U32 MAX_CLOTHING_PER_TYPE = 1;
//--------------------------------------------------------------------
@@ -127,18 +124,18 @@ public:
private:
// 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 wearableUpdated(LLWearable *wearable);
//void popWearable(LLWearable *wearable);
//void popWearable(const LLWearableType::EType type, U32 index);
void setWearable(const LLWearableType::EType type, LLWearable *wearable);
U32 pushWearable(const LLWearableType::EType type, LLWearable *wearable);
void wearableUpdated(LLWearable *wearable);
void popWearable(LLWearable *wearable);
void popWearable(const LLWearableType::EType type);
public:
void setWearableItem(LLInventoryItem* new_item, LLWearable* wearable);
void setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLWearable* >& wearables, BOOL remove);
void setWearableName(const LLUUID& item_id, const std::string& new_name);
//void addLocalTextureObject(const LLWearableType::EType wearable_type, const LLVOAvatarDefines::ETextureIndex texture_type, U32 wearable_index);
//U32 getWearableIndex(LLWearable *wearable);
U32 getWearableIndex(const LLWearable *wearable) const;
protected:
void setWearableFinal( LLInventoryItem* new_item, LLWearable* new_wearable );
@@ -159,8 +156,7 @@ protected:
* @param item_id The inventory item id of the new wearable to wear.
* @param wearable The actual wearable data.
*/
void addWearabletoAgentInventoryDone(
S32 index,
void addWearabletoAgentInventoryDone(const LLWearableType::EType type,
const LLUUID& item_id,
LLWearable* wearable);
@@ -206,8 +202,8 @@ protected:
void sendAgentWearablesUpdate();
void sendAgentWearablesRequest();
void queryWearableCache();
//void updateServer();
static void onInitialWearableAssetArrived(LLWearable* wearable, void* userdata);
void updateServer();
static void onInitialWearableAssetArrived(LLWearable* wearable, void* userdata );
//--------------------------------------------------------------------
// Outfits
@@ -224,14 +220,15 @@ public:
BOOL rename_clothing);
private:
void makeNewOutfitDone(S32 index);
void makeNewOutfitDone(S32 type);
//--------------------------------------------------------------------
// Save Wearables
//--------------------------------------------------------------------
public:
void saveWearableAs( LLWearableType::EType type, const std::string& new_name, BOOL save_in_lost_and_found );
void saveWearable( LLWearableType::EType type, BOOL send_update = TRUE );
void saveWearableAs(const LLWearableType::EType type, const std::string& new_name, BOOL save_in_lost_and_found );
void saveWearable(const LLWearableType::EType type, BOOL send_update = TRUE,
const std::string new_name = "");
void saveAllWearables();
void revertWearable( LLWearableType::EType type );
@@ -241,14 +238,16 @@ public:
// Static UI hooks
//--------------------------------------------------------------------
public:
static void userRemoveWearable( void* userdata ); // userdata is LLWearableType::EType
static void userRemoveAllClothes( void* userdata ); // userdata is NULL
static void userRemoveWearable(const LLWearableType::EType &type);
static void userRemoveAllClothes();
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-2.2.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 userRemoveAllAttachments( void* userdata); // userdata is NULLy);
static void userRemoveMultipleAttachments(llvo_vec_t& llvo_array);
static void userRemoveAllAttachments();
static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array);
@@ -276,14 +275,12 @@ private:
//--------------------------------------------------------------------
// Member variables
//--------------------------------------------------------------------
struct LLWearableEntry
{
LLWearableEntry() : mItemID( LLUUID::null ), mWearable( NULL ) {}
private:
typedef std::vector<LLWearable*> wearableentry_vec_t; // all wearables of a certain type (EG all shirts)
typedef std::map<LLWearableType::EType, wearableentry_vec_t> wearableentry_map_t; // wearable "categories" arranged by wearable type
wearableentry_map_t mWearableDatas;
LLUUID mItemID; // ID of the inventory item in the agent's inventory.
LLWearable* mWearable;
};
LLWearableEntry mWearableEntry[ LLWearableType::WT_COUNT ];
static BOOL mInitialWearablesUpdateReceived;
BOOL mWearablesLoaded;
//--------------------------------------------------------------------------------
@@ -322,15 +319,14 @@ private:
* @param wearable The wearable data.
* @param todo Bitmask of actions to take on completion.
*/
addWearableToAgentInventoryCallback(
LLPointer<LLRefCount> cb,
S32 index,
LLWearable* wearable,
U32 todo = CALL_NONE);
addWearableToAgentInventoryCallback(LLPointer<LLRefCount> cb,
LLWearableType::EType type,
LLWearable* wearable,
U32 todo = CALL_NONE);
virtual void fire(const LLUUID& inv_item);
private:
S32 mIndex;
LLWearableType::EType mType;
LLWearable* mWearable;
U32 mTodo;
LLPointer<LLRefCount> mCB;

View File

@@ -3743,6 +3743,7 @@ void LLAppViewer::idle()
gEventNotifier.update();
gIdleCallbacks.callFunctions();
gInventory.idleNotifyObservers();
}
if (gDisconnected)

View File

@@ -47,7 +47,7 @@ LLCallbackList gIdleCallbacks;
// Member functions
//
LLCallbackList::LLCallbackList() : mLoopingOverCallbackList(false)
LLCallbackList::LLCallbackList()
{
// nothing
}
@@ -96,15 +96,7 @@ BOOL LLCallbackList::deleteFunction( callback_t func, void *data)
callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t);
if (iter != mCallbackList.end())
{
if (mLoopingOverCallbackList)
{
iter->first = NULL; // Mark for removal later (when we return to LLCallbackList::callFunctions).
mNeedErase = true;
}
else
{
mCallbackList.erase(iter);
}
mCallbackList.erase(iter);
return TRUE;
}
else
@@ -116,39 +108,82 @@ BOOL LLCallbackList::deleteFunction( callback_t func, void *data)
void LLCallbackList::deleteAllFunctions()
{
llassert(!mLoopingOverCallbackList); // Only called from unit tests.
mCallbackList.clear();
}
void LLCallbackList::callFunctions()
{
llassert(!mLoopingOverCallbackList);
mLoopingOverCallbackList = true;
mNeedErase = false;
for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); ++iter)
for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); )
{
if (iter->first) // Not pending removal?
callback_list_t::iterator curiter = iter++;
curiter->first(curiter->second);
}
}
// Shim class to allow arbitrary boost::bind
// expressions to be run as one-time idle callbacks.
class OnIdleCallbackOneTime
{
public:
OnIdleCallbackOneTime(nullary_func_t callable):
mCallable(callable)
{
}
static void onIdle(void *data)
{
gIdleCallbacks.deleteFunction(onIdle, data);
OnIdleCallbackOneTime* self = reinterpret_cast<OnIdleCallbackOneTime*>(data);
self->call();
delete self;
}
void call()
{
mCallable();
}
private:
nullary_func_t mCallable;
};
void doOnIdleOneTime(nullary_func_t callable)
{
OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable);
gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor);
}
// Shim class to allow generic boost functions to be run as
// recurring idle callbacks. Callable should return true when done,
// false to continue getting called.
class OnIdleCallbackRepeating
{
public:
OnIdleCallbackRepeating(bool_func_t callable):
mCallable(callable)
{
}
// Will keep getting called until the callable returns true.
static void onIdle(void *data)
{
OnIdleCallbackRepeating* self = reinterpret_cast<OnIdleCallbackRepeating*>(data);
bool done = self->call();
if (done)
{
iter->first(iter->second); // This can theorectically set any iter->first to NULL, which means the entry should be erased.
gIdleCallbacks.deleteFunction(onIdle, data);
delete self;
}
}
mLoopingOverCallbackList = false;
if (mNeedErase)
bool call()
{
callback_list_t::iterator iter = mCallbackList.begin();
while (iter != mCallbackList.end())
{
if (!iter->first)
{
iter = mCallbackList.erase(iter);
}
else
{
++iter;
}
}
return mCallable();
}
private:
bool_func_t mCallable;
};
void doOnIdleRepeating(bool_func_t callable)
{
OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable);
gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor);
}
#ifdef _DEBUG

View File

@@ -34,6 +34,7 @@
#define LL_LLCALLBACKLIST_H
#include "llstl.h"
#include <boost/function.hpp>
class LLCallbackList
{
@@ -53,13 +54,20 @@ public:
protected:
// Use a list so that the callbacks are ordered in case that matters
typedef std::pair<callback_t,void*> callback_pair_t; // callback_t is a (function) pointer. If it is NULL it means that the entry should be considered deleted.
typedef std::pair<callback_t,void*> callback_pair_t;
typedef std::list<callback_pair_t > callback_list_t;
callback_list_t mCallbackList;
bool mLoopingOverCallbackList; // True while looping over mCallbackList and calling the callback_t functions (see callFunctions).
bool mNeedErase; // True when deleteFunction was called while mLoopingOverCallbackList was true.
};
typedef boost::function<void ()> nullary_func_t;
typedef boost::function<bool ()> bool_func_t;
// Call a given callable once in idle loop.
void doOnIdleOneTime(nullary_func_t callable);
// Repeatedly call a callable in idle loop until it returns true.
void doOnIdleRepeating(bool_func_t callable);
extern LLCallbackList gIdleCallbacks;
#endif

View File

@@ -1313,6 +1313,12 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>*
return;
}
}
else
{
static const LLCachedControl<bool> draw_orphans("ShyotlDrawOrphanAttachments",false);
if(!draw_orphans)
return;
}
}
@@ -1385,6 +1391,12 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update)
return;
}
}
else
{
static const LLCachedControl<bool> draw_orphans("ShyotlDrawOrphanAttachments",false);
if(!draw_orphans)
return;
}
}
LLCamera camera = transformCamera(camera_in);

View File

@@ -719,7 +719,7 @@ bool LLPanelEditWearable::onSelectAutoWearOption(const LLSD& notification, const
if(avatar)
{
// Create a new wearable in the default folder for the wearable's asset type.
LLWearable* wearable = gWearableList.createNewWearable( (LLWearableType::EType)notification["payload"]["wearable_type"].asInteger() );
LLWearable* wearable = LLWearableList::instance().createNewWearable( (LLWearableType::EType)notification["payload"]["wearable_type"].asInteger() );
LLAssetType::EType asset_type = wearable->getAssetType();
LLUUID folder_id;

View File

@@ -288,7 +288,7 @@ bool LLFloaterDayCycle::isOpen()
{
if (sDayCycle != NULL)
{
return true;
return sDayCycle->getVisible();
}
return false;
}

View File

@@ -197,7 +197,7 @@ bool LLFloaterEnvSettings::isOpen()
{
if (sEnvSettings != NULL)
{
return true;
return sEnvSettings->getVisible();
}
return false;
}

View File

@@ -316,7 +316,7 @@ void LLFloaterWater::show()
bool LLFloaterWater::isOpen()
{
if (sWaterMenu != NULL) {
return true;
return sWaterMenu->getVisible();
}
return false;
}

View File

@@ -473,7 +473,7 @@ void LLFloaterWindLight::show()
bool LLFloaterWindLight::isOpen()
{
if (sWindLight != NULL) {
return true;
return sWindLight->getVisible();
}
return false;
}

View File

@@ -2917,7 +2917,7 @@ void LLFolderBridge::createWearable(LLFolderBridge* bridge, LLWearableType::ETyp
// static
void LLFolderBridge::createWearable(LLUUID parent_id, LLWearableType::EType type)
{
LLWearable* wearable = gWearableList.createNewWearable(type);
LLWearable* wearable = LLWearableList::instance().createNewWearable(type);
LLAssetType::EType asset_type = wearable->getAssetType();
LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
@@ -4148,6 +4148,14 @@ std::string LLObjectBridge::getLabelSuffix() const
{
std::string attachment_point_name = avatar->getAttachedPointName(mUUID);
LLStringUtil::toLower(attachment_point_name);
LLViewerObject* pObj = (rlv_handler_t::isEnabled()) ? avatar->getWornAttachment( mUUID ) : NULL;
// [RLVa:KB]
if ( pObj && (gRlvAttachmentLocks.isLockedAttachment(pObj) ||
gRlvAttachmentLocks.isLockedAttachmentPoint(RlvAttachPtLookup::getAttachPointIndex(pObj),RLV_LOCK_REMOVE)))
{
return LLItemBridge::getLabelSuffix() + std::string(" (locked to ") + attachment_point_name + std::string(")");
}
// [/RLVa:KB]
return LLItemBridge::getLabelSuffix() + std::string(" (worn on ") + attachment_point_name + std::string(")");
}
else
@@ -4155,11 +4163,21 @@ std::string LLObjectBridge::getLabelSuffix() const
// <edit> testzone attachpt
if(avatar)
{
std::map<S32, LLUUID>::iterator iter = avatar->mUnsupportedAttachmentPoints.begin();
std::map<S32, LLUUID>::iterator end = avatar->mUnsupportedAttachmentPoints.end();
std::map<S32, std::pair<LLUUID,LLUUID> >::iterator iter = avatar->mUnsupportedAttachmentPoints.begin();
std::map<S32, std::pair<LLUUID,LLUUID> >::iterator end = avatar->mUnsupportedAttachmentPoints.end();
for( ; iter != end; ++iter)
if((*iter).second == mUUID)
if((*iter).second.first == mUUID)
{
// [RLVa:KB]
LLViewerObject* pObj = (rlv_handler_t::isEnabled()) ? gObjectList.findObject((*iter).second.second) : NULL;
if ( pObj && (gRlvAttachmentLocks.isLockedAttachment(pObj) ||
gRlvAttachmentLocks.isLockedAttachmentPoint(RlvAttachPtLookup::getAttachPointIndex(pObj),RLV_LOCK_REMOVE)))
{
return LLItemBridge::getLabelSuffix() + std::string(" (locked to unsupported point %d)", (*iter).first);
}
// [/RLVa:KB]
return LLItemBridge::getLabelSuffix() + llformat(" (worn on unsupported point %d)", (*iter).first);
}
}
// </edit>
return LLItemBridge::getLabelSuffix();
@@ -4474,7 +4492,7 @@ void wear_inventory_item_on_avatar( LLInventoryItem* item )
lldebugs << "wear_inventory_item_on_avatar( " << item->getName()
<< " )" << llendl;
gWearableList.getAsset(item->getAssetUUID(),
LLWearableList::instance().getAsset(item->getAssetUUID(),
item->getName(),
item->getType(),
LLWearableBridge::onWearOnAvatarArrived,
@@ -4596,8 +4614,8 @@ void LLOutfitObserver::done()
name = cat->getName();
}
LLViewerInventoryItem* item = NULL;
item_ref_t::iterator it = mComplete.begin();
item_ref_t::iterator end = mComplete.end();
uuid_vec_t::iterator it = mComplete.begin();
uuid_vec_t::iterator end = mComplete.end();
LLUUID pid;
for(; it < end; ++it)
{
@@ -4914,7 +4932,7 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata )
// [/RLVa:KB]
found = found_container.get(i);
gWearableList.getAsset(found->mAssetID,
LLWearableList::instance().getAsset(found->mAssetID,
found->mName,
found->mAssetType,
wear_inventory_category_on_avatar_loop,
@@ -5036,7 +5054,7 @@ void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, B
//And this code does not handle failed asset uploads properly
// if(!wearable->isMatchedToInventoryItem(item ))
// {
// wearable = gWearableList.createWearableMatchedToInventoryItem( wearable, item );
// wearable = LLWearableList::instance().createWearableMatchedToInventoryItem( wearable, item );
// // Now that we have an asset that matches the
// // item, update the item to point to the new
// // asset.
@@ -5152,7 +5170,7 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata)
if ( (pWearable) && ( (!rlv_handler_t::isEnabled()) || (gRlvWearableLocks.canRemove(pWearable->getType())) ) )
// [/RLVa:KB]
{
gWearableList.getAsset( item->getAssetUUID(),
LLWearableList::instance().getAsset( item->getAssetUUID(),
item->getName(),
item->getType(),
LLWearableBridge::onRemoveFromAvatarArrived,
@@ -5223,6 +5241,10 @@ std::string LLWearableBridge::getLabelSuffix() const
{
if (get_is_item_worn(getItem()))
{
if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canRemove(getItem())) )
{
return LLItemBridge::getLabelSuffix() + " (locked)";
}
return LLItemBridge::getLabelSuffix() + " (worn)";
}
else
@@ -5255,7 +5277,7 @@ void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* mod
LLViewerInventoryItem* item = getItem();
if (item)
{
gWearableList.getAsset(item->getAssetUUID(),
LLWearableList::instance().getAsset(item->getAssetUUID(),
item->getName(),
item->getType(),
LLWearableBridge::onRemoveFromAvatarArrived,
@@ -5470,7 +5492,7 @@ void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userda
// if(!wearable->isMatchedToInventoryItem(item))
// {
// LLWearable* new_wearable = gWearableList.createWearableMatchedToInventoryItem( wearable, item );
// LLWearable* new_wearable = LLWearableList::instance().createWearableMatchedToInventoryItem( wearable, item );
//
// // Now that we have an asset that matches the
// // item, update the item to point to the new
@@ -5549,7 +5571,7 @@ void LLWearableBridge::onRemoveFromAvatar(void* user_data)
LLViewerInventoryItem* item = self->getItem();
if (item)
{
gWearableList.getAsset(item->getAssetUUID(),
LLWearableList::instance().getAsset(item->getAssetUUID(),
item->getName(),
item->getType(),
onRemoveFromAvatarArrived,

View File

@@ -153,7 +153,10 @@ const char* NEW_CATEGORY_NAMES[LLFolderType::FT_COUNT] =
"Current Outfit", // FT_CURRENT_OUTFIT = 46,
"New Outfit", // FT_OUTFIT = 47,
"My Outfits", // FT_MY_OUTFITS = 48,
"Inbox" // FT_INBOX = 49,
"Mesh", // FT_MESH = 49,
"Inbox", // FT_INBOX = 50,
"Outbox", // FT_OUTBOX = 51,
"Basic Root" // FT_BASIC_ROOT = 52
};
struct InventoryIDPtrLess
@@ -221,22 +224,40 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
LLInventoryModel gInventory;
// Default constructor
LLInventoryModel::LLInventoryModel() :
mModifyMask(LLInventoryObserver::ALL),
LLInventoryModel::LLInventoryModel()
: mModifyMask(LLInventoryObserver::ALL),
mChangedItemIDs(),
mCategoryMap(),
mItemMap(),
mCategoryLock(),
mItemLock(),
mLastItem(NULL),
mParentChildCategoryTree(),
mParentChildItemTree(),
mObservers(),
mIsNotifyObservers(FALSE),
mIsAgentInvUsable(false)
{
}
// Destroys the object
LLInventoryModel::~LLInventoryModel()
{
cleanupInventory();
}
void LLInventoryModel::cleanupInventory()
{
empty();
for (observer_list_t::iterator iter = mObservers.begin();
iter != mObservers.end(); ++iter)
// Deleting one observer might erase others from the list, so always pop off the front
while (!mObservers.empty())
{
delete *iter;
observer_list_t::iterator iter = mObservers.begin();
LLInventoryObserver* observer = *iter;
mObservers.erase(iter);
delete observer;
}
mObservers.clear();
}
// This is a convenience function to check if one object has a parent
@@ -245,6 +266,7 @@ BOOL LLInventoryModel::isObjectDescendentOf(const LLUUID& obj_id,
const LLUUID& cat_id,
const BOOL break_on_recursion) const
{
if (obj_id == cat_id) return TRUE;
LLInventoryObject* obj = getObject(obj_id);
int depthCounter = 0;
while(obj)
@@ -502,7 +524,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
{
name.assign(pname);
}
if(preferred_type < LLFolderType::FT_TEXTURE || preferred_type > LLFolderType::FT_INBOX)
else if(preferred_type < (LLFolderType::EType)0 || preferred_type >= LLFolderType::FT_COUNT)
name.assign(NEW_CATEGORY_NAME);
else
name.assign(NEW_CATEGORY_NAMES[preferred_type]);
@@ -758,12 +780,23 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
return mask;
}
// We're hiding mesh types
#if 0
if (item->getType() == LLAssetType::AT_MESH)
{
return mask;
}
#endif
LLViewerInventoryItem* old_item = getItem(item->getUUID());
LLPointer<LLViewerInventoryItem> new_item;
if(old_item)
{
// We already have an old item, modify it's values
// We already have an old item, modify its values
new_item = old_item;
LLUUID old_parent_id = old_item->getParentUUID();
LLUUID new_parent_id = item->getParentUUID();
if(old_parent_id != new_parent_id)
{
// need to update the parent-child tree
@@ -790,7 +823,7 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
else
{
// Simply add this item
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
new_item = new LLViewerInventoryItem(item);
addItem(new_item);
if(item->getParentUUID().isNull())
@@ -850,11 +883,40 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
}
mask |= LLInventoryObserver::ADD;
}
if(item->getType() == LLAssetType::AT_CALLINGCARD)
if(new_item->getType() == LLAssetType::AT_CALLINGCARD)
{
mask |= LLInventoryObserver::CALLING_CARD;
// Handle user created calling cards.
// Target ID is stored in the description field of the card.
LLUUID id;
std::string desc = new_item->getDescription();
BOOL isId = desc.empty() ? FALSE : id.set(desc, FALSE);
if (isId)
{
// Valid UUID; set the item UUID and rename it
new_item->setCreator(id);
std::string avatar_name;
if (gCacheName->getFullName(id, avatar_name))
{
new_item->rename(avatar_name);
mask |= LLInventoryObserver::LABEL;
}
else
{
// Fetch the current name
gCacheName->get(id, FALSE,
boost::bind(&LLViewerInventoryItem::onCallingCardNameLookup, new_item.get(),
_1, _2, _3));
}
}
}
addChangedMask(mask, item->getUUID());
/*else if (new_item->getType() == LLAssetType::AT_GESTURE)
{
mask |= LLInventoryObserver::GESTURE;
}*/
addChangedMask(mask, new_item->getUUID());
return mask;
}
@@ -1001,39 +1063,40 @@ void LLInventoryModel::deleteObject(const LLUUID& id)
return;
}
lldebugs << "Deleting inventory object " << id << llendl;
mLastItem = NULL;
LLUUID parent_id = obj->getParentUUID();
mCategoryMap.erase(id);
mItemMap.erase(id);
//mInventory.erase(id);
item_array_t* item_list = getUnlockedItemArray(parent_id);
if(item_list)
{
LLViewerInventoryItem* item = (LLViewerInventoryItem*)((LLInventoryObject*)obj);
item_list->removeObj(item);
}
cat_array_t* cat_list = getUnlockedCatArray(parent_id);
if(cat_list)
{
LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)((LLInventoryObject*)obj);
cat_list->removeObj(cat);
}
item_list = getUnlockedItemArray(id);
if(item_list)
{
delete item_list;
mParentChildItemTree.erase(id);
}
cat_list = getUnlockedCatArray(id);
if(cat_list)
{
delete cat_list;
mParentChildCategoryTree.erase(id);
}
addChangedMask(LLInventoryObserver::REMOVE, id);
obj = NULL; // delete obj
lldebugs << "Deleting inventory object " << id << llendl;
mLastItem = NULL;
LLUUID parent_id = obj->getParentUUID();
mCategoryMap.erase(id);
mItemMap.erase(id);
//mInventory.erase(id);
item_array_t* item_list = getUnlockedItemArray(parent_id);
if(item_list)
{
LLViewerInventoryItem* item = (LLViewerInventoryItem*)((LLInventoryObject*)obj);
item_list->removeObj(item);
}
cat_array_t* cat_list = getUnlockedCatArray(parent_id);
if(cat_list)
{
LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)((LLInventoryObject*)obj);
cat_list->removeObj(cat);
}
item_list = getUnlockedItemArray(id);
if(item_list)
{
delete item_list;
mParentChildItemTree.erase(id);
}
cat_list = getUnlockedCatArray(id);
if(cat_list)
{
delete cat_list;
mParentChildCategoryTree.erase(id);
}
addChangedMask(LLInventoryObserver::REMOVE, id);
obj = NULL; // delete obj
gInventory.notifyObservers();
}
// Delete a particular inventory item by ID, and remove it from the server.
void LLInventoryModel::purgeObject(const LLUUID &id)
@@ -1219,39 +1282,56 @@ BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer) const
return mObservers.find(observer) != mObservers.end();
}
// Call this method when it's time to update everyone on a new state,
// by default, the inventory model will not update observers
// automatically.
// The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328]
void LLInventoryModel::notifyObservers(const std::string service_name)
void LLInventoryModel::idleNotifyObservers()
{
if (mModifyMask == LLInventoryObserver::NONE && (mChangedItemIDs.size() == 0))
{
return;
}
notifyObservers();
}
// Call this method when it's time to update everyone on a new state.
void LLInventoryModel::notifyObservers()
{
if (mIsNotifyObservers)
{
// Within notifyObservers, something called notifyObservers
// again. This type of recursion is unsafe because it causes items to be
// processed twice, and this can easily lead to infinite loops.
llwarns << "Call was made to notifyObservers within notifyObservers!" << llendl;
return;
}
mIsNotifyObservers = TRUE;
for (observer_list_t::iterator iter = mObservers.begin();
iter != mObservers.end(); )
{
LLInventoryObserver* observer = *iter;
if (service_name.empty())
{
observer->changed(mModifyMask);
}
else
{
observer->mMessageName = service_name;
observer->changed(mModifyMask);
}
observer->changed(mModifyMask);
// safe way to incrament since changed may delete entries! (@!##%@!@&*!)
// safe way to increment since changed may delete entries! (@!##%@!@&*!)
iter = mObservers.upper_bound(observer);
}
mModifyMask = LLInventoryObserver::NONE;
mChangedItemIDs.clear();
mIsNotifyObservers = FALSE;
}
// store flag for change
// and id of object change applies to
void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
{
if (mIsNotifyObservers)
{
// Something marked an item for change within a call to notifyObservers
// (which is in the process of processing the list of items marked for change).
// This means the change may fail to be processed.
llwarns << "Adding changed mask within notify observers! Change will likely be lost." << llendl;
}
mModifyMask |= mask;
if (referent.notNull())
{
@@ -1266,32 +1346,7 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
}
}
// This method to prepares a set of mock inventory which provides
// minimal functionality before the actual arrival of inventory.
/*
void LLInventoryModel::mock(const LLUUID& root_id)
{
llinfos << "LLInventoryModel::mock() " << root_id << llendl;
if(root_id.isNull())
{
llwarns << "Not a valid root id" << llendl;
return;
}
LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(
root_id,
LLUUID::null,
LLAssetType::AT_CATEGORY,
NEW_CATEGORY_NAMES[LLFolderType::FT_ROOT_CATEGORY],
gAgent.getID());
addCategory(cat);
gInventory.buildParentChildMap();
}
*/
//If we get back a normal response, handle it here
// Note: this is the responder used in "fetchInventory" cap,
// this is not responder for "WebFetchInventoryDescendents" or "agent/inventory" cap
// If we get back a normal response, handle it here
void LLInventoryModel::fetchInventoryResponder::result(const LLSD& content)
{
start_new_inventory_observer();
@@ -1352,16 +1407,16 @@ void LLInventoryModel::fetchInventoryResponder::result(const LLSD& content)
{
changes |= gInventory.updateItem(*it);
}
gInventory.notifyObservers("fetchinventory");
gInventory.notifyObservers();
gViewerWindow->getWindow()->decBusyCount();
}
//If we get back an error (not found, etc...), handle it here
void LLInventoryModel::fetchInventoryResponder::error(U32 status, const std::string& reason)
{
LL_INFOS("Inventory") << "fetchInventory::error "
<< status << ": " << reason << LL_ENDL;
gInventory.notifyObservers("fetchinventory");
llinfos << "fetchInventory::error "
<< status << ": " << reason << llendl;
gInventory.notifyObservers();
}
bool LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id) const
@@ -1462,7 +1517,7 @@ void fetchDescendentsResponder::result(const LLSD& content)
titem->setParent(lost_uuid);
titem->updateParentOnServer(FALSE);
gInventory.updateItem(titem);
gInventory.notifyObservers("fetchDescendents");
gInventory.notifyObservers();
}
}
@@ -1539,7 +1594,7 @@ void fetchDescendentsResponder::result(const LLSD& content)
LLInventoryModel::stopBackgroundFetch();
}
gInventory.notifyObservers("fetchDescendents");
gInventory.notifyObservers();
}
//If we get back an error (not found, etc...), handle it here
@@ -1572,7 +1627,7 @@ void fetchDescendentsResponder::error(U32 status, const std::string& reason)
LLInventoryModel::stopBackgroundFetch();
}
}
gInventory.notifyObservers("fetchDescendents");
gInventory.notifyObservers();
}
//static Bundle up a bunch of requests to send all at once.
@@ -1954,6 +2009,11 @@ void LLInventoryModel::addCategory(LLViewerInventoryCategory* category)
//llinfos << "LLInventoryModel::addCategory()" << llendl;
if(category)
{
// We aren't displaying the Meshes folder
if (category->getPreferredType() == LLFolderType::FT_MESH)
{
return;
}
// Insert category uniquely into the map
mCategoryMap[category->getUUID()] = category; // LLPointer will deref and delete the old one
//mInventory[category->getUUID()] = category;
@@ -1962,7 +2022,7 @@ void LLInventoryModel::addCategory(LLViewerInventoryCategory* category)
void LLInventoryModel::addItem(LLViewerInventoryItem* item)
{
//llinfos << "LLInventoryModel::addItem()" << llendl;
llassert(item);
if(item)
{
// This can happen if assettype enums from llassettype.h ever change.
@@ -2030,8 +2090,8 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const
descendents_actual += update.mDescendentDelta;
cat->setDescendentCount(descendents_actual);
cat->setVersion(++version);
llinfos << "accounted: '" << cat->getName() << "' "
<< version << " with " << descendents_actual
lldebugs << "accounted: '" << cat->getName() << "' "
<< version << " with " << descendents_actual
<< " descendents." << llendl;
}
}
@@ -3214,7 +3274,9 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
}
LLUUID tid;
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, tid);
#ifndef LL_RELEASE_FOR_DOWNLOAD
llinfos << "Bulk inventory: " << tid << llendl;
#endif
update_map_t update;
cat_array_t folders;
@@ -3342,7 +3404,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
LLInventoryView::sWearNewClothing = FALSE;
}
if (tid == LLInventoryView::sWearNewClothingTransactionID)
if (tid.notNull() && tid == LLInventoryView::sWearNewClothingTransactionID)
{
count = wearable_ids.size();
for (i = 0; i < count; ++i)
@@ -3428,6 +3490,9 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**)
{
cat->setVersion(version);
cat->setDescendentCount(descendents);
// Get this UUID on the changed list so that whatever's listening for it
// will get triggered.
gInventory.addChangedMask(LLInventoryObserver::INTERNAL, cat->getUUID());
}
gInventory.notifyObservers();
}

View File

@@ -131,6 +131,7 @@ public:
public:
LLInventoryModel();
~LLInventoryModel();
void cleanupInventory();
//<edit>
//protected:
//</edit>
@@ -375,7 +376,7 @@ public:
LLUUID createNewCategory(const LLUUID& parent_id,
LLFolderType::EType preferred_type,
const std::string& name);
// 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
@@ -446,10 +447,13 @@ public:
**/
public:
// Call to explicitly update everyone on a new state. The optional argument
// 'service_name' is used by Agent Inventory Service [DEV-20328]
void notifyObservers(const std::string service_name="");
// Called by the idle loop. Only updates if new state is detected. Call
// notifyObservers() manually to update regardless of whether state change
// has been indicated.
void idleNotifyObservers();
// Call to explicitly update everyone on a new state.
void notifyObservers();
// Allows outsiders to tell the inventory if something has
// been changed 'under the hood', but outside the control of the
// inventory. The next notify will include that notification.
@@ -459,6 +463,9 @@ protected:
// Updates all linked items pointing to this id.
void addChangedMaskForLinks(const LLUUID& object_id, U32 mask);
private:
// Flag set when notifyObservers is being called, to look for bugs
// where it's called recursively.
BOOL mIsNotifyObservers;
// Variables used to track what has changed since the last notify.
U32 mModifyMask;
changed_items_t mChangedItemIDs;

View File

@@ -44,7 +44,7 @@
#include "llcharacter.h"
#include "llviewercontrol.h"
#include "llviewervisualparam.h"
#include "llvoavatar.h"
#include "llvoavatarself.h"
#include "lldriverparam.h"
typedef std::map<std::string, std::string> controller_map_t;
@@ -497,9 +497,9 @@ BOOL LLPhysicsMotionController::onUpdate(F32 time, U8* joint_mask)
{
// Skip if disabled globally.
static const LLCachedControl<bool> avatar_physics("AvatarPhysics",false);
bool supports_physics = !avatar_physics || (!((LLVOAvatar*)mCharacter)->isSelf() && !((LLVOAvatar*)mCharacter)->mSupportsPhysics);
bool physics_unsupported = !avatar_physics || (!((LLVOAvatar*)mCharacter)->isSelf() && !((LLVOAvatar*)mCharacter)->mSupportsPhysics);
//Treat lod 0 as AvatarPhyiscs:FALSE. AvatarPhyiscs setting is superfluous unless we decide to hook it into param sending.
if (supports_physics || !LLVOAvatar::sPhysicsLODFactor)
if (physics_unsupported || !LLVOAvatar::sPhysicsLODFactor)
{
if(!mIsDefault)
{
@@ -510,8 +510,8 @@ BOOL LLPhysicsMotionController::onUpdate(F32 time, U8* joint_mask)
}
mCharacter->updateVisualParams();
}
if(!supports_physics) //Only use emerald physics if avatarphysiscs is really off, or the client doesn't seem to support new physics.
((LLVOAvatar*)mCharacter)->idleUpdateBoobEffect(); //Fall back to emerald physics
if(physics_unsupported) //Only use emerald physics if avatarphysiscs is really off, or the client doesn't seem to support new physics.
((LLVOAvatar*)mCharacter)->idleUpdateBoobEffect(); //Fall back to emerald physics
return TRUE;
}
@@ -758,7 +758,7 @@ BOOL LLPhysicsMotion::onUpdate(F32 time)
const F32 area_for_this_setting = area_for_max_settings + (area_for_min_settings-area_for_max_settings)*(1.0-lod_factor);
const F32 pixel_area = (F32) sqrt(mCharacter->getPixelArea());
const BOOL is_self = (dynamic_cast<LLVOAvatar *>(mCharacter) != NULL && ((LLVOAvatar*)mCharacter)->isSelf());
const BOOL is_self = (dynamic_cast<LLVOAvatarSelf *>(mCharacter) != NULL);
if ((pixel_area > area_for_this_setting) || is_self)
{
const F32 position_diff_local = llabs(mPositionLastUpdate_local-position_new_local_clamped);

View File

@@ -391,6 +391,11 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
object = (LLViewerObject*)object->getParent();
}
if (!object)
{
return TRUE; // unexpected, but escape
}
// Object is an avatar, so check for mute by id.
LLVOAvatar* avatar = (LLVOAvatar*)object;
std::string name = avatar->getFullname();

View File

@@ -1077,3 +1077,9 @@ LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const
}
return NULL;
}
void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const std::string& name, bool is_group)
{
rename(name);
gInventory.addChangedMask(LLInventoryObserver::LABEL, getUUID());
gInventory.notifyObservers();
}

View File

@@ -145,6 +145,8 @@ public:
LLViewerInventoryItem *getLinkedItem() const;
LLViewerInventoryCategory *getLinkedCategory() const;
// callback
void onCallingCardNameLookup(const LLUUID& id, const std::string& name, bool is_group);
protected:
BOOL mIsComplete;
LLTransactionID mTransactionID;

View File

@@ -2390,7 +2390,7 @@ class LLSelfRemoveAllAttachments : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
LLAgentWearables::userRemoveAllAttachments(NULL);
LLAgentWearables::userRemoveAllAttachments();
return true;
}
};
@@ -9173,7 +9173,7 @@ class LLEditEnableTakeOff : public view_listener_t
if ( !(rlv_handler_t::isEnabled()) || (gRlvWearableLocks.canRemove(type)) )
// [/RLVa:KB]
new_value = LLAgentWearables::selfHasWearable((void *)type);
new_value = LLAgentWearables::selfHasWearable(type);
gMenuHolder->findControl(control_name)->setValue(new_value);
return false;
@@ -9187,14 +9187,14 @@ class LLEditTakeOff : public view_listener_t
std::string clothing = userdata.asString();
if (clothing == "all")
{
LLAgentWearables::userRemoveAllClothes(NULL);
LLAgentWearables::userRemoveAllClothes();
}
else
{
LLWearableType::EType type = LLWearableType::typeNameToType(clothing);
if (type >= LLWearableType::WT_SHAPE
&& type < LLWearableType::WT_COUNT)
LLAgentWearables::userRemoveWearable((void*)type);
LLAgentWearables::userRemoveWearable(type);
}
return true;
}

View File

@@ -201,7 +201,7 @@ public:
S32 mNumUnknownKills;
S32 mNumDeadObjects;
S32 mMinNumDeadObjects;
protected:
//protected:
std::vector<U64> mOrphanParents; // LocalID/ip,port of orphaned objects
std::vector<OrphanInfo> mOrphanChildren; // UUID's of orphaned objects
S32 mNumOrphans;

View File

@@ -190,6 +190,7 @@
#include "llviewerjoystick.h"
#include "llviewernetwork.h"
#include "llpostprocess.h"
#include "llwearablelist.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
@@ -575,6 +576,57 @@ public:
ypos += y_inc;
S32 total_objects = gObjectList.getNumObjects();
S32 ID_objects = gObjectList.mUUIDObjectMap.size();
S32 dead_objects = gObjectList.mNumDeadObjects;
S32 dead_object_list = gObjectList.mDeadObjects.size();
S32 dead_object_check = 0;
S32 total_avatars = 0;
S32 ID_avatars = gObjectList.mUUIDAvatarMap.size();
S32 dead_avatar_list = 0;
S32 dead_avatar_check = 0;
S32 orphan_parents = gObjectList.getOrphanParentCount();
S32 orphan_parents_check = gObjectList.mOrphanParents.size();
S32 orphan_children = gObjectList.mOrphanChildren.size();
S32 orphan_total = gObjectList.getOrphanCount();
S32 orphan_child_attachments = 0;
for(U32 i = 0;i<gObjectList.mObjects.size();++i)
{
LLViewerObject *obj = gObjectList.mObjects[i];
if(obj)
{
if(obj->isAvatar())
++total_avatars;
if(obj->isDead())
{
++dead_object_check;
if(obj->isAvatar())
++dead_avatar_check;
}
}
}
for(std::set<LLUUID>::iterator it = gObjectList.mDeadObjects.begin();it!=gObjectList.mDeadObjects.end();++it)
{
LLViewerObject *obj = gObjectList.findObject(*it);
if(obj && obj->isAvatar())
++dead_avatar_list;
}
for(std::vector<LLViewerObjectList::OrphanInfo>::iterator it = gObjectList.mOrphanChildren.begin();it!=gObjectList.mOrphanChildren.end();++it)
{
LLViewerObject *obj = gObjectList.findObject(it->mChildInfo);
if(obj && obj->isAttachment())
++orphan_child_attachments;
}
addText(xpos,ypos, llformat("%d|%d (%d|%d|%d) Objects", total_objects, ID_objects, dead_objects, dead_object_list,dead_object_check));
ypos += y_inc;
addText(xpos,ypos, llformat("%d|%d (%d|%d) Avatars", total_avatars, ID_avatars, dead_avatar_list,dead_avatar_check));
ypos += y_inc;
addText(xpos,ypos, llformat("%d (%d|%d %d %d) Orphans", orphan_total, orphan_parents, orphan_parents_check,orphan_children, orphan_child_attachments));
ypos += y_inc;
#if MESH_ENABLED
if (gMeshRepo.meshRezEnabled())
{
@@ -1941,6 +1993,8 @@ void LLViewerWindow::shutdownGL()
gSky.cleanup();
stop_glerror();
LLWearableList::instance().cleanup() ;
gTextureList.shutdown();
stop_glerror();

View File

@@ -6858,7 +6858,7 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object)
}
if(!item_id.isNull())
{
mUnsupportedAttachmentPoints[attachmentID] = item_id;
mUnsupportedAttachmentPoints[attachmentID] = std::pair<LLUUID,LLUUID>(item_id,viewer_object->getID());
if (viewer_object->isSelected())
{
LLSelectMgr::getInstance()->updateSelectionCenter();
@@ -7128,11 +7128,11 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
}
if(!item_id.isNull())
{
std::map<S32, LLUUID>::iterator iter = mUnsupportedAttachmentPoints.begin();
std::map<S32, LLUUID>::iterator end = mUnsupportedAttachmentPoints.end();
std::map<S32, std::pair<LLUUID,LLUUID> >::iterator iter = mUnsupportedAttachmentPoints.begin();
std::map<S32, std::pair<LLUUID,LLUUID> >::iterator end = mUnsupportedAttachmentPoints.end();
for( ; iter != end; ++iter)
{
if((*iter).second == item_id)
if((*iter).second.first == item_id)
{
mUnsupportedAttachmentPoints.erase((*iter).first);
if (isSelf())
@@ -7376,10 +7376,10 @@ BOOL LLVOAvatar::isWearingAttachment( const LLUUID& inv_item_id )
// <edit> testzone attachpt
BOOL LLVOAvatar::isWearingUnsupportedAttachment( const LLUUID& inv_item_id )
{
std::map<S32, LLUUID>::iterator end = mUnsupportedAttachmentPoints.end();
for(std::map<S32, LLUUID>::iterator iter = mUnsupportedAttachmentPoints.begin(); iter != end; ++iter)
std::map<S32, std::pair<LLUUID,LLUUID> >::iterator end = mUnsupportedAttachmentPoints.end();
for(std::map<S32, std::pair<LLUUID,LLUUID> >::iterator iter = mUnsupportedAttachmentPoints.begin(); iter != end; ++iter)
{
if((*iter).second == inv_item_id)
if((*iter).second.first == inv_item_id)
{
return TRUE;
}

View File

@@ -805,7 +805,7 @@ public:
const std::string getAttachedPointName(const LLUUID& inv_item_id);
// <edit>
std::map<S32, LLUUID> mUnsupportedAttachmentPoints;
std::map<S32, std::pair<LLUUID/*inv*/,LLUUID/*object*/> > mUnsupportedAttachmentPoints;
// </edit>
/** Wearables

View File

@@ -730,7 +730,7 @@ void LLWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload_bake
}
gAgentAvatarp->updateVisualParams();
gAgentAvatarp->updateMeshTextures();
gAgentAvatarp->wearableUpdated(type, FALSE);
// if( upload_bake )
// {
@@ -797,6 +797,15 @@ void LLWearable::copyDataFrom( LLWearable* src )
}
}
void LLWearable::setItemID(const LLUUID& item_id)
{
mItemID = item_id;
}
const LLUUID& LLWearable::getItemID() const
{
return mItemID;
}
void LLWearable::setType(LLWearableType::EType type)
{
mType = type;
@@ -859,6 +868,20 @@ void LLWearable::readFromAvatar()
}
void LLWearable::setLabelUpdated() const
{
gInventory.addChangedMask(LLInventoryObserver::LABEL, getItemID());
}
void LLWearable::refreshName()
{
LLUUID item_id = getItemID();
LLInventoryItem* item = gInventory.getItem(item_id);
if( item )
{
mName = item->getName();
}
}
struct LLWearableSaveData
{

View File

@@ -108,7 +108,17 @@ public:
static void setCurrentDefinitionVersion( S32 version ) { LLWearable::sCurrentDefinitionVersion = version; }
friend std::ostream& operator<<(std::ostream &s, const LLWearable &w);
void setItemID(const LLUUID& item_id);
// Something happened that requires the wearable's label to be updated (e.g. worn/unworn).
void setLabelUpdated() const;
// the wearable was worn. make sure the name of the wearable object matches the LLViewerInventoryItem,
// not the wearable asset itself.
void refreshName();
private:
typedef std::map<S32, LLUUID> te_map_t;
static S32 sCurrentDefinitionVersion; // Depends on the current state of the avatar_lad.xml.
S32 mDefinitionVersion; // Depends on the state of the avatar_lad.xml when this asset was created.
@@ -122,8 +132,9 @@ public:
typedef std::map<S32, F32> param_map_t;
param_map_t mVisualParamMap; // maps visual param id to weight
typedef std::map<S32, LLUUID> te_map_t;
te_map_t mTEMap; // maps TE to Image ID
LLUUID mItemID; // ID of the inventory item in the agent's inventory
};
#endif // LL_LLWEARABLE_H

View File

@@ -43,18 +43,13 @@
#include "llviewerstats.h"
#include "llnotificationsutil.h"
// Globals
LLWearableList gWearableList; // Globally constructed; be careful that there's no dependency with gAgent.
// Callback struct
struct LLWearableArrivedData
{
LLWearableArrivedData(
LLAssetType::EType asset_type,
LLWearableArrivedData(LLAssetType::EType asset_type,
const std::string& wearable_name,
void(*asset_arrived_callback)(LLWearable*, void* userdata),
void* userdata )
:
void* userdata) :
mAssetType( asset_type ),
mCallback( asset_arrived_callback ),
mUserdata( userdata ),
@@ -75,6 +70,11 @@ struct LLWearableArrivedData
// LLWearableList
LLWearableList::~LLWearableList()
{
llassert_always(mList.empty()) ;
}
void LLWearableList::cleanup()
{
for_each(mList.begin(), mList.end(), DeletePairedPointer());
mList.clear();
@@ -90,8 +90,7 @@ void LLWearableList::getAsset( const LLAssetID& assetID, const std::string& wear
}
else
{
gAssetStorage->getAssetData(
assetID,
gAssetStorage->getAssetData(assetID,
asset_type,
LLWearableList::processGetAssetReply,
(void*)new LLWearableArrivedData( asset_type, wearable_name, asset_arrived_callback, userdata ),
@@ -110,8 +109,7 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID
{
LL_WARNS("Wearable") << "Bad Wearable Asset: missing file." << LL_ENDL;
}
else
if( status >= 0 )
else if (status >= 0)
{
// read the file
LLFILE* fp = LLFile::fopen(std::string(filename), "rb"); /*Flawfinder: ignore*/
@@ -180,7 +178,7 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID
if (wearable) // success
{
gWearableList.mList[ uuid ] = wearable;
LLWearableList::instance().mList[ uuid ] = wearable;
LL_DEBUGS("Wearable") << "processGetAssetReply()" << LL_ENDL;
LL_DEBUGS("Wearable") << wearable << LL_ENDL;
}

View File

@@ -37,11 +37,19 @@
#include "lluuid.h"
#include "llassetstorage.h"
class LLWearableList
// Globally constructed; be careful that there's no dependency with gAgent.
/*
BUG: mList's system of mapping between assetIDs and wearables is flawed
since LLWearable* has an associated itemID, and you can have multiple
inventory items pointing to the same asset (i.e. more than one ItemID
per assetID). EXT-6252
*/
class LLWearableList : public LLSingleton<LLWearableList>
{
public:
LLWearableList() {}
~LLWearableList();
void cleanup() ;
S32 getLength() { return mList.size(); }
@@ -62,9 +70,7 @@ public:
protected:
LLWearable* generateNewWearable(); // used for the create... functions
private:
std::map< LLUUID, LLWearable* > mList;
std::map<LLUUID, LLWearable*> mList;
};
extern LLWearableList gWearableList;
#endif // LL_LLWEARABLELIST_H

View File

@@ -2382,6 +2382,8 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
root->getVObj()->isAttachment())
{
LLDrawable* rootparent = root->getParent();
static const LLCachedControl<bool> draw_orphans("ShyotlDrawOrphanAttachments",false);
if (rootparent) // this IS sometimes NULL
{
LLViewerObject *vobj = rootparent->getVObj();
@@ -2389,12 +2391,16 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
if (vobj) // this test may not be needed, see above
{
const LLVOAvatar* av = vobj->asAvatar();
if (av && av->isImpostor())
if (av && av->isImpostor() )
{
return;
return;
}
else if(!draw_orphans && (!av || av->isDead()))
return;
}
}
else if(!draw_orphans)
return;
}
sCull->pushBridge((LLSpatialBridge*) drawablep);
}

View File

@@ -17,6 +17,7 @@
#include "llviewerprecompiledheaders.h"
#include "llfloateravatarlist.h"
#include "llavatarnamecache.h"
#include "llcallbacklist.h"
#include "llfloaterbeacons.h"
#include "llfloaterchat.h"
#include "llfloaterdaycycle.h"

View File

@@ -845,14 +845,14 @@ void RlvForceWear::done()
return;
}
// If all the assets are available locally then "pWearData" will be freed *before* the last "gWearableList.getAsset()" call returns
// If all the assets are available locally then "pWearData" will be freed *before* the last "LLWearableList::instance().getAsset()" call returns
bool fContinue = true; LLWearableHoldingPattern::found_list_t::const_iterator itWearable = pWearData->mFoundList.begin();
while ( (fContinue) && (itWearable != pWearData->mFoundList.end()) )
{
const LLFoundData* pFound = *itWearable;
++itWearable;
fContinue = (itWearable != pWearData->mFoundList.end());
gWearableList.getAsset(pFound->mAssetID, pFound->mName, pFound->mAssetType, wear_inventory_category_on_avatar_loop, (void*)pWearData);
LLWearableList::instance().getAsset(pFound->mAssetID, pFound->mName, pFound->mAssetType, wear_inventory_category_on_avatar_loop, (void*)pWearData);
}
m_addWearables.clear();

View File

@@ -16,6 +16,7 @@
#include "llviewerprecompiledheaders.h"
#include "llagent.h"
#include "llcallbacklist.h"
#include "llstartup.h"
#include "llviewerobject.h"
#include "llvoavatar.h"
@@ -142,7 +143,7 @@ void RlvInventory::fetchWornItems()
// Fetch all currently worn clothing layers and body parts
for (int type = 0; type < LLWearableType::WT_COUNT; type++)
{
const LLUUID& idItem = gAgentWearables.getWearableItemID((LLWearableType::EType)type);
const LLUUID idItem = gAgentWearables.getWearableItemID((LLWearableType::EType)type);
if (idItem.notNull())
idItems.push_back(idItem);
}

View File

@@ -181,6 +181,11 @@ void RlvAttachmentLocks::addAttachmentLock(const LLUUID& idAttachObj, const LLUU
#endif // RLV_RELEASE
m_AttachObjRem.insert(std::pair<LLUUID, LLUUID>(idAttachObj, idRlvObj));
if(LLViewerObject *pObj = gObjectList.findObject(idAttachObj)) //OK
{
gInventory.addChangedMask(LLInventoryObserver::LABEL, pObj->getAttachmentItemID());
gInventory.notifyObservers();
}
updateLockedHUD();
}
@@ -197,6 +202,27 @@ void RlvAttachmentLocks::addAttachmentPointLock(S32 idxAttachPt, const LLUUID& i
if (eLock & RLV_LOCK_REMOVE)
{
m_AttachPtRem.insert(std::pair<S32, LLUUID>(idxAttachPt, idRlvObj));
LLVOAvatar* pAvatar = gAgentAvatarp;
if (pAvatar)
{
bool need_update = false;
LLVOAvatar::attachment_map_t::iterator iter = pAvatar->mAttachmentPoints.find(idxAttachPt);
if (iter != pAvatar->mAttachmentPoints.end())
{
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = iter->second->mAttachedObjects.begin();
attachment_iter != iter->second->mAttachedObjects.end();++attachment_iter)
{
LLViewerObject* attached_object = (*attachment_iter);
if(attached_object)
{
gInventory.addChangedMask(LLInventoryObserver::LABEL, attached_object->getAttachmentItemID());
need_update = true;
}
}
}
if(need_update)
gInventory.notifyObservers();
}
updateLockedHUD();
}
if (eLock & RLV_LOCK_ADD)
@@ -314,6 +340,11 @@ void RlvAttachmentLocks::removeAttachmentLock(const LLUUID& idAttachObj, const L
if (idRlvObj == itAttachObj->second)
{
m_AttachObjRem.erase(itAttachObj);
if(LLViewerObject *pObj = gObjectList.findObject(idAttachObj)) //OK
{
gInventory.addChangedMask(LLInventoryObserver::LABEL, pObj->getAttachmentItemID());
gInventory.notifyObservers();
}
updateLockedHUD();
break;
}
@@ -331,6 +362,7 @@ void RlvAttachmentLocks::removeAttachmentPointLock(S32 idxAttachPt, const LLUUID
if (eLock & RLV_LOCK_REMOVE)
{
bool removed_entry = false;
RLV_ASSERT( m_AttachPtRem.lower_bound(idxAttachPt) != m_AttachPtRem.upper_bound(idxAttachPt) ); // The lock should always exist
for (rlv_attachptlock_map_t::iterator itAttachPt = m_AttachPtRem.lower_bound(idxAttachPt),
endAttachPt = m_AttachPtRem.upper_bound(idxAttachPt); itAttachPt != endAttachPt; ++itAttachPt)
@@ -338,10 +370,38 @@ void RlvAttachmentLocks::removeAttachmentPointLock(S32 idxAttachPt, const LLUUID
if (idRlvObj == itAttachPt->second)
{
m_AttachPtRem.erase(itAttachPt);
removed_entry = true;
updateLockedHUD();
break;
}
}
if(removed_entry)
{
if(m_AttachPtRem.find(idxAttachPt) == m_AttachPtRem.end())
{
LLVOAvatar* pAvatar = gAgentAvatarp;
if (pAvatar)
{
bool need_update = false;
LLVOAvatar::attachment_map_t::iterator iter = pAvatar->mAttachmentPoints.find(idxAttachPt);
if (iter != pAvatar->mAttachmentPoints.end())
{
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = iter->second->mAttachedObjects.begin();
attachment_iter != iter->second->mAttachedObjects.end();++attachment_iter)
{
LLViewerObject* attached_object = (*attachment_iter);
if(attached_object)
{
gInventory.addChangedMask(LLInventoryObserver::LABEL, attached_object->getAttachmentItemID());
need_update = true;
}
}
if(need_update)
gInventory.notifyObservers();
}
}
}
}
}
if (eLock & RLV_LOCK_ADD)
{
@@ -362,7 +422,7 @@ void RlvAttachmentLocks::removeAttachmentPointLock(S32 idxAttachPt, const LLUUID
void RlvAttachmentLocks::updateLockedHUD()
{
LLVOAvatar* pAvatar = gAgentAvatarp;
if (!pAvatar)
if (!pAvatar || pAvatar->isDead())
return;
m_fHasLockedHUD = false;
@@ -814,7 +874,15 @@ void RlvWearableLocks::addWearableTypeLock(LLWearableType::EType eType, const LL
// NOTE: m_WearableTypeXXX can contain duplicate <eType, idRlvObj> pairs (ie @remoutfit:shirt=n,remoutfit=n from the same object)
if (eLock & RLV_LOCK_REMOVE)
{
m_WearableTypeRem.insert(std::pair<LLWearableType::EType, LLUUID>(eType, idRlvObj));
LLUUID item_id = gAgentWearables.getWearableItemID(eType);
if(item_id.notNull())
{
gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
gInventory.notifyObservers();
}
}
if (eLock & RLV_LOCK_ADD)
m_WearableTypeAdd.insert(std::pair<LLWearableType::EType, LLUUID>(eType, idRlvObj));
}
@@ -889,15 +957,29 @@ void RlvWearableLocks::removeWearableTypeLock(LLWearableType::EType eType, const
if (eLock & RLV_LOCK_REMOVE)
{
RLV_ASSERT( m_WearableTypeRem.lower_bound(eType) != m_WearableTypeRem.upper_bound(eType) ); // The lock should always exist
bool removed_entry = false;
for (rlv_wearabletypelock_map_t::iterator itWearableType = m_WearableTypeRem.lower_bound(eType),
endWearableType = m_WearableTypeRem.upper_bound(eType); itWearableType != endWearableType; ++itWearableType)
{
if (idRlvObj == itWearableType->second)
{
m_WearableTypeRem.erase(itWearableType);
removed_entry = true;
break;
}
}
if(removed_entry)
{
if(m_WearableTypeRem.find(eType) == m_WearableTypeRem.end())
{
LLUUID item_id = gAgentWearables.getWearableItemID(eType);
if(item_id.notNull())
{
gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
gInventory.notifyObservers();
}
}
}
}
if (eLock & RLV_LOCK_ADD)
{

View File

@@ -26,78 +26,6 @@
#include "llviewerinventory.h"
#include "rlvviewer2.h"
// ============================================================================
// From llappearancemgr.cpp
// Shim class to allow arbitrary boost::bind
// expressions to be run as one-time idle callbacks.
//
// TODO: rework idle function spec to take a boost::function in the first place.
class OnIdleCallbackOneTime
{
public:
OnIdleCallbackOneTime(nullary_func_t callable):
mCallable(callable)
{
}
static void onIdle(void *data)
{
gIdleCallbacks.deleteFunction(onIdle, data);
OnIdleCallbackOneTime* self = reinterpret_cast<OnIdleCallbackOneTime*>(data);
self->call();
delete self;
}
void call()
{
mCallable();
}
private:
nullary_func_t mCallable;
};
void doOnIdleOneTime(nullary_func_t callable)
{
OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable);
gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor);
}
// Shim class to allow generic boost functions to be run as
// recurring idle callbacks. Callable should return true when done,
// false to continue getting called.
//
// TODO: rework idle function spec to take a boost::function in the first place.
class OnIdleCallbackRepeating
{
public:
OnIdleCallbackRepeating(bool_func_t callable):
mCallable(callable)
{
}
// Will keep getting called until the callable returns true.
static void onIdle(void *data)
{
OnIdleCallbackRepeating* self = reinterpret_cast<OnIdleCallbackRepeating*>(data);
bool done = self->call();
if (done)
{
gIdleCallbacks.deleteFunction(onIdle, data);
delete self;
}
}
bool call()
{
return mCallable();
}
private:
bool_func_t mCallable;
};
void doOnIdleRepeating(bool_func_t callable)
{
OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable);
gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor);
}
// ============================================================================
// From llinventoryobserver.cpp

View File

@@ -29,18 +29,6 @@
#include "boost/function.hpp"
// ============================================================================
// From llappearancemgr.h
typedef boost::function<void ()> nullary_func_t;
typedef boost::function<bool ()> bool_func_t;
// Call a given callable once in idle loop.
void doOnIdleOneTime(nullary_func_t callable);
// Repeatedly call a callable in idle loop until it returns true.
void doOnIdleRepeating(bool_func_t callable);
// ============================================================================
// From llinventoryobserver.h