diff options
27 files changed, 568 insertions, 321 deletions
| @@ -500,3 +500,6 @@ d3d0101e980ec95043e0af9b7903045d3bc447e4 3.7.24-release  9978a8c3a2ffce4a5e1c186256581c2ac139c9dc 3.7.25-release  000e9dda4162cbf0a83ba88558b19473654a09a9 3.7.26-release  afd8d4756e8eda3c8f760625d1c17a2ad40ad6c8 3.7.27-release +566874eb5ab26c003ef7fb0e22ce40c5fa0013f4 3.7.28-release +d07f76c5b9860fb87924d00ca729f7d4532534d6 3.7.29-release +67edc442c80b8d2fadd2a6c4a7184b469906cdbf 3.7.30-release diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 79fbc90fbc..70d85b864c 100755 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -68,76 +68,87 @@ if(WINDOWS)      # Copy MS C runtime dlls, required for packaging.      # *TODO - Adapt this to support VC9      if (MSVC80) -        set(MSVC_VER 80) -        set(MSVC_VERDOT 8.0) +        list(APPEND LMSVC_VER 80) +        list(APPEND LMSVC_VERDOT 8.0)      elseif (MSVC_VERSION EQUAL 1600) # VisualStudio 2010 -        set(MSVC_VER 100) -        set(MSVC_VERDOT 10.0) +        MESSAGE(STATUS "MSVC_VERSION ${MSVC_VERSION}")      elseif (MSVC_VERSION EQUAL 1800) # VisualStudio 2013, which is (sigh) VS 12 -        set(MSVC_VER 120) -        set(MSVC_VERDOT 12.0) +        list(APPEND LMSVC_VER 120) +        list(APPEND LMSVC_VERDOT 12.0)      else (MSVC80)          MESSAGE(WARNING "New MSVC_VERSION ${MSVC_VERSION} of MSVC: adapt Copy3rdPartyLibs.cmake")      endif (MSVC80) -    FIND_PATH(debug_msvc_redist_path msvcr${MSVC_VER}d.dll -        PATHS -        ${MSVC_DEBUG_REDIST_PATH} -         [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\${MSVC_VERDOT}\\Setup\\VC;ProductDir]/redist/Debug_NonRedist/x86/Microsoft.VC${MSVC_VER}.DebugCRT -        [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/SysWOW64 -        [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/System32 -        NO_DEFAULT_PATH -        ) - -    if(EXISTS ${debug_msvc_redist_path}) -        set(debug_msvc_files -            msvcr${MSVC_VER}d.dll -            msvcp${MSVC_VER}d.dll -            ) - -        copy_if_different( -            ${debug_msvc_redist_path} -            "${SHARED_LIB_STAGING_DIR_DEBUG}" -            out_targets -            ${debug_msvc_files} -            ) -        set(third_party_targets ${third_party_targets} ${out_targets}) - -    endif () - -    FIND_PATH(release_msvc_redist_path msvcr${MSVC_VER}.dll -        PATHS -        ${MSVC_REDIST_PATH} -         [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\${MSVC_VERDOT}\\Setup\\VC;ProductDir]/redist/x86/Microsoft.VC${MSVC_VER}.CRT -        [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/SysWOW64 -        [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/System32 -        NO_DEFAULT_PATH -        ) - -    if(EXISTS ${release_msvc_redist_path}) -        set(release_msvc_files -            msvcr${MSVC_VER}.dll -            msvcp${MSVC_VER}.dll -            ) - -        copy_if_different( -            ${release_msvc_redist_path} -            "${SHARED_LIB_STAGING_DIR_RELEASE}" -            out_targets -            ${release_msvc_files} +    # try to copy VS2010 redist independently of system version +    list(APPEND LMSVC_VER 100) +    list(APPEND LMSVC_VERDOT 10.0) +     +    list(LENGTH LMSVC_VER count) +    math(EXPR count "${count}-1") +    foreach(i RANGE ${count}) +        list(GET LMSVC_VER ${i} MSVC_VER) +        list(GET LMSVC_VERDOT ${i} MSVC_VERDOT) +        MESSAGE(STATUS "Copying redist libs for VC ${MSVC_VERDOT}") +        FIND_PATH(debug_msvc_redist_path NAME msvcr${MSVC_VER}d.dll +            PATHS             +            [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\${MSVC_VERDOT}\\Setup\\VC;ProductDir]/redist/Debug_NonRedist/x86/Microsoft.VC${MSVC_VER}.DebugCRT +            [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/SysWOW64 +            [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/System32 +            ${MSVC_DEBUG_REDIST_PATH} +            NO_DEFAULT_PATH              ) -        set(third_party_targets ${third_party_targets} ${out_targets}) -        copy_if_different( -            ${release_msvc_redist_path} -            "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}" -            out_targets -            ${release_msvc_files} +        if(EXISTS ${debug_msvc_redist_path}) +            set(debug_msvc_files +                msvcr${MSVC_VER}d.dll +                msvcp${MSVC_VER}d.dll +                ) + +            copy_if_different( +                ${debug_msvc_redist_path} +                "${SHARED_LIB_STAGING_DIR_DEBUG}" +                out_targets +                ${debug_msvc_files} +                ) +            set(third_party_targets ${third_party_targets} ${out_targets}) + +            unset(debug_msvc_redist_path CACHE) +        endif() + +        FIND_PATH(release_msvc_redist_path NAME msvcr${MSVC_VER}.dll +            PATHS             +            [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\${MSVC_VERDOT}\\Setup\\VC;ProductDir]/redist/x86/Microsoft.VC${MSVC_VER}.CRT +            [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/SysWOW64 +            [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/System32 +            ${MSVC_REDIST_PATH} +            NO_DEFAULT_PATH              ) -        set(third_party_targets ${third_party_targets} ${out_targets}) -           -    endif () +        if(EXISTS ${release_msvc_redist_path}) +            set(release_msvc_files +                msvcr${MSVC_VER}.dll +                msvcp${MSVC_VER}.dll +                ) + +            copy_if_different( +                ${release_msvc_redist_path} +                "${SHARED_LIB_STAGING_DIR_RELEASE}" +                out_targets +                ${release_msvc_files} +                ) +            set(third_party_targets ${third_party_targets} ${out_targets}) + +            copy_if_different( +                ${release_msvc_redist_path} +                "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}" +                out_targets +                ${release_msvc_files} +                ) +            set(third_party_targets ${third_party_targets} ${out_targets}) + +            unset(release_msvc_redist_path CACHE) +        endif() +    endforeach()  elseif(DARWIN)      set(SHARED_LIB_STAGING_DIR_DEBUG            "${SHARED_LIB_STAGING_DIR}/Debug/Resources") diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp index 5dfb201fc4..2bf3b9085b 100755 --- a/indra/llappearance/llwearabledata.cpp +++ b/indra/llappearance/llwearabledata.cpp @@ -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,9 +100,8 @@ 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;  	} -	if (type < LLWearableType::WT_COUNT || mWearableDatas[type].size() < MAX_CLOTHING_PER_TYPE) +	if (canAddWearable(type))  	{  		mWearableDatas[type].push_back(wearable);  		if (trigger_updated) @@ -110,9 +109,7 @@ U32 LLWearableData::pushWearable(const LLWearableType::EType type,  			const BOOL removed = FALSE;  			wearableUpdated(wearable, removed);  		} -		return mWearableDatas[type].size()-1;  	} -	return MAX_CLOTHING_PER_TYPE;  }  // virtual @@ -125,7 +122,7 @@ void LLWearableData::wearableUpdated(LLWearable *wearable, BOOL removed)  	}  } -void LLWearableData::popWearable(LLWearable *wearable) +void LLWearableData::eraseWearable(LLWearable *wearable)  {  	if (wearable == NULL)  	{ @@ -133,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) @@ -204,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(); @@ -216,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 diff --git a/indra/llappearance/llwearabledata.h b/indra/llappearance/llwearabledata.h index 03bd179f25..a0c446ea9e 100644..100755 --- a/indra/llappearance/llwearabledata.h +++ b/indra/llappearance/llwearabledata.h @@ -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); diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp index 618e2a1941..87109a5906 100644..100755 --- a/indra/llappearance/llwearabletype.cpp +++ b/indra/llappearance/llwearabletype.cpp @@ -27,6 +27,7 @@  #include "linden_common.h"  #include "llwearabletype.h"  #include "llinventorytype.h" +#include "llinventorydefines.h"  static LLTranslationBridge* sTrans = NULL; @@ -160,7 +161,7 @@ BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type)  	return entry->mDisableCameraSwitch;  } -// static  +// static  BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type)  {  	const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); @@ -169,3 +170,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); +} + diff --git a/indra/llappearance/llwearabletype.h b/indra/llappearance/llwearabletype.h index 7c9594644d..519d5b92a2 100644..100755 --- a/indra/llappearance/llwearabletype.h +++ b/indra/llappearance/llwearabletype.h @@ -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() {} diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index f60129e601..4c05d001a0 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -170,7 +170,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; @@ -1810,7 +1811,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(); @@ -1822,6 +1822,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);  } diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 08e0a6220a..114dd7bd2f 100755 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -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); } @@ -300,6 +305,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. diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 0cd20a0f2d..5ad5731cad 100644..100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -454,5 +454,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 diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 7c35ff8c4b..ca06baa571 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -3.7.28 +3.7.31 diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index f06ffb4fb3..5589ab4aa7 100755 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -633,10 +633,13 @@ 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; -			saveWearable(wearable->getType(),index); +			U32 index; +			if (getWearableIndex(wearable,index)) +			{ +				LL_INFOS() << "forcing wearable type " << wearable->getType() << " to version 22 from 24" << LL_ENDL; +				wearable->setDefinitionVersion(22); +				saveWearable(wearable->getType(),index); +			}  		}  		checkWearableAgainstInventory(viewer_wearable); @@ -949,7 +952,7 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo  			LLViewerWearable* old_wearable = getViewerWearable(type,i);  			if (old_wearable)  			{ -				popWearable(old_wearable); +				eraseWearable(old_wearable);  				old_wearable->removeFromAvatar();  			}  		} @@ -961,7 +964,7 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo  		if (old_wearable)  		{ -			popWearable(old_wearable); +			eraseWearable(old_wearable);  			old_wearable->removeFromAvatar();  		}  	} @@ -1163,7 +1166,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; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index a64d5b50b3..b3317e937e 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1338,90 +1338,113 @@ void wear_on_avatar_cb(const LLUUID& inv_item, bool do_replace = false)  	}  } -bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, +void LLAppearanceMgr::wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear, +                                        bool do_update, +                                        bool replace, +                                        LLPointer<LLInventoryCallback> cb) +{ +    bool first = true; + +    LLInventoryObject::const_object_list_t items_to_link; + +    for (uuid_vec_t::const_iterator it = item_ids_to_wear.begin(); +         it != item_ids_to_wear.end(); +         ++it) +    { +        replace = first && replace; +        first = false; + +        const LLUUID& item_id_to_wear = *it; + +        if (item_id_to_wear.isNull()) continue; + +        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; +        } + +        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; + +            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; + +            default: continue; +        } +    } + +    // Batch up COF link creation - more efficient if using AIS. +    if (items_to_link.size()) +    { +        link_inventory_array(getCOF(), items_to_link, cb);  +    } +} + +void LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear,  									   bool do_update,  									   bool replace,  									   LLPointer<LLInventoryCallback> cb)  { - -	if (item_id_to_wear.isNull()) return false; - -	// *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. - -	// Disabled for now because it is *not* acceptable to call updateAppearanceFromCOF() multiple times -//	gAgentWearables.notifyLoadingStarted(); - -	LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear); -	if (!item_to_wear) return false; - -	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; -	} - -	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); -			} - -			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); -		} -		addCOFItemLink(item_to_wear, cb); -		break; - -		case LLAssetType::AT_OBJECT: -		rez_attachment(item_to_wear, NULL, replace); -		break; - -		default: return false;; -	} - -	return true; +    uuid_vec_t ids; +    ids.push_back(item_id_to_wear); +    wearItemsOnAvatar(ids, do_update, replace, cb);  }  // Update appearance from outfit folder. @@ -1782,6 +1805,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; @@ -1804,25 +1870,39 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLIn  // 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) -{ -	// 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); -		for (S32 j = start_index; j<size; j++) -		{ -			items.push_back(items_by_type[i][j]); -		} -	} +	LLInventoryModel::item_array_t& items, S32 max_per_type, S32 max_total) +{ +    // 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; +    } + +    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); +            for (S32 j = start_index; j<size; j++) +            { +                items.push_back(items_by_type[i][j]); +            } +        } +    }  }  void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) @@ -1864,7 +1944,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)  		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; @@ -1873,7 +1953,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)  	getDescendentsOfAssetType(category, wear_items, LLAssetType::AT_CLOTHING);  	// Reduce wearables to max of one per type.  	removeDuplicateItems(wear_items); -	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; @@ -2062,7 +2142,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; @@ -2071,9 +2152,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); @@ -2092,11 +2173,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) @@ -2588,7 +2669,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? @@ -2608,14 +2688,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);  			}  		} @@ -4071,16 +4150,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 diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 7742a19c07..ee9d3b7209 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -67,7 +67,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); @@ -99,6 +100,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); @@ -117,8 +121,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. @@ -235,7 +244,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, diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 1dc5558555..a047ed6fee 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -74,6 +74,7 @@  #include "llviewerwindow.h"  #include "llvoavatarself.h"  #include "llwearablelist.h" +#include "llwearableitemslist.h"  #include "lllandmarkactions.h"  #include "llpanellandmarks.h" @@ -557,6 +558,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) @@ -765,6 +806,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)  { @@ -1120,7 +1186,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;  			} -			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::inventoryFlagsToWearableType(flags));  			break;  		case LLAssetType::AT_CATEGORY:  			if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) @@ -3585,7 +3651,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(); @@ -5770,7 +5836,7 @@ 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))  						{  							disabled_items.push_back(std::string("Wearable Add"));  						} @@ -6439,4 +6505,22 @@ 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); +} +  // EOF diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index f8ef15991d..300cef7deb 100755 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -37,6 +37,7 @@  #include "llviewerwearable.h"  #include "lltooldraganddrop.h"  #include "lllandmarklist.h" +#include "llfolderviewitem.h"  class LLInventoryFilter;  class LLInventoryPanel; @@ -689,4 +690,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 diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 1abc09bf3b..2546db546b 100755 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -45,6 +45,7 @@  // newview includes  #include "llappearancemgr.h"  #include "llappviewer.h" +#include "llavataractions.h"  #include "llclipboard.h"  #include "lldonotdisturbnotificationstorage.h"  #include "llfloaterinventory.h" @@ -1114,16 +1115,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) diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp index b7c4ec6f8b..013a5a7629 100755 --- a/indra/newview/llinventoryicon.cpp +++ b/indra/newview/llinventoryicon.cpp @@ -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);  } diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 3546317471..4a230accb6 100755 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -146,7 +146,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; @@ -186,6 +187,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; diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index a490dfce5d..bc4c10e441 100755 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -43,6 +43,7 @@ class LLInvFVBridge;  class LLInventoryFolderViewModelBuilder;  class LLInvPanelComplObserver;  class LLFolderViewModelInventory; +class LLFolderViewGroupedItemBridge;  namespace LLInitParam  { @@ -240,6 +241,7 @@ protected:  	LLScrollContainer*			mScroller;  	LLFolderViewModelInventory	mInventoryViewModel; +    LLPointer<LLFolderViewGroupedItemBridge> mGroupedItemBridge;  	Params						mParams;	// stored copy of parameter block  	std::map<LLUUID, LLFolderViewItem*> mItemMap; diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 8fb7550169..1380345164 100755 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -545,12 +545,14 @@ 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); -						gAgentAvatarp->wearableUpdated(type); - -						/* 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); +							gAgentAvatarp->wearableUpdated(type); +							/* telling the manager to rebake once update cycle is fully done */ +							LLLocalBitmapMgr::setNeedsRebake(); +						}  					}  				} diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 19a86cdcea..9bd6007772 100755 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -925,17 +925,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; @@ -978,10 +978,17 @@ void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl)                          }                          if (getWearable())                          { -                                U32 index = gAgentWearables.getWearableIndex(getWearable()); -                                gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index); -                                LLVisualParamHint::requestHintUpdates(); -                                gAgentAvatarp->wearableUpdated(type); +							U32 index; +							if (gAgentWearables.getWearableIndex(getWearable(), index)) +							{ +								gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index); +								LLVisualParamHint::requestHintUpdates(); +								gAgentAvatarp->wearableUpdated(type); +							} +							else +							{ +								LL_WARNS() << "wearable not found in gAgentWearables" << LL_ENDL; +							}                          }                  }                  else @@ -1058,7 +1065,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(); @@ -1574,6 +1586,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)          { @@ -1581,9 +1599,8 @@ 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); -                gAgentAvatarp->wearableUpdated(getWearable()->getType()); +				gAgentAvatarp->setLocalTexture(te, image, FALSE, index); +				gAgentAvatarp->wearableUpdated(getWearable()->getType());          }          else          { @@ -1598,7 +1615,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);                  gAgentAvatarp->wearableUpdated(getWearable()->getType());          } diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 64f24cd291..ea7cf82674 100755 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -212,7 +212,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(); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d6c8ba10f6..d112118082 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -2106,7 +2106,7 @@ LLWearableType::EType LLViewerInventoryItem::getWearableType() const  	{  		return LLWearableType::WT_INVALID;  	} -	return LLWearableType::EType(getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK); +	return LLWearableType::inventoryFlagsToWearableType(getFlags());  } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 1e9945b514..56997c928a 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1570,8 +1570,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 diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index fac0fd63ee..888ead0613 100755 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -894,13 +894,13 @@ 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);  	//visible only when one item selected and this item is worn  	setMenuItemVisible(menu, "edit",				!standalone && mask & (MASK_CLOTHING|MASK_BODYPART) && n_worn == n_items && n_worn == 1);  	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); @@ -1004,65 +1004,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 diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index c731a7d6cf..e6788ab249 100755 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -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;  	}; diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 32c4350b40..fa80730407 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -387,9 +387,13 @@ class Windows_i686_Manifest(ViewerManifest):              if self.args['configuration'].lower() == 'debug':                   self.path("msvcr120d.dll")                   self.path("msvcp120d.dll") +                 self.path("msvcr100d.dll") +                 self.path("msvcp100d.dll")              else:                   self.path("msvcr120.dll")                   self.path("msvcp120.dll") +                 self.path("msvcr100.dll") +                 self.path("msvcp100.dll")              # Vivox runtimes              self.path("SLVoice.exe") | 
