summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBradley Payne <vir@lindenlab.com>2009-09-24 18:05:38 +0000
committerBradley Payne <vir@lindenlab.com>2009-09-24 18:05:38 +0000
commit7eca974a11cba4c4ed0bc89bccb937b044770c29 (patch)
treee655f479d446715e921731180b37d01be426483b
parent7b2737e0e14f815e69da7114dda693cdaea2c341 (diff)
Merging down avatar-pipeline/currently-worn-folder-8. Includes fixes for EXT-1121: Attaching / detaching objects doesn't affect the Current Outfit folder, and EXT-1090: Attachments detach on login, as well as work in progress for ensemble support and look details.
-rw-r--r--indra/newview/llagentwearables.cpp99
-rw-r--r--indra/newview/llagentwearables.h2
-rw-r--r--indra/newview/llappearancemgr.cpp205
-rw-r--r--indra/newview/llappearancemgr.h16
-rw-r--r--indra/newview/llfloaterinventory.cpp14
-rw-r--r--indra/newview/llinventorybridge.cpp123
-rw-r--r--indra/newview/llinventorymodel.cpp9
-rw-r--r--indra/newview/llinventorymodel.h15
-rw-r--r--indra/newview/llstartup.cpp4
-rw-r--r--indra/newview/llviewermenu.cpp2
-rw-r--r--indra/newview/llvoavatar.cpp13
-rw-r--r--indra/newview/llvoavatarself.cpp6
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory.xml8
13 files changed, 351 insertions, 165 deletions
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index c4e01808f7..6eb248ef74 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1172,99 +1172,24 @@ LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name,
return LLUUID::null;
}
- // First, make a folder in the Clothes directory.
+ // First, make a folder in the My Outfits directory.
+ LLUUID parent_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_MY_OUTFITS);
LLUUID folder_id = gInventory.createNewCategory(
- gInventory.findCategoryUUIDForType(LLAssetType::AT_MY_OUTFITS),
+ parent_id,
LLAssetType::AT_OUTFIT,
new_folder_name);
-// bool found_first_item = false;
-
- ///////////////////
- // Wearables
+ LLAppearanceManager::shallowCopyCategory(LLAppearanceManager::getCOF(),folder_id, NULL);
- if (wearables_to_include.count())
+#if 0
+ LLViewerInventoryCategory *parent_category = gInventory.getCategory(parent_id);
+ if (parent_category)
{
- // Then, iterate though each of the wearables and save links to them in the folder.
- S32 i;
- S32 count = wearables_to_include.count();
- LLDynamicArray<LLUUID> delete_items;
- LLPointer<LLRefCount> cbdone = NULL;
- for (i = 0; i < count; ++i)
- {
- const S32 type = wearables_to_include[i];
- for (U32 j=0; j<getWearableCount((EWearableType)i); j++)
- {
- LLWearable* old_wearable = getWearable((EWearableType)type,j);
- if (old_wearable)
- {
- LLViewerInventoryItem* item = gInventory.getItem(getWearableItemID((EWearableType) type, j));
- if (!item) continue;
- LLPointer<LLInventoryCallback> cb = NULL;
- link_inventory_item(gAgent.getID(),
- item->getLinkedUUID(),
- folder_id,
- item->getName(),
- LLAssetType::AT_LINK,
- cb);
- }
- }
- }
- gInventory.notifyObservers();
+ parent_category->setSelectionByID(folder_id,TRUE);
+ parent_category->setNeedsAutoRename(TRUE);
}
+#endif
-
- ///////////////////
- // Attachments
-
- if (attachments_to_include.count())
- {
- for (S32 i = 0; i < attachments_to_include.count(); i++)
- {
- S32 attachment_pt = attachments_to_include[i];
- LLViewerJointAttachment* attachment = get_if_there(mAvatarObject->mAttachmentPoints, attachment_pt, (LLViewerJointAttachment*)NULL);
- if (!attachment) continue;
- LLViewerObject* attached_object = attachment->getObject();
- if (!attached_object) continue;
- const LLUUID& item_id = attachment->getItemID();
- if (item_id.isNull()) continue;
- LLInventoryItem* item = gInventory.getItem(item_id);
- if (!item) continue;
-
- LLPointer<LLInventoryCallback> cb = NULL;
- link_inventory_item(gAgent.getID(),
- item->getLinkedUUID(),
- folder_id,
- item->getName(),
- LLAssetType::AT_LINK,
- 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;
}
@@ -1759,7 +1684,7 @@ void LLAgentWearables::userRemoveAllClothesStep2(BOOL proceed)
}
}
-void LLAgentWearables::userRemoveAllAttachments(void* userdata)
+void LLAgentWearables::userRemoveAllAttachments()
{
LLVOAvatar* avatarp = gAgent.getAvatarObject();
if (!avatarp)
@@ -1819,7 +1744,7 @@ void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_arra
msg->nextBlockFast(_PREHASH_HeaderData);
msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id );
msg->addU8Fast(_PREHASH_TotalObjects, obj_count );
- msg->addBOOLFast(_PREHASH_FirstDetachAll, true );
+ msg->addBOOLFast(_PREHASH_FirstDetachAll, true ); // BAP changing this doesn't seem to matter?
}
const LLInventoryItem* item = obj_item_array.get(i).get();
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index cb4de555d5..f34b23e220 100644
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -181,7 +181,7 @@ public:
// MULTI-WEARABLE: assuming one wearable per type. Need upstream changes.
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 userRemoveAllAttachments();
static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array);
BOOL itemUpdatePending(const LLUUID& item_id) const;
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 6c234f23fe..74a8d8fe15 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -239,33 +239,25 @@ void LLOutfitFetch::done()
}
}
-class LLUpdateAppearanceOnCount: public LLInventoryCallback
+class LLUpdateAppearanceOnDestroy: public LLInventoryCallback
{
public:
- LLUpdateAppearanceOnCount(S32 count):
- mCount(count)
+ LLUpdateAppearanceOnDestroy():
+ mFireCount(0)
{
}
- virtual ~LLUpdateAppearanceOnCount()
+ virtual ~LLUpdateAppearanceOnDestroy()
{
+ LLAppearanceManager::updateAppearanceFromCOF();
}
/* virtual */ void fire(const LLUUID& inv_item)
{
- mCount--;
- if (mCount==0)
- {
- done();
- }
- }
-
- void done()
- {
- LLAppearanceManager::updateAppearanceFromCOF();
+ mFireCount++;
}
private:
- S32 mCount;
+ U32 mFireCount;
};
struct LLFoundData
@@ -362,25 +354,42 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory
}
// Update appearance from outfit folder.
-/* static */ void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, bool append, bool follow_folder_links)
+/* static */ void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, bool append)
{
if (!proceed)
return;
-
- updateCOFFromOutfit(category, append, follow_folder_links);
+
+ if (append)
+ {
+ updateCOFFromCategory(category, append); // append is true - add non-duplicates to COF.
+ }
+ else
+ {
+ LLViewerInventoryCategory* catp = gInventory.getCategory(category);
+ if (catp->getPreferredType() == LLAssetType::AT_NONE ||
+ LLAssetType::lookupIsEnsembleCategoryType(catp->getPreferredType()))
+ {
+ updateCOFFromCategory(category, append); // append is false - rebuild COF.
+ }
+ else if (catp->getPreferredType() == LLAssetType::AT_OUTFIT)
+ {
+ rebuildCOFFromOutfit(category);
+ }
+ }
}
-// Update COF contents from outfit folder.
-/* static */ void LLAppearanceManager::updateCOFFromOutfit(const LLUUID& category, bool append, bool follow_folder_links)
+// Append to current COF contents by recursively traversing a folder.
+/* static */ void LLAppearanceManager::updateCOFFromCategory(const LLUUID& category, bool append)
{
- // BAP consolidate into one "get all 3 types of descendents" function, use both places.
+ // 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;
+ LLInventoryModel::item_array_t obj_items;
+ LLInventoryModel::item_array_t gest_items;
+ bool follow_folder_links = false;
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;
+ lldebugs << "appendCOFFromCategory()" << llendl;
if( !wear_items.count() && !obj_items.count() && !gest_items.count())
{
LLNotifications::instance().add("CouldNotPutOnOutfit");
@@ -395,31 +404,26 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory
LLInventoryModel::item_array_t cof_items;
gInventory.collectDescendents(current_outfit_id, cof_cats, cof_items,
LLInventoryModel::EXCLUDE_TRASH);
+ // Remove duplicates
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)
+ S32 total_links = gest_items.count() + wear_items.count() + obj_items.count();
+
+ if (!append && total_links > 0)
{
- if (!append)
+ // Remove all current outfit folder links since we're now replacing the contents.
+ for (S32 i = 0; i < cof_items.count(); ++i)
{
- // 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());
- }
+ 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);
+ LLPointer<LLUpdateAppearanceOnDestroy> link_waiter = new LLUpdateAppearanceOnDestroy;
// Link all gestures in this folder
if (gest_items.count() > 0)
@@ -469,11 +473,86 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory
}
}
}
+}
+
+/* static */ void LLAppearanceManager::shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
+ LLPointer<LLInventoryCallback> cb)
+{
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ gInventory.collectDescendents(src_id, cats, items,
+ LLInventoryModel::EXCLUDE_TRASH);
+ for (S32 i = 0; i < items.count(); ++i)
+ {
+ const LLViewerInventoryItem* item = items.get(i).get();
+ if (item->getActualType() == LLAssetType::AT_LINK)
+ {
+ link_inventory_item(gAgent.getID(),
+ item->getLinkedUUID(),
+ dst_id,
+ item->getName(),
+ LLAssetType::AT_LINK, cb);
+ }
+ else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER)
+ {
+ link_inventory_item(gAgent.getID(),
+ item->getLinkedUUID(),
+ dst_id,
+ item->getName(),
+ LLAssetType::AT_LINK_FOLDER, cb);
+ }
+ else
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ dst_id,
+ item->getName(),
+ cb);
+ }
+ }
+}
+
+// Replace COF contents from a given outfit folder.
+/* static */ void LLAppearanceManager::rebuildCOFFromOutfit(const LLUUID& category)
+{
+ lldebugs << "rebuildCOFFromOutfit()" << llendl;
+
+ // Find all the wearables that are in the category's subtree.
+ LLInventoryModel::item_array_t items;
+ getCOFValidDescendents(category, items);
+
+ if( items.count() == 0)
+ {
+ LLNotifications::instance().add("CouldNotPutOnOutfit");
+ return;
+ }
+
+ 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 cof_cats;
+ LLInventoryModel::item_array_t cof_items;
+ gInventory.collectDescendents(current_outfit_id, cof_cats, cof_items,
+ LLInventoryModel::EXCLUDE_TRASH);
+
+ if (items.count() > 0)
+ {
+ // Remove all current outfit folder links since we're now replacing the contents.
+ for (S32 i = 0; i < cof_items.count(); ++i)
+ {
+ gInventory.purgeObject(cof_items.get(i)->getUUID());
+ }
+ }
- // In the particular case that we're switching to a different outfit,
- // create a link to the folder that we wore.
+ LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
+ LLAppearanceManager::shallowCopyCategory(category, current_outfit_id, link_waiter);
+
+ // Create a link to the outfit that we wore.
LLViewerInventoryCategory* catp = gInventory.getCategory(category);
- if (!append && catp && catp->getPreferredType() == LLAssetType::AT_OUTFIT)
+ if (catp && catp->getPreferredType() == LLAssetType::AT_OUTFIT)
{
link_inventory_item(gAgent.getID(), category, current_outfit_id, catp->getName(),
LLAssetType::AT_LINK_FOLDER, LLPointer<LLInventoryCallback>(NULL));
@@ -621,7 +700,7 @@ void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* 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);
+ LLAgentWearables::userRemoveAllAttachments();
}
if( obj_items.count() > 0 )
@@ -635,6 +714,21 @@ void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder,
}
}
+/* static */
+void LLAppearanceManager::getCOFValidDescendents(const LLUUID& category,
+ LLInventoryModel::item_array_t& items)
+{
+ LLInventoryModel::cat_array_t cats;
+ LLFindCOFValidItems is_cof_valid;
+ bool follow_folder_links = false;
+ gInventory.collectDescendentsIf(category,
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_cof_valid,
+ follow_folder_links);
+}
+
/* static */ void LLAppearanceManager::getUserDescendents(const LLUUID& category,
LLInventoryModel::item_array_t& wear_items,
LLInventoryModel::item_array_t& obj_items,
@@ -708,14 +802,13 @@ void LLAppearanceManager::wearInventoryCategoryOnAvatar( LLInventoryCategory* ca
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));
+ gFloaterCustomize->askToSaveIfDirty(boost::bind(LLAppearanceManager::changeOutfit, _1, category->getUUID(), append));
}
else
{
- LLAppearanceManager::changeOutfit(TRUE, category->getUUID(), append, follow_folder_links );
+ LLAppearanceManager::changeOutfit(TRUE, category->getUUID(), append);
}
}
@@ -767,6 +860,7 @@ void LLAppearanceManager::wearOutfitByName(const std::string& name)
//dec_busy_count();
}
+/* static */
void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update )
{
// BAP add check for already in COF.
@@ -779,6 +873,7 @@ void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update )
cb);
}
+/* static */
void LLAppearanceManager::wearEnsemble( LLInventoryCategory* cat, bool do_update )
{
// BAP add check for already in COF.
@@ -791,3 +886,25 @@ void LLAppearanceManager::wearEnsemble( LLInventoryCategory* cat, bool do_update
cb);
}
+/* static */
+void LLAppearanceManager::removeItemLinks(LLUUID& item_id, bool do_update)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ gInventory.collectDescendents(LLAppearanceManager::getCOF(),
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ for (S32 i=0; i<item_array.count(); i++)
+ {
+ const LLInventoryItem* item = item_array.get(i).get();
+ if (item->getLinkedUUID() == item_id)
+ {
+ gInventory.purgeObject(item_array.get(i)->getUUID());
+ }
+ }
+ if (do_update)
+ {
+ LLAppearanceManager::updateAppearanceFromCOF();
+ }
+}
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 89b95833d7..2aa10e0bea 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -35,6 +35,7 @@
#include "llsingleton.h"
#include "llinventorymodel.h"
+#include "llviewerinventory.h"
class LLWearable;
struct LLWearableHoldingPattern;
@@ -44,20 +45,29 @@ 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 changeOutfit(bool proceed, const LLUUID& category, bool append);
+ static void updateCOFFromCategory(const LLUUID& category, bool append);
+ static void rebuildCOFFromOutfit(const LLUUID& category);
static void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append);
static void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append);
static void wearOutfitByName(const std::string& name);
+ static void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
+ LLPointer<LLInventoryCallback> cb);
// 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);
+ static LLUUID getCOF();
+
+ // Remove COF entries
+ static void removeItemLinks(LLUUID& item_id, bool do_update = true);
private:
- static LLUUID getCOF();
+ static void getCOFValidDescendents(const LLUUID& category,
+ LLInventoryModel::item_array_t& items);
+
static void getUserDescendents(const LLUUID& category,
LLInventoryModel::item_array_t& wear_items,
LLInventoryModel::item_array_t& obj_items,
diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp
index 6a3a6c9514..27eb12b9cc 100644
--- a/indra/newview/llfloaterinventory.cpp
+++ b/indra/newview/llfloaterinventory.cpp
@@ -1229,7 +1229,11 @@ BOOL LLInventoryPanel::postBuild()
// build everything.
mInventoryObserver = new LLInventoryPanelObserver(this);
mInventory->addObserver(mInventoryObserver);
- rebuildViewsFor(LLUUID::null, LLInventoryObserver::ADD);
+ // build view of inventory if inventory ready, otherwise wait for modelChanged() callback
+ if (mInventory->isInventoryUsable())
+ {
+ rebuildViewsFor(LLUUID::null, LLInventoryObserver::ADD);
+ }
// bit of a hack to make sure the inventory is open.
mFolders->openFolder(std::string("My Inventory"));
@@ -1326,6 +1330,14 @@ void LLInventoryPanel::modelChanged(U32 mask)
LLFastTimer t2(FTM_REFRESH);
bool handled = false;
+
+ // inventory just initialized, do complete build
+ if ((mask & LLInventoryObserver::ADD) && gInventory.getChangedIDs().empty())
+ {
+ rebuildViewsFor(LLUUID::null, LLInventoryObserver::ADD);
+ return;
+ }
+
if(mask & LLInventoryObserver::LABEL)
{
handled = true;
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index eb07078402..40c5a243cc 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1481,8 +1481,8 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if(!avatar) return FALSE;
- // cannot drag categories into library or COF
- if(!isAgentInventory() || isCOFFolder())
+ // cannot drag categories into library
+ if(!isAgentInventory())
{
return FALSE;
}
@@ -1729,6 +1729,34 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
return accept;
}
+bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item)
+{
+ // Valid COF items are:
+ // - links to wearables (body parts or clothing)
+ // - links to attachments
+ // - links to gestures
+ // - links to ensemble folders
+ LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); // BAP - safe?
+ if (linked_item)
+ {
+ LLAssetType::EType type = linked_item->getType();
+ return (type == LLAssetType::AT_CLOTHING ||
+ type == LLAssetType::AT_BODYPART ||
+ type == LLAssetType::AT_GESTURE ||
+ type == LLAssetType::AT_OBJECT);
+ }
+ else
+ {
+ LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe?
+ // BAP remove AT_NONE support after ensembles are fully working?
+ return (linked_category &&
+ ((linked_category->getPreferredType() == LLAssetType::AT_NONE) ||
+ (LLAssetType::lookupIsEnsembleCategoryType(linked_category->getPreferredType()))));
+ }
+}
+
+
bool LLFindWearables::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
@@ -1743,6 +1771,8 @@ bool LLFindWearables::operator()(LLInventoryCategory* cat,
return FALSE;
}
+
+
//Used by LLFolderBridge as callback for directory recursion.
class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver
{
@@ -1948,6 +1978,15 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model
modifyOutfit(FALSE);
return;
}
+ else if ("wearasensemble" == action)
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(!cat) return;
+ LLAppearanceManager::wearEnsemble(cat,true);
+ return;
+ }
else if ("addtooutfit" == action)
{
modifyOutfit(TRUE);
@@ -2277,8 +2316,11 @@ void LLFolderBridge::folderOptionsMenu()
if(!model) return;
const LLInventoryCategory* category = model->getCategory(mUUID);
- const bool is_default_folder = category &&
- (LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()));
+ LLAssetType::EType type = category->getPreferredType();
+ const bool is_default_folder = category && LLAssetType::lookupIsProtectedCategoryType(type);
+ // BAP change once we're no longer treating regular categories as ensembles.
+ const bool is_ensemble = category && (type == LLAssetType::AT_NONE ||
+ LLAssetType::lookupIsEnsembleCategoryType(type));
// calling card related functionality for folders.
@@ -2313,6 +2355,10 @@ void LLFolderBridge::folderOptionsMenu()
mItems.push_back(std::string("Add To Outfit"));
mItems.push_back(std::string("Replace Outfit"));
}
+ if (is_ensemble)
+ {
+ mItems.push_back(std::string("Wear As Ensemble"));
+ }
mItems.push_back(std::string("Take Off Items"));
}
hideContextEntries(*mMenu, mItems, disabled_items);
@@ -2370,8 +2416,10 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
LLViewerInventoryCategory *cat = getCategory();
- if (!isCOFFolder() && cat &&
- LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))
+ // BAP removed protected check to re-enable standard ops in untyped folders.
+ // Not sure what the right thing is to do here.
+ if (!isCOFFolder() && cat /*&&
+ LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/)
{
// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
@@ -3983,6 +4031,16 @@ void remove_inventory_category_from_avatar( LLInventoryCategory* category )
}
}
+struct OnRemoveStruct
+{
+ LLUUID mUUID;
+ LLFolderView *mFolderToDeleteSelected;
+ OnRemoveStruct(const LLUUID& uuid, LLFolderView *fv = NULL):
+ mUUID(uuid),
+ mFolderToDeleteSelected(fv)
+ {
+ }
+};
void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id)
{
@@ -4030,10 +4088,10 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_
if( gAgentWearables.isWearingItem (item_array.get(i)->getUUID()) )
{
LLWearableList::instance().getAsset(item_array.get(i)->getAssetUUID(),
- item_array.get(i)->getName(),
- item_array.get(i)->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new LLUUID(item_array.get(i)->getUUID()));
+ item_array.get(i)->getName(),
+ item_array.get(i)->getType(),
+ LLWearableBridge::onRemoveFromAvatarArrived,
+ new OnRemoveStruct(item_array.get(i)->getUUID()));
}
}
@@ -4134,12 +4192,25 @@ void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* mod
{
LLViewerInventoryItem* item = getItem();
if (item)
- {
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new LLUUID(mUUID));
+ {
+ if (item->getIsLinkType() &&
+ model->isObjectDescendentOf(mUUID,LLAppearanceManager::getCOF()))
+ {
+ // Delete link after item has been taken off.
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ LLWearableBridge::onRemoveFromAvatarArrived,
+ new OnRemoveStruct(mUUID, folder));
+ }
+ else
+ {
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ LLWearableBridge::onRemoveFromAvatarArrived,
+ new OnRemoveStruct(mUUID));
+ }
}
}
}
@@ -4452,11 +4523,12 @@ void LLWearableBridge::onRemoveFromAvatar(void* user_data)
LLViewerInventoryItem* item = self->getItem();
if (item)
{
+ LLUUID parent_id = item->getParentUUID();
LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- onRemoveFromAvatarArrived,
- new LLUUID(self->mUUID));
+ item->getName(),
+ item->getType(),
+ onRemoveFromAvatarArrived,
+ new OnRemoveStruct(LLUUID(self->mUUID)));
}
}
}
@@ -4465,10 +4537,11 @@ void LLWearableBridge::onRemoveFromAvatar(void* user_data)
void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
void* userdata)
{
- LLUUID* item_id = (LLUUID*) userdata;
+ OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata;
+ LLUUID item_id = on_remove_struct->mUUID;
if(wearable)
{
- if( gAgentWearables.isWearingItem( *item_id ) )
+ if( gAgentWearables.isWearingItem( item_id ) )
{
EWearableType type = wearable->getType();
@@ -4481,7 +4554,11 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
}
}
}
- delete item_id;
+ if (on_remove_struct->mFolderToDeleteSelected)
+ {
+ on_remove_struct->mFolderToDeleteSelected->removeSelectedItems();
+ }
+ delete on_remove_struct;
}
LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 4cbf3e169b..2f3171a868 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -474,7 +474,10 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
if (item->getActualType() == LLAssetType::AT_LINK_FOLDER)
{
LLViewerInventoryCategory *linked_cat = item->getLinkedCategory();
- if (linked_cat)
+ if (linked_cat && linked_cat->getPreferredType() != LLAssetType::AT_OUTFIT)
+ // BAP - was
+ // LLAssetType::lookupIsEnsembleCategoryType(linked_cat->getPreferredType()))
+ // Change back once ensemble typing is in place.
{
if(add(linked_cat,NULL))
{
@@ -2492,6 +2495,10 @@ void LLInventoryModel::buildParentChildMap()
// root of the agent's inv found.
// The inv tree is built.
mIsAgentInvUsable = true;
+
+ llinfos << "Inventory initialized, notifying observers" << llendl;
+ addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
+ notifyObservers();
}
}
}
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index e3e4f6aca0..91a1906fab 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -731,6 +731,21 @@ protected:
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLFindCOFValidItems
+//
+// Collects items that can be legitimately linked to in the COF.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLFindCOFValidItems : public LLInventoryCollectFunctor
+{
+public:
+ LLFindCOFValidItems() {}
+ virtual ~LLFindCOFValidItems() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
+
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFindWearables
//
// Collects wearables based on item type.
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index dbb3062323..6a55b571ae 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2158,10 +2158,6 @@ bool idle_startup()
// lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" and fill it with buddies
LLFriendCardsManager::instance().syncFriendsFolder();
- llinfos << "Setting Inventory changed mask and notifying observers" << llendl;
- gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
- gInventory.notifyObservers();
-
// set up callbacks
llinfos << "Registering Callbacks" << llendl;
LLMessageSystem* msg = gMessageSystem;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 2ebf803e5e..9d278e6a6c 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -2836,7 +2836,7 @@ class LLSelfRemoveAllAttachments : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- LLAgentWearables::userRemoveAllAttachments(NULL);
+ LLAgentWearables::userRemoveAllAttachments();
return true;
}
};
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 1d9ca12af8..92dbb29d8e 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -80,6 +80,7 @@
#include "llsky.h"
#include "llanimstatelabels.h"
#include "lltrans.h"
+#include "llappearancemgr.h"
#include "llgesturemgr.h" //needed to trigger the voice gesticulations
#include "llvoiceclient.h"
@@ -5492,6 +5493,18 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
if (isSelf())
{
// Then make sure the inventory is in sync with the avatar.
+
+ // Update COF contents, don't trigger appearance update.
+ if (gAgent.getAvatarObject() == NULL)
+ {
+ llinfos << "removeItemLinks skipped, avatar is under destruction" << llendl;
+ }
+ else
+ {
+ LLAppearanceManager::removeItemLinks(item_id, false);
+ }
+
+ // BAP - needs to change for label to track link.
gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
gInventory.notifyObservers();
}
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index dfc82ea8d5..20b8750fbf 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -82,6 +82,7 @@
#include "llgesturemgr.h" //needed to trigger the voice gesticulations
#include "llvoiceclient.h"
#include "llvoicevisualizer.h" // Ventrella
+#include "llappearancemgr.h"
#include "boost/lexical_cast.hpp"
@@ -983,6 +984,11 @@ LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *viewer_obj
updateAttachmentVisibility(gAgent.getCameraMode());
// Then make sure the inventory is in sync with the avatar.
+ LLViewerInventoryItem *item = gInventory.getItem(attachment->getItemID());
+ if (item)
+ {
+ LLAppearanceManager::wearItem(item,false); // Add COF link for item.
+ }
gInventory.addChangedMask(LLInventoryObserver::LABEL, attachment->getItemID());
gInventory.notifyObservers();
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 7762a7f667..72cbd3bcd5 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -457,6 +457,14 @@
function="Inventory.DoToSelected"
parameter="replaceoutfit" />
</menu_item_call>
+ <menu_item_call
+ label="Wear As Ensemble"
+ layout="topleft"
+ name="Wear As Ensemble">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="wearasensemble" />
+ </menu_item_call>
<menu_item_separator
layout="topleft" />
<menu_item_call