summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorLoren Shih <seraph@lindenlab.com>2009-08-18 15:34:09 +0000
committerLoren Shih <seraph@lindenlab.com>2009-08-18 15:34:09 +0000
commitac1b723fd79b63a9dab94c839d3c0acb2ddde129 (patch)
tree4da36d5bae02191ce86dea8b5b074b48f516a3ae /indra/newview
parentd53725ece11eb3403128dd77834742a1d084138f (diff)
svn merge -r130469:130817 svn+ssh://svn.lindenlab.com/svn/linden/branches/avatar-pipeline/currently-worn-folder-6 into svn+ssh://svn.lindenlab.com/svn/linden/branches/viewer/viewer-2.0.0-3
This merges in all appearance side panel bug fixes.
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llagentwearables.cpp258
-rw-r--r--indra/newview/llagentwearables.h40
-rw-r--r--indra/newview/llfloaterinventory.cpp5
-rw-r--r--indra/newview/llfolderviewitem.cpp8
-rw-r--r--indra/newview/llinventorybridge.cpp109
-rw-r--r--indra/newview/llinventorybridge.h3
-rw-r--r--indra/newview/llinventoryfilter.cpp10
-rw-r--r--indra/newview/llinventorymodel.cpp57
-rw-r--r--indra/newview/llviewerinventory.cpp5
-rw-r--r--indra/newview/llvoavatarself.cpp13
-rw-r--r--indra/newview/llvoavatarself.h1
-rw-r--r--indra/newview/skins/default/textures/textures.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_customize.xml10
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory.xml16
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory.xml32
-rw-r--r--indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml8
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml1
17 files changed, 334 insertions, 244 deletions
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 4834b31bc7..1b496d44cd 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -44,12 +44,42 @@
#include "llvoavatarself.h"
#include "llwearable.h"
#include "llwearablelist.h"
+#include "llgesturemgr.h"
#include <boost/scoped_ptr.hpp>
-// For viewer2.0 internal demo, don't use current outfit folder contents at all during initial startup. Will reenable
-// this once we're sure this works completely.
-// #define USE_CURRENT_OUTFIT_FOLDER
+#define USE_CURRENT_OUTFIT_FOLDER
+
+//--------------------------------------------------------------------
+// Classes for fetching initial wearables data
+//--------------------------------------------------------------------
+// Outfit folder fetching callback structure.
+class LLInitialWearablesFetch : public LLInventoryFetchDescendentsObserver
+{
+public:
+ LLInitialWearablesFetch() {}
+ ~LLInitialWearablesFetch() {}
+ virtual void done();
+
+ struct InitialWearableData
+ {
+ EWearableType mType;
+ U32 mIndex;
+ LLUUID mItemID;
+ LLUUID mAssetID;
+ InitialWearableData(EWearableType type, U32 index, LLUUID itemID, LLUUID assetID) :
+ mType(type), mIndex(index), mItemID(itemID), mAssetID(assetID) { }
+ };
+
+ typedef std::vector<InitialWearableData> initial_wearable_data_vec_t;
+ initial_wearable_data_vec_t mCOFInitialWearables; // Wearables from the Current Outfit Folder
+ initial_wearable_data_vec_t mAgentInitialWearables; // Wearables from the old agent wearables msg
+
+protected:
+ void processInitialWearables();
+};
+
+
LLAgentWearables gAgentWearables;
@@ -668,6 +698,9 @@ BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id, BOOL include_linked_
// MULTI-WEARABLE: update for multiple
// static
+// ! BACKWARDS COMPATIBILITY ! When we stop supporting viewer1.23, we can assume
+// that viewers have a Current Outfit Folder and won't need this message, and thus
+// we can remove/ignore this whole function.
void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data)
{
// We should only receive this message a single time. Ignore subsequent AgentWearablesUpdates
@@ -696,7 +729,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
// Get the UUID of the current outfit folder (will be created if it doesn't exist)
LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
- LLOutfitFolderFetch* outfit = new LLOutfitFolderFetch();
+ LLInitialWearablesFetch* outfit = new LLInitialWearablesFetch();
//lldebugs << "processAgentInitialWearablesUpdate()" << llendl;
// Add wearables
@@ -733,8 +766,8 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
// MULTI-WEARABLE: TODO: update once messages change. Currently use results to populate the zeroth element.
// Store initial wearables data until we know whether we have the current outfit folder or need to use the data.
- InitialWearableData * temp_wearable_data = new InitialWearableData(type, 0, item_id, asset_id); // MULTI-WEARABLE: update
- outfit->mAgentInitialWearables.push_back(temp_wearable_data);
+ LLInitialWearablesFetch::InitialWearableData wearable_data(type, 0, item_id, asset_id); // MULTI-WEARABLE: update
+ outfit->mAgentInitialWearables.push_back(wearable_data);
}
@@ -761,52 +794,11 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
}
}
-// static
-void LLAgentWearables::fetchInitialWearables(initial_wearable_data_vec_t & current_outfit_links, initial_wearable_data_vec_t & message_wearables)
-{
-#ifdef USE_CURRENT_OUTFIT_FOLDER
- if (!current_outfit_links.empty())
- {
- for (U8 i = 0; i < current_outfit_links.size(); ++i)
- {
- // Fetch the wearables in the current outfit folder
- LLWearableList::instance().getAsset(current_outfit_links[i]->mAssetID,
- LLStringUtil::null,
- LLWearableDictionary::getAssetType(current_outfit_links[i]->mType),
- onInitialWearableAssetArrived, (void*)(current_outfit_links[i]));
- }
- }
- else
-#endif
- if (!message_wearables.empty()) // We have an empty current outfit folder, use the message data instead.
- {
- LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
- for (U8 i = 0; i < message_wearables.size(); ++i)
- {
- // Populate the current outfit folder with links to the wearables passed in the message
-#ifdef USE_CURRENT_OUTFIT_FOLDER
- std::string link_name = "WearableLink";
- link_inventory_item(gAgent.getID(), message_wearables[i]->mItemID, current_outfit_id, link_name,
- LLAssetType::AT_LINK, LLPointer<LLInventoryCallback>(NULL));
-#endif
- // Fetch the wearables
- LLWearableList::instance().getAsset(message_wearables[i]->mAssetID,
- LLStringUtil::null,
- LLWearableDictionary::getAssetType(message_wearables[i]->mType),
- onInitialWearableAssetArrived, (void*)(message_wearables[i]));
- }
- }
- else
- {
- LL_WARNS("Wearables") << "No current outfit folder iterms found and no initial wearables fallback message received." << LL_ENDL;
- }
-}
-
// A single wearable that the avatar was wearing on start-up has arrived from the database.
// static
void LLAgentWearables::onInitialWearableAssetArrived(LLWearable* wearable, void* userdata)
{
- boost::scoped_ptr<InitialWearableData> wear_data((InitialWearableData*)userdata);
+ boost::scoped_ptr<LLInitialWearablesFetch::InitialWearableData> wear_data((LLInitialWearablesFetch::InitialWearableData*)userdata);
const EWearableType type = wear_data->mType;
const U32 index = wear_data->mIndex;
@@ -999,6 +991,18 @@ void LLAgentWearables::createStandardWearablesAllDone()
mAvatarObject->onFirstTEMessageReceived();
}
+void LLAgentWearables::getAllWearablesArray(LLDynamicArray<S32>& wearables)
+{
+ for( S32 i = 0; i < WT_COUNT; ++i )
+ {
+ // MULTI-WEARABLE: Properly handle multiwearables later.
+ if (getWearable( (EWearableType) i, 0 ) != NULL)
+ {
+ wearables.push_back(i);
+ }
+ }
+}
+
// Note: wearables_to_include should be a list of EWearableType types
// attachments_to_include should be a list of attachment points
void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name,
@@ -1134,16 +1138,31 @@ void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name,
}
}
+LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name)
+{
+ if (mAvatarObject.isNull())
+ {
+ return LLUUID::null;
+ }
+
+ LLDynamicArray<S32> wearables_to_include;
+ getAllWearablesArray(wearables_to_include);
+
+ LLDynamicArray<S32> attachments_to_include;
+ mAvatarObject->getAllAttachmentsArray(attachments_to_include);
+
+ return makeNewOutfitLinks(new_folder_name, wearables_to_include, attachments_to_include);
+}
+
// Note: wearables_to_include should be a list of EWearableType types
// attachments_to_include should be a list of attachment points
-void LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name,
- const LLDynamicArray<S32>& wearables_to_include,
- const LLDynamicArray<S32>& attachments_to_include,
- BOOL rename_clothing)
+LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name,
+ const LLDynamicArray<S32>& wearables_to_include,
+ const LLDynamicArray<S32>& attachments_to_include)
{
if (mAvatarObject.isNull())
{
- return;
+ return LLUUID::null;
}
// First, make a folder in the Clothes directory.
@@ -1172,22 +1191,13 @@ void LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name,
LLWearable* old_wearable = getWearable((EWearableType)type,j);
if (old_wearable)
{
- std::string new_name;
- if (rename_clothing)
- {
- new_name = new_folder_name;
- new_name.append(" ");
- new_name.append(old_wearable->getTypeLabel());
- LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN);
- }
-
LLViewerInventoryItem* item = gInventory.getItem(getWearableItemID((EWearableType) type, j));
if (!item) continue;
LLPointer<LLInventoryCallback> cb = NULL;
link_inventory_item(gAgent.getID(),
item->getUUID(),
folder_id,
- new_name,
+ item->getName(),
LLAssetType::AT_LINK,
cb);
}
@@ -1223,6 +1233,32 @@ void LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name,
cb);
}
}
+
+ ///////////////////
+ // Gestures
+
+ /* Disabling this for now, otherwise this adds all your default gestures and all previous
+ active gestures. Need to rethink the intended behavior.
+ for (LLGestureManager::item_map_t::iterator iter = LLGestureManager::instance().mActive.begin();
+ iter != LLGestureManager::instance().mActive.end();
+ ++iter)
+ {
+ const LLUUID &gesture_id = (*iter).first;
+ LLViewerInventoryItem* item = gInventory.getItem(gesture_id);
+ if (item)
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_item(gAgent.getID(),
+ item->getUUID(),
+ folder_id,
+ item->getName(),
+ LLAssetType::AT_LINK,
+ cb);
+ }
+ }
+ */
+
+ return folder_id;
}
void LLAgentWearables::makeNewOutfitDone(S32 type, U32 index)
@@ -1774,11 +1810,10 @@ void LLAgentWearables::updateServer()
gAgent.sendAgentSetAppearance();
}
-void LLAgentWearables::LLOutfitFolderFetch::done()
+void LLInitialWearablesFetch::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.
+ // 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(),
@@ -1786,43 +1821,70 @@ void LLAgentWearables::LLOutfitFolderFetch::done()
item_array,
LLInventoryModel::EXCLUDE_TRASH);
S32 count = item_array.count();
- LLAgentWearables::initial_wearable_data_vec_t current_outfit_links;
- current_outfit_links.reserve(count);
+ mCOFInitialWearables.reserve(count);
- for(S32 i = 0; i < count; ++i)
- {
- // A bit of a hack since wearables database doesn't contain asset types...
- // Perform indirection in case this assetID is in fact a link. This only works
- // because of the assumption that all assetIDs and itemIDs are unique (i.e.
- // no assetID is also used as an itemID elsewhere); therefore if the assetID
- // exists as an itemID in the user's inventory, then this must be a link.
- const LLInventoryItem *linked_item = gInventory.getItem(item_array.get(i)->getUUID());
- LLAssetType::EType asset_type = (LLAssetType::EType) 0;
- if (linked_item)
+ 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)
{
- asset_type = linked_item->getType();
- LLInventoryItem * base_item = gInventory.getItem(linked_item->getLinkedUUID());
- if (base_item)
- {
- EWearableType type = (EWearableType) (base_item->getFlags() & LLInventoryItem::II_FLAGS_WEARABLES_MASK);
- // MULTI-WEARABLE: update
- InitialWearableData * temp_wearable_data = new InitialWearableData(type, 0, linked_item->getLinkedUUID(), base_item->getAssetUUID());
- current_outfit_links.push_back(temp_wearable_data);
- }
- else
- {
- llwarns << "Null base_item in LLOutfitFolderFetch::done, linkedUUID is " << linked_item->getLinkedUUID().asString() << llendl;
- }
- }
- else
- {
- llwarns << "Null linked_item in LLOutfitFolderFetch::done, UUID is " << item_array.get(i)->getUUID().asString() << llendl;
+ 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);
}
gInventory.removeObserver(this);
- LLAgentWearables::fetchInitialWearables(current_outfit_links, mAgentInitialWearables);
- mAgentInitialWearables.clear();
+ processInitialWearables();
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()
+{
+#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.
+ LLWearableList::instance().getAsset(wearable_data->mAssetID,
+ LLStringUtil::null,
+ LLWearableDictionary::getAssetType(wearable_data->mType),
+ LLAgentWearables::onInitialWearableAssetArrived, (void*)(wearable_data));
+ }
+ }
+ 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);
+ for (U8 i = 0; i < mAgentInitialWearables.size(); ++i)
+ {
+ // 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.
+#ifdef USE_CURRENT_OUTFIT_FOLDER
+ const std::string link_name = "WearableLink"; // Unimportant what this is named, it isn't exposed.
+ link_inventory_item(gAgent.getID(), wearable_data->mItemID, current_outfit_id, link_name,
+ LLAssetType::AT_LINK, LLPointer<LLInventoryCallback>(NULL));
+#endif
+ // Fetch the wearables
+ LLWearableList::instance().getAsset(wearable_data->mAssetID,
+ LLStringUtil::null,
+ LLWearableDictionary::getAssetType(wearable_data->mType),
+ LLAgentWearables::onInitialWearableAssetArrived, (void*)(wearable_data));
+ }
+ }
+ else
+ {
+ LL_WARNS("Wearables") << "No current outfit folder items found and no initial wearables fallback message received." << LL_ENDL;
+ }
+}
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 971fd9ee37..b415ef9eb3 100644
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -43,30 +43,16 @@
class LLInventoryItem;
class LLVOAvatarSelf;
class LLWearable;
-
-// Forward Declaration
-class LLInventoryFetchDescendentsObserver;
+class LLInitialWearablesFetch;
class LLAgentWearables
{
//--------------------------------------------------------------------
- // Data Types
- //--------------------------------------------------------------------
- typedef struct _InitialWearableData
- {
- EWearableType mType;
- U32 mIndex;
- LLUUID mItemID;
- LLUUID mAssetID;
- _InitialWearableData(EWearableType type, U32 index, LLUUID itemID, LLUUID assetID) :
- mType(type), mIndex(index), mItemID(itemID), mAssetID(assetID) { }
- } InitialWearableData;
- typedef std::vector<InitialWearableData *> initial_wearable_data_vec_t;
-
- //--------------------------------------------------------------------
// Constructors / destructors / Initializers
//--------------------------------------------------------------------
public:
+ friend class LLInitialWearablesFetch;
+
LLAgentWearables();
virtual ~LLAgentWearables();
void setAvatarObject(LLVOAvatarSelf *avatar);
@@ -149,7 +135,6 @@ protected:
public:
// Processes the initial wearables update message (if necessary, since the outfit folder makes it redundant)
static void processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data);
- static void fetchInitialWearables(initial_wearable_data_vec_t & current_outfit_links, initial_wearable_data_vec_t & message_wearables);
protected:
void sendAgentWearablesUpdate();
void sendAgentWearablesRequest();
@@ -161,6 +146,8 @@ protected:
// Outfits
//--------------------------------------------------------------------
public:
+ void getAllWearablesArray(LLDynamicArray<S32>& wearables);
+
// Note: wearables_to_include should be a list of EWearableType types
// attachments_to_include should be a list of attachment points
void makeNewOutfit(const std::string& new_folder_name,
@@ -170,10 +157,10 @@ public:
// Note: wearables_to_include should be a list of EWearableType types
// attachments_to_include should be a list of attachment points
- void makeNewOutfitLinks(const std::string& new_folder_name,
+ LLUUID makeNewOutfitLinks(const std::string& new_folder_name);
+ LLUUID makeNewOutfitLinks(const std::string& new_folder_name,
const LLDynamicArray<S32>& wearables_to_include,
- const LLDynamicArray<S32>& attachments_to_include,
- BOOL rename_clothing);
+ const LLDynamicArray<S32>& attachments_to_include);
private:
void makeNewOutfitDone(S32 type, U32 index);
@@ -254,17 +241,6 @@ private:
U32 mTodo;
LLPointer<LLRefCount> mCB;
};
-
- // Outfit folder fetching callback structure.
- class LLOutfitFolderFetch : public LLInventoryFetchDescendentsObserver
- {
- public:
- LLOutfitFolderFetch() {}
- ~LLOutfitFolderFetch() {}
- virtual void done();
-
- LLAgentWearables::initial_wearable_data_vec_t mAgentInitialWearables;
- };
}; // LLAgentWearables
diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp
index 718719fe57..3c66a2add1 100644
--- a/indra/newview/llfloaterinventory.cpp
+++ b/indra/newview/llfloaterinventory.cpp
@@ -1138,10 +1138,10 @@ const std::string& get_item_icon_name(LLAssetType::EType asset_type,
idx = LANDMARK_ICON_NAME;
break;
case LLAssetType::AT_LINK:
- idx = BODYPART_ICON_NAME; // Seraph replace this with broken item link icon
+ idx = LINKITEM_ICON_NAME;
break;
case LLAssetType::AT_LINK_FOLDER:
- idx = BODYPART_ICON_NAME; // Seraph replace this with broken folder link icon
+ idx = LINKFOLDER_ICON_NAME;
break;
default:
break;
@@ -1684,6 +1684,7 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it
fv->startRenamingSelectedItem();
}
}
+ // Seraph - Put determineFolderType in here for ensemble typing?
}
//----------------------------------------------------------------------------
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index 69ce2f0e0e..de6a1a097d 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -2115,6 +2115,14 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask )
BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask )
{
+ const LLUUID &cat_uuid = getListener()->getUUID();
+ const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid);
+ if (cat && cat->getPreferredType() == LLAssetType::AT_OUTFIT)
+ {
+ getListener()->performAction(NULL, NULL,"replaceoutfit");
+ return TRUE;
+ }
+
BOOL handled = FALSE;
if( mIsOpen )
{
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 59041792a2..45003fe56c 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -155,6 +155,9 @@ std::string ICON_NAME[ICON_NAME_COUNT] =
"inv_item_animation.tga",
"inv_item_gesture.tga",
+
+ "inv_item_linkitem.tga",
+ "inv_item_linkfolder.tga"
};
BOOL gAddToOutfit = FALSE;
@@ -2309,8 +2312,6 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
else if(isAgentInventory()) // do not allow creating in library
{
mItems.push_back(std::string("New Folder"));
- mItems.push_back(std::string("New Outfit"));
- mItems.push_back(std::string("New My Outfits"));
mItems.push_back(std::string("New Script"));
mItems.push_back(std::string("New Note"));
mItems.push_back(std::string("New Gesture"));
@@ -4157,6 +4158,58 @@ void wear_inventory_category_on_avatar( LLInventoryCategory* category, BOOL appe
}
}
+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;
+}
+
void wear_inventory_category_on_avatar_step2( BOOL proceed, LLUUID category, BOOL append, BOOL follow_folder_links )
{
// Find all the wearables that are in the category's subtree.
@@ -4205,22 +4258,35 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, LLUUID category, BOO
}
const LLUUID &current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
+ // Processes that take time should show the busy cursor
+ inc_busy_count();
+
+ LLInventoryModel::cat_array_t co_cat_array;
+ LLInventoryModel::item_array_t co_item_array;
+ gInventory.collectDescendents(current_outfit_id, co_cat_array, co_item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ if (append)
+ {
+ // Remove duplicates and update counts.
+ removeDuplicateItems(item_array,co_item_array);
+ wearable_count = item_array.count();
+
+ removeDuplicateItems(obj_item_array,co_item_array);
+ obj_count = obj_item_array.count();
+
+ removeDuplicateItems(gest_item_array,co_item_array);
+ gest_count = gest_item_array.count();
+ }
+
if (wearable_count > 0 || obj_count > 0)
{
- // Processes that take time should show the busy cursor
- inc_busy_count();
-
- // Remove all current outfit folder links if we're now replacing the contents.
- if (!append)
+ if (!append)
{
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- gInventory.collectDescendents(current_outfit_id, cat_array, item_array,
- LLInventoryModel::EXCLUDE_TRASH);
- for (i = 0; i < item_array.count(); ++i)
+ // Remove all current outfit folder links if we're now replacing the contents.
+ for (i = 0; i < co_item_array.count(); ++i)
{
- gInventory.purgeObject(item_array.get(i)->getUUID());
+ gInventory.purgeObject(co_item_array.get(i)->getUUID());
}
}
}
@@ -4272,10 +4338,10 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, LLUUID category, BOO
// Fetch the wearables about to be worn.
LLWearableList::instance().getAsset(found->mAssetID,
- found->mName,
- found->mAssetType,
- wear_inventory_category_on_avatar_loop,
- (void*)holder);
+ found->mName,
+ found->mAssetType,
+ wear_inventory_category_on_avatar_loop,
+ (void*)holder);
}
}
@@ -4352,9 +4418,10 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, LLUUID category, BOO
}
}
- // Create a link to the folder that we wore.
+ // 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 (catp)
+ 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));
@@ -5240,6 +5307,10 @@ std::string LLLinkItemBridge::sPrefix("Link: ");
LLUIImagePtr LLLinkItemBridge::getIcon() const
{
+ if (LLViewerInventoryItem *item = getItem())
+ {
+ return get_item_icon(item->getActualType(), LLInventoryType::IT_NONE, 0, FALSE);
+ }
return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE);
}
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 5cfebe6c15..3af54c52ea 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -76,6 +76,9 @@ enum EInventoryIcon
ANIMATION_ICON_NAME,
GESTURE_ICON_NAME,
+ LINKITEM_ICON_NAME,
+ LINKFOLDER_ICON_NAME,
+
ICON_NAME_COUNT
};
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 596211f16c..f5525ec1f2 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -111,7 +111,15 @@ BOOL LLInventoryFilter::check(LLFolderViewItem* item)
}
else
{
- passed_type |= ((1LL << listener->getInventoryType() & mFilterOps.mFilterTypes) != U64(0)) || listener->getInventoryType() == LLInventoryType::IT_NONE;
+ passed_type |= ((1LL << listener->getInventoryType() & mFilterOps.mFilterTypes) != U64(0));
+ if (listener->getInventoryType() == LLInventoryType::IT_NONE)
+ {
+ const LLInventoryObject *obj = gInventory.getObject(listener->getUUID());
+ if (!obj->getIsLinkType())
+ {
+ passed_type = TRUE;
+ }
+ }
}
BOOL passed = passed_type
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index b27fbbff88..aadda3fbfd 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1790,7 +1790,7 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
// The item will show up as a broken link.
if (item->getIsBrokenLink())
{
- llwarns << "Add link item without baseobj present ( itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) " << llendl;
+ llwarns << "Add link item without baseobj present ( name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << llendl;
}
mItemMap[item->getUUID()] = item;
//mInventory[item->getUUID()] = item;
@@ -2041,6 +2041,7 @@ bool LLInventoryModel::loadSkeleton(
{
cat_array_t categories;
item_array_t items;
+ cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded.
std::string owner_id_str;
owner_id.toString(owner_id_str);
std::string path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, owner_id_str));
@@ -2106,7 +2107,7 @@ bool LLInventoryModel::loadSkeleton(
}
// go ahead and add the cats returned during the download
- std::set<LLUUID>::iterator not_cached_id = cached_ids.end();
+ std::set<LLUUID>::const_iterator not_cached_id = cached_ids.end();
cached_category_count = cached_ids.size();
for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
{
@@ -2126,30 +2127,28 @@ bool LLInventoryModel::loadSkeleton(
// category with a correctly cached parent
count = items.count();
cat_map_t::iterator unparented = mCategoryMap.end();
- for(int i = 0; i < count; ++i)
+ for(item_array_t::const_iterator item_iter = items.begin();
+ item_iter != items.end();
+ ++item_iter)
{
- LLViewerInventoryItem *item = items[i].get();
- cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID());
+ LLViewerInventoryItem *item = (*item_iter).get();
+ const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID());
if(cit != unparented)
{
- LLViewerInventoryCategory* cat = cit->second;
+ const LLViewerInventoryCategory* cat = cit->second.get();
if(cat->getVersion() != NO_VERSION)
{
+ // This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache.
if (item->getIsBrokenLink())
{
llinfos << "Attempted to cached link item without baseobj present ( itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) " << llendl;
- child_counts[cat->getUUID()].mValue = -1; // Invalidate this category's cache.
+ invalid_categories.insert(cit->second);
continue;
}
addItem(item);
cached_item_count += 1;
-
- // If this category had any broken links, keep it invalidated.
- if (child_counts[cat->getUUID()].mValue != -1)
- {
- ++child_counts[cat->getUUID()];
- }
+ ++child_counts[cat->getUUID()];
}
}
}
@@ -2169,29 +2168,35 @@ bool LLInventoryModel::loadSkeleton(
// At this point, we need to set the known descendents for each
// category which successfully cached so that we do not
// needlessly fetch descendents for categories which we have.
- update_map_t::iterator no_child_counts = child_counts.end();
- update_map_t::iterator the_count;
+ update_map_t::const_iterator no_child_counts = child_counts.end();
for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
{
- LLViewerInventoryCategory* cat = (*it);
+ LLViewerInventoryCategory* cat = (*it).get();
if(cat->getVersion() != NO_VERSION)
{
- the_count = child_counts.find(cat->getUUID());
+ update_map_t::const_iterator the_count = child_counts.find(cat->getUUID());
if(the_count != no_child_counts)
{
- S32 num_descendents = (*the_count).second.mValue;
-
- // -1 means that one of the children was a broken link, so we can't consider this folder successfully cached.
- if (num_descendents != -1)
- {
- cat->setDescendentCount(num_descendents);
- continue;
- }
+ cat->setDescendentCount((*the_count).second.mValue);
+ }
+ else
+ {
+ cat->setDescendentCount(0);
}
- cat->setDescendentCount(0);
}
}
+ // Invalidate all categories that failed fetching descendents for whatever
+ // reason (e.g. one of the descendents was a broken link).
+ for (cat_set_t::iterator invalid_cat_it = invalid_categories.begin();
+ invalid_cat_it != invalid_categories.end();
+ invalid_cat_it++)
+ {
+ LLViewerInventoryCategory* cat = (*invalid_cat_it).get();
+ cat->setVersion(NO_VERSION);
+ llinfos << "Invalidating category name: " << cat->getName() << " UUID: " << cat->getUUID() << " due to invalid descendents cache" << llendl;
+ }
+
if(remove_inventory_file)
{
// clean up the gunzipped file.
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 9a090be76a..4645b9bf59 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -612,10 +612,7 @@ void LLViewerInventoryCategory::determineFolderType()
return;
if (item->getInventoryType() == LLInventoryType::IT_WEARABLE)
{
- U32 flags = item->getFlags();
- if (flags > WT_COUNT)
- return;
- const EWearableType wearable_type = EWearableType(flags);
+ const EWearableType wearable_type = EWearableType(item->getFlags() & LLInventoryItem::II_FLAGS_WEARABLES_MASK);
const std::string& wearable_name = LLWearableDictionary::getTypeName(wearable_type);
U64 valid_folder_types = LLFolderType::lookupValidFolderTypes(wearable_name);
folder_valid |= valid_folder_types;
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 9df25bdb11..5b4a649ee1 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -990,6 +990,19 @@ LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *viewer_obj
return attachment;
}
+void LLVOAvatarSelf::getAllAttachmentsArray(LLDynamicArray<S32>& attachments)
+{
+ for (LLVOAvatar::attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end(); ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ if ( attachment && (attachment->getNumObjects() > 0))
+ {
+ attachments.push_back(iter->first);
+ }
+ }
+}
+
U32 LLVOAvatarSelf::getNumWearables(LLVOAvatarDefines::ETextureIndex i) const
{
EWearableType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i);
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index e34f09aca2..17744cce1b 100644
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -261,6 +261,7 @@ public:
LLViewerObject* getWornAttachment(const LLUUID& inv_item_id ) const;
const std::string getAttachedPointName(const LLUUID& inv_item_id) const;
/*virtual*/ LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object);
+ void getAllAttachmentsArray(LLDynamicArray<S32>& attachments);
//--------------------------------------------------------------------
// HUDs
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 1515a34eeb..ad208806b7 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -414,6 +414,8 @@
<texture name="inv_item_jacket.tga"/>
<texture name="inv_item_landmark.tga"/>
<texture name="inv_item_landmark_visited.tga"/>
+ <texture name="inv_item_linkitem.tga"/>
+ <texture name="inv_item_linkfolder.tga"/>
<texture name="inv_item_notecard.tga"/>
<texture name="inv_item_object.tga"/>
<texture name="inv_item_object_multi.tga"/>
diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml
index 41bd417c12..824df082d8 100644
--- a/indra/newview/skins/default/xui/en/floater_customize.xml
+++ b/indra/newview/skins/default/xui/en/floater_customize.xml
@@ -3561,14 +3561,4 @@ scratch and wear it.
name="Ok"
right="-116"
width="100" />
- <button
- follows="left|bottom"
- height="20"
- label="Make Outfit..."
- label_selected="Make Outfit..."
- layout="topleft"
- left_delta="-178"
- name="Make Outfit"
- top_delta="0"
- width="100" />
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml
index 610c62a21a..37c6cbf391 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory.xml
@@ -207,22 +207,6 @@
parameter="category" />
</menu_item_call>
<menu_item_call
- label="New Outfit"
- layout="topleft"
- name="New Outfit">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="outfit" />
- </menu_item_call>
- <menu_item_call
- label="New My Outfits"
- layout="topleft"
- name="New My Outfits">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="my_otfts" />
- </menu_item_call>
- <menu_item_call
label="New Script"
layout="topleft"
name="New Script">
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index dd8acea4ed..7762a7f667 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -77,30 +77,6 @@
parameter="category" />
</menu_item_call>
<menu_item_call
- label="New Current"
- layout="topleft"
- name="New Current">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="current" />
- </menu_item_call>
- <menu_item_call
- label="New Outfit"
- layout="topleft"
- name="New Outfit">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="outfit" />
- </menu_item_call>
- <menu_item_call
- label="New My Outfits"
- layout="topleft"
- name="New My Outfits">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="my_otfts" />
- </menu_item_call>
- <menu_item_call
label="New Script"
layout="topleft"
name="New Script">
@@ -338,14 +314,6 @@
function="Inventory.DoToSelected"
parameter="change_folder_type_undershirt" />
</menu_item_call>
- <menu_item_call
- label="Outfit"
- layout="topleft"
- name="Outfit">
- <menu_item_call.on_click
- function="Inventory.DoToSelected"
- parameter="change_folder_type_outfit" />
- </menu_item_call>
</menu>
<menu_item_call
label="Teleport"
diff --git a/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml b/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml
index 7ea059ba6a..e87517e200 100644
--- a/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml
+++ b/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml
@@ -149,11 +149,11 @@
text_color="white"
top="40"
word_wrap="true">
- Change your profile, your look and quick links to your outfits.
+ Change your profile.
</text>
</panel>
<panel
- background_visible="true"
+ background_visible="true"
bg_alpha_color="DkGray2"
class="panel_sidetray_home_info"
follows="left|top|right"
@@ -197,7 +197,7 @@
text_color="white"
top="40"
word_wrap="true">
- Change your appearance.
+ Change your apperance and looks.
</text>
- </panel>
+ </panel>
</panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index fb1aa25b25..f89625c535 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -149,6 +149,7 @@
<string name="gesture">gesture</string>
<string name="simstate">simstate</string>
<string name="favorite">favorite</string>
+ <string name="symbolic link">link</string>
<!-- llvoavatar. Displayed in the avatar chat bubble -->
<string name="AvatarEditingAppearance">(Editing Appearance)</string>