diff options
Diffstat (limited to 'indra')
25 files changed, 573 insertions, 148 deletions
| diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h index 87fe7001e0..ddda9fb6af 100644 --- a/indra/llcommon/llversionserver.h +++ b/indra/llcommon/llversionserver.h @@ -36,7 +36,7 @@  const S32 LL_VERSION_MAJOR = 2;  const S32 LL_VERSION_MINOR = 1;  const S32 LL_VERSION_PATCH = 0; -const S32 LL_VERSION_BUILD = 0; +const S32 LL_VERSION_BUILD = 13828;  const char * const LL_CHANNEL = "Second Life Server"; diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index fc531f93d4..5c7cacedec 100644 --- a/indra/newview/English.lproj/InfoPlist.strings +++ b/indra/newview/English.lproj/InfoPlist.strings @@ -2,6 +2,6 @@  CFBundleName = "Second Life"; -CFBundleShortVersionString = "Second Life version 2.1.0.0"; -CFBundleGetInfoString = "Second Life version 2.1.0.0, Copyright 2004-2009 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version 2.1.0.13828"; +CFBundleGetInfoString = "Second Life version 2.1.0.13828, Copyright 2004-2009 Linden Research, Inc."; diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index 9bc95f9b95..f7b11b217c 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -60,7 +60,7 @@  		</dict>  	</array>  	<key>CFBundleVersion</key> -	<string>2.1.0.0</string> +	<string>2.1.0.13828</string>  	<key>CSResourcesFileMapped</key>  	<true/>  </dict> diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 4dc78e9a1d..e97e152a38 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -1149,10 +1149,9 @@ void LLAgentCamera::updateCamera()  	static LLFastTimer::DeclareTimer ftm("Camera");  	LLFastTimer t(ftm); -	//Ventrella - changed camera_skyward to the new global "mCameraUpVector" +	// - changed camera_skyward to the new global "mCameraUpVector"  	mCameraUpVector = LLVector3::z_axis;  	//LLVector3	camera_skyward(0.f, 0.f, 1.f); -	//end Ventrella  	U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode; @@ -1162,10 +1161,8 @@ void LLAgentCamera::updateCamera()  		gAgentAvatarp->isSitting() &&  		camera_mode == CAMERA_MODE_MOUSELOOK)  	{ -		//Ventrella  		//changed camera_skyward to the new global "mCameraUpVector"  		mCameraUpVector = mCameraUpVector * gAgentAvatarp->getRenderRotation(); -		//end Ventrella  	}  	if (cameraThirdPerson() && mFocusOnAvatar && LLFollowCamMgr::getActiveFollowCamParams()) @@ -1173,13 +1170,11 @@ void LLAgentCamera::updateCamera()  		changeCameraToFollow();  	} -	//Ventrella  	//NOTE - this needs to be integrated into a general upVector system here within llAgent.   	if ( camera_mode == CAMERA_MODE_FOLLOW && mFocusOnAvatar )  	{  		mCameraUpVector = mFollowCam.getUpVector();  	} -	//end Ventrella  	if (mSitCameraEnabled)  	{ @@ -1256,7 +1251,6 @@ void LLAgentCamera::updateCamera()  	// lerp camera focus offset  	mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLCriticalDamp::getInterpolant(CAMERA_FOCUS_HALF_LIFE)); -	//Ventrella  	if ( mCameraMode == CAMERA_MODE_FOLLOW )  	{  		if (isAgentAvatarValid()) @@ -1283,7 +1277,6 @@ void LLAgentCamera::updateCamera()  			}  		}  	} -	// end Ventrella  	BOOL hit_limit;  	LLVector3d camera_pos_global; @@ -1414,10 +1407,8 @@ void LLAgentCamera::updateCamera()  	// Move the camera -	//Ventrella  	LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, mCameraUpVector, focus_agent);  	//LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, camera_skyward, focus_agent); -	//end Ventrella  	// Change FOV  	LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor)); @@ -1532,12 +1523,11 @@ LLVector3d LLAgentCamera::calcFocusPositionTargetGlobal()  		clearFocusObject();  	} -	// Ventrella  	if (mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar)  	{  		mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedFocus());  		return mFocusTargetGlobal; -	}// End Ventrella  +	}  	else if (mCameraMode == CAMERA_MODE_MOUSELOOK)  	{  		LLVector3d at_axis(1.0, 0.0, 0.0); @@ -1706,11 +1696,10 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit)  	LLVector3d camera_position_global; -	// Ventrella   	if (mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar)  	{  		camera_position_global = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedPosition()); -	}// End Ventrella +	}  	else if (mCameraMode == CAMERA_MODE_MOUSELOOK)  	{  		if (!isAgentAvatarValid() || gAgentAvatarp->mDrawable.isNull()) @@ -2130,7 +2119,6 @@ void LLAgentCamera::changeCameraToDefault()  } -// Ventrella  //-----------------------------------------------------------------------------  // changeCameraToFollow()  //----------------------------------------------------------------------------- diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 337878cf96..5db16d9250 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1756,7 +1756,7 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj  			LLViewerObject *objectp = (*attachment_iter);  			if (objectp)  			{ -				LLUUID object_item_id = objectp->getItemID(); +				LLUUID object_item_id = objectp->getAttachmentItemID();  				if (requested_item_ids.find(object_item_id) != requested_item_ids.end())  				{  					// Object currently worn, was requested. diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index d911d123f4..f6bb1b9bc9 100644 --- a/indra/newview/llagentwearablesfetch.cpp +++ b/indra/newview/llagentwearablesfetch.cpp @@ -215,7 +215,7 @@ void LLInitialWearablesFetch::processWearablesMessage()  				{  					LLViewerObject* attached_object = (*attachment_iter);  					if (!attached_object) continue; -					const LLUUID& item_id = attached_object->getItemID(); +					const LLUUID& item_id = attached_object->getAttachmentItemID();  					if (item_id.isNull()) continue;  					ids.push_back(item_id);  				} diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 6fdd71bfbf..b844803cb6 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1012,7 +1012,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up  		addCOFItemLink(item_to_wear, do_update, cb);  		break;  	case LLAssetType::AT_OBJECT: -		rez_attachment(item_to_wear, NULL); +		rez_attachment(item_to_wear, NULL, replace);  		break;  	default: return false;;  	} @@ -1828,9 +1828,9 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool  	llinfos << "wearInventoryCategory( " << category->getName()  			 << " )" << llendl; -	callAfterCategoryFetch(category->getUUID(), boost::bind(&LLAppearanceMgr::wearCategoryFinal, -															&LLAppearanceMgr::instance(), -															category->getUUID(), copy, append)); +	callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal, +														   &LLAppearanceMgr::instance(), +														   category->getUUID(), copy, append));  }  void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append) diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp index 307c937f6e..43f158658a 100644 --- a/indra/newview/llfloatergroups.cpp +++ b/indra/newview/llfloatergroups.cpp @@ -95,7 +95,7 @@ BOOL LLFloaterGroupPicker::postBuild()  	setDefaultBtn("OK"); -	childEnable("OK"); +	getChildView("OK")->setEnabled(TRUE);  	return TRUE;  } @@ -176,8 +176,8 @@ void LLPanelGroups::reset()  	{  		group_list->operateOnAll(LLCtrlListInterface::OP_DELETE);  	} -	childSetTextArg("groupcount", "[COUNT]", llformat("%d",gAgent.mGroups.count())); -	childSetTextArg("groupcount", "[MAX]", llformat("%d",MAX_AGENT_GROUPS)); +	getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.count())); +	getChild<LLUICtrl>("groupcount")->setTextArg("[MAX]", llformat("%d",MAX_AGENT_GROUPS));  	init_group_list(getChild<LLScrollListCtrl>("group list"), gAgent.getGroupID());  	enableButtons(); @@ -187,8 +187,8 @@ BOOL LLPanelGroups::postBuild()  {  	childSetCommitCallback("group list", onGroupList, this); -	childSetTextArg("groupcount", "[COUNT]", llformat("%d",gAgent.mGroups.count())); -	childSetTextArg("groupcount", "[MAX]", llformat("%d",MAX_AGENT_GROUPS)); +	getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.count())); +	getChild<LLUICtrl>("groupcount")->setTextArg("[MAX]", llformat("%d",MAX_AGENT_GROUPS));  	LLScrollListCtrl *list = getChild<LLScrollListCtrl>("group list");  	if (list) @@ -228,25 +228,25 @@ void LLPanelGroups::enableButtons()  	if(group_id != gAgent.getGroupID())  	{ -		childEnable("Activate"); +		getChildView("Activate")->setEnabled(TRUE);  	}  	else  	{ -		childDisable("Activate"); +		getChildView("Activate")->setEnabled(FALSE);  	}  	if (group_id.notNull())  	{ -		childEnable("Info"); -		childEnable("IM"); -		childEnable("Leave"); +		getChildView("Info")->setEnabled(TRUE); +		getChildView("IM")->setEnabled(TRUE); +		getChildView("Leave")->setEnabled(TRUE);  	}  	else  	{ -		childDisable("Info"); -		childDisable("IM"); -		childDisable("Leave"); +		getChildView("Info")->setEnabled(FALSE); +		getChildView("IM")->setEnabled(FALSE); +		getChildView("Leave")->setEnabled(FALSE);  	} -	childSetEnabled("Create", gAgent.canJoinGroups()); +	getChildView("Create")->setEnabled(gAgent.canJoinGroups());  } diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 81f00af948..d37886806b 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -62,6 +62,7 @@  #include "llviewerwindow.h"  #include "llvoavatar.h"  #include "llfloaterproperties.h" +#include "llnotificationsutil.h"  // Linden library includes  #include "lldbstrings.h" @@ -183,7 +184,6 @@ LLFolderView::LLFolderView(const Params& p)  	mSourceID(p.task_id),  	mRenameItem( NULL ),  	mNeedsScroll( FALSE ), -	mEnableScroll( true ),  	mUseLabelSuffix(p.use_label_suffix),  	mPinningSelectedItem(FALSE),  	mNeedsAutoSelect( FALSE ), @@ -249,7 +249,7 @@ LLFolderView::LLFolderView(const Params& p)  	text_p.name(std::string(p.name));  	text_p.font(font);  	text_p.visible(false); -	text_p.allow_html(true); +	text_p.parse_urls(true);  	text_p.wrap(true); // allow multiline text. See EXT-7564, EXT-7047  	// set text padding the same as in People panel. EXT-7047, EXT-4837  	text_p.h_pad(STATUS_TEXT_HPAD); @@ -1014,6 +1014,17 @@ void LLFolderView::closeRenamer( void )  void LLFolderView::removeSelectedItems( void )  { +	if (mSelectedItems.empty()) return; +	LLSD args; +	args["QUESTION"] = LLTrans::getString(mSelectedItems.size() > 1 ? "DeleteItems" :  "DeleteItem"); +	LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLFolderView::onItemsRemovalConfirmation, this, _1, _2)); +} + +void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response) +{ +	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +	if (option != 0) return; // canceled +  	if(getVisible() && getEnabled())  	{  		// just in case we're removing the renaming item. @@ -1965,7 +1976,9 @@ void LLFolderView::deleteAllChildren()  void LLFolderView::scrollToShowSelection()  { -	if (mEnableScroll && mSelectedItems.size()) +	// If items are filtered while background fetch is in progress +	// scrollbar resets to the first filtered item. See EXT-3981. +	if (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() && mSelectedItems.size())  	{  		mNeedsScroll = TRUE;  	} diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 31352d04bf..21004fdb16 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -274,7 +274,6 @@ public:  	void dumpSelectionInformation();  	virtual S32	notify(const LLSD& info) ; -	void setEnableScroll(bool enable_scroll) { mEnableScroll = enable_scroll; }  	bool useLabelSuffix() { return mUseLabelSuffix; }  private: @@ -294,6 +293,8 @@ protected:  	BOOL addNoOptions(LLMenuGL* menu) const; +	void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response); +  protected:  	LLHandle<LLView>					mPopupMenuHandle; @@ -309,7 +310,6 @@ protected:  	LLLineEditor*					mRenamer;  	BOOL							mNeedsScroll; -	bool							mEnableScroll;  	BOOL							mPinningSelectedItem;  	LLRect							mScrollConstraintRect;  	BOOL							mNeedsAutoSelect; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 9bbc6514b4..53622f7188 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3936,7 +3936,7 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)  		item = (LLViewerInventoryItem*)gInventory.getItem(object_id);  		if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID()))  		{ -			rez_attachment(item, NULL); +			rez_attachment(item, NULL, true); // Replace if "Wear"ing.  		}  		else if(item && item->isFinished())  		{ @@ -3952,6 +3952,10 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)  		}  		gFocusMgr.setKeyboardFocus(NULL);  	} +	else if ("wear_add" == action) +	{ +		LLAppearanceMgr::instance().wearItemOnAvatar(mUUID, true, false); // Don't replace if adding. +	}  	else if (isRemoveAction(action))  	{  		LLInventoryItem* item = gInventory.getItem(mUUID); @@ -4003,7 +4007,7 @@ std::string LLObjectBridge::getLabelSuffix() const  	}  } -void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment) +void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment, bool replace)  {  	LLSD payload;  	payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link. @@ -4022,9 +4026,14 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach  		}  	} +	if (!replace) +	{ +		attach_pt |= ATTACHMENT_ADD; +	} +  	payload["attachment_point"] = attach_pt; -	if (!gSavedSettings.getBOOL("MultipleAttachments") && +	if (replace &&  		(attachment && attachment->getNumObjects() > 0))  	{  		LLNotificationsUtil::add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez); @@ -4053,8 +4062,6 @@ bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& respon  		if (itemp)  		{  			U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); -			if (gSavedSettings.getBOOL("MultipleAttachments")) -				attachment_pt |= ATTACHMENT_ADD;  			LLMessageSystem* msg = gMessageSystem;  			msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv); @@ -4111,6 +4118,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  			{  				items.push_back(std::string("Wearable And Object Separator"));  				items.push_back(std::string("Wearable And Object Wear")); +				items.push_back(std::string("Wearable Add"));  				items.push_back(std::string("Attach To"));  				items.push_back(std::string("Attach To HUD"));  				// commented out for DEV-32347 @@ -4119,6 +4127,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  				if (!gAgentAvatarp->canAttachMoreObjects())  				{  					disabled_items.push_back(std::string("Wearable And Object Wear")); +					disabled_items.push_back(std::string("Wearable Add"));  					disabled_items.push_back(std::string("Attach To"));  					disabled_items.push_back(std::string("Attach To HUD"));  				} diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 2b6c80bac8..f2207e5c00 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -403,6 +403,12 @@ void LLOutfitsList::onOpen(const LLSD& /*info*/)  		mIsInitialized = true;  	} + +	LLAccordionCtrlTab* selected_tab = mAccordion->getSelectedTab(); +	if (!selected_tab) return; + +	// Pass focus to the selected outfit tab. +	selected_tab->showAndFocusHeader();  }  void LLOutfitsList::refreshList(const LLUUID& category_id) diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index d76a5c586f..cfd31b6829 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -42,6 +42,7 @@  #include "lloutfitobserver.h"  #include "llcofwearables.h"  #include "llfilteredwearablelist.h" +#include "llfolderviewitem.h"  #include "llinventory.h"  #include "llinventoryitemslist.h"  #include "llviewercontrol.h" @@ -85,6 +86,11 @@ const U64 ALL_ITEMS_MASK = WEARABLE_MASK | ATTACHMENT_MASK;  static const std::string REVERT_BTN("revert_btn"); + +/////////////////////////////////////////////////////////////////////////////// +// LLShopURLDispatcher +/////////////////////////////////////////////////////////////////////////////// +  class LLShopURLDispatcher  {  public: @@ -144,6 +150,10 @@ std::string LLShopURLDispatcher::resolveURL(LLAssetType::EType asset_type, ESex  	return gSavedSettings.getString(setting_name);  } +/////////////////////////////////////////////////////////////////////////////// +// LLPanelOutfitEditGearMenu +/////////////////////////////////////////////////////////////////////////////// +  class LLPanelOutfitEditGearMenu  {  public: @@ -159,7 +169,6 @@ public:  		if (menu)  		{  			populateCreateWearableSubmenus(menu); -			menu->buildDrawLabels();  		}  		return menu; @@ -208,6 +217,147 @@ private:  	}  }; +/////////////////////////////////////////////////////////////////////////////// +// LLAddWearablesGearMenu +/////////////////////////////////////////////////////////////////////////////// + +class LLAddWearablesGearMenu : public LLInitClass<LLAddWearablesGearMenu> +{ +public: +	static LLMenuGL* create(LLWearableItemsList* flat_list, LLInventoryPanel* inventory_panel) +	{ +		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +		LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + +		llassert(flat_list); +		llassert(inventory_panel); + +		LLHandle<LLView> flat_list_handle = flat_list->getHandle(); +		LLHandle<LLPanel> inventory_panel_handle = inventory_panel->getHandle(); + +		registrar.add("AddWearable.Gear.Sort", boost::bind(onSort, flat_list_handle, inventory_panel_handle, _2)); +		enable_registrar.add("AddWearable.Gear.Check", boost::bind(onCheck, flat_list_handle, inventory_panel_handle, _2)); +		enable_registrar.add("AddWearable.Gear.Visible", boost::bind(onVisible, inventory_panel_handle, _2)); + +		LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>( +			"menu_add_wearable_gear.xml", +			LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); + +		return menu; +	} + +private: +	static void onSort(LLHandle<LLView> flat_list_handle, +					   LLHandle<LLPanel> inventory_panel_handle, +					   LLSD::String sort_order_str) +	{ +		if (flat_list_handle.isDead() || inventory_panel_handle.isDead()) return; + +		LLWearableItemsList* flat_list = dynamic_cast<LLWearableItemsList*>(flat_list_handle.get()); +		LLInventoryPanel* inventory_panel = dynamic_cast<LLInventoryPanel*>(inventory_panel_handle.get()); + +		if (!flat_list || !inventory_panel) return; + +		LLWearableItemsList::ESortOrder	sort_order; + +		if ("by_most_recent" == sort_order_str) +		{ +			sort_order = LLWearableItemsList::E_SORT_BY_MOST_RECENT; +		} +		else if ("by_name" == sort_order_str) +		{ +			sort_order = LLWearableItemsList::E_SORT_BY_NAME; +		} +		else if ("by_type" == sort_order_str) +		{ +			sort_order = LLWearableItemsList::E_SORT_BY_TYPE_NAME; +		} +		else +		{ +			llwarns << "Unrecognized sort order action" << llendl; +			return; +		} + +		if (inventory_panel->getVisible()) +		{ +			inventory_panel->setSortOrder(sort_order); +		} +		else +		{ +			flat_list->setSortOrder(sort_order); +		} +	} + +	static bool onCheck(LLHandle<LLView> flat_list_handle, +						LLHandle<LLPanel> inventory_panel_handle, +						LLSD::String sort_order_str) +	{ +		if (flat_list_handle.isDead() || inventory_panel_handle.isDead()) return false; + +		LLWearableItemsList* flat_list = dynamic_cast<LLWearableItemsList*>(flat_list_handle.get()); +		LLInventoryPanel* inventory_panel = dynamic_cast<LLInventoryPanel*>(inventory_panel_handle.get()); + +		if (!inventory_panel || !flat_list) return false; + +		// Inventory panel uses its own sort order independent from +		// flat list view so this flag is used to distinguish between +		// currently visible "tree" or "flat" representation of inventory. +		bool inventory_tree_visible = inventory_panel->getVisible(); + +		if (inventory_tree_visible) +		{ +			U32 sort_order = inventory_panel->getSortOrder(); + +			if ("by_most_recent" == sort_order_str) +			{ +				return LLWearableItemsList::E_SORT_BY_MOST_RECENT & sort_order; +			} +			else if ("by_name" == sort_order_str) +			{ +				// If inventory panel is not sorted by date then it is sorted by name. +				return LLWearableItemsList::E_SORT_BY_MOST_RECENT & ~sort_order; +			} +			llwarns << "Unrecognized inventory panel sort order" << llendl; +		} +		else +		{ +			LLWearableItemsList::ESortOrder	sort_order = flat_list->getSortOrder(); + +			if ("by_most_recent" == sort_order_str) +			{ +				return LLWearableItemsList::E_SORT_BY_MOST_RECENT == sort_order; +			} +			else if ("by_name" == sort_order_str) +			{ +				return LLWearableItemsList::E_SORT_BY_NAME == sort_order; +			} +			else if ("by_type" == sort_order_str) +			{ +				return LLWearableItemsList::E_SORT_BY_TYPE_NAME == sort_order; +			} +			llwarns << "Unrecognized wearable list sort order" << llendl; +		} +		return false; +	} + +	static bool onVisible(LLHandle<LLPanel> inventory_panel_handle, +						  LLSD::String sort_order_str) +	{ +		if (inventory_panel_handle.isDead()) return false; + +		LLInventoryPanel* inventory_panel = dynamic_cast<LLInventoryPanel*>(inventory_panel_handle.get()); + +		// Enable sorting by type only for the flat list of items +		// because inventory panel doesn't support this kind of sorting. +		return ( "by_type" == sort_order_str ) +				&&	( !inventory_panel || !inventory_panel->getVisible() ); +	} +}; + +/////////////////////////////////////////////////////////////////////////////// +// LLCOFDragAndDropObserver +/////////////////////////////////////////////////////////////////////////////// +  class LLCOFDragAndDropObserver : public LLInventoryAddItemByAssetObserver  {  public: @@ -243,12 +393,17 @@ void LLCOFDragAndDropObserver::done()  	LLAppearanceMgr::instance().updateAppearanceFromCOF();  } +/////////////////////////////////////////////////////////////////////////////// +// LLPanelOutfitEdit +/////////////////////////////////////////////////////////////////////////////// +  LLPanelOutfitEdit::LLPanelOutfitEdit()  :	LLPanel(),   	mSearchFilter(NULL),  	mCOFWearables(NULL),  	mInventoryItemsPanel(NULL),  	mGearMenu(NULL), +	mAddWearablesGearMenu(NULL),  	mCOFDragAndDropObserver(NULL),  	mInitialized(false),  	mAddWearablesPanel(NULL), @@ -301,7 +456,7 @@ BOOL LLPanelOutfitEdit::postBuild()  	mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.All"), new LLFindNonLinksByMask(ALL_ITEMS_MASK)));  	mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Clothing"), new LLIsTypeActual(LLAssetType::AT_CLOTHING)));  	mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Bodyparts"), new LLIsTypeActual(LLAssetType::AT_BODYPART))); -	mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Objects"), new LLFindByMask(ATTACHMENT_MASK)));; +	mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Objects"), new LLFindNonLinksByMask(ATTACHMENT_MASK)));;  	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("shape"), new LLFindActualWearablesOfType(LLWearableType::WT_SHAPE)));  	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("skin"), new LLFindActualWearablesOfType(LLWearableType::WT_SKIN)));  	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("hair"), new LLFindActualWearablesOfType(LLWearableType::WT_HAIR))); @@ -326,7 +481,9 @@ BOOL LLPanelOutfitEdit::postBuild()  	childSetCommitCallback("filter_button", boost::bind(&LLPanelOutfitEdit::showWearablesFilter, this), NULL);  	childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesFolderView, this), NULL); +	childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::saveListSelection, this), NULL);  	childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesListView, this), NULL); +	childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::saveListSelection, this), NULL);  	childSetCommitCallback("wearables_gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);  	childSetCommitCallback("gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);  	childSetCommitCallback("shop_btn_1", boost::bind(&LLPanelOutfitEdit::onShopButtonClicked, this), NULL); @@ -396,10 +553,10 @@ BOOL LLPanelOutfitEdit::postBuild()  	 *  - each LLWearableType::EType by name (EXT-8205)  	*/  	mWearableListViewItemsComparator = new LLWearableItemTypeNameComparator(); -	mWearableListViewItemsComparator->setOrder(LLAssetType::AT_CLOTHING, LLWearableItemTypeNameComparator::ORDER_RANG_1, false, true); +	mWearableListViewItemsComparator->setOrder(LLAssetType::AT_CLOTHING, LLWearableItemTypeNameComparator::ORDER_RANK_1, false, true);  	mWearablesListViewPanel = getChild<LLPanel>("filtered_wearables_panel"); -	mWearableItemsList = getChild<LLInventoryItemsList>("list_view"); +	mWearableItemsList = getChild<LLWearableItemsList>("list_view");  	mWearableItemsList->setCommitOnSelectionChange(true);  	mWearableItemsList->setCommitCallback(boost::bind(&LLPanelOutfitEdit::updatePlusButton, this));  	mWearableItemsList->setDoubleClickCallback(boost::bind(&LLPanelOutfitEdit::onPlusBtnClicked, this)); @@ -443,35 +600,46 @@ void LLPanelOutfitEdit::showAddWearablesPanel(bool show_add_wearables)  {  	mAddWearablesPanel->setVisible(show_add_wearables); -	childSetValue("show_add_wearables_btn", show_add_wearables); +	getChild<LLUICtrl>("show_add_wearables_btn")->setValue(show_add_wearables);  	updateFiltersVisibility(); -	childSetVisible("filter_button", show_add_wearables); +	getChildView("filter_button")->setVisible( show_add_wearables);  	//search filter should be disabled  	if (!show_add_wearables)  	{ -		childSetValue("filter_button", false); +		getChild<LLUICtrl>("filter_button")->setValue(false);  		mFolderViewFilterCmbBox->setVisible(false);  		mListViewFilterCmbBox->setVisible(false);  		showWearablesFilter(); +		/* +		 * By default AT_CLOTHING are sorted by (in in MY OUTFITS): +		 *  - by type (types order determined in LLWearableType::EType) +		 *  - each LLWearableType::EType by outer layer on top +		 * +		 * In Add More panel AT_CLOTHING should be sorted in a such way: +		 *  - by type (types order determined in LLWearableType::EType) +		 *  - each LLWearableType::EType by name (EXT-8205) +		*/ +		mWearableItemsList->setSortOrder(LLWearableItemsList::E_SORT_BY_TYPE_NAME); +  		// Reset mWearableItemsList position to top. See EXT-8180.  		mWearableItemsList->goToTop();  	}  	//switching button bars -	childSetVisible("no_add_wearables_button_bar", !show_add_wearables); -	childSetVisible("add_wearables_button_bar", show_add_wearables); +	getChildView("no_add_wearables_button_bar")->setVisible( !show_add_wearables); +	getChildView("add_wearables_button_bar")->setVisible( show_add_wearables);  }  void LLPanelOutfitEdit::showWearablesFilter()  { -	bool filter_visible = childGetValue("filter_button"); +	bool filter_visible = getChild<LLUICtrl>("filter_button")->getValue(); -	childSetVisible("filter_panel", filter_visible); +	getChildView("filter_panel")->setVisible( filter_visible);  	if(!filter_visible)  	{ @@ -488,9 +656,7 @@ void LLPanelOutfitEdit::showWearablesListView()  {  	if(switchPanels(mInventoryItemsPanel, mWearablesListViewPanel))  	{ -		mFolderViewBtn->setToggleState(FALSE); -		mFolderViewBtn->setImageOverlay(getString("folder_view_off"), mFolderViewBtn->getImageOverlayHAlign()); -		mListViewBtn->setImageOverlay(getString("list_view_on"), mListViewBtn->getImageOverlayHAlign()); +		updateWearablesPanelVerbButtons();  		updateFiltersVisibility();  	}  	mListViewBtn->setToggleState(TRUE); @@ -500,9 +666,7 @@ void LLPanelOutfitEdit::showWearablesFolderView()  {  	if(switchPanels(mWearablesListViewPanel, mInventoryItemsPanel))  	{ -		mListViewBtn->setToggleState(FALSE); -		mListViewBtn->setImageOverlay(getString("list_view_off"), mListViewBtn->getImageOverlayHAlign()); -		mFolderViewBtn->setImageOverlay(getString("folder_view_on"), mFolderViewBtn->getImageOverlayHAlign()); +		updateWearablesPanelVerbButtons();  		updateFiltersVisibility();  	}  	mFolderViewBtn->setToggleState(TRUE); @@ -643,8 +807,17 @@ void LLPanelOutfitEdit::onShopButtonClicked()  	if (isAgentAvatarValid())  	{  		// try to get wearable type from 'Add More' panel first (EXT-7639) -		LLWearableType::EType type = getAddMorePanelSelectionType(); +		selection_info_t selection_info = getAddMorePanelSelectionType(); +		LLWearableType::EType type = selection_info.first; + +		if (selection_info.second > 1) +		{ +			// the second argument is not important in this case: generic market place will be opened +			url = url_resolver.resolveURL(LLWearableType::WT_NONE, SEX_FEMALE); +		} +		else +		{  		if (type == LLWearableType::WT_NONE)  		{  			type = getCOFWearablesSelectionType(); @@ -660,7 +833,9 @@ void LLPanelOutfitEdit::onShopButtonClicked()  		if (url.empty())  		{ -			url = url_resolver.resolveURL(mCOFWearables->getExpandedAccordionAssetType(), sex); +				url = url_resolver.resolveURL( +						mCOFWearables->getExpandedAccordionAssetType(), sex); +			}  		}  	}  	else @@ -699,9 +874,9 @@ LLWearableType::EType LLPanelOutfitEdit::getCOFWearablesSelectionType() const  	return type;  } -LLWearableType::EType LLPanelOutfitEdit::getAddMorePanelSelectionType() const +LLPanelOutfitEdit::selection_info_t LLPanelOutfitEdit::getAddMorePanelSelectionType() const  { -	LLWearableType::EType type = LLWearableType::WT_NONE; +	selection_info_t result = std::make_pair(LLWearableType::WT_NONE, 0);  	if (mAddWearablesPanel != NULL && mAddWearablesPanel->getVisible())  	{ @@ -709,9 +884,11 @@ LLWearableType::EType LLPanelOutfitEdit::getAddMorePanelSelectionType() const  		{  			std::set<LLUUID> selected_uuids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); -			if (selected_uuids.size() == 1) +			result.second = selected_uuids.size(); + +			if (result.second == 1)  			{ -				type = getWearableTypeByItemUUID(*(selected_uuids.begin())); +				result.first = getWearableTypeByItemUUID(*(selected_uuids.begin()));  			}  		}  		else if (mWearableItemsList != NULL && mWearableItemsList->getVisible()) @@ -719,14 +896,16 @@ LLWearableType::EType LLPanelOutfitEdit::getAddMorePanelSelectionType() const  			std::vector<LLUUID> selected_uuids;  			mWearableItemsList->getSelectedUUIDs(selected_uuids); -			if (selected_uuids.size() == 1) +			result.second = selected_uuids.size(); + +			if (result.second == 1)  			{ -				type = getWearableTypeByItemUUID(selected_uuids.front()); +				result.first = getWearableTypeByItemUUID(selected_uuids.front());  			}  		}  	} -	return type; +	return result;  }  LLWearableType::EType LLPanelOutfitEdit::getWearableTypeByItemUUID(const LLUUID& item_uuid) const @@ -763,7 +942,7 @@ void LLPanelOutfitEdit::updatePlusButton()  	}  	// If any of the selected items are not wearable (due to already being worn OR being of the wrong type), disable the add button. -	uuid_vec_t::iterator unwearable_item = std::find_if(selected_items.begin(), selected_items.end(), !boost::bind(& get_can_item_be_worn, _1)); +	uuid_vec_t::iterator unwearable_item = std::find_if(selected_items.begin(), selected_items.end(), !boost::bind(&get_can_item_be_worn, _1));  	bool can_add = ( unwearable_item == selected_items.end() );  	mPlusBtn->setEnabled(can_add); @@ -1011,7 +1190,7 @@ void LLPanelOutfitEdit::updateVerbs()  	bool has_baseoutfit = LLAppearanceMgr::getInstance()->getBaseOutfitUUID().notNull();  	mSaveComboBtn->setSaveBtnEnabled(!outfit_locked && outfit_is_dirty); -	childSetEnabled(REVERT_BTN, outfit_is_dirty && has_baseoutfit); +	getChildView(REVERT_BTN)->setEnabled(outfit_is_dirty && has_baseoutfit);  	mSaveComboBtn->setMenuItemEnabled("save_outfit", !outfit_locked && outfit_is_dirty); @@ -1048,13 +1227,33 @@ void LLPanelOutfitEdit::resetAccordionState()  void LLPanelOutfitEdit::onGearButtonClick(LLUICtrl* clicked_button)  { -	if(!mGearMenu) +	LLMenuGL* menu = NULL; + +	if (mAddWearablesPanel->getVisible())  	{ -		mGearMenu = LLPanelOutfitEditGearMenu::create(); +		if (!mAddWearablesGearMenu) +		{ +			mAddWearablesGearMenu = LLAddWearablesGearMenu::create(mWearableItemsList, mInventoryItemsPanel); +		} + +		menu = mAddWearablesGearMenu; +	} +	else +	{ +		if (!mGearMenu) +		{ +			mGearMenu = LLPanelOutfitEditGearMenu::create(); +		} + +		menu = mGearMenu;  	} -	S32 menu_y = mGearMenu->getRect().getHeight() + clicked_button->getRect().getHeight(); -	LLMenuGL::showPopup(clicked_button, mGearMenu, 0, menu_y); +	if (!menu) return; + +	menu->arrangeAndClear(); // update menu height +	S32 menu_y = menu->getRect().getHeight() + clicked_button->getRect().getHeight(); +	menu->buildDrawLabels(); +	LLMenuGL::showPopup(clicked_button, menu, 0, menu_y);  }  void LLPanelOutfitEdit::onAddMoreButtonClicked() @@ -1146,5 +1345,62 @@ void LLPanelOutfitEdit::onCOFChanged()  	update();  } +void LLPanelOutfitEdit::updateWearablesPanelVerbButtons() +{ +	if(mWearablesListViewPanel->getVisible()) +	{ +		mFolderViewBtn->setToggleState(FALSE); +		mFolderViewBtn->setImageOverlay(getString("folder_view_off"), mFolderViewBtn->getImageOverlayHAlign()); +		mListViewBtn->setImageOverlay(getString("list_view_on"), mListViewBtn->getImageOverlayHAlign()); +	} +	else if(mInventoryItemsPanel->getVisible()) +	{ +		mListViewBtn->setToggleState(FALSE); +		mListViewBtn->setImageOverlay(getString("list_view_off"), mListViewBtn->getImageOverlayHAlign()); +		mFolderViewBtn->setImageOverlay(getString("folder_view_on"), mFolderViewBtn->getImageOverlayHAlign()); +	} +} + +void LLPanelOutfitEdit::saveListSelection() +{ +	if(mWearablesListViewPanel->getVisible()) +	{ +		std::set<LLUUID> selected_ids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); + +		if(!selected_ids.size()) return; + +		for (std::set<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) +		{ +			mWearableItemsList->selectItemByUUID(*item_id, true); +		} +		mWearableItemsList->scrollToShowFirstSelectedItem(); +	} +	else if(mInventoryItemsPanel->getVisible()) +	{ +		std::vector<LLUUID> selected_ids; +		mWearableItemsList->getSelectedUUIDs(selected_ids); + +		if(!selected_ids.size()) return; + +		mInventoryItemsPanel->clearSelection(); +		LLFolderView* root = mInventoryItemsPanel->getRootFolder(); + +		if(!root) return; + +		for(std::vector<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) +		{ +			LLFolderViewItem* item = root->getItemByID(*item_id); +			if (!item) continue; + +			LLFolderViewFolder* parent = item->getParentFolder(); +			if(parent) +			{ +				parent->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); +			} +			mInventoryItemsPanel->getRootFolder()->changeSelection(item, TRUE); +		} +		mInventoryItemsPanel->getRootFolder()->scrollToShowSelection(); +	} +}  // EOF diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index 784c2bcad1..8d0325a4d6 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -43,8 +43,8 @@  #include "llremoteparcelrequest.h"  #include "llinventory.h"  #include "llinventoryfunctions.h" -#include "llinventoryitemslist.h"  #include "llinventorymodel.h" +#include "llwearableitemslist.h"  class LLButton;  class LLCOFWearables; @@ -201,8 +201,17 @@ private:  	void getCurrentItemUUID(LLUUID& selected_id);  	void onCOFChanged(); +	/** +	 * Method preserves selection while switching between folder/list view modes +	*/ +	void saveListSelection(); + +	void updateWearablesPanelVerbButtons(); + +	typedef std::pair<LLWearableType::EType, size_t> selection_info_t; +  	LLWearableType::EType getCOFWearablesSelectionType() const; -	LLWearableType::EType getAddMorePanelSelectionType() const; +	selection_info_t getAddMorePanelSelectionType() const;  	LLWearableType::EType getWearableTypeByItemUUID(const LLUUID& item_uuid) const;  	LLTextBox*			mCurrentOutfitName; @@ -221,7 +230,7 @@ private:  	LLComboBox*			mListViewFilterCmbBox;  	LLFilteredWearableListManager* 	mWearableListManager; -	LLInventoryItemsList* 			mWearableItemsList; +	LLWearableItemsList* 			mWearableItemsList;  	LLPanel*						mWearablesListViewPanel;  	LLWearableItemTypeNameComparator* mWearableListViewItemsComparator; @@ -232,6 +241,7 @@ private:  	LLCOFWearables*		mCOFWearables;  	LLMenuGL*			mGearMenu; +	LLMenuGL*			mAddWearablesGearMenu;  	bool				mInitialized;  	std::auto_ptr<LLSaveOutfitComboBtn> mSaveComboBtn; diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index adfd457664..33a464fea6 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -473,7 +473,7 @@ void LLSidepanelAppearance::fetchInventory()  			{  				LLViewerObject* attached_object = (*attachment_iter);  				if (!attached_object) continue; -				const LLUUID& item_id = attached_object->getItemID(); +				const LLUUID& item_id = attached_object->getAttachmentItemID();  				if (item_id.isNull()) continue;  				ids.push_back(item_id);  			} diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp index 2b4b78d82d..da4960b69d 100644 --- a/indra/newview/llviewerjointattachment.cpp +++ b/indra/newview/llviewerjointattachment.cpp @@ -172,19 +172,7 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)  		// re-connect object to the joint correctly  	} -	// Find the inventory item ID of the attached object -	LLNameValue* item_id_nv = object->getNVPair("AttachItemID"); -	if( item_id_nv ) -	{ -		const char* s = item_id_nv->getString(); -		if( s ) -		{ -			LLUUID item_id; -			item_id.set(s); -			object->setItemID(item_id); -			lldebugs << "getNVPair( AttachItemID ) = " << item_id << llendl; -		} -	} +	object->extractAttachmentItemID();  	mAttachedObjects.push_back(object);  	setupDrawable(object); @@ -303,7 +291,7 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)  	{  		mUpdateXform = FALSE;  	} -	object->setItemID(LLUUID::null); +	object->setAttachmentItemID(LLUUID::null);  }  //----------------------------------------------------------------------------- @@ -429,7 +417,7 @@ const LLViewerObject *LLViewerJointAttachment::getAttachedObject(const LLUUID &o  		 ++iter)  	{  		const LLViewerObject* attached_object = (*iter); -		if (attached_object->getItemID() == object_id) +		if (attached_object->getAttachmentItemID() == object_id)  		{  			return attached_object;  		} @@ -444,7 +432,7 @@ LLViewerObject *LLViewerJointAttachment::getAttachedObject(const LLUUID &object_  		 ++iter)  	{  		LLViewerObject* attached_object = (*iter); -		if (attached_object->getItemID() == object_id) +		if (attached_object->getAttachmentItemID() == object_id)  		{  			return attached_object;  		} diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 40bf62acc9..2a72e255d0 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -6074,7 +6074,7 @@ static bool onEnableAttachmentLabel(LLUICtrl* ctrl, const LLSD& data)  				const LLViewerObject* attached_object = (*attachment_iter);  				if (attached_object)  				{ -					LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getItemID()); +					LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID());  					if (itemp)  					{  						label += std::string(" (") + itemp->getName() + std::string(")"); @@ -6193,14 +6193,14 @@ class LLAttachmentEnableDrop : public view_listener_t  				{  					// make sure item is in your inventory (it could be a delayed attach message being sent from the sim)  					// so check to see if the item is in the inventory already -					item = gInventory.getItem((*attachment_iter)->getItemID()); +					item = gInventory.getItem((*attachment_iter)->getAttachmentItemID());  					if (!item)  					{  						// Item does not exist, make an observer to enable the pie menu   						// when the item finishes fetching worst case scenario   						// if a fetch is already out there (being sent from a slow sim)  						// we refetch and there are 2 fetches -						LLWornItemFetchedObserver* worn_item_fetched = new LLWornItemFetchedObserver((*attachment_iter)->getItemID());		 +						LLWornItemFetchedObserver* worn_item_fetched = new LLWornItemFetchedObserver((*attachment_iter)->getAttachmentItemID());		  						worn_item_fetched->startFetch();  						gInventory.addObserver(worn_item_fetched);  					} @@ -6547,7 +6547,7 @@ void handle_dump_attachments(void*)  							!attached_object->mDrawable->isRenderType(0));  			LLVector3 pos;  			if (visible) pos = attached_object->mDrawable->getPosition(); -			llinfos << "ATTACHMENT " << key << ": item_id=" << attached_object->getItemID() +			llinfos << "ATTACHMENT " << key << ": item_id=" << attached_object->getAttachmentItemID()  					<< (attached_object ? " present " : " absent ")  					<< (visible ? "visible " : "invisible ")  					<<  " at " << pos diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 15bdf126c5..d3e6f01bc8 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5233,3 +5233,28 @@ void LLViewerObject::resetChildrenPosition(const LLVector3& offset, BOOL simplif  	return ;  } +const LLUUID &LLViewerObject::getAttachmentItemID() const +{ +	return mAttachmentItemID; +} + +void LLViewerObject::setAttachmentItemID(const LLUUID &id) +{ +	mAttachmentItemID = id; +} + +const LLUUID &LLViewerObject::extractAttachmentItemID() +{ +	LLUUID item_id = LLUUID::null; +	LLNameValue* item_id_nv = getNVPair("AttachItemID"); +	if( item_id_nv ) +	{ +		const char* s = item_id_nv->getString(); +		if( s ) +		{ +			item_id.set(s); +		} +	} +	setAttachmentItemID(item_id); +	return getAttachmentItemID(); +} diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index be83fb7ef8..33fda9fa2d 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -678,11 +678,15 @@ protected:  private:	  	static S32 sNumObjects; +	//-------------------------------------------------------------------- +	// For objects that are attachments +	//--------------------------------------------------------------------  public: -	const LLUUID &getItemID() const { return mAttachmentItemID; } -	void setItemID(const LLUUID &id) { mAttachmentItemID = id; } +	const LLUUID &getAttachmentItemID() const; +	void setAttachmentItemID(const LLUUID &id); +	const LLUUID &extractAttachmentItemID(); // find&set the inventory item ID of the attached object  private: -	LLUUID mAttachmentItemID; // ItemID when item is in user inventory. +	LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory.  };  /////////////////// diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 9b3243a1bc..8491b19f89 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2136,7 +2136,7 @@ void LLViewerFetchedTexture::deleteCallbackEntry(const LLLoadedCallbackEntry::so  void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list)  {  	if(!callback_list) -	{ +{  		mPauseLoadedCallBacks = FALSE ;  		return ;  	} @@ -2165,7 +2165,7 @@ void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry:  void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list)  {  	if(!callback_list) -	{ +{  		return ;  	} diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 6392aad248..455900eb3a 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2753,7 +2753,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)  {  	// update chat bubble  	//-------------------------------------------------------------------- -	// draw text label over characters head +	// draw text label over character's head  	//--------------------------------------------------------------------  	if (mChatTimer.getElapsedTimeF32() > BUBBLE_CHAT_TIME)  	{ @@ -5553,6 +5553,7 @@ BOOL LLVOAvatar::setParent(LLViewerObject* parent)  void LLVOAvatar::addChild(LLViewerObject *childp)  { +	childp->extractAttachmentItemID(); // find the inventory item this object is associated with.  	LLViewerObject::addChild(childp);  	if (childp->mDrawable)  	{ diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index bddde08ca9..95402c2e06 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1067,7 +1067,7 @@ const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *view  	// Should just be the last object added  	if (attachment->isObjectAttached(viewer_object))  	{ -		const LLUUID& attachment_id = viewer_object->getItemID(); +		const LLUUID& attachment_id = viewer_object->getAttachmentItemID();  		LLAppearanceMgr::instance().registerAttachment(attachment_id);  	} @@ -1077,7 +1077,7 @@ const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *view  //virtual  BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object)  { -	const LLUUID attachment_id = viewer_object->getItemID(); +	const LLUUID attachment_id = viewer_object->getAttachmentItemID();  	if (LLVOAvatar::detachObject(viewer_object))  	{  		// the simulator should automatically handle permission revocation diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 5e23965f62..4d916db714 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -478,9 +478,9 @@ LLWearableItemTypeNameComparator::LLWearableItemTypeNameComparator()  	// 1. CLOTHING - sorted by name  	// 2. OBJECT   - sorted by type  	// 3. BODYPART - sorted by name -	mWearableOrder[LLAssetType::AT_CLOTHING] = LLWearableTypeOrder(ORDER_RANG_1, false, false); -	mWearableOrder[LLAssetType::AT_OBJECT]   = LLWearableTypeOrder(ORDER_RANG_2, true, true); -	mWearableOrder[LLAssetType::AT_BODYPART] = LLWearableTypeOrder(ORDER_RANG_3, false, true); +	mWearableOrder[LLAssetType::AT_CLOTHING] = LLWearableTypeOrder(ORDER_RANK_1, false, false); +	mWearableOrder[LLAssetType::AT_OBJECT]   = LLWearableTypeOrder(ORDER_RANK_2, true, true); +	mWearableOrder[LLAssetType::AT_BODYPART] = LLWearableTypeOrder(ORDER_RANK_3, false, true);  }  void LLWearableItemTypeNameComparator::setOrder(LLAssetType::EType items_of_type,  LLWearableItemTypeNameComparator::ETypeListOrder order_priority, bool sort_asset_items_by_name, bool sort_wearable_items_by_name) @@ -555,7 +555,7 @@ LLWearableItemTypeNameComparator::ETypeListOrder LLWearableItemTypeNameComparato  	if(const_it == mWearableOrder.end())  	{  		llwarns<<"Absent information about order rang of items of "<<LLAssetType::getDesc(item_type)<<" type"<<llendl; -		return ORDER_RANG_UNKNOWN; +		return ORDER_RANK_UNKNOWN;  	}  	return const_it->second.mOrderPriority; @@ -574,7 +574,7 @@ bool LLWearableItemTypeNameComparator::sortAssetTypeByName(LLAssetType::EType it  	return const_it->second.mSortAssetTypeByName; -} +	}  bool LLWearableItemTypeNameComparator::sortWearableTypeByName(LLAssetType::EType item_type) const @@ -586,16 +586,33 @@ bool LLWearableItemTypeNameComparator::sortWearableTypeByName(LLAssetType::EType  	{  		llwarns<<"Absent information about sorting items of "<<LLAssetType::getDesc(item_type)<<" type"<<llendl;  		return true; -	} +}  	return const_it->second.mSortWearableTypeByName;  } + +/*virtual*/ +bool LLWearableItemCreationDateComparator::doCompare(const LLPanelInventoryListItemBase* item1, const LLPanelInventoryListItemBase* item2) const +{ +	time_t date1 = item1->getCreationDate(); +	time_t date2 = item2->getCreationDate(); + +	if (date1 == date2) +	{ +		return LLWearableItemNameComparator::doCompare(item1, item2); +	} + +	return date1 > date2; +}  //////////////////////////////////////////////////////////////////////////  //////////////////////////////////////////////////////////////////////////  ////////////////////////////////////////////////////////////////////////// -static const LLWearableItemTypeNameComparator WEARABLE_TYPE_NAME_COMPARATOR; +static LLWearableItemTypeNameComparator WEARABLE_TYPE_NAME_COMPARATOR; +static const LLWearableItemTypeNameComparator WEARABLE_TYPE_LAYER_COMPARATOR; +static const LLWearableItemNameComparator WEARABLE_NAME_COMPARATOR; +static const LLWearableItemCreationDateComparator WEARABLE_CREATION_DATE_COMPARATOR;  static const LLDefaultChildRegistry::Register<LLWearableItemsList> r("wearable_items_list"); @@ -607,7 +624,7 @@ LLWearableItemsList::Params::Params()  LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p)  :	LLInventoryItemsList(p)  { -	setComparator(&WEARABLE_TYPE_NAME_COMPARATOR); +	setSortOrder(E_SORT_BY_TYPE_LAYER, false);  	mIsStandalone = p.standalone;  	if (mIsStandalone)  	{ @@ -707,6 +724,38 @@ void LLWearableItemsList::onRightClick(S32 x, S32 y)  	ContextMenu::instance().show(this, selected_uuids, x, y);  } +void LLWearableItemsList::setSortOrder(ESortOrder sort_order, bool sort_now) +{ +	switch (sort_order) +	{ +	case E_SORT_BY_MOST_RECENT: +		setComparator(&WEARABLE_CREATION_DATE_COMPARATOR); +		break; +	case E_SORT_BY_NAME: +		setComparator(&WEARABLE_NAME_COMPARATOR); +		break; +	case E_SORT_BY_TYPE_LAYER: +		setComparator(&WEARABLE_TYPE_LAYER_COMPARATOR); +		break; +	case E_SORT_BY_TYPE_NAME: +	{ +		WEARABLE_TYPE_NAME_COMPARATOR.setOrder(LLAssetType::AT_CLOTHING, LLWearableItemTypeNameComparator::ORDER_RANK_1, false, true); +		setComparator(&WEARABLE_TYPE_NAME_COMPARATOR); +		break; +	} + +	// No "default:" to raise compiler warning +	// if we're not handling something +	} + +	mSortOrder = sort_order; + +	if (sort_now) +	{ +		sort(); +	} +} +  //////////////////////////////////////////////////////////////////////////  /// ContextMenu  ////////////////////////////////////////////////////////////////////////// @@ -777,6 +826,8 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu  	U32 n_links = 0;				// number of links among the selected items  	U32 n_editable = 0;				// number of editable items among the selected ones +	bool can_be_worn = true; +  	for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it)  	{  		LLUUID id = *it; @@ -812,16 +863,22 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu  		{  			++n_already_worn;  		} + +		if (can_be_worn) +		{ +			can_be_worn = get_can_item_be_worn(item->getLinkedUUID()); +		}  	} // for  	bool standalone = mParent ? mParent->isStandalone() : false; +	bool wear_add_visible = mask & (MASK_CLOTHING|MASK_ATTACHMENT) && n_worn == 0 && can_be_worn && (n_already_worn != 0 || mask & MASK_ATTACHMENT);  	// *TODO: eliminate multiple traversals over the menu items -	setMenuItemVisible(menu, "wear_wear", 			n_already_worn == 0 && n_worn == 0); +	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",			mask == MASK_CLOTHING && n_worn == 0 && n_already_worn != 0); -	setMenuItemEnabled(menu, "wear_add",			n_items == 1 && canAddWearable(ids.front()) && n_already_worn != 0); -	setMenuItemVisible(menu, "wear_replace",		n_worn == 0 && n_already_worn != 0); +	setMenuItemVisible(menu, "wear_add",			wear_add_visible); +	setMenuItemEnabled(menu, "wear_add",			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); @@ -929,20 +986,61 @@ void LLWearableItemsList::ContextMenu::createNewWearable(const LLUUID& item_id)  	LLAgentWearables::createWearable(item->getWearableType(), true);  } -// Can we wear another wearable of the given item's wearable type? +// Returns true if all the given objects and clothes can be added.  // static -bool LLWearableItemsList::ContextMenu::canAddWearable(const LLUUID& item_id) +bool LLWearableItemsList::ContextMenu::canAddWearables(const uuid_vec_t& item_ids)  {  	// TODO: investigate wearables may not be loaded at this point EXT-8231 -	LLViewerInventoryItem* item = gInventory.getItem(item_id); -	if (!item || item->getType() != LLAssetType::AT_CLOTHING) +	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 +		{ +			llwarns << "Unexpected wearable type" << llendl; +			return false; +		} +	} + +	// Check whether we can add all the objects. +	if (!isAgentAvatarValid() || !gAgentAvatarp->canAttachMoreObjects(n_objects))  	{  		return false;  	} -	U32 wearable_count = gAgentWearables.getWearableCount(item->getWearableType()); -	return wearable_count < LLAgentWearables::MAX_CLOTHING_PER_TYPE; +	// 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 + 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 237ba1af43..b5e64abad0 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -313,10 +313,10 @@ public:  	enum ETypeListOrder  	{ -		ORDER_RANG_1 = 1, -		ORDER_RANG_2, -		ORDER_RANG_3, -		ORDER_RANG_UNKNOWN +		ORDER_RANK_1 = 1, +		ORDER_RANK_2, +		ORDER_RANK_3, +		ORDER_RANK_UNKNOWN  	};  	void setOrder(LLAssetType::EType items_of_type, ETypeListOrder order_priority, bool sort_items_by_name, bool sort_wearable_items_by_name); @@ -325,28 +325,28 @@ protected:  	/**  	 * All information about sort order is stored in mWearableOrder map  	 * -	 * mWearableOrder :      KEYES              VALUES +	 * mWearableOrder :      KEYS              VALUES  	 *                  [LLAssetType] [struct LLWearableTypeOrder]  	 *  	 *--------------------------------------------------------------------------------------------- -	 * I. Determines order (ORDER_RANG) in which items of LLAssetType should be displayed in list. +	 * I. Determines order (ORDER_RANK) in which items of LLAssetType should be displayed in list.  	 *     For example by spec in MY OUTFITS the order is: -	 *     1. AT_CLOTHING (ORDER_RANG_1) -	 *     2. AT_OBJECT   (ORDER_RANG_2) -	 *     3. AT_BODYPART (ORDER_RANG_3) +	 *     1. AT_CLOTHING (ORDER_RANK_1) +	 *     2. AT_OBJECT   (ORDER_RANK_2) +	 *     3. AT_BODYPART (ORDER_RANK_3)  	 *  	 * II.Items of each type(LLAssetType) are sorted by name or type(LLWearableType)  	 *     For example by spec in MY OUTFITS the order within each items type(LLAssetType) is:  	 *     1. AT_OBJECTS (abc order)  	 *     2. AT_CLOTHINGS -	 *       - by type (types order determined in LLWearableType::EType) -	 *       - outer layer on top +	 *         - by type (types order determined in LLWearableType::EType) +	 *         - outer layer on top  	 *     3. AT_BODYPARTS  (abc order)  	 *---------------------------------------------------------------------------------------------  	 *  	 * For each LLAssetType (KEYS in mWearableOrder) the information about:  	 * -	 *                                             I.  ORDER_RANG (the flag is LLWearableTypeOrder::mOrderPriority) +	 *                                             I.  ORDER_RANK (the flag is LLWearableTypeOrder::mOrderPriority)  	 *  	 *                                             II. whether items of this LLAssetType type should be ordered  	 *                                                 by name or by LLWearableType::EType (the flag is LLWearableTypeOrder::mSortAssetTypeByName) @@ -380,6 +380,19 @@ private:  };  /** + * @class LLWearableItemCreationDateComparator + * + * Comparator for sorting wearable list items by creation date (newest go first). + */ +class LLWearableItemCreationDateComparator : public LLWearableItemNameComparator +{ +	LOG_CLASS(LLWearableItemCreationDateComparator); + +protected: +	/*virtual*/ bool doCompare(const LLPanelInventoryListItemBase* item1, const LLPanelInventoryListItemBase* item2) const; +}; + +/**   * @class LLWearableItemsList   *   * A flat list of wearable inventory items. @@ -418,7 +431,7 @@ 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 canAddWearable(const LLUUID& item_id); +		static bool canAddWearables(const uuid_vec_t& item_ids);  		LLWearableItemsList*	mParent;  	}; @@ -431,6 +444,14 @@ public:  		Params();  	}; +	typedef enum e_sort_order { +		// Values should be compatible with InventorySortOrder setting. +		E_SORT_BY_NAME			= 0, +		E_SORT_BY_MOST_RECENT	= 1, +		E_SORT_BY_TYPE_LAYER	= 2, +		E_SORT_BY_TYPE_NAME 	= 3, +	} ESortOrder; +  	virtual ~LLWearableItemsList();  	/*virtual*/ void addNewItem(LLViewerInventoryItem* item, bool rearrange = true); @@ -445,6 +466,10 @@ public:  	bool isStandalone() const { return mIsStandalone; } +	ESortOrder getSortOrder() const { return mSortOrder; } + +	void setSortOrder(ESortOrder sort_order, bool sort_now = true); +  protected:  	friend class LLUICtrlFactory;  	LLWearableItemsList(const LLWearableItemsList::Params& p); @@ -453,6 +478,8 @@ protected:  	bool mIsStandalone;  	bool mWornIndicationEnabled; + +	ESortOrder		mSortOrder;  };  #endif //LL_LLWEARABLEITEMSLIST_H diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index df2fb2a6ea..9bafc28705 100644 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -129,8 +129,8 @@ TOOLSIT                 CURSOR                  "toolsit.cur"  //  VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,1,0,0 - PRODUCTVERSION 2,1,0,0 + FILEVERSION 2,1,0,13828 + PRODUCTVERSION 2,1,0,13828   FILEFLAGSMASK 0x3fL  #ifdef _DEBUG   FILEFLAGS 0x1L @@ -147,12 +147,12 @@ BEGIN          BEGIN              VALUE "CompanyName", "Linden Lab"              VALUE "FileDescription", "Second Life" -            VALUE "FileVersion", "2.1.0.0" +            VALUE "FileVersion", "2.1.0.13828"              VALUE "InternalName", "Second Life"              VALUE "LegalCopyright", "Copyright © 2001-2008, Linden Research, Inc."              VALUE "OriginalFilename", "SecondLife.exe"              VALUE "ProductName", "Second Life" -            VALUE "ProductVersion", "2.1.0.0" +            VALUE "ProductVersion", "2.1.0.13828"          END      END      BLOCK "VarFileInfo" | 
