Merge LL V3.7.30
commit
0e2a827873
1
.hgtags
1
.hgtags
|
|
@ -531,3 +531,4 @@ d3d0101e980ec95043e0af9b7903045d3bc447e4 3.7.24-release
|
|||
000e9dda4162cbf0a83ba88558b19473654a09a9 3.7.26-release
|
||||
afd8d4756e8eda3c8f760625d1c17a2ad40ad6c8 3.7.27-release
|
||||
566874eb5ab26c003ef7fb0e22ce40c5fa0013f4 3.7.28-release
|
||||
d07f76c5b9860fb87924d00ca729f7d4532534d6 3.7.29-release
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ void LLWearableData::setWearable(const LLWearableType::EType type, U32 index, LL
|
|||
}
|
||||
}
|
||||
|
||||
U32 LLWearableData::pushWearable(const LLWearableType::EType type,
|
||||
void LLWearableData::pushWearable(const LLWearableType::EType type,
|
||||
LLWearable *wearable,
|
||||
bool trigger_updated /* = true */)
|
||||
{
|
||||
|
|
@ -100,39 +100,16 @@ U32 LLWearableData::pushWearable(const LLWearableType::EType type,
|
|||
{
|
||||
// no null wearables please!
|
||||
LL_WARNS() << "Null wearable sent for type " << type << LL_ENDL;
|
||||
return MAX_CLOTHING_PER_TYPE;
|
||||
}
|
||||
// [RLVa:KB] - Checked: 2010-06-08 (RLVa-1.2.0)
|
||||
if ( (type < LLWearableType::WT_COUNT) && (mWearableDatas[type].size() < MAX_CLOTHING_PER_TYPE) )
|
||||
if (canAddWearable(type))
|
||||
{
|
||||
// Don't add the same wearable twice
|
||||
U32 idxWearable = getWearableIndex(wearable);
|
||||
llassert(MAX_CLOTHING_PER_TYPE == idxWearable); // pushWearable() on an already added wearable is a bug *somewhere*
|
||||
if (MAX_CLOTHING_PER_TYPE == idxWearable)
|
||||
{
|
||||
mWearableDatas[type].push_back(wearable);
|
||||
idxWearable = mWearableDatas[type].size() - 1;
|
||||
}
|
||||
|
||||
mWearableDatas[type].push_back(wearable);
|
||||
if (trigger_updated)
|
||||
{
|
||||
const BOOL removed = FALSE;
|
||||
wearableUpdated(wearable, removed);
|
||||
}
|
||||
return idxWearable;
|
||||
}
|
||||
// [/RLVa:KB]
|
||||
// if (type < LLWearableType::WT_COUNT || mWearableDatas[type].size() < MAX_CLOTHING_PER_TYPE)
|
||||
// {
|
||||
// mWearableDatas[type].push_back(wearable);
|
||||
// if (trigger_updated)
|
||||
// {
|
||||
// const BOOL removed = FALSE;
|
||||
// wearableUpdated(wearable, removed);
|
||||
// }
|
||||
// return mWearableDatas[type].size()-1;
|
||||
// }
|
||||
return MAX_CLOTHING_PER_TYPE;
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
|
@ -145,7 +122,7 @@ void LLWearableData::wearableUpdated(LLWearable *wearable, BOOL removed)
|
|||
}
|
||||
}
|
||||
|
||||
void LLWearableData::popWearable(LLWearable *wearable)
|
||||
void LLWearableData::eraseWearable(LLWearable *wearable)
|
||||
{
|
||||
if (wearable == NULL)
|
||||
{
|
||||
|
|
@ -153,16 +130,16 @@ void LLWearableData::popWearable(LLWearable *wearable)
|
|||
return;
|
||||
}
|
||||
|
||||
U32 index = getWearableIndex(wearable);
|
||||
const LLWearableType::EType type = wearable->getType();
|
||||
|
||||
if (index < MAX_CLOTHING_PER_TYPE && index < getWearableCount(type))
|
||||
U32 index;
|
||||
if (getWearableIndex(wearable,index))
|
||||
{
|
||||
popWearable(type, index);
|
||||
eraseWearable(type, index);
|
||||
}
|
||||
}
|
||||
|
||||
void LLWearableData::popWearable(const LLWearableType::EType type, U32 index)
|
||||
void LLWearableData::eraseWearable(const LLWearableType::EType type, U32 index)
|
||||
{
|
||||
LLWearable *wearable = getWearable(type, index);
|
||||
if (wearable)
|
||||
|
|
@ -224,11 +201,11 @@ void LLWearableData::pullCrossWearableValues(const LLWearableType::EType type)
|
|||
}
|
||||
|
||||
|
||||
U32 LLWearableData::getWearableIndex(const LLWearable *wearable) const
|
||||
BOOL LLWearableData::getWearableIndex(const LLWearable *wearable, U32& index_found) const
|
||||
{
|
||||
if (wearable == NULL)
|
||||
{
|
||||
return MAX_CLOTHING_PER_TYPE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const LLWearableType::EType type = wearable->getType();
|
||||
|
|
@ -236,18 +213,50 @@ U32 LLWearableData::getWearableIndex(const LLWearable *wearable) const
|
|||
if (wearable_iter == mWearableDatas.end())
|
||||
{
|
||||
LL_WARNS() << "tried to get wearable index with an invalid type!" << LL_ENDL;
|
||||
return MAX_CLOTHING_PER_TYPE;
|
||||
return FALSE;
|
||||
}
|
||||
const wearableentry_vec_t& wearable_vec = wearable_iter->second;
|
||||
for(U32 index = 0; index < wearable_vec.size(); index++)
|
||||
{
|
||||
if (wearable_vec[index] == wearable)
|
||||
{
|
||||
return index;
|
||||
index_found = index;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return MAX_CLOTHING_PER_TYPE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
U32 LLWearableData::getClothingLayerCount() const
|
||||
{
|
||||
U32 count = 0;
|
||||
for (S32 i = 0; i < LLWearableType::WT_COUNT; i++)
|
||||
{
|
||||
LLWearableType::EType type = (LLWearableType::EType)i;
|
||||
if (LLWearableType::getAssetType(type)==LLAssetType::AT_CLOTHING)
|
||||
{
|
||||
count += getWearableCount(type);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
BOOL LLWearableData::canAddWearable(const LLWearableType::EType type) const
|
||||
{
|
||||
LLAssetType::EType a_type = LLWearableType::getAssetType(type);
|
||||
if (a_type==LLAssetType::AT_CLOTHING)
|
||||
{
|
||||
return (getClothingLayerCount() < MAX_CLOTHING_LAYERS);
|
||||
}
|
||||
else if (a_type==LLAssetType::AT_BODYPART)
|
||||
{
|
||||
return (getWearableCount(type) < 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLWearableData::isOnTop(LLWearable* wearable) const
|
||||
|
|
|
|||
|
|
@ -60,11 +60,13 @@ public:
|
|||
const LLWearable* getBottomWearable(const LLWearableType::EType type) const;
|
||||
U32 getWearableCount(const LLWearableType::EType type) const;
|
||||
U32 getWearableCount(const U32 tex_index) const;
|
||||
U32 getWearableIndex(const LLWearable *wearable) const;
|
||||
BOOL getWearableIndex(const LLWearable *wearable, U32& index) const;
|
||||
U32 getClothingLayerCount() const;
|
||||
BOOL canAddWearable(const LLWearableType::EType type) const;
|
||||
|
||||
BOOL isOnTop(LLWearable* wearable) const;
|
||||
|
||||
static const U32 MAX_CLOTHING_PER_TYPE = 5;
|
||||
|
||||
static const U32 MAX_CLOTHING_LAYERS = 60;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Setters
|
||||
|
|
@ -72,11 +74,11 @@ public:
|
|||
protected:
|
||||
// Low-level data structure setter - public access is via setWearableItem, etc.
|
||||
void setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable);
|
||||
U32 pushWearable(const LLWearableType::EType type, LLWearable *wearable,
|
||||
void pushWearable(const LLWearableType::EType type, LLWearable *wearable,
|
||||
bool trigger_updated = true);
|
||||
virtual void wearableUpdated(LLWearable *wearable, BOOL removed);
|
||||
void popWearable(LLWearable *wearable);
|
||||
void popWearable(const LLWearableType::EType type, U32 index);
|
||||
void eraseWearable(LLWearable *wearable);
|
||||
void eraseWearable(const LLWearableType::EType type, U32 index);
|
||||
// void clearWearableType(const LLWearableType::EType type);
|
||||
bool swapWearables(const LLWearableType::EType type, U32 index_a, U32 index_b);
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "linden_common.h"
|
||||
#include "llwearabletype.h"
|
||||
#include "llinventorytype.h"
|
||||
#include "llinventorydefines.h"
|
||||
|
||||
static LLTranslationBridge* sTrans = NULL;
|
||||
|
||||
|
|
@ -169,7 +170,7 @@ BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type)
|
|||
return entry->mDisableCameraSwitch;
|
||||
}
|
||||
|
||||
// static
|
||||
// static
|
||||
BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type)
|
||||
{
|
||||
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
||||
|
|
@ -178,3 +179,9 @@ BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type)
|
|||
return entry->mAllowMultiwear;
|
||||
}
|
||||
|
||||
// static
|
||||
LLWearableType::EType LLWearableType::inventoryFlagsToWearableType(U32 flags)
|
||||
{
|
||||
return (LLWearableType::EType)(flags & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ public:
|
|||
static LLInventoryType::EIconName getIconName(EType type);
|
||||
static BOOL getDisableCameraSwitch(EType type);
|
||||
static BOOL getAllowMultiwear(EType type);
|
||||
static EType inventoryFlagsToWearableType(U32 flags);
|
||||
|
||||
protected:
|
||||
LLWearableType() {}
|
||||
|
|
|
|||
|
|
@ -174,7 +174,8 @@ LLFolderView::LLFolderView(const Params& p)
|
|||
mDraggingOverItem(NULL),
|
||||
mStatusTextBox(NULL),
|
||||
mShowItemLinkOverlays(p.show_item_link_overlays),
|
||||
mViewModel(p.view_model)
|
||||
mViewModel(p.view_model),
|
||||
mGroupedItemModel(p.grouped_item_model)
|
||||
{
|
||||
claimMem(mViewModel);
|
||||
LLPanel* panel = p.parent_panel;
|
||||
|
|
@ -1860,7 +1861,6 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu)
|
|||
}
|
||||
|
||||
// Successively filter out invalid options
|
||||
|
||||
U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0);
|
||||
U32 flags = multi_select_flag | FIRST_SELECTED_ITEM;
|
||||
for (selected_items_t::iterator item_itor = mSelectedItems.begin();
|
||||
|
|
@ -1872,6 +1872,14 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu)
|
|||
flags = multi_select_flag;
|
||||
}
|
||||
|
||||
// This adds a check for restrictions based on the entire
|
||||
// selection set - for example, any one wearable may not push you
|
||||
// over the limit, but all wearables together still might.
|
||||
if (getFolderViewGroupedItemModel())
|
||||
{
|
||||
getFolderViewGroupedItemModel()->groupFilterContextMenu(mSelectedItems,*menu);
|
||||
}
|
||||
|
||||
addNoOptions(menu);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "llscrollcontainer.h"
|
||||
|
||||
class LLFolderViewModelInterface;
|
||||
class LLFolderViewGroupedItemModel;
|
||||
class LLFolderViewFolder;
|
||||
class LLFolderViewItem;
|
||||
class LLFolderViewFilter;
|
||||
|
|
@ -93,6 +94,7 @@ public:
|
|||
use_ellipses,
|
||||
show_item_link_overlays;
|
||||
Mandatory<LLFolderViewModelInterface*> view_model;
|
||||
Optional<LLFolderViewGroupedItemModel*> grouped_item_model;
|
||||
Mandatory<std::string> options_menu;
|
||||
|
||||
|
||||
|
|
@ -100,7 +102,7 @@ public:
|
|||
};
|
||||
|
||||
friend class LLFolderViewScrollContainer;
|
||||
typedef std::deque<LLFolderViewItem*> selected_items_t;
|
||||
typedef folder_view_item_deque selected_items_t;
|
||||
|
||||
LLFolderView(const Params&);
|
||||
virtual ~LLFolderView( void );
|
||||
|
|
@ -113,6 +115,9 @@ public:
|
|||
LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; }
|
||||
const LLFolderViewModelInterface* getFolderViewModel() const { return mViewModel; }
|
||||
|
||||
LLFolderViewGroupedItemModel* getFolderViewGroupedItemModel() { return mGroupedItemModel; }
|
||||
const LLFolderViewGroupedItemModel* getFolderViewGroupedItemModel() const { return mGroupedItemModel; }
|
||||
|
||||
typedef boost::signals2::signal<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)> signal_t;
|
||||
void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); }
|
||||
void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); }
|
||||
|
|
@ -308,6 +313,7 @@ protected:
|
|||
LLHandle<LLPanel> mParentPanel;
|
||||
|
||||
LLFolderViewModelInterface* mViewModel;
|
||||
LLFolderViewGroupedItemModel* mGroupedItemModel;
|
||||
|
||||
/**
|
||||
* Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll.
|
||||
|
|
|
|||
|
|
@ -468,5 +468,12 @@ public:
|
|||
template<typename SORT_FUNC> void sortItems(const SORT_FUNC& func) { mItems.sort(func); }
|
||||
};
|
||||
|
||||
typedef std::deque<LLFolderViewItem*> folder_view_item_deque;
|
||||
|
||||
class LLFolderViewGroupedItemModel: public LLRefCount
|
||||
{
|
||||
public:
|
||||
virtual void groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu) = 0;
|
||||
};
|
||||
|
||||
#endif // LLFOLDERVIEWITEM_H
|
||||
|
|
|
|||
|
|
@ -706,12 +706,15 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed)
|
|||
// the versions themselves are compatible. This code can be removed before release.
|
||||
if( wearable->getDefinitionVersion() == 24 )
|
||||
{
|
||||
wearable->setDefinitionVersion(22);
|
||||
U32 index = getWearableIndex(wearable);
|
||||
LL_INFOS() << "forcing wearable type " << wearable->getType() << " to version 22 from 24" << LL_ENDL;
|
||||
// <FS:Ansariel> [Legacy Bake]
|
||||
//saveWearable(wearable->getType(),index);
|
||||
saveWearable(wearable->getType(),index, TRUE);
|
||||
U32 index;
|
||||
if (getWearableIndex(wearable,index))
|
||||
{
|
||||
LL_INFOS() << "forcing wearable type " << wearable->getType() << " to version 22 from 24" << LL_ENDL;
|
||||
wearable->setDefinitionVersion(22);
|
||||
// <FS:Ansariel> [Legacy Bake]
|
||||
//saveWearable(wearable->getType(),index);
|
||||
saveWearable(wearable->getType(),index, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
checkWearableAgainstInventory(viewer_wearable);
|
||||
|
|
@ -1052,7 +1055,7 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
|
|||
LLViewerWearable* old_wearable = getViewerWearable(type,i);
|
||||
if (old_wearable)
|
||||
{
|
||||
popWearable(old_wearable);
|
||||
eraseWearable(old_wearable);
|
||||
// <FS:Ansariel> [Legacy Bake]
|
||||
//old_wearable->removeFromAvatar();
|
||||
old_wearable->removeFromAvatar(TRUE);
|
||||
|
|
@ -1070,7 +1073,7 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
|
|||
|
||||
if (old_wearable)
|
||||
{
|
||||
popWearable(old_wearable);
|
||||
eraseWearable(old_wearable);
|
||||
// <FS:Ansariel> [Legacy Bake]
|
||||
//old_wearable->removeFromAvatar();
|
||||
old_wearable->removeFromAvatar(TRUE);
|
||||
|
|
@ -1290,7 +1293,13 @@ bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD&
|
|||
{
|
||||
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
|
||||
LLInventoryItem* new_item = gInventory.getItem(notification["payload"]["item_id"].asUUID());
|
||||
U32 index = gAgentWearables.getWearableIndex(wearable);
|
||||
U32 index;
|
||||
if (!gAgentWearables.getWearableIndex(wearable,index))
|
||||
{
|
||||
LL_WARNS() << "Wearable not found" << LL_ENDL;
|
||||
delete wearable;
|
||||
return false;
|
||||
}
|
||||
if (!new_item)
|
||||
{
|
||||
delete wearable;
|
||||
|
|
|
|||
|
|
@ -1361,46 +1361,48 @@ void wear_on_avatar_cb(const LLUUID& inv_item, bool do_replace = false)
|
|||
}
|
||||
}
|
||||
|
||||
bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear,
|
||||
bool do_update,
|
||||
bool replace,
|
||||
LLPointer<LLInventoryCallback> cb)
|
||||
void LLAppearanceMgr::wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear,
|
||||
bool do_update,
|
||||
bool replace,
|
||||
LLPointer<LLInventoryCallback> cb)
|
||||
{
|
||||
bool first = true;
|
||||
|
||||
if (item_id_to_wear.isNull()) return false;
|
||||
LLInventoryObject::const_object_list_t items_to_link;
|
||||
|
||||
// *TODO: issue with multi-wearable should be fixed:
|
||||
// in this case this method will be called N times - loading started for each item
|
||||
// and than N times will be called - loading completed for each item.
|
||||
// That means subscribers will be notified that loading is done after first item in a batch is worn.
|
||||
// (loading indicator disappears for example before all selected items are worn)
|
||||
// Have not fix this issue for 2.1 because of stability reason. EXT-7777.
|
||||
for (uuid_vec_t::const_iterator it = item_ids_to_wear.begin();
|
||||
it != item_ids_to_wear.end();
|
||||
++it)
|
||||
{
|
||||
replace = first && replace;
|
||||
first = false;
|
||||
|
||||
// Disabled for now because it is *not* acceptable to call updateAppearanceFromCOF() multiple times
|
||||
// gAgentWearables.notifyLoadingStarted();
|
||||
const LLUUID& item_id_to_wear = *it;
|
||||
|
||||
LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear);
|
||||
if (!item_to_wear) return false;
|
||||
if (item_id_to_wear.isNull()) continue;
|
||||
|
||||
if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID()))
|
||||
{
|
||||
LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(wear_on_avatar_cb,_1,replace));
|
||||
copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(), cb);
|
||||
return false;
|
||||
}
|
||||
else if (!gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getRootFolderID()))
|
||||
{
|
||||
return false; // not in library and not in agent's inventory
|
||||
}
|
||||
else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)))
|
||||
{
|
||||
LLNotificationsUtil::add("CannotWearTrash");
|
||||
return false;
|
||||
}
|
||||
else if (isLinkedInCOF(item_to_wear->getUUID())) // EXT-84911
|
||||
{
|
||||
return false;
|
||||
}
|
||||
LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear);
|
||||
if (!item_to_wear) continue;
|
||||
|
||||
if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID()))
|
||||
{
|
||||
LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(wear_on_avatar_cb,_1,replace));
|
||||
copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(), cb);
|
||||
continue;
|
||||
}
|
||||
else if (!gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getRootFolderID()))
|
||||
{
|
||||
continue; // not in library and not in agent's inventory
|
||||
}
|
||||
else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)))
|
||||
{
|
||||
LLNotificationsUtil::add("CannotWearTrash");
|
||||
continue;
|
||||
}
|
||||
else if (isLinkedInCOF(item_to_wear->getUUID())) // EXT-84911
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// [RLVa:KB] - Checked: 2013-02-12 (RLVa-1.4.8)
|
||||
replace |= (LLAssetType::AT_BODYPART == item_to_wear->getType()); // Body parts should always replace
|
||||
|
|
@ -1410,49 +1412,70 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear,
|
|||
}
|
||||
// [/RLVa:KB]
|
||||
|
||||
switch (item_to_wear->getType())
|
||||
{
|
||||
case LLAssetType::AT_CLOTHING:
|
||||
if (gAgentWearables.areWearablesLoaded())
|
||||
{
|
||||
if (!cb && do_update)
|
||||
{
|
||||
cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
|
||||
}
|
||||
S32 wearable_count = gAgentWearables.getWearableCount(item_to_wear->getWearableType());
|
||||
if ((replace && wearable_count != 0) ||
|
||||
(wearable_count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) )
|
||||
{
|
||||
LLUUID item_id = gAgentWearables.getWearableItemID(item_to_wear->getWearableType(),
|
||||
wearable_count-1);
|
||||
removeCOFItemLinks(item_id, cb);
|
||||
}
|
||||
switch (item_to_wear->getType())
|
||||
{
|
||||
case LLAssetType::AT_CLOTHING:
|
||||
{
|
||||
if (gAgentWearables.areWearablesLoaded())
|
||||
{
|
||||
if (!cb && do_update)
|
||||
{
|
||||
cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
|
||||
}
|
||||
LLWearableType::EType type = item_to_wear->getWearableType();
|
||||
S32 wearable_count = gAgentWearables.getWearableCount(type);
|
||||
if ((replace && wearable_count != 0) || !gAgentWearables.canAddWearable(type))
|
||||
{
|
||||
LLUUID item_id = gAgentWearables.getWearableItemID(item_to_wear->getWearableType(),
|
||||
wearable_count-1);
|
||||
removeCOFItemLinks(item_id, cb);
|
||||
}
|
||||
|
||||
items_to_link.push_back(item_to_wear);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
addCOFItemLink(item_to_wear, cb);
|
||||
}
|
||||
break;
|
||||
case LLAssetType::AT_BODYPART:
|
||||
{
|
||||
// TODO: investigate wearables may not be loaded at this point EXT-8231
|
||||
|
||||
// Remove the existing wearables of the same type.
|
||||
// Remove existing body parts anyway because we must not be able to wear e.g. two skins.
|
||||
removeCOFLinksOfType(item_to_wear->getWearableType());
|
||||
if (!cb && do_update)
|
||||
{
|
||||
cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
|
||||
}
|
||||
items_to_link.push_back(item_to_wear);
|
||||
}
|
||||
break;
|
||||
|
||||
case LLAssetType::AT_OBJECT:
|
||||
{
|
||||
rez_attachment(item_to_wear, NULL, replace);
|
||||
}
|
||||
break;
|
||||
|
||||
case LLAssetType::AT_BODYPART:
|
||||
// TODO: investigate wearables may not be loaded at this point EXT-8231
|
||||
|
||||
// Remove the existing wearables of the same type.
|
||||
// Remove existing body parts anyway because we must not be able to wear e.g. two skins.
|
||||
removeCOFLinksOfType(item_to_wear->getWearableType());
|
||||
if (!cb && do_update)
|
||||
{
|
||||
cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
|
||||
}
|
||||
addCOFItemLink(item_to_wear, cb);
|
||||
break;
|
||||
default: continue;
|
||||
}
|
||||
}
|
||||
|
||||
case LLAssetType::AT_OBJECT:
|
||||
rez_attachment(item_to_wear, NULL, replace);
|
||||
break;
|
||||
// Batch up COF link creation - more efficient if using AIS.
|
||||
if (items_to_link.size())
|
||||
{
|
||||
link_inventory_array(getCOF(), items_to_link, cb);
|
||||
}
|
||||
}
|
||||
|
||||
default: return false;;
|
||||
}
|
||||
|
||||
return true;
|
||||
void LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear,
|
||||
bool do_update,
|
||||
bool replace,
|
||||
LLPointer<LLInventoryCallback> cb)
|
||||
{
|
||||
uuid_vec_t ids;
|
||||
ids.push_back(item_id_to_wear);
|
||||
wearItemsOnAvatar(ids, do_update, replace, cb);
|
||||
}
|
||||
|
||||
// Update appearance from outfit folder.
|
||||
|
|
@ -1860,6 +1883,49 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
|
|||
return items.size() > 0;
|
||||
}
|
||||
|
||||
// Moved from LLWearableList::ContextMenu for wider utility.
|
||||
bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids)
|
||||
{
|
||||
// TODO: investigate wearables may not be loaded at this point EXT-8231
|
||||
|
||||
U32 n_objects = 0;
|
||||
U32 n_clothes = 0;
|
||||
|
||||
// Count given clothes (by wearable type) and objects.
|
||||
for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it)
|
||||
{
|
||||
LLViewerInventoryItem* item = gInventory.getItem(*it);
|
||||
if (!item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item->getType() == LLAssetType::AT_OBJECT)
|
||||
{
|
||||
++n_objects;
|
||||
}
|
||||
else if (item->getType() == LLAssetType::AT_CLOTHING)
|
||||
{
|
||||
++n_clothes;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Unexpected wearable type" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether we can add all the objects.
|
||||
if (!isAgentAvatarValid() || !gAgentAvatarp->canAttachMoreObjects(n_objects))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check whether we can add all the clothes.
|
||||
U32 sum_clothes = n_clothes + gAgentWearables.getClothingLayerCount();
|
||||
return sum_clothes <= LLAgentWearables::MAX_CLOTHING_LAYERS;
|
||||
}
|
||||
|
||||
void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> cb)
|
||||
{
|
||||
LLInventoryModel::cat_array_t cats;
|
||||
|
|
@ -1911,28 +1977,42 @@ void LLAppearanceMgr::purgeItemsOfType(LLAssetType::EType asset_type)
|
|||
// Keep the last N wearables of each type. For viewer 2.0, N is 1 for
|
||||
// both body parts and clothing items.
|
||||
void LLAppearanceMgr::filterWearableItems(
|
||||
LLInventoryModel::item_array_t& items, S32 max_per_type)
|
||||
LLInventoryModel::item_array_t& items, S32 max_per_type, S32 max_total)
|
||||
{
|
||||
// Divvy items into arrays by wearable type.
|
||||
std::vector<LLInventoryModel::item_array_t> items_by_type(LLWearableType::WT_COUNT);
|
||||
divvyWearablesByType(items, items_by_type);
|
||||
// Restrict by max total items first.
|
||||
if ((max_total > 0) && (items.size() > max_total))
|
||||
{
|
||||
LLInventoryModel::item_array_t items_to_keep;
|
||||
for (S32 i=0; i<max_total; i++)
|
||||
{
|
||||
items_to_keep.push_back(items[i]);
|
||||
}
|
||||
items = items_to_keep;
|
||||
}
|
||||
|
||||
// rebuild items list, retaining the last max_per_type of each array
|
||||
items.clear();
|
||||
for (S32 i=0; i<LLWearableType::WT_COUNT; i++)
|
||||
{
|
||||
S32 size = items_by_type[i].size();
|
||||
if (size <= 0)
|
||||
continue;
|
||||
// S32 start_index = llmax(0,size-max_per_type);
|
||||
if (max_per_type > 0)
|
||||
{
|
||||
// Divvy items into arrays by wearable type.
|
||||
std::vector<LLInventoryModel::item_array_t> items_by_type(LLWearableType::WT_COUNT);
|
||||
divvyWearablesByType(items, items_by_type);
|
||||
|
||||
// rebuild items list, retaining the last max_per_type of each array
|
||||
items.clear();
|
||||
for (S32 i=0; i<LLWearableType::WT_COUNT; i++)
|
||||
{
|
||||
S32 size = items_by_type[i].size();
|
||||
if (size <= 0)
|
||||
continue;
|
||||
// S32 start_index = llmax(0,size-max_per_type);
|
||||
// [SL:KB] - Patch: Appearance-Misc | Checked: 2010-05-11 (Catznip-2.0)
|
||||
S32 start_index = llmax(0, size - ((LLAssetType::AT_BODYPART == LLWearableType::getAssetType((LLWearableType::EType)i)) ? 1 : max_per_type));
|
||||
// [/SL:KB[
|
||||
for (S32 j = start_index; j<size; j++)
|
||||
{
|
||||
items.push_back(items_by_type[i][j]);
|
||||
}
|
||||
}
|
||||
for (S32 j = start_index; j<size; j++)
|
||||
{
|
||||
items.push_back(items_by_type[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
|
||||
|
|
@ -2002,7 +2082,7 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new,
|
|||
// reverse(body_items.begin(), body_items.end());
|
||||
// Reduce body items to max of one per type.
|
||||
removeDuplicateItems(body_items);
|
||||
filterWearableItems(body_items, 1);
|
||||
filterWearableItems(body_items, 1, 0);
|
||||
|
||||
// - Wearables: include COF contents only if appending.
|
||||
LLInventoryModel::item_array_t wear_items;
|
||||
|
|
@ -2028,7 +2108,7 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new,
|
|||
// [SL:KB] - Patch: Appearance-WearableDuplicateAssets | Checked: 2011-07-24 (Catznip-2.6.0e) | Added: Catznip-2.6.0e
|
||||
removeDuplicateWearableItemsByAssetID(wear_items);
|
||||
// [/SL:KB]
|
||||
filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE);
|
||||
filterWearableItems(wear_items, 0, LLAgentWearables::MAX_CLOTHING_LAYERS);
|
||||
|
||||
// - Attachments: include COF contents only if appending.
|
||||
LLInventoryModel::item_array_t obj_items;
|
||||
|
|
@ -2302,7 +2382,8 @@ void item_array_diff(LLInventoryModel::item_array_t& full_list,
|
|||
|
||||
S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id,
|
||||
LLAssetType::EType type,
|
||||
S32 max_items,
|
||||
S32 max_items_per_type,
|
||||
S32 max_items_total,
|
||||
LLInventoryObject::object_list_t& items_to_kill)
|
||||
{
|
||||
S32 to_kill_count = 0;
|
||||
|
|
@ -2311,9 +2392,9 @@ S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id,
|
|||
getDescendentsOfAssetType(cat_id, items, type);
|
||||
LLInventoryModel::item_array_t curr_items = items;
|
||||
removeDuplicateItems(items);
|
||||
if (max_items > 0)
|
||||
if (max_items_per_type > 0 || max_items_total > 0)
|
||||
{
|
||||
filterWearableItems(items, max_items);
|
||||
filterWearableItems(items, max_items_per_type, max_items_total);
|
||||
}
|
||||
LLInventoryModel::item_array_t kill_items;
|
||||
item_array_diff(curr_items,items,kill_items);
|
||||
|
|
@ -2332,11 +2413,11 @@ void LLAppearanceMgr::findAllExcessOrDuplicateItems(const LLUUID& cat_id,
|
|||
LLInventoryObject::object_list_t& items_to_kill)
|
||||
{
|
||||
findExcessOrDuplicateItems(cat_id,LLAssetType::AT_BODYPART,
|
||||
1, items_to_kill);
|
||||
1, 0, items_to_kill);
|
||||
findExcessOrDuplicateItems(cat_id,LLAssetType::AT_CLOTHING,
|
||||
LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill);
|
||||
0, LLAgentWearables::MAX_CLOTHING_LAYERS, items_to_kill);
|
||||
findExcessOrDuplicateItems(cat_id,LLAssetType::AT_OBJECT,
|
||||
-1, items_to_kill);
|
||||
0, 0, items_to_kill);
|
||||
}
|
||||
|
||||
void LLAppearanceMgr::enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb)
|
||||
|
|
@ -2881,7 +2962,6 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item,
|
|||
item_array,
|
||||
LLInventoryModel::EXCLUDE_TRASH);
|
||||
bool linked_already = false;
|
||||
U32 count = 0;
|
||||
for (S32 i=0; i<item_array.size(); i++)
|
||||
{
|
||||
// Are these links to the same object?
|
||||
|
|
@ -2901,14 +2981,13 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item,
|
|||
// type? If so, new item will replace old.
|
||||
else if ((vitem->isWearableType()) && (vitem->getWearableType() == wearable_type))
|
||||
{
|
||||
++count;
|
||||
if (is_body_part && inv_item->getIsLinkType() && (vitem->getWearableType() == wearable_type))
|
||||
if (is_body_part && inv_item->getIsLinkType())
|
||||
{
|
||||
remove_inventory_item(inv_item->getUUID(), cb);
|
||||
}
|
||||
else if (count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE)
|
||||
else if (!gAgentWearables.canAddWearable(wearable_type))
|
||||
{
|
||||
// MULTI-WEARABLES: make sure we don't go over MAX_CLOTHING_PER_TYPE
|
||||
// MULTI-WEARABLES: make sure we don't go over clothing limits
|
||||
remove_inventory_item(inv_item->getUUID(), cb);
|
||||
}
|
||||
// [SL:KB] - Patch: Appearance-WearableDuplicateAssets | Checked: 2011-07-24 (Catznip-2.6.0e) | Added: Catznip-2.6.0e
|
||||
|
|
@ -4437,16 +4516,7 @@ void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb)
|
|||
void wear_multiple(const uuid_vec_t& ids, bool replace)
|
||||
{
|
||||
LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
|
||||
|
||||
bool first = true;
|
||||
uuid_vec_t::const_iterator it;
|
||||
for (it = ids.begin(); it != ids.end(); ++it)
|
||||
{
|
||||
// if replace is requested, the first item worn will replace the current top
|
||||
// item, and others will be added.
|
||||
LLAppearanceMgr::instance().wearItemOnAvatar(*it,false,first && replace,cb);
|
||||
first = false;
|
||||
}
|
||||
LLAppearanceMgr::instance().wearItemsOnAvatar(ids, false, replace, cb);
|
||||
}
|
||||
|
||||
// SLapp for easy-wearing of a stock (library) avatar
|
||||
|
|
|
|||
|
|
@ -79,7 +79,8 @@ public:
|
|||
void addCategoryToCurrentOutfit(const LLUUID& cat_id);
|
||||
S32 findExcessOrDuplicateItems(const LLUUID& cat_id,
|
||||
LLAssetType::EType type,
|
||||
S32 max_items,
|
||||
S32 max_items_per_type,
|
||||
S32 max_items_total,
|
||||
LLInventoryObject::object_list_t& items_to_kill);
|
||||
void findAllExcessOrDuplicateItems(const LLUUID& cat_id,
|
||||
LLInventoryObject::object_list_t& items_to_kill);
|
||||
|
|
@ -111,6 +112,9 @@ public:
|
|||
// Determine whether we can replace current outfit with the given one.
|
||||
bool getCanReplaceCOF(const LLUUID& outfit_cat_id);
|
||||
|
||||
// Can we add all referenced items to the avatar?
|
||||
bool canAddWearables(const uuid_vec_t& item_ids);
|
||||
|
||||
// Copy all items in a category.
|
||||
void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
|
@ -129,8 +133,13 @@ public:
|
|||
// find the UUID of the currently worn outfit (Base Outfit)
|
||||
const LLUUID getBaseOutfitUUID();
|
||||
|
||||
void wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear,
|
||||
bool do_update,
|
||||
bool replace,
|
||||
LLPointer<LLInventoryCallback> cb = NULL);
|
||||
|
||||
// Wear/attach an item (from a user's inventory) on the agent
|
||||
bool wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update, bool replace = false,
|
||||
void wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update, bool replace = false,
|
||||
LLPointer<LLInventoryCallback> cb = NULL);
|
||||
|
||||
// Update the displayed outfit name in UI.
|
||||
|
|
@ -247,7 +256,7 @@ protected:
|
|||
|
||||
private:
|
||||
|
||||
void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type);
|
||||
void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type, S32 max_total);
|
||||
|
||||
void getDescendentsOfAssetType(const LLUUID& category,
|
||||
LLInventoryModel::item_array_t& items,
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@
|
|||
#include "llviewerwindow.h"
|
||||
#include "llvoavatarself.h"
|
||||
#include "llwearablelist.h"
|
||||
#include "llwearableitemslist.h"
|
||||
#include "lllandmarkactions.h"
|
||||
#include "llpanellandmarks.h"
|
||||
// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1)
|
||||
|
|
@ -588,6 +589,46 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void disable_context_entries_if_present(LLMenuGL& menu,
|
||||
const menuentry_vec_t &disabled_entries)
|
||||
{
|
||||
const LLView::child_list_t *list = menu.getChildList();
|
||||
for (LLView::child_list_t::const_iterator itor = list->begin();
|
||||
itor != list->end();
|
||||
++itor)
|
||||
{
|
||||
LLView *menu_item = (*itor);
|
||||
std::string name = menu_item->getName();
|
||||
|
||||
// descend into split menus:
|
||||
LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(menu_item);
|
||||
if ((name == "More") && branchp)
|
||||
{
|
||||
disable_context_entries_if_present(*branchp->getBranch(), disabled_entries);
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
menuentry_vec_t::const_iterator itor2;
|
||||
for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
|
||||
{
|
||||
if (*itor2 == name)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
menu_item->setVisible(TRUE);
|
||||
// A bit of a hack so we can remember that some UI element explicitly set this to be visible
|
||||
// so that some other UI element from multi-select doesn't later set this invisible.
|
||||
menu_item->pushVisible(TRUE);
|
||||
|
||||
menu_item->setEnabled(FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
void hide_context_entries(LLMenuGL& menu,
|
||||
const menuentry_vec_t &entries_to_show,
|
||||
const menuentry_vec_t &disabled_entries)
|
||||
|
|
@ -887,6 +928,31 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
|||
hide_context_entries(menu, items, disabled_items);
|
||||
}
|
||||
|
||||
bool get_selection_item_uuids(LLFolderView::selected_items_t& selected_items, uuid_vec_t& ids)
|
||||
{
|
||||
uuid_vec_t results;
|
||||
S32 non_item = 0;
|
||||
for(LLFolderView::selected_items_t::iterator it = selected_items.begin(); it != selected_items.end(); ++it)
|
||||
{
|
||||
LLItemBridge *view_model = dynamic_cast<LLItemBridge *>((*it)->getViewModelItem());
|
||||
|
||||
if(view_model && view_model->getUUID().notNull())
|
||||
{
|
||||
results.push_back(view_model->getUUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
non_item++;
|
||||
}
|
||||
}
|
||||
if (non_item == 0)
|
||||
{
|
||||
ids = results;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLInvFVBridge::addTrashContextMenuOptions(menuentry_vec_t &items,
|
||||
menuentry_vec_t &disabled_items)
|
||||
{
|
||||
|
|
@ -1285,10 +1351,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
|
|||
{
|
||||
LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
|
||||
}
|
||||
// <FS> FIRE-6627: Clear high bits to determine proper wearable type
|
||||
//new_listener = new LLWearableBridge(inventory, root, uuid, asset_type, inv_type, (LLWearableType::EType)flags);
|
||||
new_listener = new LLWearableBridge(inventory, root, uuid, asset_type, inv_type, LLWearableType::EType(flags & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK));
|
||||
// </FS>
|
||||
new_listener = new LLWearableBridge(inventory, root, uuid, asset_type, inv_type, LLWearableType::inventoryFlagsToWearableType(flags));
|
||||
break;
|
||||
case LLAssetType::AT_CATEGORY:
|
||||
if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
|
||||
|
|
@ -3966,7 +4029,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
|||
if(!model) return;
|
||||
|
||||
buildContextMenuOptions(flags, items, disabled_items);
|
||||
hide_context_entries(menu, items, disabled_items);
|
||||
hide_context_entries(menu, items, disabled_items);
|
||||
|
||||
// Reposition the menu, in case we're adding items to an existing menu.
|
||||
menu.needsArrange();
|
||||
|
|
@ -6466,9 +6529,9 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
|||
if (LLWearableType::getAllowMultiwear(mWearableType))
|
||||
{
|
||||
items.push_back(std::string("Wearable Add"));
|
||||
// if (gAgentWearables.getWearableCount(mWearableType) >= LLAgentWearables::MAX_CLOTHING_PER_TYPE)
|
||||
// if (!gAgentWearables.canAddWearable(mWearableType))
|
||||
// [SL:KB] - Patch: Appearance-WearableDuplicateAssets | Checked: 2011-07-24 (Catznip-2.6.0e) | Added: Catznip-2.6.0e
|
||||
if ( (gAgentWearables.getWearableCount(mWearableType) >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) ||
|
||||
if ( (!gAgentWearables.canAddWearable(mWearableType)) ||
|
||||
(gAgentWearables.getWearableFromAssetID(item->getAssetUUID())) )
|
||||
// [/SL:KB]
|
||||
{
|
||||
|
|
@ -7178,6 +7241,24 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge(
|
|||
return new_listener;
|
||||
}
|
||||
|
||||
LLFolderViewGroupedItemBridge::LLFolderViewGroupedItemBridge()
|
||||
{
|
||||
}
|
||||
|
||||
void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu)
|
||||
{
|
||||
uuid_vec_t ids;
|
||||
menuentry_vec_t disabled_items;
|
||||
if (get_selection_item_uuids(selected_items, ids))
|
||||
{
|
||||
if (!LLAppearanceMgr::instance().canAddWearables(ids))
|
||||
{
|
||||
disabled_items.push_back(std::string("Wearable Add"));
|
||||
}
|
||||
}
|
||||
disable_context_entries_if_present(menu, disabled_items);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Worn Inventory Panel related classes */
|
||||
/************************************************************************/
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "llviewerwearable.h"
|
||||
#include "lltooldraganddrop.h"
|
||||
#include "lllandmarklist.h"
|
||||
#include "llfolderviewitem.h"
|
||||
|
||||
class LLInventoryFilter;
|
||||
class LLInventoryPanel;
|
||||
|
|
@ -761,4 +762,11 @@ void hide_context_entries(LLMenuGL& menu,
|
|||
const menuentry_vec_t &entries_to_show,
|
||||
const menuentry_vec_t &disabled_entries);
|
||||
|
||||
class LLFolderViewGroupedItemBridge: public LLFolderViewGroupedItemModel
|
||||
{
|
||||
public:
|
||||
LLFolderViewGroupedItemBridge();
|
||||
virtual void groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu);
|
||||
};
|
||||
|
||||
#endif // LL_LLINVENTORYBRIDGE_H
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
// newview includes
|
||||
#include "llappearancemgr.h"
|
||||
#include "llappviewer.h"
|
||||
#include "llavataractions.h"
|
||||
#include "llclipboard.h"
|
||||
#include "lldonotdisturbnotificationstorage.h"
|
||||
#include "llfloaterinventory.h"
|
||||
|
|
@ -1323,16 +1324,35 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
|
|||
LLFloater::setFloaterHost(multi_propertiesp);
|
||||
}
|
||||
|
||||
std::set<LLFolderViewItem*>::iterator set_iter;
|
||||
|
||||
for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
|
||||
{
|
||||
LLFolderViewItem* folder_item = *set_iter;
|
||||
if(!folder_item) continue;
|
||||
LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();
|
||||
if(!bridge) continue;
|
||||
bridge->performAction(model, action);
|
||||
}
|
||||
|
||||
std::set<LLUUID> selected_uuid_set = LLAvatarActions::getInventorySelectedUUIDs();
|
||||
uuid_vec_t ids;
|
||||
std::copy(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids));
|
||||
// Check for actions that get handled in bulk
|
||||
if (action == "wear")
|
||||
{
|
||||
wear_multiple(ids, true);
|
||||
}
|
||||
else if (action == "wear_add")
|
||||
{
|
||||
wear_multiple(ids, false);
|
||||
}
|
||||
else if (action == "take_off" || action == "detach")
|
||||
{
|
||||
LLAppearanceMgr::instance().removeItemsFromAvatar(ids);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::set<LLFolderViewItem*>::iterator set_iter;
|
||||
for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
|
||||
{
|
||||
LLFolderViewItem* folder_item = *set_iter;
|
||||
if(!folder_item) continue;
|
||||
LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();
|
||||
if(!bridge) continue;
|
||||
bridge->performAction(model, action);
|
||||
}
|
||||
}
|
||||
|
||||
LLFloater::setFloaterHost(NULL);
|
||||
if (multi_previewp)
|
||||
|
|
|
|||
|
|
@ -183,6 +183,6 @@ const std::string& LLInventoryIcon::getIconName(LLInventoryType::EIconName idx)
|
|||
|
||||
LLInventoryType::EIconName LLInventoryIcon::assignWearableIcon(U32 misc_flag)
|
||||
{
|
||||
const LLWearableType::EType wearable_type = LLWearableType::EType(LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK & misc_flag);
|
||||
const LLWearableType::EType wearable_type = LLWearableType::inventoryFlagsToWearableType(misc_flag);
|
||||
return LLWearableType::getIconName(wearable_type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,7 +152,8 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
|
|||
mShowEmptyMessage(p.show_empty_message),
|
||||
mViewsInitialized(false),
|
||||
mInvFVBridgeBuilder(NULL),
|
||||
mInventoryViewModel(p.name)
|
||||
mInventoryViewModel(p.name),
|
||||
mGroupedItemBridge(new LLFolderViewGroupedItemBridge)
|
||||
{
|
||||
mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER;
|
||||
|
||||
|
|
@ -196,6 +197,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )
|
|||
NULL,
|
||||
root_id);
|
||||
p.view_model = &mInventoryViewModel;
|
||||
p.grouped_item_model = mGroupedItemBridge;
|
||||
p.use_label_suffix = mParams.use_label_suffix;
|
||||
p.allow_multiselect = mAllowMultiSelect;
|
||||
p.show_empty_message = mShowEmptyMessage;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ class LLInvFVBridge;
|
|||
class LLInventoryFolderViewModelBuilder;
|
||||
class LLInvPanelComplObserver;
|
||||
class LLFolderViewModelInventory;
|
||||
class LLFolderViewGroupedItemBridge;
|
||||
|
||||
namespace LLInitParam
|
||||
{
|
||||
|
|
@ -251,6 +252,7 @@ protected:
|
|||
LLScrollContainer* mScroller;
|
||||
|
||||
LLFolderViewModelInventory mInventoryViewModel;
|
||||
LLPointer<LLFolderViewGroupedItemBridge> mGroupedItemBridge;
|
||||
Params mParams; // stored copy of parameter block
|
||||
|
||||
std::map<LLUUID, LLFolderViewItem*> mItemMap;
|
||||
|
|
|
|||
|
|
@ -561,14 +561,16 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp
|
|||
LLAvatarAppearanceDefines::ETextureIndex reg_texind = getTexIndex(type, baked_texind);
|
||||
if (reg_texind != LLAvatarAppearanceDefines::TEX_NUM_INDICES)
|
||||
{
|
||||
U32 index = gAgentWearables.getWearableIndex(wearable);
|
||||
gAgentAvatarp->setLocalTexture(reg_texind, gTextureList.getImage(new_id), FALSE, index);
|
||||
// <FS:Ansariel> [Legacy Bake]
|
||||
//gAgentAvatarp->wearableUpdated(type);
|
||||
gAgentAvatarp->wearableUpdated(type, FALSE);
|
||||
|
||||
/* telling the manager to rebake once update cycle is fully done */
|
||||
LLLocalBitmapMgr::setNeedsRebake();
|
||||
U32 index;
|
||||
if (gAgentWearables.getWearableIndex(wearable,index))
|
||||
{
|
||||
gAgentAvatarp->setLocalTexture(reg_texind, gTextureList.getImage(new_id), FALSE, index);
|
||||
// <FS:Ansariel> [Legacy Bake]
|
||||
//gAgentAvatarp->wearableUpdated(type);
|
||||
gAgentAvatarp->wearableUpdated(type, FALSE);
|
||||
/* telling the manager to rebake once update cycle is fully done */
|
||||
LLLocalBitmapMgr::setNeedsRebake();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -932,17 +932,17 @@ void LLPanelEditWearable::onCommitSexChange()
|
|||
if (!isAgentAvatarValid()) return;
|
||||
|
||||
LLWearableType::EType type = mWearablePtr->getType();
|
||||
U32 index = gAgentWearables.getWearableIndex(mWearablePtr);
|
||||
|
||||
if( !gAgentWearables.isWearableModifiable(type, index))
|
||||
U32 index;
|
||||
if( !gAgentWearables.getWearableIndex(mWearablePtr, index) ||
|
||||
!gAgentWearables.isWearableModifiable(type, index))
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
LLViewerVisualParam* param = static_cast<LLViewerVisualParam*>(gAgentAvatarp->getVisualParam( "male" ));
|
||||
if( !param )
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_new_sex_male = (gSavedSettings.getU32("AvatarSex") ? SEX_MALE : SEX_FEMALE) == SEX_MALE;
|
||||
|
|
@ -992,12 +992,19 @@ void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl)
|
|||
}
|
||||
if (getWearable())
|
||||
{
|
||||
U32 index = gAgentWearables.getWearableIndex(getWearable());
|
||||
gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index);
|
||||
LLVisualParamHint::requestHintUpdates();
|
||||
// <FS:Ansariel> [Legacy Bake]
|
||||
//gAgentAvatarp->wearableUpdated(type);
|
||||
gAgentAvatarp->wearableUpdated(type, FALSE);
|
||||
U32 index;
|
||||
if (gAgentWearables.getWearableIndex(getWearable(), index))
|
||||
{
|
||||
gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index);
|
||||
LLVisualParamHint::requestHintUpdates();
|
||||
// <FS:Ansariel> [Legacy Bake]
|
||||
//gAgentAvatarp->wearableUpdated(type);
|
||||
gAgentAvatarp->wearableUpdated(type, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "wearable not found in gAgentWearables" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1078,7 +1085,12 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
|
|||
return;
|
||||
}
|
||||
|
||||
U32 index = gAgentWearables.getWearableIndex(mWearablePtr);
|
||||
U32 index;
|
||||
if (!gAgentWearables.getWearableIndex(mWearablePtr, index))
|
||||
{
|
||||
LL_WARNS() << "wearable not found" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string new_name = mNameEditor->getText();
|
||||
|
||||
|
|
@ -1605,6 +1617,12 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
|
|||
|
||||
LL_INFOS() << "onInvisibilityCommit, self " << this << " checkbox_ctrl " << checkbox_ctrl << LL_ENDL;
|
||||
|
||||
U32 index;
|
||||
if (!gAgentWearables.getWearableIndex(getWearable(),index))
|
||||
{
|
||||
LL_WARNS() << "wearable not found" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
bool new_invis_state = checkbox_ctrl->get();
|
||||
if (new_invis_state)
|
||||
{
|
||||
|
|
@ -1612,11 +1630,10 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
|
|||
mPreviousAlphaTexture[te] = lto->getID();
|
||||
|
||||
LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( IMG_INVISIBLE );
|
||||
U32 index = gAgentWearables.getWearableIndex(getWearable());
|
||||
gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
|
||||
// <FS:Ansariel> [Legacy Bake]
|
||||
//gAgentAvatarp->wearableUpdated(getWearable()->getType());
|
||||
gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE);
|
||||
gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
|
||||
// <FS:Ansariel> [Legacy Bake]
|
||||
//gAgentAvatarp->wearableUpdated(getWearable()->getType());
|
||||
gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1631,7 +1648,6 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
|
|||
LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(prev_id);
|
||||
if (!image) return;
|
||||
|
||||
U32 index = gAgentWearables.getWearableIndex(getWearable());
|
||||
gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
|
||||
// <FS:Ansariel> [Legacy Bake]
|
||||
//gAgentAvatarp->wearableUpdated(getWearable()->getType());
|
||||
|
|
|
|||
|
|
@ -214,7 +214,8 @@ void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility)
|
|||
}
|
||||
if (is_wearable_edit_visible)
|
||||
{
|
||||
if (gAgentWearables.getWearableIndex(wearable_ptr) == LLAgentWearables::MAX_CLOTHING_PER_TYPE)
|
||||
U32 index;
|
||||
if (!gAgentWearables.getWearableIndex(wearable_ptr,index))
|
||||
{
|
||||
// we're no longer wearing the wearable we were last editing, switch back to outfit editor
|
||||
showOutfitEditPanel();
|
||||
|
|
|
|||
|
|
@ -2127,7 +2127,7 @@ LLWearableType::EType LLViewerInventoryItem::getWearableType() const
|
|||
{
|
||||
return LLWearableType::WT_INVALID;
|
||||
}
|
||||
return LLWearableType::EType(getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK);
|
||||
return LLWearableType::inventoryFlagsToWearableType(getFlags());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1925,8 +1925,16 @@ BOOL LLVOAvatarSelf::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex t
|
|||
return LLVOAvatar::isTextureVisible(type);
|
||||
}
|
||||
|
||||
U32 index = gAgentWearables.getWearableIndex(wearable);
|
||||
return isTextureVisible(type,index);
|
||||
U32 index;
|
||||
if (gAgentWearables.getWearableIndex(wearable,index))
|
||||
{
|
||||
return isTextureVisible(type,index);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Wearable not found" << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
bool LLVOAvatarSelf::areTexturesCurrent() const
|
||||
|
|
|
|||
|
|
@ -962,11 +962,11 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu
|
|||
setMenuItemVisible(menu, "wear_wear", n_already_worn == 0 && n_worn == 0 && can_be_worn);
|
||||
// setMenuItemEnabled(menu, "wear_wear", n_already_worn == 0 && n_worn == 0);
|
||||
setMenuItemVisible(menu, "wear_add", wear_add_visible);
|
||||
// setMenuItemEnabled(menu, "wear_add", canAddWearables(ids));
|
||||
// setMenuItemEnabled(menu, "wear_add", LLAppearanceMgr::instance().canAddWearables(ids));
|
||||
setMenuItemVisible(menu, "wear_replace", n_worn == 0 && n_already_worn != 0 && can_be_worn);
|
||||
// [RLVa:KB] - Checked: 2010-09-04 (RLVa-1.2.1a) | Added: RLVa-1.2.1a
|
||||
setMenuItemEnabled(menu, "wear_wear", n_already_worn == 0 && n_worn == 0 && rlvCanWearReplace);
|
||||
setMenuItemEnabled(menu, "wear_add", canAddWearables(ids) && rlvCanWearAdd);
|
||||
setMenuItemEnabled(menu, "wear_add", LLAppearanceMgr::instance().canAddWearables(ids) && rlvCanWearAdd);
|
||||
setMenuItemEnabled(menu, "wear_replace", rlvCanWearReplace);
|
||||
// [/RLVa:KB]
|
||||
//visible only when one item selected and this item is worn
|
||||
|
|
@ -976,7 +976,7 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu
|
|||
// [/SL:KB]
|
||||
setMenuItemEnabled(menu, "edit", n_editable == 1 && n_worn == 1 && n_items == 1);
|
||||
setMenuItemVisible(menu, "create_new", mask & (MASK_CLOTHING|MASK_BODYPART) && n_items == 1);
|
||||
setMenuItemEnabled(menu, "create_new", canAddWearables(ids));
|
||||
setMenuItemEnabled(menu, "create_new", LLAppearanceMgr::instance().canAddWearables(ids));
|
||||
setMenuItemVisible(menu, "show_original", !standalone);
|
||||
setMenuItemEnabled(menu, "show_original", n_items == 1 && n_links == n_items);
|
||||
setMenuItemVisible(menu, "take_off", mask == MASK_CLOTHING && n_worn == n_items);
|
||||
|
|
@ -1085,65 +1085,4 @@ void LLWearableItemsList::ContextMenu::createNewWearable(const LLUUID& item_id)
|
|||
LLAgentWearables::createWearable(item->getWearableType(), true);
|
||||
}
|
||||
|
||||
// Returns true if all the given objects and clothes can be added.
|
||||
// static
|
||||
bool LLWearableItemsList::ContextMenu::canAddWearables(const uuid_vec_t& item_ids)
|
||||
{
|
||||
// TODO: investigate wearables may not be loaded at this point EXT-8231
|
||||
|
||||
U32 n_objects = 0;
|
||||
boost::unordered_map<LLWearableType::EType, U32> clothes_by_type;
|
||||
|
||||
// Count given clothes (by wearable type) and objects.
|
||||
for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it)
|
||||
{
|
||||
LLViewerInventoryItem* item = gInventory.getItem(*it);
|
||||
if (!item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item->getType() == LLAssetType::AT_OBJECT)
|
||||
{
|
||||
++n_objects;
|
||||
}
|
||||
else if (item->getType() == LLAssetType::AT_CLOTHING)
|
||||
{
|
||||
++clothes_by_type[item->getWearableType()];
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Unexpected wearable type" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether we can add all the objects.
|
||||
if (!isAgentAvatarValid() || !gAgentAvatarp->canAttachMoreObjects(n_objects))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check whether we can add all the clothes.
|
||||
boost::unordered_map<LLWearableType::EType, U32>::const_iterator m_it;
|
||||
for (m_it = clothes_by_type.begin(); m_it != clothes_by_type.end(); ++m_it)
|
||||
{
|
||||
LLWearableType::EType w_type = m_it->first;
|
||||
U32 n_clothes = m_it->second;
|
||||
|
||||
U32 wearable_count = gAgentWearables.getWearableCount(w_type);
|
||||
if ((wearable_count > 0) && !LLWearableType::getAllowMultiwear(w_type))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((wearable_count + n_clothes) > LLAgentWearables::MAX_CLOTHING_PER_TYPE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
|
|
|||
|
|
@ -429,7 +429,6 @@ public:
|
|||
static void setMenuItemEnabled(LLContextMenu* menu, const std::string& name, bool val);
|
||||
static void updateMask(U32& mask, LLAssetType::EType at);
|
||||
static void createNewWearable(const LLUUID& item_id);
|
||||
static bool canAddWearables(const uuid_vec_t& item_ids);
|
||||
|
||||
LLWearableItemsList* mParent;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue