For DEV-34223: Avatar Pipeline Project - M6 (Current Outfit Folder, Appearance Side Panel) - brought merge branch changes from avatar-pipeline/viewer-2.0.0-3_cwf-7_merge into viewer-2.0.0-3.
svn merge -r132878:132947 svn+ssh://svn.lindenlab.com/svn/linden/branches/avatar-pipeline/viewer-2.0.0-3_cwf-7_mergemaster
parent
3dfa1e4ab9
commit
73d152093d
|
|
@ -80,27 +80,27 @@ LLAssetDictionary::LLAssetDictionary()
|
|||
{
|
||||
// DESCRIPTION TYPE NAME HUMAN NAME CATEGORY NAME DRAG&DROP CAN LINK? PROTECTED?
|
||||
// |--------------------|-----------|-------------------|-------------------|---------------|-----------|-----------|
|
||||
addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", "Textures", DAD_TEXTURE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", "Sounds", DAD_SOUND, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", "Calling Cards", DAD_CALLINGCARD, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", "Landmarks", DAD_LANDMARK, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", "Scripts", DAD_NONE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", "Textures", DAD_TEXTURE, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", "Sounds", DAD_SOUND, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", "Calling Cards", DAD_CALLINGCARD, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", "Landmarks", DAD_LANDMARK, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", "Scripts", DAD_NONE, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", "Clothing", DAD_CLOTHING, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", "Objects", DAD_OBJECT, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", "Notecards", DAD_NOTECARD, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", "Notecards", DAD_NOTECARD, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", "New Folder", DAD_CATEGORY, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_ROOT_CATEGORY, new AssetEntry("ROOT_CATEGORY", "root", "root", "Inventory", DAD_ROOT_CATEGORY, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", "Scripts", DAD_SCRIPT, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", "Scripts", DAD_NONE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", "Uncompressed Images", DAD_NONE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", "Scripts", DAD_SCRIPT, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", "Scripts", DAD_NONE, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", "Uncompressed Images", DAD_NONE, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", "Body Parts", DAD_BODYPART, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_TRASH, new AssetEntry("TRASH", "trash", "trash", "Trash", DAD_NONE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot", "snapshot", "Photo Album", DAD_NONE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_LOST_AND_FOUND, new AssetEntry("LOST_AND_FOUND", "lstndfnd", "lost and found", "Lost And Found", DAD_NONE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", "Uncompressed SoundS", DAD_NONE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", "Uncompressed Images", DAD_NONE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", "Uncompressed Images", DAD_NONE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", "Animations", DAD_ANIMATION, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", "Uncompressed SoundS", DAD_NONE, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", "Uncompressed Images", DAD_NONE, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", "Uncompressed Images", DAD_NONE, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", "Animations", DAD_ANIMATION, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", "Gestures", DAD_GESTURE, TRUE, TRUE));
|
||||
addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", "New Folder", DAD_NONE, FALSE, TRUE));
|
||||
addEntry(LLAssetType::AT_FAVORITE, new AssetEntry("FAVORITE", "favorite", "favorite", "favorite", DAD_NONE, FALSE, TRUE));
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ set(viewer_SOURCE_FILES
|
|||
llagentui.cpp
|
||||
llagentwearables.cpp
|
||||
llanimstatelabels.cpp
|
||||
llappearancemgr.cpp
|
||||
llappviewer.cpp
|
||||
llassetuploadresponders.cpp
|
||||
llassetuploadqueue.cpp
|
||||
|
|
@ -532,6 +533,7 @@ set(viewer_HEADER_FILES
|
|||
llassetuploadresponders.h
|
||||
llassetuploadqueue.h
|
||||
llaudiosourcevo.h
|
||||
llappearancemgr.h
|
||||
llavataractions.h
|
||||
llavatariconctrl.h
|
||||
llavatarlist.h
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "llwearable.h"
|
||||
#include "llwearablelist.h"
|
||||
#include "llgesturemgr.h"
|
||||
#include "llappearancemgr.h"
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
|
|
@ -76,11 +77,9 @@ public:
|
|||
initial_wearable_data_vec_t mAgentInitialWearables; // Wearables from the old agent wearables msg
|
||||
|
||||
protected:
|
||||
void processInitialWearables();
|
||||
void processWearablesMessage();
|
||||
};
|
||||
|
||||
|
||||
|
||||
LLAgentWearables gAgentWearables;
|
||||
|
||||
BOOL LLAgentWearables::mInitialWearablesUpdateReceived = FALSE;
|
||||
|
|
@ -737,7 +736,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
|
|||
gAgentWearables.mItemsAwaitingWearableUpdate.clear();
|
||||
for (S32 i=0; i < num_wearables; i++)
|
||||
{
|
||||
// Parse initial werables data from message system
|
||||
// Parse initial wearables data from message system
|
||||
U8 type_u8 = 0;
|
||||
gMessageSystem->getU8Fast(_PREHASH_WearableData, _PREHASH_WearableType, type_u8, i);
|
||||
if (type_u8 >= WT_COUNT)
|
||||
|
|
@ -1195,7 +1194,7 @@ LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name,
|
|||
if (!item) continue;
|
||||
LLPointer<LLInventoryCallback> cb = NULL;
|
||||
link_inventory_item(gAgent.getID(),
|
||||
item->getUUID(),
|
||||
item->getLinkedUUID(),
|
||||
folder_id,
|
||||
item->getName(),
|
||||
LLAssetType::AT_LINK,
|
||||
|
|
@ -1226,7 +1225,7 @@ LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name,
|
|||
|
||||
LLPointer<LLInventoryCallback> cb = NULL;
|
||||
link_inventory_item(gAgent.getID(),
|
||||
item->getUUID(),
|
||||
item->getLinkedUUID(),
|
||||
folder_id,
|
||||
item->getName(),
|
||||
LLAssetType::AT_LINK,
|
||||
|
|
@ -1781,6 +1780,57 @@ void LLAgentWearables::userRemoveAllAttachments(void* userdata)
|
|||
gMessageSystem->sendReliable(gAgent.getRegionHost());
|
||||
}
|
||||
|
||||
void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array)
|
||||
{
|
||||
// Build a compound message to send all the objects that need to be rezzed.
|
||||
S32 obj_count = obj_item_array.count();
|
||||
|
||||
// Limit number of packets to send
|
||||
const S32 MAX_PACKETS_TO_SEND = 10;
|
||||
const S32 OBJECTS_PER_PACKET = 4;
|
||||
const S32 MAX_OBJECTS_TO_SEND = MAX_PACKETS_TO_SEND * OBJECTS_PER_PACKET;
|
||||
if( obj_count > MAX_OBJECTS_TO_SEND )
|
||||
{
|
||||
obj_count = MAX_OBJECTS_TO_SEND;
|
||||
}
|
||||
|
||||
// Create an id to keep the parts of the compound message together
|
||||
LLUUID compound_msg_id;
|
||||
compound_msg_id.generate();
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
|
||||
for(S32 i = 0; i < obj_count; ++i)
|
||||
{
|
||||
if( 0 == (i % OBJECTS_PER_PACKET) )
|
||||
{
|
||||
// Start a new message chunk
|
||||
msg->newMessageFast(_PREHASH_RezMultipleAttachmentsFromInv);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->nextBlockFast(_PREHASH_HeaderData);
|
||||
msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id );
|
||||
msg->addU8Fast(_PREHASH_TotalObjects, obj_count );
|
||||
msg->addBOOLFast(_PREHASH_FirstDetachAll, true );
|
||||
}
|
||||
|
||||
const LLInventoryItem* item = obj_item_array.get(i).get();
|
||||
msg->nextBlockFast(_PREHASH_ObjectData );
|
||||
msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
|
||||
msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner());
|
||||
msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // Wear at the previous or default attachment point
|
||||
pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
|
||||
msg->addStringFast(_PREHASH_Name, item->getName());
|
||||
msg->addStringFast(_PREHASH_Description, item->getDescription());
|
||||
|
||||
if( (i+1 == obj_count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) )
|
||||
{
|
||||
// End of message chunk
|
||||
msg->sendReliable( gAgent.getRegion()->getHost() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLAgentWearables::checkWearablesLoaded() const
|
||||
{
|
||||
#ifdef SHOW_ASSERT
|
||||
|
|
@ -1812,69 +1862,29 @@ void LLAgentWearables::updateServer()
|
|||
|
||||
void LLInitialWearablesFetch::done()
|
||||
{
|
||||
// Get the complete information on the items in the library,
|
||||
// and set up an observer that will wait for that to happen.
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t item_array;
|
||||
|
||||
LLFindWearables is_wearable;
|
||||
gInventory.collectDescendentsIf(mCompleteFolders.front(),
|
||||
cat_array,
|
||||
item_array,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
is_wearable);
|
||||
S32 count = item_array.count();
|
||||
mCOFInitialWearables.reserve(count);
|
||||
|
||||
for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
|
||||
iter != item_array.end();
|
||||
iter++)
|
||||
{
|
||||
const LLViewerInventoryItem *item = (*iter).get();
|
||||
// We're only concerned with linked items in the COF. Ignore
|
||||
// any non-link items or links to folders.
|
||||
if (item->getActualType() != LLAssetType::AT_LINK)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
EWearableType type = (EWearableType) (item->getFlags() & LLInventoryItem::II_FLAGS_WEARABLES_MASK);
|
||||
// MULTI-WEARABLE: update
|
||||
InitialWearableData wearable_data(type, 0, item->getUUID(), item->getAssetUUID());
|
||||
mCOFInitialWearables.push_back(wearable_data);
|
||||
}
|
||||
|
||||
// No longer need this observer hanging around.
|
||||
gInventory.removeObserver(this);
|
||||
processInitialWearables();
|
||||
|
||||
// Fetch the wearable items from the Current Outfit Folder
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t wearable_array;
|
||||
LLFindWearables is_wearable;
|
||||
gInventory.collectDescendentsIf(mCompleteFolders.front(), cat_array, wearable_array,
|
||||
LLInventoryModel::EXCLUDE_TRASH, is_wearable);
|
||||
|
||||
if (wearable_array.count() > 0)
|
||||
{
|
||||
LLAppearanceManager::instance().updateAppearanceFromCOF();
|
||||
}
|
||||
else
|
||||
{
|
||||
processWearablesMessage();
|
||||
}
|
||||
delete this;
|
||||
}
|
||||
|
||||
// This will either grab the contents of the Current Outfit Folder if they exist,
|
||||
// or use the old-style initial agent wearables message.
|
||||
void LLInitialWearablesFetch::processInitialWearables()
|
||||
void LLInitialWearablesFetch::processWearablesMessage()
|
||||
{
|
||||
#ifdef USE_CURRENT_OUTFIT_FOLDER
|
||||
if (!mCOFInitialWearables.empty())
|
||||
{
|
||||
for (U8 i = 0; i < mCOFInitialWearables.size(); ++i)
|
||||
{
|
||||
// Fetch the wearables in the current outfit folder
|
||||
InitialWearableData *wearable_data = new InitialWearableData(mCOFInitialWearables[i]); // This will be deleted in the callback.
|
||||
if (wearable_data->mAssetID.notNull())
|
||||
{
|
||||
LLWearableList::instance().getAsset(wearable_data->mAssetID,
|
||||
LLStringUtil::null,
|
||||
LLWearableDictionary::getAssetType(wearable_data->mType),
|
||||
LLAgentWearables::onInitialWearableAssetArrived, (void*)(wearable_data));
|
||||
}
|
||||
else
|
||||
{
|
||||
llinfos << "Invalid wearable, type " << wearable_data->mType << " itemID "
|
||||
<< wearable_data->mItemID << " assetID " << wearable_data->mAssetID << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!mAgentInitialWearables.empty()) // We have an empty current outfit folder, use the message data instead.
|
||||
{
|
||||
LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
|
||||
|
|
@ -1882,7 +1892,7 @@ void LLInitialWearablesFetch::processInitialWearables()
|
|||
{
|
||||
// Populate the current outfit folder with links to the wearables passed in the message
|
||||
InitialWearableData *wearable_data = new InitialWearableData(mAgentInitialWearables[i]); // This will be deleted in the callback.
|
||||
|
||||
|
||||
if (wearable_data->mAssetID.notNull())
|
||||
{
|
||||
#ifdef USE_CURRENT_OUTFIT_FOLDER
|
||||
|
|
@ -1899,7 +1909,7 @@ void LLInitialWearablesFetch::processInitialWearables()
|
|||
else
|
||||
{
|
||||
llinfos << "Invalid wearable, type " << wearable_data->mType << " itemID "
|
||||
<< wearable_data->mItemID << " assetID " << wearable_data->mAssetID << llendl;
|
||||
<< wearable_data->mItemID << " assetID " << wearable_data->mAssetID << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1908,3 +1918,5 @@ void LLInitialWearablesFetch::processInitialWearables()
|
|||
LL_WARNS("Wearables") << "No current outfit folder items found and no initial wearables fallback message received." << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ public:
|
|||
static void userRemoveWearable(void* userdata); // userdata is EWearableType
|
||||
static void userRemoveAllClothes(void* userdata); // userdata is NULL
|
||||
static void userRemoveAllAttachments(void* userdata); // userdata is NULL
|
||||
static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array);
|
||||
|
||||
BOOL itemUpdatePending(const LLUUID& item_id) const;
|
||||
U32 itemUpdatePendingCount() const;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,793 @@
|
|||
/**
|
||||
* @file llappearancemgr.cpp
|
||||
* @brief Manager for initiating appearance changes on the viewer
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2004-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llappearancemgr.h"
|
||||
#include "llinventorymodel.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llgesturemgr.h"
|
||||
#include "llinventorybridge.h"
|
||||
#include "llwearablelist.h"
|
||||
#include "llagentwearables.h"
|
||||
#include "llagent.h"
|
||||
#include "llvoavatar.h"
|
||||
#include "llvoavatarself.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llfloatercustomize.h"
|
||||
|
||||
class LLWearInventoryCategoryCallback : public LLInventoryCallback
|
||||
{
|
||||
public:
|
||||
LLWearInventoryCategoryCallback(const LLUUID& cat_id, bool append)
|
||||
{
|
||||
mCatID = cat_id;
|
||||
mAppend = append;
|
||||
}
|
||||
void fire(const LLUUID& item_id)
|
||||
{
|
||||
/*
|
||||
* Do nothing. We only care about the destructor
|
||||
*
|
||||
* The reason for this is that this callback is used in a hack where the
|
||||
* same callback is given to dozens of items, and the destructor is called
|
||||
* after the last item has fired the event and dereferenced it -- if all
|
||||
* the events actually fire!
|
||||
*/
|
||||
}
|
||||
|
||||
protected:
|
||||
~LLWearInventoryCategoryCallback()
|
||||
{
|
||||
// Is the destructor called by ordinary dereference, or because the app's shutting down?
|
||||
// If the inventory callback manager goes away, we're shutting down, no longer want the callback.
|
||||
if( LLInventoryCallbackManager::is_instantiated() )
|
||||
{
|
||||
LLAppearanceManager::wearInventoryCategoryOnAvatar(gInventory.getCategory(mCatID), mAppend);
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
LLUUID mCatID;
|
||||
bool mAppend;
|
||||
};
|
||||
|
||||
class LLOutfitObserver : public LLInventoryFetchObserver
|
||||
{
|
||||
public:
|
||||
LLOutfitObserver(const LLUUID& cat_id, bool copy_items, bool append) :
|
||||
mCatID(cat_id),
|
||||
mCopyItems(copy_items),
|
||||
mAppend(append)
|
||||
{}
|
||||
~LLOutfitObserver() {}
|
||||
virtual void done(); //public
|
||||
|
||||
protected:
|
||||
LLUUID mCatID;
|
||||
bool mCopyItems;
|
||||
bool mAppend;
|
||||
};
|
||||
|
||||
void LLOutfitObserver::done()
|
||||
{
|
||||
// We now have an outfit ready to be copied to agent inventory. Do
|
||||
// it, and wear that outfit normally.
|
||||
if(mCopyItems)
|
||||
{
|
||||
LLInventoryCategory* cat = gInventory.getCategory(mCatID);
|
||||
std::string name;
|
||||
if(!cat)
|
||||
{
|
||||
// should never happen.
|
||||
name = "New Outfit";
|
||||
}
|
||||
else
|
||||
{
|
||||
name = cat->getName();
|
||||
}
|
||||
LLViewerInventoryItem* item = NULL;
|
||||
item_ref_t::iterator it = mComplete.begin();
|
||||
item_ref_t::iterator end = mComplete.end();
|
||||
LLUUID pid;
|
||||
for(; it < end; ++it)
|
||||
{
|
||||
item = (LLViewerInventoryItem*)gInventory.getItem(*it);
|
||||
if(item)
|
||||
{
|
||||
if(LLInventoryType::IT_GESTURE == item->getInventoryType())
|
||||
{
|
||||
pid = gInventory.findCategoryUUIDForType(LLAssetType::AT_GESTURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(pid.isNull())
|
||||
{
|
||||
pid = gInventory.getRootFolderID();
|
||||
}
|
||||
|
||||
LLUUID cat_id = gInventory.createNewCategory(
|
||||
pid,
|
||||
LLAssetType::AT_NONE,
|
||||
name);
|
||||
mCatID = cat_id;
|
||||
LLPointer<LLInventoryCallback> cb = new LLWearInventoryCategoryCallback(mCatID, mAppend);
|
||||
it = mComplete.begin();
|
||||
for(; it < end; ++it)
|
||||
{
|
||||
item = (LLViewerInventoryItem*)gInventory.getItem(*it);
|
||||
if(item)
|
||||
{
|
||||
copy_inventory_item(
|
||||
gAgent.getID(),
|
||||
item->getPermissions().getOwner(),
|
||||
item->getUUID(),
|
||||
cat_id,
|
||||
std::string(),
|
||||
cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wear the inventory category.
|
||||
LLAppearanceManager::wearInventoryCategoryOnAvatar(gInventory.getCategory(mCatID), mAppend);
|
||||
}
|
||||
}
|
||||
|
||||
class LLOutfitFetch : public LLInventoryFetchDescendentsObserver
|
||||
{
|
||||
public:
|
||||
LLOutfitFetch(bool copy_items, bool append) : mCopyItems(copy_items), mAppend(append) {}
|
||||
~LLOutfitFetch() {}
|
||||
virtual void done();
|
||||
protected:
|
||||
bool mCopyItems;
|
||||
bool mAppend;
|
||||
};
|
||||
|
||||
void LLOutfitFetch::done()
|
||||
{
|
||||
// What we do here is get the complete information on the items in
|
||||
// the library, and set up an observer that will wait for that to
|
||||
// happen.
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t item_array;
|
||||
gInventory.collectDescendents(mCompleteFolders.front(),
|
||||
cat_array,
|
||||
item_array,
|
||||
LLInventoryModel::EXCLUDE_TRASH);
|
||||
S32 count = item_array.count();
|
||||
if(!count)
|
||||
{
|
||||
llwarns << "Nothing fetched in category " << mCompleteFolders.front()
|
||||
<< llendl;
|
||||
//dec_busy_count();
|
||||
gInventory.removeObserver(this);
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
LLOutfitObserver* outfit_observer = new LLOutfitObserver(mCompleteFolders.front(), mCopyItems, mAppend);
|
||||
LLInventoryFetchObserver::item_ref_t ids;
|
||||
for(S32 i = 0; i < count; ++i)
|
||||
{
|
||||
ids.push_back(item_array.get(i)->getUUID());
|
||||
}
|
||||
|
||||
// clean up, and remove this as an observer since the call to the
|
||||
// outfit could notify observers and throw us into an infinite
|
||||
// loop.
|
||||
//dec_busy_count();
|
||||
gInventory.removeObserver(this);
|
||||
delete this;
|
||||
|
||||
// increment busy count and either tell the inventory to check &
|
||||
// call done, or add this object to the inventory for observation.
|
||||
//inc_busy_count();
|
||||
|
||||
// do the fetch
|
||||
outfit_observer->fetchItems(ids);
|
||||
if(outfit_observer->isEverythingComplete())
|
||||
{
|
||||
// everything is already here - call done.
|
||||
outfit_observer->done();
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's all on it's way - add an observer, and the inventory
|
||||
// will call done for us when everything is here.
|
||||
gInventory.addObserver(outfit_observer);
|
||||
}
|
||||
}
|
||||
|
||||
class LLUpdateAppearanceOnCount: public LLInventoryCallback
|
||||
{
|
||||
public:
|
||||
LLUpdateAppearanceOnCount(S32 count):
|
||||
mCount(count)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~LLUpdateAppearanceOnCount()
|
||||
{
|
||||
}
|
||||
|
||||
/* virtual */ void fire(const LLUUID& inv_item)
|
||||
{
|
||||
mCount--;
|
||||
if (mCount==0)
|
||||
{
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
void done()
|
||||
{
|
||||
LLAppearanceManager::updateAppearanceFromCOF();
|
||||
}
|
||||
private:
|
||||
S32 mCount;
|
||||
};
|
||||
|
||||
struct LLFoundData
|
||||
{
|
||||
LLFoundData(const LLUUID& item_id,
|
||||
const LLUUID& asset_id,
|
||||
const std::string& name,
|
||||
LLAssetType::EType asset_type) :
|
||||
mItemID(item_id),
|
||||
mAssetID(asset_id),
|
||||
mName(name),
|
||||
mAssetType(asset_type),
|
||||
mWearable( NULL ) {}
|
||||
|
||||
LLUUID mItemID;
|
||||
LLUUID mAssetID;
|
||||
std::string mName;
|
||||
LLAssetType::EType mAssetType;
|
||||
LLWearable* mWearable;
|
||||
};
|
||||
|
||||
|
||||
struct LLWearableHoldingPattern
|
||||
{
|
||||
LLWearableHoldingPattern() : mResolved(0) {}
|
||||
~LLWearableHoldingPattern()
|
||||
{
|
||||
for_each(mFoundList.begin(), mFoundList.end(), DeletePointer());
|
||||
mFoundList.clear();
|
||||
}
|
||||
typedef std::list<LLFoundData*> found_list_t;
|
||||
found_list_t mFoundList;
|
||||
S32 mResolved;
|
||||
bool append;
|
||||
};
|
||||
|
||||
|
||||
void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventoryModel::item_array_t& src)
|
||||
{
|
||||
LLInventoryModel::item_array_t new_dst;
|
||||
std::set<LLUUID> mark_inventory;
|
||||
std::set<LLUUID> mark_asset;
|
||||
|
||||
S32 inventory_dups = 0;
|
||||
S32 asset_dups = 0;
|
||||
|
||||
for (LLInventoryModel::item_array_t::const_iterator src_pos = src.begin();
|
||||
src_pos != src.end();
|
||||
++src_pos)
|
||||
{
|
||||
LLUUID src_item_id = (*src_pos)->getLinkedUUID();
|
||||
mark_inventory.insert(src_item_id);
|
||||
LLUUID src_asset_id = (*src_pos)->getAssetUUID();
|
||||
mark_asset.insert(src_asset_id);
|
||||
}
|
||||
|
||||
for (LLInventoryModel::item_array_t::const_iterator dst_pos = dst.begin();
|
||||
dst_pos != dst.end();
|
||||
++dst_pos)
|
||||
{
|
||||
LLUUID dst_item_id = (*dst_pos)->getLinkedUUID();
|
||||
|
||||
if (mark_inventory.find(dst_item_id) == mark_inventory.end())
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
inventory_dups++;
|
||||
}
|
||||
|
||||
LLUUID dst_asset_id = (*dst_pos)->getAssetUUID();
|
||||
|
||||
if (mark_asset.find(dst_asset_id) == mark_asset.end())
|
||||
{
|
||||
// Item is not already present in COF.
|
||||
new_dst.put(*dst_pos);
|
||||
mark_asset.insert(dst_item_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
asset_dups++;
|
||||
}
|
||||
}
|
||||
llinfos << "removeDups, original " << dst.count() << " final " << new_dst.count()
|
||||
<< " inventory dups " << inventory_dups << " asset_dups " << asset_dups << llendl;
|
||||
|
||||
dst = new_dst;
|
||||
}
|
||||
|
||||
|
||||
/* static */ LLUUID LLAppearanceManager::getCOF()
|
||||
{
|
||||
return gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
|
||||
}
|
||||
|
||||
// Update appearance from outfit folder.
|
||||
/* static */ void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, bool append, bool follow_folder_links)
|
||||
{
|
||||
if (!proceed)
|
||||
return;
|
||||
|
||||
updateCOFFromOutfit(category, append, follow_folder_links);
|
||||
}
|
||||
|
||||
// Update COF contents from outfit folder.
|
||||
/* static */ void LLAppearanceManager::updateCOFFromOutfit(const LLUUID& category, bool append, bool follow_folder_links)
|
||||
{
|
||||
// BAP consolidate into one "get all 3 types of descendents" function, use both places.
|
||||
LLInventoryModel::item_array_t wear_items;
|
||||
LLInventoryModel::item_array_t obj_items;
|
||||
LLInventoryModel::item_array_t gest_items;
|
||||
getUserDescendents(category, wear_items, obj_items, gest_items, follow_folder_links);
|
||||
|
||||
// Find all the wearables that are in the category's subtree.
|
||||
lldebugs << "updateCOFFromOutfit()" << llendl;
|
||||
if( !wear_items.count() && !obj_items.count() && !gest_items.count())
|
||||
{
|
||||
LLNotifications::instance().add("CouldNotPutOnOutfit");
|
||||
return;
|
||||
}
|
||||
|
||||
const LLUUID ¤t_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
|
||||
// Processes that take time should show the busy cursor
|
||||
//inc_busy_count();
|
||||
|
||||
LLInventoryModel::cat_array_t cof_cats;
|
||||
LLInventoryModel::item_array_t cof_items;
|
||||
gInventory.collectDescendents(current_outfit_id, cof_cats, cof_items,
|
||||
LLInventoryModel::EXCLUDE_TRASH);
|
||||
if (append)
|
||||
{
|
||||
// Remove duplicates
|
||||
removeDuplicateItems(wear_items, cof_items);
|
||||
removeDuplicateItems(obj_items, cof_items);
|
||||
removeDuplicateItems(gest_items, cof_items);
|
||||
}
|
||||
|
||||
|
||||
if (wear_items.count() > 0 || obj_items.count() > 0)
|
||||
{
|
||||
if (!append)
|
||||
{
|
||||
// Remove all current outfit folder links if we're now replacing the contents.
|
||||
for (S32 i = 0; i < cof_items.count(); ++i)
|
||||
{
|
||||
gInventory.purgeObject(cof_items.get(i)->getUUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BAP should we just link all contents, rather than restricting to these 3 types?
|
||||
|
||||
S32 total_links = gest_items.count() + wear_items.count() + obj_items.count();
|
||||
LLPointer<LLUpdateAppearanceOnCount> link_waiter = new LLUpdateAppearanceOnCount(total_links);
|
||||
|
||||
// Link all gestures in this folder
|
||||
if (gest_items.count() > 0)
|
||||
{
|
||||
llinfos << "Linking " << gest_items.count() << " gestures" << llendl;
|
||||
for (S32 i = 0; i < gest_items.count(); ++i)
|
||||
{
|
||||
const LLInventoryItem* gest_item = gest_items.get(i).get();
|
||||
link_inventory_item(gAgent.getID(), gest_item->getLinkedUUID(), current_outfit_id,
|
||||
gest_item->getName(),
|
||||
LLAssetType::AT_LINK, link_waiter);
|
||||
}
|
||||
}
|
||||
|
||||
// Link all wearables
|
||||
if(wear_items.count() > 0)
|
||||
{
|
||||
llinfos << "Linking " << wear_items.count() << " wearables" << llendl;
|
||||
for(S32 i = 0; i < wear_items.count(); ++i)
|
||||
{
|
||||
// Populate the current outfit folder with links to the newly added wearables
|
||||
const LLInventoryItem* wear_item = wear_items.get(i).get();
|
||||
link_inventory_item(gAgent.getID(),
|
||||
wear_item->getLinkedUUID(), // If this item is a link, then we'll use the linked item's UUID.
|
||||
current_outfit_id,
|
||||
wear_item->getName(),
|
||||
LLAssetType::AT_LINK,
|
||||
link_waiter);
|
||||
}
|
||||
}
|
||||
|
||||
// Link all attachments.
|
||||
if( obj_items.count() > 0 )
|
||||
{
|
||||
llinfos << "Linking " << obj_items.count() << " attachments" << llendl;
|
||||
LLVOAvatar* avatar = gAgent.getAvatarObject();
|
||||
if( avatar )
|
||||
{
|
||||
for(S32 i = 0; i < obj_items.count(); ++i)
|
||||
{
|
||||
const LLInventoryItem* obj_item = obj_items.get(i).get();
|
||||
link_inventory_item(gAgent.getID(),
|
||||
obj_item->getLinkedUUID(), // If this item is a link, then we'll use the linked item's UUID.
|
||||
current_outfit_id,
|
||||
obj_item->getName(),
|
||||
LLAssetType::AT_LINK, link_waiter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In the particular case that we're switching to a different outfit,
|
||||
// create a link to the folder that we wore.
|
||||
LLViewerInventoryCategory* catp = gInventory.getCategory(category);
|
||||
if (!append && catp && catp->getPreferredType() == LLAssetType::AT_OUTFIT)
|
||||
{
|
||||
link_inventory_item(gAgent.getID(), category, current_outfit_id, catp->getName(),
|
||||
LLAssetType::AT_LINK_FOLDER, LLPointer<LLInventoryCallback>(NULL));
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void LLAppearanceManager::onWearableAssetFetch(LLWearable* wearable, void* data)
|
||||
{
|
||||
LLWearableHoldingPattern* holder = (LLWearableHoldingPattern*)data;
|
||||
bool append = holder->append;
|
||||
|
||||
if(wearable)
|
||||
{
|
||||
for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
|
||||
iter != holder->mFoundList.end(); ++iter)
|
||||
{
|
||||
LLFoundData* data = *iter;
|
||||
if(wearable->getAssetID() == data->mAssetID)
|
||||
{
|
||||
data->mWearable = wearable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
holder->mResolved += 1;
|
||||
if(holder->mResolved >= (S32)holder->mFoundList.size())
|
||||
{
|
||||
LLAppearanceManager::updateAgentWearables(holder, append);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder, bool append)
|
||||
{
|
||||
lldebugs << "updateAgentWearables()" << llendl;
|
||||
LLInventoryItem::item_array_t items;
|
||||
LLDynamicArray< LLWearable* > wearables;
|
||||
|
||||
// For each wearable type, find the first instance in the category
|
||||
// that we recursed through.
|
||||
for( S32 i = 0; i < WT_COUNT; i++ )
|
||||
{
|
||||
for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
|
||||
iter != holder->mFoundList.end(); ++iter)
|
||||
{
|
||||
LLFoundData* data = *iter;
|
||||
LLWearable* wearable = data->mWearable;
|
||||
if( wearable && ((S32)wearable->getType() == i) )
|
||||
{
|
||||
LLViewerInventoryItem* item;
|
||||
item = (LLViewerInventoryItem*)gInventory.getItem(data->mItemID);
|
||||
if( item && (item->getAssetUUID() == wearable->getAssetID()) )
|
||||
{
|
||||
items.put(item);
|
||||
wearables.put(wearable);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(wearables.count() > 0)
|
||||
{
|
||||
gAgentWearables.setWearableOutfit(items, wearables, !append);
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
|
||||
delete holder;
|
||||
|
||||
// dec_busy_count();
|
||||
}
|
||||
|
||||
/* static */ void LLAppearanceManager::updateAppearanceFromCOF()
|
||||
{
|
||||
bool follow_folder_links = true;
|
||||
LLUUID current_outfit_id = getCOF();
|
||||
|
||||
// Find all the wearables that are in the COF's subtree.
|
||||
lldebugs << "LLAppearanceManager::updateFromCOF()" << llendl;
|
||||
LLInventoryModel::item_array_t wear_items;
|
||||
LLInventoryModel::item_array_t obj_items;
|
||||
LLInventoryModel::item_array_t gest_items;
|
||||
getUserDescendents(current_outfit_id, wear_items, obj_items, gest_items, follow_folder_links);
|
||||
|
||||
if( !wear_items.count() && !obj_items.count() && !gest_items.count())
|
||||
{
|
||||
LLNotifications::instance().add("CouldNotPutOnOutfit");
|
||||
return;
|
||||
}
|
||||
|
||||
// Processes that take time should show the busy cursor
|
||||
//inc_busy_count(); // BAP this is currently a no-op in llinventorybridge.cpp - do we need it?
|
||||
|
||||
// Activate all gestures in this folder
|
||||
if (gest_items.count() > 0)
|
||||
{
|
||||
llinfos << "Activating " << gest_items.count() << " gestures" << llendl;
|
||||
|
||||
LLGestureManager::instance().activateGestures(gest_items);
|
||||
|
||||
// Update the inventory item labels to reflect the fact
|
||||
// they are active.
|
||||
LLViewerInventoryCategory* catp = gInventory.getCategory(current_outfit_id);
|
||||
if (catp)
|
||||
{
|
||||
gInventory.updateCategory(catp);
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
if(wear_items.count() > 0)
|
||||
{
|
||||
// Note: can't do normal iteration, because if all the
|
||||
// wearables can be resolved immediately, then the
|
||||
// callback will be called (and this object deleted)
|
||||
// before the final getNextData().
|
||||
LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
|
||||
LLFoundData* found;
|
||||
LLDynamicArray<LLFoundData*> found_container;
|
||||
for(S32 i = 0; i < wear_items.count(); ++i)
|
||||
{
|
||||
found = new LLFoundData(wear_items.get(i)->getUUID(),
|
||||
wear_items.get(i)->getAssetUUID(),
|
||||
wear_items.get(i)->getName(),
|
||||
wear_items.get(i)->getType());
|
||||
holder->mFoundList.push_front(found);
|
||||
found_container.put(found);
|
||||
}
|
||||
for(S32 i = 0; i < wear_items.count(); ++i)
|
||||
{
|
||||
holder->append = false;
|
||||
found = found_container.get(i);
|
||||
|
||||
// Fetch the wearables about to be worn.
|
||||
LLWearableList::instance().getAsset(found->mAssetID,
|
||||
found->mName,
|
||||
found->mAssetType,
|
||||
LLAppearanceManager::onWearableAssetFetch,
|
||||
(void*)holder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//If the folder doesn't contain only gestures, take off all attachments.
|
||||
if (!(wear_items.count() == 0 && obj_items.count() == 0 && gest_items.count() > 0) )
|
||||
{
|
||||
LLAgentWearables::userRemoveAllAttachments(NULL);
|
||||
}
|
||||
|
||||
if( obj_items.count() > 0 )
|
||||
{
|
||||
// We've found some attachments. Add these.
|
||||
LLVOAvatar* avatar = gAgent.getAvatarObject();
|
||||
if( avatar )
|
||||
{
|
||||
LLAgentWearables::userAttachMultipleAttachments(obj_items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void LLAppearanceManager::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)
|
||||
{
|
||||
LLInventoryModel::cat_array_t wear_cats;
|
||||
LLFindWearables is_wearable;
|
||||
gInventory.collectDescendentsIf(category,
|
||||
wear_cats,
|
||||
wear_items,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
is_wearable,
|
||||
follow_folder_links);
|
||||
|
||||
LLInventoryModel::cat_array_t obj_cats;
|
||||
LLIsType is_object( LLAssetType::AT_OBJECT );
|
||||
gInventory.collectDescendentsIf(category,
|
||||
obj_cats,
|
||||
obj_items,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
is_object,
|
||||
follow_folder_links);
|
||||
|
||||
// Find all gestures in this folder
|
||||
LLInventoryModel::cat_array_t gest_cats;
|
||||
LLIsType is_gesture( LLAssetType::AT_GESTURE );
|
||||
gInventory.collectDescendentsIf(category,
|
||||
gest_cats,
|
||||
gest_items,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
is_gesture,
|
||||
follow_folder_links);
|
||||
}
|
||||
|
||||
void LLAppearanceManager::wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append)
|
||||
{
|
||||
if(!category) return;
|
||||
|
||||
lldebugs << "wearInventoryCategory( " << category->getName()
|
||||
<< " )" << llendl;
|
||||
// What we do here is get the complete information on the items in
|
||||
// the inventory, and set up an observer that will wait for that to
|
||||
// happen.
|
||||
LLOutfitFetch* outfit_fetcher = new LLOutfitFetch(copy, append);
|
||||
LLInventoryFetchDescendentsObserver::folder_ref_t folders;
|
||||
folders.push_back(category->getUUID());
|
||||
outfit_fetcher->fetchDescendents(folders);
|
||||
//inc_busy_count();
|
||||
if(outfit_fetcher->isEverythingComplete())
|
||||
{
|
||||
// everything is already here - call done.
|
||||
outfit_fetcher->done();
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's all on it's way - add an observer, and the inventory
|
||||
// will call done for us when everything is here.
|
||||
gInventory.addObserver(outfit_fetcher);
|
||||
}
|
||||
}
|
||||
|
||||
// *NOTE: hack to get from avatar inventory to avatar
|
||||
/* static */
|
||||
void LLAppearanceManager::wearInventoryCategoryOnAvatar( LLInventoryCategory* category, bool append )
|
||||
{
|
||||
// Avoid unintentionally overwriting old wearables. We have to do
|
||||
// this up front to avoid having to deal with the case of multiple
|
||||
// wearables being dirty.
|
||||
if(!category) return;
|
||||
lldebugs << "wearInventoryCategoryOnAvatar( " << category->getName()
|
||||
<< " )" << llendl;
|
||||
|
||||
bool follow_folder_links = (category->getPreferredType() == LLAssetType::AT_CURRENT_OUTFIT || category->getPreferredType() == LLAssetType::AT_OUTFIT );
|
||||
if( gFloaterCustomize )
|
||||
{
|
||||
gFloaterCustomize->askToSaveIfDirty(boost::bind(LLAppearanceManager::changeOutfit, _1, category->getUUID(), append, follow_folder_links));
|
||||
}
|
||||
else
|
||||
{
|
||||
LLAppearanceManager::changeOutfit(TRUE, category->getUUID(), append, follow_folder_links );
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void LLAppearanceManager::wearOutfitByName(const std::string& name)
|
||||
{
|
||||
llinfos << "Wearing category " << name << llendl;
|
||||
//inc_busy_count();
|
||||
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t item_array;
|
||||
LLNameCategoryCollector has_name(name);
|
||||
gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
|
||||
cat_array,
|
||||
item_array,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
has_name);
|
||||
bool copy_items = false;
|
||||
LLInventoryCategory* cat = NULL;
|
||||
if (cat_array.count() > 0)
|
||||
{
|
||||
// Just wear the first one that matches
|
||||
cat = cat_array.get(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gInventory.collectDescendentsIf(LLUUID::null,
|
||||
cat_array,
|
||||
item_array,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
has_name);
|
||||
if(cat_array.count() > 0)
|
||||
{
|
||||
cat = cat_array.get(0);
|
||||
copy_items = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(cat)
|
||||
{
|
||||
LLAppearanceManager::wearInventoryCategory(cat, copy_items, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Couldn't find outfit " <<name<< " in wearOutfitByName()"
|
||||
<< llendl;
|
||||
}
|
||||
|
||||
//dec_busy_count();
|
||||
}
|
||||
|
||||
void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update )
|
||||
{
|
||||
// BAP add check for already in COF.
|
||||
LLPointer<LLInventoryCallback> cb = do_update ? new ModifiedCOFCallback : 0;
|
||||
link_inventory_item( gAgent.getID(),
|
||||
item->getLinkedUUID(),
|
||||
getCOF(),
|
||||
item->getName(),
|
||||
LLAssetType::AT_LINK,
|
||||
cb);
|
||||
}
|
||||
|
||||
void LLAppearanceManager::wearEnsemble( LLInventoryCategory* cat, bool do_update )
|
||||
{
|
||||
// BAP add check for already in COF.
|
||||
LLPointer<LLInventoryCallback> cb = do_update ? new ModifiedCOFCallback : 0;
|
||||
link_inventory_item( gAgent.getID(),
|
||||
cat->getLinkedUUID(),
|
||||
getCOF(),
|
||||
cat->getName(),
|
||||
LLAssetType::AT_LINK_FOLDER,
|
||||
cb);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* @file llappearancemgr.h
|
||||
* @brief Manager for initiating appearance changes on the viewer
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2004-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLAPPEARANCEMGR_H
|
||||
#define LL_LLAPPEARANCEMGR_H
|
||||
|
||||
#include "llsingleton.h"
|
||||
#include "llinventorymodel.h"
|
||||
|
||||
class LLWearable;
|
||||
struct LLWearableHoldingPattern;
|
||||
|
||||
class LLAppearanceManager: public LLSingleton<LLAppearanceManager>
|
||||
{
|
||||
public:
|
||||
static void updateAppearanceFromCOF();
|
||||
static bool needToSaveCOF();
|
||||
static void changeOutfit(bool proceed, const LLUUID& category, bool append, bool follow_folder_links);
|
||||
static void updateCOFFromOutfit(const LLUUID& category, bool append, bool follow_folder_links);
|
||||
static void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append);
|
||||
static void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append);
|
||||
static void wearOutfitByName(const std::string& name);
|
||||
|
||||
// Add COF link to individual item.
|
||||
static void wearItem(LLInventoryItem* item, bool do_update = true);
|
||||
|
||||
// Add COF link to ensemble folder.
|
||||
static void wearEnsemble(LLInventoryCategory* item, bool do_update = true);
|
||||
|
||||
private:
|
||||
static LLUUID getCOF();
|
||||
static 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);
|
||||
static void onWearableAssetFetch(LLWearable* wearable, void* data);
|
||||
static void updateAgentWearables(LLWearableHoldingPattern* holder, bool append);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1183,6 +1183,8 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
|
|||
// you will automatically fail this time, so we only
|
||||
// check against items that have passed the filter
|
||||
S32 must_pass_generation = filter.getMustPassGeneration();
|
||||
|
||||
bool autoopen_folders = (filter.hasFilterString());
|
||||
|
||||
// if we have already been filtered against this generation, skip out
|
||||
if (getCompletedFilterGeneration() >= filter_generation)
|
||||
|
|
@ -1255,7 +1257,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
|
|||
if ((*fit)->getFiltered() || (*fit)->hasFilteredDescendants(filter.getMinRequiredGeneration()))
|
||||
{
|
||||
mMostFilteredDescendantGeneration = filter_generation;
|
||||
if (getRoot()->needsAutoSelect())
|
||||
if (getRoot()->needsAutoSelect() && autoopen_folders)
|
||||
{
|
||||
(*fit)->setOpenArrangeRecursively(TRUE);
|
||||
}
|
||||
|
|
@ -1271,7 +1273,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
|
|||
if ((*fit)->getFiltered() || (*fit)->hasFilteredDescendants(filter_generation))
|
||||
{
|
||||
mMostFilteredDescendantGeneration = filter_generation;
|
||||
if (getRoot()->needsAutoSelect())
|
||||
if (getRoot()->needsAutoSelect() && autoopen_folders)
|
||||
{
|
||||
(*fit)->setOpenArrangeRecursively(TRUE);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -200,9 +200,8 @@ protected:
|
|||
BOOL isInTrash() const;
|
||||
BOOL isLinkedObjectInTrash() const; // Is this obj or its baseobj in the trash?
|
||||
|
||||
// return true if the item is in agent inventory. if false, it
|
||||
// must be lost or in the inventory library.
|
||||
BOOL isAgentInventory() const;
|
||||
BOOL isAgentInventory() const; // false if lost or in the inventory library
|
||||
BOOL isCOFFolder() const; // true if COF or descendent of.
|
||||
virtual BOOL isItemPermissive() const;
|
||||
static void changeItemParent(LLInventoryModel* model,
|
||||
LLViewerInventoryItem* item,
|
||||
|
|
@ -295,6 +294,7 @@ public:
|
|||
virtual BOOL isItemMovable();
|
||||
virtual BOOL isUpToDate() const;
|
||||
virtual BOOL isItemCopyable() const;
|
||||
virtual BOOL isClipboardPasteableAsLink() const;
|
||||
virtual BOOL copyToClipboard() const;
|
||||
|
||||
static void createWearable(LLFolderBridge* bridge, EWearableType type);
|
||||
|
|
@ -769,8 +769,6 @@ protected:
|
|||
};
|
||||
|
||||
void wear_inventory_item_on_avatar(LLInventoryItem* item);
|
||||
void wear_outfit_by_name(const std::string& name);
|
||||
void wear_inventory_category(LLInventoryCategory* category, bool copy, bool append);
|
||||
|
||||
class LLViewerJointAttachment;
|
||||
void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment);
|
||||
|
|
@ -787,4 +785,5 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
|
|||
|
||||
void teleport_via_landmark(const LLUUID& asset_id);
|
||||
|
||||
|
||||
#endif // LL_LLINVENTORYBRIDGE_H
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ public:
|
|||
BOOL isModified();
|
||||
BOOL isModifiedAndClear();
|
||||
BOOL isSinceLogoff();
|
||||
bool hasFilterString() { return mFilterSubString.size() > 0; }
|
||||
void clearModified() { mModified = FALSE; mFilterBehavior = FILTER_NONE; }
|
||||
const std::string getName() const { return mName; }
|
||||
std::string getFilterText();
|
||||
|
|
|
|||
|
|
@ -187,9 +187,9 @@ LLInventoryModel::~LLInventoryModel()
|
|||
// This is a convenience function to check if one object has a parent
|
||||
// chain up to the category specified by UUID.
|
||||
BOOL LLInventoryModel::isObjectDescendentOf(const LLUUID& obj_id,
|
||||
const LLUUID& cat_id)
|
||||
const LLUUID& cat_id) const
|
||||
{
|
||||
LLInventoryObject* obj = getObject(obj_id);
|
||||
const LLInventoryObject* obj = getObject(obj_id);
|
||||
while(obj)
|
||||
{
|
||||
const LLUUID& parent_id = obj->getParentUUID();
|
||||
|
|
@ -307,13 +307,13 @@ void LLInventoryModel::unlockDirectDescendentArrays(const LLUUID& cat_id)
|
|||
// inventory category on the fly if one does not exist.
|
||||
LLUUID LLInventoryModel::findCategoryUUIDForType(LLAssetType::EType t, bool create_folder)
|
||||
{
|
||||
LLUUID rv = findCatUUID(t);
|
||||
const LLUUID &rv = findCatUUID(t);
|
||||
if(rv.isNull() && isInventoryUsable() && create_folder)
|
||||
{
|
||||
LLUUID root_id = gInventory.getRootFolderID();
|
||||
const LLUUID &root_id = gInventory.getRootFolderID();
|
||||
if(root_id.notNull())
|
||||
{
|
||||
rv = createNewCategory(root_id, t, LLStringUtil::null);
|
||||
return createNewCategory(root_id, t, LLStringUtil::null);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
|
|
@ -321,9 +321,9 @@ LLUUID LLInventoryModel::findCategoryUUIDForType(LLAssetType::EType t, bool crea
|
|||
|
||||
// Internal method which looks for a category with the specified
|
||||
// preferred type. Returns LLUUID::null if not found.
|
||||
LLUUID LLInventoryModel::findCatUUID(LLAssetType::EType preferred_type)
|
||||
const LLUUID &LLInventoryModel::findCatUUID(LLAssetType::EType preferred_type) const
|
||||
{
|
||||
LLUUID root_id = gInventory.getRootFolderID();
|
||||
const LLUUID &root_id = gInventory.getRootFolderID();
|
||||
if(LLAssetType::AT_CATEGORY == preferred_type)
|
||||
{
|
||||
return root_id;
|
||||
|
|
@ -440,7 +440,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
|
|||
// Start with categories
|
||||
if(!include_trash)
|
||||
{
|
||||
LLUUID trash_id(findCatUUID(LLAssetType::AT_TRASH));
|
||||
const LLUUID trash_id = findCategoryUUIDForType(LLAssetType::AT_TRASH);
|
||||
if(trash_id.notNull() && (trash_id == id))
|
||||
return;
|
||||
}
|
||||
|
|
@ -473,8 +473,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
|
|||
item = item_array->get(i);
|
||||
if (item->getActualType() == LLAssetType::AT_LINK_FOLDER)
|
||||
{
|
||||
// BAP either getLinkedCategory() should return non-const, or the functor should take const.
|
||||
LLViewerInventoryCategory *linked_cat = const_cast<LLViewerInventoryCategory*>(item->getLinkedCategory());
|
||||
LLViewerInventoryCategory *linked_cat = item->getLinkedCategory();
|
||||
if (linked_cat)
|
||||
{
|
||||
if(add(linked_cat,NULL))
|
||||
|
|
@ -548,10 +547,10 @@ void LLInventoryModel::collectLinkedItems(const LLUUID& id,
|
|||
|
||||
// Generates a string containing the path to the item specified by
|
||||
// item_id.
|
||||
void LLInventoryModel::appendPath(const LLUUID& id, std::string& path)
|
||||
void LLInventoryModel::appendPath(const LLUUID& id, std::string& path) const
|
||||
{
|
||||
std::string temp;
|
||||
LLInventoryObject* obj = getObject(id);
|
||||
const LLInventoryObject* obj = getObject(id);
|
||||
LLUUID parent_id;
|
||||
if(obj) parent_id = obj->getParentUUID();
|
||||
std::string forward_slash("/");
|
||||
|
|
@ -567,7 +566,7 @@ void LLInventoryModel::appendPath(const LLUUID& id, std::string& path)
|
|||
path.append(temp);
|
||||
}
|
||||
|
||||
bool LLInventoryModel::isInventoryUsable()
|
||||
bool LLInventoryModel::isInventoryUsable() const
|
||||
{
|
||||
bool result = false;
|
||||
if(gInventory.getRootFolderID().notNull() && mIsAgentInvUsable)
|
||||
|
|
@ -1086,7 +1085,7 @@ void LLInventoryModel::removeObserver(LLInventoryObserver* observer)
|
|||
mObservers.erase(observer);
|
||||
}
|
||||
|
||||
BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer)
|
||||
BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer) const
|
||||
{
|
||||
return mObservers.find(observer) != mObservers.end();
|
||||
}
|
||||
|
|
@ -1791,6 +1790,7 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
|
|||
if (item->getIsBrokenLink())
|
||||
{
|
||||
llwarns << "Add link item without baseobj present ( name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << llendl;
|
||||
// llassert_always(FALSE); // DO NOT MERGE THIS IN. This is an AVP debugging line. If this line triggers, it means that you just loaded in a broken link. Unless that happens because you actually deleted a baseobj without deleting the link, it's indicative of a serious problem (likely with your inventory) and should be diagnosed.
|
||||
}
|
||||
mItemMap[item->getUUID()] = item;
|
||||
//mInventory[item->getUUID()] = item;
|
||||
|
|
@ -1817,7 +1817,7 @@ void LLInventoryModel::empty()
|
|||
//mInventory.clear();
|
||||
}
|
||||
|
||||
void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update)
|
||||
void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const
|
||||
{
|
||||
LLViewerInventoryCategory* cat = getCategory(update.mCategoryID);
|
||||
if(cat)
|
||||
|
|
@ -2177,7 +2177,8 @@ bool LLInventoryModel::loadSkeleton(
|
|||
update_map_t::const_iterator the_count = child_counts.find(cat->getUUID());
|
||||
if(the_count != no_child_counts)
|
||||
{
|
||||
cat->setDescendentCount((*the_count).second.mValue);
|
||||
const S32 num_descendents = (*the_count).second.mValue;
|
||||
cat->setDescendentCount(num_descendents);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2481,7 +2482,7 @@ void LLInventoryModel::buildParentChildMap()
|
|||
}
|
||||
}
|
||||
|
||||
LLUUID agent_inv_root_id = gInventory.getRootFolderID();
|
||||
const LLUUID &agent_inv_root_id = gInventory.getRootFolderID();
|
||||
if (agent_inv_root_id.notNull())
|
||||
{
|
||||
cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id);
|
||||
|
|
@ -3324,7 +3325,7 @@ void LLInventoryModel::emptyFolderType(const std::string notification, LLAssetTy
|
|||
void LLInventoryModel::removeItem(const LLUUID& item_id)
|
||||
{
|
||||
LLViewerInventoryItem* item = getItem(item_id);
|
||||
const LLUUID& new_parent = findCategoryUUIDForType(LLAssetType::AT_TRASH);
|
||||
const LLUUID new_parent = findCategoryUUIDForType(LLAssetType::AT_TRASH);
|
||||
if (item && item->getParentUUID() != new_parent)
|
||||
{
|
||||
LLInventoryModel::update_list_t update;
|
||||
|
|
@ -3342,7 +3343,7 @@ void LLInventoryModel::removeItem(const LLUUID& item_id)
|
|||
}
|
||||
}
|
||||
|
||||
LLUUID LLInventoryModel::getRootFolderID() const
|
||||
const LLUUID &LLInventoryModel::getRootFolderID() const
|
||||
{
|
||||
return mRootFolderID;
|
||||
}
|
||||
|
|
@ -3352,7 +3353,7 @@ void LLInventoryModel::setRootFolderID(const LLUUID& val)
|
|||
mRootFolderID = val;
|
||||
}
|
||||
|
||||
LLUUID LLInventoryModel::getLibraryRootFolderID() const
|
||||
const LLUUID &LLInventoryModel::getLibraryRootFolderID() const
|
||||
{
|
||||
return mLibraryRootFolderID;
|
||||
}
|
||||
|
|
@ -3362,7 +3363,7 @@ void LLInventoryModel::setLibraryRootFolderID(const LLUUID& val)
|
|||
mLibraryRootFolderID = val;
|
||||
}
|
||||
|
||||
LLUUID LLInventoryModel::getLibraryOwnerID() const
|
||||
const LLUUID &LLInventoryModel::getLibraryOwnerID() const
|
||||
{
|
||||
return mLibraryOwnerID;
|
||||
}
|
||||
|
|
@ -3375,13 +3376,13 @@ void LLInventoryModel::setLibraryOwnerID(const LLUUID& val)
|
|||
//----------------------------------------------------------------------------
|
||||
|
||||
// *NOTE: DEBUG functionality
|
||||
void LLInventoryModel::dumpInventory()
|
||||
void LLInventoryModel::dumpInventory() const
|
||||
{
|
||||
llinfos << "\nBegin Inventory Dump\n**********************:" << llendl;
|
||||
llinfos << "mCategroy[] contains " << mCategoryMap.size() << " items." << llendl;
|
||||
for(cat_map_t::iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
|
||||
llinfos << "mCategory[] contains " << mCategoryMap.size() << " items." << llendl;
|
||||
for(cat_map_t::const_iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
|
||||
{
|
||||
LLViewerInventoryCategory* cat = cit->second;
|
||||
const LLViewerInventoryCategory* cat = cit->second;
|
||||
if(cat)
|
||||
{
|
||||
llinfos << " " << cat->getUUID() << " '" << cat->getName() << "' "
|
||||
|
|
@ -3394,9 +3395,9 @@ void LLInventoryModel::dumpInventory()
|
|||
}
|
||||
}
|
||||
llinfos << "mItemMap[] contains " << mItemMap.size() << " items." << llendl;
|
||||
for(item_map_t::iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
|
||||
for(item_map_t::const_iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
|
||||
{
|
||||
LLViewerInventoryItem* item = iit->second;
|
||||
const LLViewerInventoryItem* item = iit->second;
|
||||
if(item)
|
||||
{
|
||||
llinfos << " " << item->getUUID() << " "
|
||||
|
|
|
|||
|
|
@ -99,12 +99,12 @@ class LLInventoryCollectFunctor;
|
|||
class LLInventoryModel
|
||||
{
|
||||
public:
|
||||
typedef enum e_has_children
|
||||
enum EHasChildren
|
||||
{
|
||||
CHILDREN_NO,
|
||||
CHILDREN_YES,
|
||||
CHILDREN_MAYBE
|
||||
}EHasChildren;
|
||||
};
|
||||
|
||||
// These are used a lot...
|
||||
typedef LLDynamicArray<LLPointer<LLViewerInventoryCategory> > cat_array_t;
|
||||
|
|
@ -133,7 +133,7 @@ public:
|
|||
|
||||
// This is a convenience function to 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);
|
||||
BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id) const;
|
||||
|
||||
// Get the object by id. Returns NULL if not found.
|
||||
// * WARNING: use the pointer returned for read operations - do
|
||||
|
|
@ -197,7 +197,7 @@ public:
|
|||
|
||||
// The inventory model usage is sensitive to the initial construction of the
|
||||
// model.
|
||||
bool isInventoryUsable();
|
||||
bool isInventoryUsable() const;
|
||||
|
||||
//
|
||||
// Mutators
|
||||
|
|
@ -261,7 +261,7 @@ public:
|
|||
// to remove it.
|
||||
void addObserver(LLInventoryObserver* observer);
|
||||
void removeObserver(LLInventoryObserver* observer);
|
||||
BOOL containsObserver(LLInventoryObserver* observer);
|
||||
BOOL containsObserver(LLInventoryObserver* observer) const;
|
||||
|
||||
//
|
||||
// Misc Methods
|
||||
|
|
@ -312,7 +312,7 @@ public:
|
|||
|
||||
// Generates a string containing the path to the item specified by
|
||||
// item_id.
|
||||
void appendPath(const LLUUID& id, std::string& path);
|
||||
void appendPath(const LLUUID& id, std::string& path) const;
|
||||
|
||||
// message handling functionality
|
||||
static void registerCallbacks(LLMessageSystem* msg);
|
||||
|
|
@ -370,7 +370,7 @@ public:
|
|||
// Call these methods when there are category updates, but call
|
||||
// them *before* the actual update so the method can do descendent
|
||||
// accounting correctly.
|
||||
void accountForUpdate(const LLCategoryUpdate& update);
|
||||
void accountForUpdate(const LLCategoryUpdate& update) const;
|
||||
void accountForUpdate(const update_list_t& updates);
|
||||
void accountForUpdate(const update_map_t& updates);
|
||||
|
||||
|
|
@ -404,9 +404,9 @@ public:
|
|||
// gInventory is a singleton and represents the agent's inventory.
|
||||
// The "library" is actually the inventory of a special agent,
|
||||
// usually Alexandria Linden.
|
||||
LLUUID getRootFolderID() const;
|
||||
LLUUID getLibraryOwnerID() const;
|
||||
LLUUID getLibraryRootFolderID() const;
|
||||
const LLUUID &getRootFolderID() const;
|
||||
const LLUUID &getLibraryOwnerID() const;
|
||||
const LLUUID &getLibraryRootFolderID() const;
|
||||
|
||||
// These are set during login with data from the server
|
||||
void setRootFolderID(const LLUUID& id);
|
||||
|
|
@ -422,9 +422,13 @@ protected:
|
|||
void addCategory(LLViewerInventoryCategory* category);
|
||||
void addItem(LLViewerInventoryItem* item);
|
||||
|
||||
// ! DEPRECRATE ! Remove this and add it into findCategoryUUIDForType,
|
||||
// since that's the only function that uses this. It's too confusing
|
||||
// having both methods.
|
||||
//
|
||||
// Internal method which looks for a category with the specified
|
||||
// preferred type. Returns LLUUID::null if not found
|
||||
LLUUID findCatUUID(LLAssetType::EType preferred_type);
|
||||
const LLUUID &findCatUUID(LLAssetType::EType preferred_type) const;
|
||||
|
||||
// Empty the entire contents
|
||||
void empty();
|
||||
|
|
@ -515,7 +519,7 @@ protected:
|
|||
|
||||
public:
|
||||
// *NOTE: DEBUG functionality
|
||||
void dumpInventory();
|
||||
void dumpInventory() const;
|
||||
static bool isBulkFetchProcessingComplete();
|
||||
static void stopBackgroundFetch(); // stop fetch process
|
||||
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@
|
|||
#include "llagentlanguage.h"
|
||||
#include "llwearable.h"
|
||||
#include "llinventorybridge.h"
|
||||
#include "llappearancemgr.h"
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include "llwindebug.h"
|
||||
|
|
@ -3345,10 +3346,10 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
|
|||
}
|
||||
else
|
||||
{
|
||||
wear_outfit_by_name(outfit_folder_name);
|
||||
LLAppearanceManager::wearOutfitByName(outfit_folder_name);
|
||||
}
|
||||
wear_outfit_by_name(gestures);
|
||||
wear_outfit_by_name(COMMON_GESTURES_FOLDER);
|
||||
LLAppearanceManager::wearOutfitByName(gestures);
|
||||
LLAppearanceManager::wearOutfitByName(COMMON_GESTURES_FOLDER);
|
||||
|
||||
// This is really misnamed -- it means we have started loading
|
||||
// an outfit/shape that will give the avatar a gender eventually. JC
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@
|
|||
#include "llimview.h"
|
||||
#include "llrootview.h"
|
||||
#include "llagentui.h"
|
||||
#include "llappearancemgr.h"
|
||||
|
||||
// MAX ITEMS is based on (sizeof(uuid)+2) * count must be < MTUBYTES
|
||||
// or 18 * count < 1200 => count < 1200/18 => 66. I've cut it down a
|
||||
|
|
@ -2508,7 +2509,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory(
|
|||
if(drop)
|
||||
{
|
||||
BOOL append = ( (mask & MASK_SHIFT) ? TRUE : FALSE );
|
||||
wear_inventory_category(category, false, append);
|
||||
LLAppearanceManager::wearInventoryCategory(category, false, append);
|
||||
}
|
||||
return ACCEPT_YES_MULTI;
|
||||
}
|
||||
|
|
@ -2516,7 +2517,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory(
|
|||
{
|
||||
if(drop)
|
||||
{
|
||||
wear_inventory_category(category, true, false);
|
||||
LLAppearanceManager::wearInventoryCategory(category, true, false);
|
||||
}
|
||||
return ACCEPT_YES_MULTI;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
#include "llpreviewgesture.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "lltrans.h"
|
||||
#include "llappearancemgr.h"
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Local function declarations, constants, enums, and typedefs
|
||||
|
|
@ -760,6 +761,11 @@ void WearOnAvatarCallback::fire(const LLUUID& inv_item)
|
|||
}
|
||||
}
|
||||
|
||||
void ModifiedCOFCallback::fire(const LLUUID& inv_item)
|
||||
{
|
||||
LLAppearanceManager::instance().updateAppearanceFromCOF();
|
||||
}
|
||||
|
||||
RezAttachmentCallback::RezAttachmentCallback(LLViewerJointAttachment *attachmentp)
|
||||
{
|
||||
mAttach = attachmentp;
|
||||
|
|
@ -874,6 +880,27 @@ void link_inventory_item(
|
|||
const LLAssetType::EType asset_type,
|
||||
LLPointer<LLInventoryCallback> cb)
|
||||
{
|
||||
const LLInventoryObject *baseobj = gInventory.getObject(item_id);
|
||||
if (!baseobj)
|
||||
{
|
||||
llwarns << "attempt to link to unknown item, linked-to-item's itemID " << item_id << llendl;
|
||||
return;
|
||||
}
|
||||
if (baseobj && baseobj->getIsLinkType())
|
||||
{
|
||||
llwarns << "attempt to create a link to a link, linked-to-item's itemID " << item_id << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (baseobj && !LLAssetType::lookupCanLink(baseobj->getType()))
|
||||
{
|
||||
// Fail if item can be found but is of a type that can't be linked.
|
||||
// Arguably should fail if the item can't be found too, but that could
|
||||
// be a larger behavioral change.
|
||||
llwarns << "attempt to link an unlinkable item, type = " << baseobj->getActualType() << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_LinkInventoryItem);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
|
|
@ -1291,21 +1318,26 @@ bool LLViewerInventoryItem::getIsBrokenLink() const
|
|||
return LLAssetType::lookupIsLinkType(getType());
|
||||
}
|
||||
|
||||
const LLViewerInventoryItem *LLViewerInventoryItem::getLinkedItem() const
|
||||
LLViewerInventoryItem *LLViewerInventoryItem::getLinkedItem() const
|
||||
{
|
||||
if (mType == LLAssetType::AT_LINK)
|
||||
{
|
||||
const LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID);
|
||||
LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID);
|
||||
if (linked_item && linked_item->getIsLinkType())
|
||||
{
|
||||
llwarns << "Warning: Accessing link to link" << llendl;
|
||||
return NULL;
|
||||
}
|
||||
return linked_item;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const
|
||||
LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const
|
||||
{
|
||||
if (mType == LLAssetType::AT_LINK_FOLDER)
|
||||
{
|
||||
const LLViewerInventoryCategory *linked_category = gInventory.getCategory(mAssetUUID);
|
||||
LLViewerInventoryCategory *linked_category = gInventory.getCategory(mAssetUUID);
|
||||
return linked_category;
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -149,8 +149,8 @@ public:
|
|||
LLTransactionID getTransactionID() const { return mTransactionID; }
|
||||
|
||||
bool getIsBrokenLink() const; // true if the baseitem this points to doesn't exist in memory.
|
||||
const LLViewerInventoryItem *getLinkedItem() const;
|
||||
const LLViewerInventoryCategory *getLinkedCategory() const;
|
||||
LLViewerInventoryItem *getLinkedItem() const;
|
||||
LLViewerInventoryCategory *getLinkedCategory() const;
|
||||
|
||||
// callback
|
||||
void onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name);
|
||||
|
|
@ -234,6 +234,11 @@ class WearOnAvatarCallback : public LLInventoryCallback
|
|||
void fire(const LLUUID& inv_item);
|
||||
};
|
||||
|
||||
class ModifiedCOFCallback : public LLInventoryCallback
|
||||
{
|
||||
void fire(const LLUUID& inv_item);
|
||||
};
|
||||
|
||||
class LLViewerJointAttachment;
|
||||
|
||||
class RezAttachmentCallback : public LLInventoryCallback
|
||||
|
|
|
|||
|
|
@ -212,6 +212,7 @@
|
|||
#include "llfloaternotificationsconsole.h"
|
||||
|
||||
#include "lltexlayer.h"
|
||||
#include "llappearancemgr.h"
|
||||
|
||||
using namespace LLVOAvatarDefines;
|
||||
|
||||
|
|
@ -6375,13 +6376,13 @@ void handle_selected_texture_info(void*)
|
|||
|
||||
void handle_test_male(void*)
|
||||
{
|
||||
wear_outfit_by_name("Male Shape & Outfit");
|
||||
LLAppearanceManager::wearOutfitByName("Male Shape & Outfit");
|
||||
//gGestureList.requestResetFromServer( TRUE );
|
||||
}
|
||||
|
||||
void handle_test_female(void*)
|
||||
{
|
||||
wear_outfit_by_name("Female Shape & Outfit");
|
||||
LLAppearanceManager::wearOutfitByName("Female Shape & Outfit");
|
||||
//gGestureList.requestResetFromServer( FALSE );
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue