diff options
| author | Brad Payne (Vir Linden) <vir@lindenlab.com> | 2016-07-06 20:07:14 -0400 | 
|---|---|---|
| committer | Brad Payne (Vir Linden) <vir@lindenlab.com> | 2016-07-06 20:07:14 -0400 | 
| commit | 4807d2745813d6f1490a45b7060ee5d434bd369e (patch) | |
| tree | 826e4edf9a38453768f1f080568435ba20c22389 /indra/newview | |
| parent | 880fd82d0be58aa4cc5ea16518d15fed3178aa29 (diff) | |
| parent | fa4339f3c78b053f986997744b8b4a4808b79c3a (diff) | |
merge
Diffstat (limited to 'indra/newview')
| -rw-r--r-- | indra/newview/llavatarrenderinfoaccountant.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/lleventpoll.cpp | 6 | ||||
| -rw-r--r-- | indra/newview/llinventorymodel.cpp | 153 | ||||
| -rw-r--r-- | indra/newview/llinventorymodel.h | 2 | ||||
| -rw-r--r-- | indra/newview/llinventoryobserver.cpp | 30 | ||||
| -rw-r--r-- | indra/newview/llskinningutil.cpp | 18 | ||||
| -rw-r--r-- | indra/newview/lltooldraganddrop.cpp | 60 | ||||
| -rw-r--r-- | indra/newview/llviewerinventory.cpp | 320 | ||||
| -rw-r--r-- | indra/newview/llviewerinventory.h | 7 | ||||
| -rw-r--r-- | indra/newview/llvoavatar.cpp | 122 | ||||
| -rw-r--r-- | indra/newview/llvoavatar.h | 1 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/strings.xml | 4 | 
12 files changed, 191 insertions, 534 deletions
| diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp index 5431daca32..7413dbed20 100644 --- a/indra/newview/llavatarrenderinfoaccountant.cpp +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -354,7 +354,7 @@ void LLAvatarRenderInfoAccountant::resetRenderInfoScanTimer()  // are returned for a new LLViewerRegion, and is the earliest time to get render info  void LLAvatarRenderInfoAccountant::scanNewRegion(const LLUUID& region_id)  { -	LL_INFOS("AvatarRenderInfo") << region_id << LL_ENDL; +	LL_DEBUGS("AvatarRenderInfo") << region_id << LL_ENDL;  	// Reset the global timer so it will scan regions on the next call to ::idle  	LLAvatarRenderInfoAccountant::getInstance()->resetRenderInfoScanTimer(); diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 7178042b32..15110701e4 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -142,7 +142,7 @@ namespace Details          int errorCount = 0;          int counter = mCounter; // saved on the stack for logging.  -        LL_INFOS("LLEventPollImpl") << " <" << counter << "> entering coroutine." << LL_ENDL; +        LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> entering coroutine." << LL_ENDL;          mAdapter = httpAdapter; @@ -170,7 +170,7 @@ namespace Details              {                  if (status == LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT))                  {   // A standard timeout response we get this when there are no events. -                    LL_INFOS("LLEventPollImpl") << "All is very quiet on target server. It may have gone idle?" << LL_ENDL; +                    LL_DEBUGS("LLEventPollImpl") << "All is very quiet on target server. It may have gone idle?" << LL_ENDL;                      errorCount = 0;                      continue;                  } @@ -264,7 +264,7 @@ namespace Details                  }              }          } -        LL_INFOS("LLEventPollImpl") << " <" << counter << "> Leaving coroutine." << LL_ENDL; +        LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> Leaving coroutine." << LL_ENDL;      }  } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index cada2d7cf2..9a33e210ff 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -2726,24 +2726,13 @@ void LLInventoryModel::registerCallbacks(LLMessageSystem* msg)  	msg->setHandlerFuncFast(_PREHASH_RemoveInventoryObjects,  							processRemoveInventoryObjects,  							NULL);	 -	//msg->setHandlerFuncFast(_PREHASH_ExchangeCallingCard, -	//						processExchangeCallingcard, -	//						NULL); -	//msg->setHandlerFuncFast(_PREHASH_AddCallingCard, -	//					processAddCallingcard, -	//					NULL); -	//msg->setHandlerFuncFast(_PREHASH_DeclineCallingCard, -	//					processDeclineCallingcard, -	//					NULL);  	msg->setHandlerFuncFast(_PREHASH_SaveAssetIntoInventory,  						processSaveAssetIntoInventory,  						NULL);  	msg->setHandlerFuncFast(_PREHASH_BulkUpdateInventory,  							processBulkUpdateInventory,  							NULL); -	msg->setHandlerFunc("InventoryDescendents", processInventoryDescendents);  	msg->setHandlerFunc("MoveInventoryItem", processMoveInventoryItem); -	msg->setHandlerFunc("FetchInventoryReply", processFetchInventoryReply);  } @@ -2763,14 +2752,6 @@ void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, vo  } -// static -void LLInventoryModel::processFetchInventoryReply(LLMessageSystem* msg, void**) -{ -	// no accounting -	gInventory.messageUpdateCore(msg, false); -} - -  bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, U32 mask)  {  	//make sure our added inventory observer is active @@ -3213,85 +3194,6 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)  		InventoryCallbackInfo cbinfo = (*inv_it);  		gInventoryCallbacks.fire(cbinfo.mCallback, cbinfo.mInvID);  	} - -	//gInventory.validate(); - -	// Don't show the inventory.  We used to call showAgentInventory here. -	//LLFloaterInventory* view = LLFloaterInventory::getActiveInventory(); -	//if(view) -	//{ -	//	const BOOL take_keyboard_focus = FALSE; -	//	view->setSelection(category.getUUID(), take_keyboard_focus ); -	//	LLView* focus_view = gFocusMgr.getKeyboardFocus(); -	//	LLFocusMgr::FocusLostCallback callback = gFocusMgr.getFocusCallback(); -	//	// HACK to open inventory offers that are accepted.  This information -	//	// really needs to flow through the instant messages and inventory -	//	// transfer/update messages. -	//	if (LLFloaterInventory::sOpenNextNewItem) -	//	{ -	//		view->openSelected(); -	//		LLFloaterInventory::sOpenNextNewItem = FALSE; -	//	} -	// -	//	// restore keyboard focus -	//	gFocusMgr.setKeyboardFocus(focus_view); -	//} -} - -// static -void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**) -{ -	LLUUID agent_id; -	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); -	if(agent_id != gAgent.getID()) -	{ -		LL_WARNS() << "Got a UpdateInventoryItem for the wrong agent." << LL_ENDL; -		return; -	} -	LLUUID parent_id; -	msg->getUUID("AgentData", "FolderID", parent_id); -	LLUUID owner_id; -	msg->getUUID("AgentData", "OwnerID", owner_id); -	S32 version; -	msg->getS32("AgentData", "Version", version); -	S32 descendents; -	msg->getS32("AgentData", "Descendents", descendents); - -	S32 i; -	S32 count = msg->getNumberOfBlocksFast(_PREHASH_FolderData); -	LLPointer<LLViewerInventoryCategory> tcategory = new LLViewerInventoryCategory(owner_id); -	for(i = 0; i < count; ++i) -	{ -		tcategory->unpackMessage(msg, _PREHASH_FolderData, i); -		gInventory.updateCategory(tcategory); -	} - -	count = msg->getNumberOfBlocksFast(_PREHASH_ItemData); -	LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem; -	for(i = 0; i < count; ++i) -	{ -		titem->unpackMessage(msg, _PREHASH_ItemData, i); -		// If the item has already been added (e.g. from link prefetch), then it doesn't need to be re-added. -		if (gInventory.getItem(titem->getUUID())) -		{ -			LL_DEBUGS("Inventory") << "Skipping prefetched item [ Name: " << titem->getName() -								   << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << LL_ENDL; -			continue; -		} -		gInventory.updateItem(titem); -	} - -	// set version and descendentcount according to message. -	LLViewerInventoryCategory* cat = gInventory.getCategory(parent_id); -	if(cat) -	{ -		cat->setVersion(version); -		cat->setDescendentCount(descendents); -		// Get this UUID on the changed list so that whatever's listening for it -		// will get triggered. -		gInventory.addChangedMask(LLInventoryObserver::INTERNAL, cat->getUUID()); -	} -	gInventory.notifyObservers();  }  // static @@ -3578,30 +3480,6 @@ void LLInventoryModel::updateItemsOrder(LLInventoryModel::item_array_t& items, c  	}  } -//* @param[in] items vector of items in order to be saved. -/* -void LLInventoryModel::saveItemsOrder(const LLInventoryModel::item_array_t& items) -{ -	int sortField = 0; - -	// current order is saved by setting incremental values (1, 2, 3, ...) for the sort field -	for (item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) -	{ -		LLViewerInventoryItem* item = *i; - -		item->setSortField(++sortField); -		item->setComplete(TRUE); -		item->updateServer(FALSE); - -		updateItem(item); - -		// Tell the parent folder to refresh its sort order. -		addChangedMask(LLInventoryObserver::SORT, item->getParentUUID()); -	} - -	notifyObservers(); -} -*/  // See also LLInventorySort where landmarks in the Favorites folder are sorted.  class LLViewerInventoryItemSort  { @@ -3612,37 +3490,6 @@ public:  	}  }; -/** - * Sorts passed items by LLViewerInventoryItem sort field. - * - * @param[in, out] items - array of items, not sorted. - */ -//static void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items) -//{ -//	static LLViewerInventoryItemSort sort_functor; -//	std::sort(items.begin(), items.end(), sort_functor); -//} - -// * @param source_item_id - LLUUID of the source item to be moved into new position -// * @param target_item_id - LLUUID of the target item before which source item should be placed. -/* -void LLInventoryModel::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) -{ -	LLInventoryModel::cat_array_t cats; -	LLInventoryModel::item_array_t items; -	LLIsType is_type(LLAssetType::AT_LANDMARK); -	LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); -	gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); - -	// ensure items are sorted properly before changing order. EXT-3498 -	rearrange_item_order_by_sort_field(items); - -	// update order -	updateItemsOrder(items, source_item_id, target_item_id); - -	saveItemsOrder(items); -} -*/  //----------------------------------------------------------------------------  // *NOTE: DEBUG functionality diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 3004eaf7c1..826d1f880d 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -630,9 +630,7 @@ public:  	static void processRemoveInventoryObjects(LLMessageSystem* msg, void**);  	static void processSaveAssetIntoInventory(LLMessageSystem* msg, void**);  	static void processBulkUpdateInventory(LLMessageSystem* msg, void**); -	static void processInventoryDescendents(LLMessageSystem* msg, void**);  	static void processMoveInventoryItem(LLMessageSystem* msg, void**); -	static void processFetchInventoryReply(LLMessageSystem* msg, void**);  protected:  	bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting, U32 mask = 0x0); diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 72ec092ed4..ce8705b7ac 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -241,33 +241,11 @@ void fetch_items_from_llsd(const LLSD& items_llsd)  			gInventory.requestPost(true, url, body[i], handler, (i ? "Library Item" : "Inventory Item"));  			continue;  		} +        else +        { +            LL_WARNS("INVENTORY") << "Failed to get capability." << LL_ENDL; +        } -		LLMessageSystem* msg = gMessageSystem; -		BOOL start_new_message = TRUE; -		for (S32 j=0; j<body[i]["items"].size(); j++) -		{ -			LLSD item_entry = body[i]["items"][j]; -			if (start_new_message) -			{ -				start_new_message = FALSE; -				msg->newMessageFast(_PREHASH_FetchInventory); -				msg->nextBlockFast(_PREHASH_AgentData); -				msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -				msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -			} -			msg->nextBlockFast(_PREHASH_InventoryData); -			msg->addUUIDFast(_PREHASH_OwnerID, item_entry["owner_id"].asUUID()); -			msg->addUUIDFast(_PREHASH_ItemID, item_entry["item_id"].asUUID()); -			if (msg->isSendFull(NULL)) -			{ -				start_new_message = TRUE; -				gAgent.sendReliableMessage(); -			} -		} -		if (!start_new_message) -		{ -			gAgent.sendReliableMessage(); -		}  	}  } diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index b36bfc870f..d69432ad21 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -72,7 +72,7 @@ U32 get_valid_joint_index(const std::string& name, LLVOAvatar *avatar, std::vect              return j;          }      } -    // BENTO how to handle? +    // Shouldn't ever get here, because of the name cleanup pass in remapSkinInfoJoints()      LL_ERRS() << "no valid joints in joint_names" << LL_ENDL;      return 0;  } @@ -118,7 +118,7 @@ U32 LLSkinningUtil::getMaxJointCount()      U32 result = LL_MAX_JOINTS_PER_MESH_OBJECT;      if (!sIncludeEnhancedSkeleton)      { -        // BENTO - currently the remap logic does not guarantee joint count <= 52; +        // Currently the remap logic does not guarantee joint count <= 52;          // if one of the base ancestors is not rigged in a given mesh, an extended  		// joint can still be included.          result = llmin(result,(U32)52); @@ -160,6 +160,16 @@ void LLSkinningUtil::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* ski      U32 max_joints = getMeshJointCount(skin);      // Compute the remap +    for (U32 j = 0; j < skin->mJointNames.size(); ++j) +    { +        // Fix invalid names to "mPelvis". Currently meshes with +        // invalid names will be blocked on upload, so this is just +        // needed for handling of any legacy bad data. +        if (!avatar->getJoint(skin->mJointNames[j])) +        { +            skin->mJointNames[j] = "mPelvis"; +        } +    }      std::vector<U32> j_proxy(skin->mJointNames.size());      for (U32 j = 0; j < skin->mJointNames.size(); ++j)      { @@ -179,8 +189,6 @@ void LLSkinningUtil::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* ski              {                  top++;              } - -                       }      }      // Then use j_proxy to fill in j_remap for the joints that will be discarded @@ -285,7 +293,7 @@ void LLSkinningUtil::remapSkinWeights(LLVector4a* weights, U32 num_vertices, con  void LLSkinningUtil::checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin)  {  #ifndef LL_RELEASE_FOR_DOWNLOAD -	const S32 max_joints = skin->mJointNames.size(); +	const S32 max_joints = skin->mJointRemap.size();      if (skin->mJointRemap.size()>0)      {          // Check the weights are consistent with the current remap. diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 98586e3b3d..27c4c90857 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -223,66 +223,6 @@ void LLCategoryDropObserver::done()  	}  	delete this;  } -/* Doesn't seem to be used anymore. -class LLCategoryDropDescendentsObserver : public LLInventoryFetchDescendentsObserver -{ -public: -	LLCategoryDropDescendentsObserver( -		const LLUUID& obj_id, LLToolDragAndDrop::ESource src) : -		mObjectID(obj_id), -		mSource(src) -	{} -	~LLCategoryDropDescendentsObserver() {} -	virtual void done(); - -protected: -	LLUUID mObjectID; -	LLToolDragAndDrop::ESource mSource; -}; - -void LLCategoryDropDescendentsObserver::done() -{ - -	gInventory.removeObserver(this); -	uuid_vec_t::iterator it = mComplete.begin(); -	uuid_vec_t::iterator end = mComplete.end(); -	LLViewerInventoryCategory::cat_array_t cats; -	LLViewerInventoryItem::item_array_t items; -	for(; it != end; ++it) -	{ -		gInventory.collectDescendents( -			(*it), -			cats, -			items, -			LLInventoryModel::EXCLUDE_TRASH); -	} - -	S32 count = items.size(); -	if (count) -	{ -		std::set<LLUUID> unique_ids; -		for(S32 i = 0; i < count; ++i) -		{ -			unique_ids.insert(items.get(i)->getUUID()); -		} -		uuid_vec_t ids; -		std::back_insert_iterator<uuid_vec_t> copier(ids); -		std::copy(unique_ids.begin(), unique_ids.end(), copier); -		LLCategoryDropObserver* dropper; -		dropper = new LLCategoryDropObserver(ids, mObjectID, mSource); -		dropper->startFetch(); -		if (dropper->isDone()) -		{ -			dropper->done(); -		} -		else -		{ -			gInventory.addObserver(dropper); -		} -	} -	delete this; -} -*/  S32 LLToolDragAndDrop::sOperationId = 0; diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 0ee873d7a1..d0813544f8 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -384,16 +384,26 @@ void LLViewerInventoryItem::updateServer(BOOL is_new) const  	LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0);  	gInventory.accountForUpdate(up); -	LLMessageSystem* msg = gMessageSystem; -	msg->newMessageFast(_PREHASH_UpdateInventoryItem); -	msg->nextBlockFast(_PREHASH_AgentData); -	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -	msg->addUUIDFast(_PREHASH_TransactionID, mTransactionID); -	msg->nextBlockFast(_PREHASH_InventoryData); -	msg->addU32Fast(_PREHASH_CallbackID, 0); -	packMessage(msg); -	gAgent.sendReliableMessage(); +    LLSD updates = asLLSD(); +    // Replace asset_id and/or shadow_id with transaction_id (hash_id) +    if (updates.has("asset_id")) +    { +        updates.erase("asset_id"); +        if(getTransactionID().notNull()) +        { +            updates["hash_id"] = getTransactionID(); +        } +    } +    if (updates.has("shadow_id")) +    { +        updates.erase("shadow_id"); +        if(getTransactionID().notNull()) +        { +            updates["hash_id"] = getTransactionID(); +        } +    } +    AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>)NULL, _1); +    AISAPI::UpdateItem(getUUID(), updates, cr);  }  void LLViewerInventoryItem::fetchFromServer(void) const @@ -636,17 +646,9 @@ void LLViewerInventoryCategory::updateServer(BOOL is_new) const  		return;  	} -	LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0); -	gInventory.accountForUpdate(up); - -	LLMessageSystem* msg = gMessageSystem; -	msg->newMessageFast(_PREHASH_UpdateInventoryFolder); -	msg->nextBlockFast(_PREHASH_AgentData); -	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -	msg->nextBlockFast(_PREHASH_FolderData); -	packMessage(msg); -	gAgent.sendReliableMessage(); +    LLSD new_llsd = asLLSD(); +    AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>)NULL, _1); +    AISAPI::UpdateCategory(getUUID(), new_llsd, cr);  }  S32 LLViewerInventoryCategory::getVersion() const @@ -669,18 +671,6 @@ bool LLViewerInventoryCategory::fetch()  		mDescendentsRequested.reset();  		mDescendentsRequested.setTimerExpirySec(FETCH_TIMER_EXPIRY); -		// bitfield -		// 1 = by date -		// 2 = folders by date -		// Need to mask off anything but the first bit. -		// This comes from LLInventoryFilter from llfolderview.h -		U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER) & 0x1; - -		// *NOTE: For bug EXT-2879, originally commented out -		// gAgent.getRegion()->getCapability in order to use the old -		// message-based system.  This has been uncommented now that -		// AIS folks are aware of the issue and have a fix in process. -		// see ticket for details.  		std::string url;  		if (gAgent.getRegion()) @@ -695,24 +685,6 @@ bool LLViewerInventoryCategory::fetch()  		{  			LLInventoryModelBackgroundFetch::instance().start(mUUID, false);			  		} -		else -		{	//Deprecated, but if we don't have a capability, use the old system. -			LL_INFOS(LOG_INV) << "FetchInventoryDescendents2 capability not found.  Using deprecated UDP message." << LL_ENDL; -			 -			LLMessageSystem* msg = gMessageSystem; -			msg->newMessage("FetchInventoryDescendents"); -			msg->nextBlock("AgentData"); -			msg->addUUID("AgentID", gAgent.getID()); -			msg->addUUID("SessionID", gAgent.getSessionID()); -			msg->nextBlock("InventoryData"); -			msg->addUUID("FolderID", mUUID); -			msg->addUUID("OwnerID", mOwnerID); - -			msg->addS32("SortOrder", sort_order); -			msg->addBOOL("FetchFolders", FALSE); -			msg->addBOOL("FetchItems", TRUE); -			gAgent.sendReliableMessage(); -		}  		return true;  	}  	return false; @@ -905,17 +877,16 @@ void LLViewerInventoryCategory::changeType(LLFolderType::EType new_folder_type)  	const LLUUID &parent_id = getParentUUID();  	const std::string &name = getName(); -	LLMessageSystem* msg = gMessageSystem; -	msg->newMessageFast(_PREHASH_UpdateInventoryFolder); -	msg->nextBlockFast(_PREHASH_AgentData); -	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -	msg->nextBlockFast(_PREHASH_FolderData); -	msg->addUUIDFast(_PREHASH_FolderID, folder_id); -	msg->addUUIDFast(_PREHASH_ParentID, parent_id); -	msg->addS8Fast(_PREHASH_Type, new_folder_type); -	msg->addStringFast(_PREHASH_Name, name); -	gAgent.sendReliableMessage(); +    LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(folder_id, +                                                                                 parent_id, +                                                                                 new_folder_type, +                                                                                 name, +                                                                                 gAgent.getID()); +         +         +    LLSD new_llsd = new_cat->asLLSD(); +    AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>) NULL, _1); +    AISAPI::UpdateCategory(folder_id, new_llsd, cr);  	setPreferredType(new_folder_type);  	gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id); @@ -1289,40 +1260,10 @@ void link_inventory_array(const LLUUID& category,  						   << " UUID:" << category << " ] " << LL_ENDL;  #endif  	} - -    if (AISAPI::isAvailable()) -	{ -		LLSD new_inventory = LLSD::emptyMap(); -		new_inventory["links"] = links; -        AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t(); -        AISAPI::CreateInventory(category, new_inventory, cr); -	} -    else -	{ -		LLMessageSystem* msg = gMessageSystem; -		for (LLSD::array_iterator iter = links.beginArray(); iter != links.endArray(); ++iter ) -		{ -			msg->newMessageFast(_PREHASH_LinkInventoryItem); -			msg->nextBlock(_PREHASH_AgentData); -			{ -				msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -				msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -			} -			msg->nextBlock(_PREHASH_InventoryBlock); -			{ -				LLSD link = (*iter); -				msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb)); -				msg->addUUIDFast(_PREHASH_FolderID, category); -				msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); -				msg->addUUIDFast(_PREHASH_OldItemID, link["linked_id"].asUUID()); -				msg->addS8Fast(_PREHASH_Type, link["type"].asInteger()); -				msg->addS8Fast(_PREHASH_InvType, link["inv_type"].asInteger()); -				msg->addStringFast(_PREHASH_Name, link["name"].asString()); -				msg->addStringFast(_PREHASH_Description, link["desc"].asString()); -			} -			gAgent.sendReliableMessage(); -		} -	} +    LLSD new_inventory = LLSD::emptyMap(); +    new_inventory["links"] = links; +    AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); +    AISAPI::CreateInventory(category, new_inventory, cr);  }  void move_inventory_item( @@ -1354,49 +1295,21 @@ void update_inventory_item(  	LLPointer<LLInventoryCallback> cb)  {  	const LLUUID& item_id = update_item->getUUID(); -    if (AISAPI::isAvailable()) -	{ -		LLSD updates = update_item->asLLSD(); -		// Replace asset_id and/or shadow_id with transaction_id (hash_id) -		if (updates.has("asset_id")) -		{ -			updates.erase("asset_id"); -			updates["hash_id"] = update_item->getTransactionID(); -		} -		if (updates.has("shadow_id")) -		{ -			updates.erase("shadow_id"); -			updates["hash_id"] = update_item->getTransactionID(); -		} -        AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t(); -        AISAPI::UpdateItem(item_id, updates, cr); -	} -    else -	{ -		LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id); -		LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (update_item ? update_item->getName() : "(NOT FOUND)") << LL_ENDL; -		if(obj) -		{ -			LLMessageSystem* msg = gMessageSystem; -			msg->newMessageFast(_PREHASH_UpdateInventoryItem); -			msg->nextBlockFast(_PREHASH_AgentData); -			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -			msg->addUUIDFast(_PREHASH_TransactionID, update_item->getTransactionID()); -			msg->nextBlockFast(_PREHASH_InventoryData); -			msg->addU32Fast(_PREHASH_CallbackID, 0); -			update_item->packMessage(msg); -			gAgent.sendReliableMessage(); - -			LLInventoryModel::LLCategoryUpdate up(update_item->getParentUUID(), 0); -			gInventory.accountForUpdate(up); -			gInventory.updateItem(update_item); -			if (cb) -			{ -				cb->fire(item_id); -			} -		} -	} +   +    LLSD updates = update_item->asLLSD(); +    // Replace asset_id and/or shadow_id with transaction_id (hash_id) +    if (updates.has("asset_id")) +    { +        updates.erase("asset_id"); +        updates["hash_id"] = update_item->getTransactionID(); +    } +    if (updates.has("shadow_id")) +    { +        updates.erase("shadow_id"); +        updates["hash_id"] = update_item->getTransactionID(); +    } +    AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); +    AISAPI::UpdateItem(item_id, updates, cr);  }  // Note this only supports updating an existing item. Goes through AISv3 @@ -1407,41 +1320,8 @@ void update_inventory_item(  	const LLSD& updates,  	LLPointer<LLInventoryCallback> cb)  { -    if (AISAPI::isAvailable()) -	{ -        AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t(); -        AISAPI::UpdateItem(item_id, updates, cr); -	} -    else -	{ -		LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id); -		LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL; -		if(obj) -		{ -			LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem); -			new_item->copyViewerItem(obj); -			new_item->fromLLSD(updates,false); - -			LLMessageSystem* msg = gMessageSystem; -			msg->newMessageFast(_PREHASH_UpdateInventoryItem); -			msg->nextBlockFast(_PREHASH_AgentData); -			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -			msg->addUUIDFast(_PREHASH_TransactionID, new_item->getTransactionID()); -			msg->nextBlockFast(_PREHASH_InventoryData); -			msg->addU32Fast(_PREHASH_CallbackID, 0); -			new_item->packMessage(msg); -			gAgent.sendReliableMessage(); - -			LLInventoryModel::LLCategoryUpdate up(new_item->getParentUUID(), 0); -			gInventory.accountForUpdate(up); -			gInventory.updateItem(new_item); -			if (cb) -			{ -				cb->fire(item_id); -			} -		} -	} +    AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); +    AISAPI::UpdateItem(item_id, updates, cr);  }  void update_inventory_category( @@ -1461,32 +1341,9 @@ void update_inventory_category(  		LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(obj);  		new_cat->fromLLSD(updates); -		// FIXME - restore this once the back-end work has been done. -        if (AISAPI::isAvailable()) -		{ -			LLSD new_llsd = new_cat->asLLSD(); -            AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t(); -            AISAPI::UpdateCategory(cat_id, new_llsd, cr); -		} -		else // no cap -		{ -			LLMessageSystem* msg = gMessageSystem; -			msg->newMessageFast(_PREHASH_UpdateInventoryFolder); -			msg->nextBlockFast(_PREHASH_AgentData); -			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -			msg->nextBlockFast(_PREHASH_FolderData); -			new_cat->packMessage(msg); -			gAgent.sendReliableMessage(); - -			LLInventoryModel::LLCategoryUpdate up(new_cat->getParentUUID(), 0); -			gInventory.accountForUpdate(up); -			gInventory.updateCategory(new_cat); -			if (cb) -			{ -				cb->fire(cat_id); -			} -		} +        LLSD new_llsd = new_cat->asLLSD(); +        AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); +        AISAPI::UpdateCategory(cat_id, new_llsd, cr);  	}  } @@ -1604,41 +1461,8 @@ void remove_inventory_category(  			LLNotificationsUtil::add("CannotRemoveProtectedCategories");  			return;  		} -        if (AISAPI::isAvailable()) -		{ -            AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t(); -            AISAPI::RemoveCategory(cat_id, cr); -		} -		else // no cap -		{ -			// RemoveInventoryFolder does not remove children, so must -			// clear descendents first. -			LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(cat_id); -			if(children != LLInventoryModel::CHILDREN_NO) -			{ -				LL_DEBUGS(LOG_INV) << "Will purge descendents first before deleting category " << cat_id << LL_ENDL; -				LLPointer<LLInventoryCallback> wrap_cb = new LLRemoveCategoryOnDestroy(cat_id, cb);  -				purge_descendents_of(cat_id, wrap_cb); -				return; -			} - -			LLMessageSystem* msg = gMessageSystem; -			msg->newMessageFast(_PREHASH_RemoveInventoryFolder); -			msg->nextBlockFast(_PREHASH_AgentData); -			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -			msg->nextBlockFast(_PREHASH_FolderData); -			msg->addUUIDFast(_PREHASH_FolderID, cat_id); -			gAgent.sendReliableMessage(); - -			// Update inventory and call callback immediately since -			// message-based system has no callback mechanism (!) -			gInventory.onObjectDeletedFromServer(cat_id); -			if (cb) -			{ -				cb->fire(cat_id); -			} -		} +        AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); +        AISAPI::RemoveCategory(cat_id, cr);  	}  	else  	{ @@ -1857,29 +1681,11 @@ void slam_inventory_folder(const LLUUID& folder_id,  						   const LLSD& contents,  						   LLPointer<LLInventoryCallback> cb)  { -    if (AISAPI::isAvailable()) -	{ -		LL_DEBUGS(LOG_INV) << "using AISv3 to slam folder, id " << folder_id -						   << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL; +    LL_DEBUGS(LOG_INV) << "using AISv3 to slam folder, id " << folder_id +                       << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL; -        AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t(); -        AISAPI::SlamFolder(folder_id, contents, cr); -	} -	else // no cap -	{ -		LL_DEBUGS(LOG_INV) << "using item-by-item calls to slam folder, id " << folder_id -						   << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL; -		for (LLSD::array_const_iterator it = contents.beginArray(); -			 it != contents.endArray(); -			 ++it) -		{ -			const LLSD& item_contents = *it; -			LLViewerInventoryItem *item = new LLViewerInventoryItem; -			item->fromLLSD(item_contents); -			link_inventory_object(folder_id, item, cb); -		} -		remove_folder_contents(folder_id,false,cb); -	} +    AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); +    AISAPI::SlamFolder(folder_id, contents, cr);  }  void remove_folder_contents(const LLUUID& category, bool keep_outfit_links, diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 4e91e4110a..5194679a0c 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -38,6 +38,7 @@ class LLInventoryPanel;  class LLFolderView;  class LLFolderBridge;  class LLViewerInventoryCategory; +class LLInventoryCallback;  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLViewerInventoryItem @@ -387,9 +388,9 @@ void update_inventory_item(  	LLPointer<LLInventoryCallback> cb);  void update_inventory_category( -	const LLUUID& cat_id, -	const LLSD& updates, -	LLPointer<LLInventoryCallback> cb); +    const LLUUID& cat_id, +    const LLSD& updates, +    LLPointer<LLInventoryCallback> cb);  void remove_inventory_items(  	LLInventoryObject::object_list_t& items, diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 0448fc6138..d3cd85e9f4 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1907,16 +1907,6 @@ void LLVOAvatar::resetSkeleton()      // Restore attachment pos overrides      rebuildAttachmentPosOverrides(); -    // Restore mPelvis state -    //getJoint("mPelvis")->setRotation(pelvis_rot); -    //getJoint("mPelvis")->setPosition(pelvis_pos); -     -    // Restart animations BENTO - not needed? Removing this fixes a -    // problem seen if avatar is sitting and animated relative to sit -    // point. - -    //resetAnimations(); -      LL_DEBUGS("Avatar") << avString() << " reset ends" << LL_ENDL;  } @@ -3356,23 +3346,31 @@ void LLVOAvatar::updateDebugText()  		{  			debug_line += llformat(" - cof rcv:%d", last_received_cof_version);  		} -		debug_line += llformat(" bsz-z: %f avofs-z: %f", mBodySize[2], mAvatarOffset[2]); +		debug_line += llformat(" bsz-z: %.3f", mBodySize[2]); +        if (mAvatarOffset[2] != 0.0f) +        { +            debug_line += llformat("avofs-z: %.3f", mAvatarOffset[2]); +        }  		bool hover_enabled = getRegion() && getRegion()->avatarHoverHeightEnabled();  		debug_line += hover_enabled ? " H" : " h";  		const LLVector3& hover_offset = getHoverOffset();  		if (hover_offset[2] != 0.0)  		{ -			debug_line += llformat(" hov_z: %f", hover_offset[2]); +			debug_line += llformat(" hov_z: %.3f", hover_offset[2]);  			debug_line += llformat(" %s", (mIsSitting ? "S" : "T"));  			debug_line += llformat("%s", (isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED) ? "G" : "-"));  		} -		F32 elapsed = mLastAppearanceMessageTimer.getElapsedTimeF32(); -		static const char *elapsed_chars = "Xx*..."; -		U32 bucket = U32(elapsed*2); -		if (bucket < strlen(elapsed_chars)) -		{ -			debug_line += llformat(" %c", elapsed_chars[bucket]); -		} +        LLVector3 ankle_right_pos_agent = mFootRightp->getWorldPosition(); +		LLVector3 normal; +        LLVector3 ankle_right_ground_agent = ankle_right_pos_agent; +        resolveHeightAgent(ankle_right_pos_agent, ankle_right_ground_agent, normal); +        F32 rightElev = llmax(-0.2f, ankle_right_pos_agent.mV[VZ] - ankle_right_ground_agent.mV[VZ]); +        debug_line += llformat(" relev %.3f", rightElev); + +        LLVector3 root_pos = mRoot->getPosition(); +        LLVector3 pelvis_pos = mPelvisp->getPosition(); +        debug_line += llformat(" rp %.3f pp %.3f", root_pos[2], pelvis_pos[2]); +  		addDebugText(debug_line);  	}  	if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) @@ -3598,6 +3596,12 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  		}  		mInAir = in_air; +        // SL-402: with the ability to animate the position of joints +        // that affect the body size calculation, computed body size +        // can get stale much more easily. Simplest fix is to update +        // it frequently. +        computeBodySize(); +      		// correct for the fact that the pelvis is not necessarily the center   		// of the agent's physical representation  		root_pos.mdV[VZ] -= (0.5f * mBodySize.mV[VZ]) - mPelvisToFoot; @@ -3923,10 +3927,78 @@ void LLVOAvatar::updateHeadOffset()  		mHeadOffset = lerp(midEyePt, mHeadOffset,  u);  	}  } + +void LLVOAvatar::debugBodySize() const +{ +	LLVector3 pelvis_scale = mPelvisp->getScale(); + +	// some of the joints have not been cached +	LLVector3 skull = mSkullp->getPosition(); +    LL_DEBUGS("Avatar") << "skull pos " << skull << LL_ENDL; +	//LLVector3 skull_scale = mSkullp->getScale(); + +	LLVector3 neck = mNeckp->getPosition(); +	LLVector3 neck_scale = mNeckp->getScale(); +    LL_DEBUGS("Avatar") << "neck pos " << neck << " neck_scale " << neck_scale << LL_ENDL; + +	LLVector3 chest = mChestp->getPosition(); +	LLVector3 chest_scale = mChestp->getScale(); +    LL_DEBUGS("Avatar") << "chest pos " << chest << " chest_scale " << chest_scale << LL_ENDL; + +	// the rest of the joints have been cached +	LLVector3 head = mHeadp->getPosition(); +	LLVector3 head_scale = mHeadp->getScale(); +    LL_DEBUGS("Avatar") << "head pos " << head << " head_scale " << head_scale << LL_ENDL; + +	LLVector3 torso = mTorsop->getPosition(); +	LLVector3 torso_scale = mTorsop->getScale(); +    LL_DEBUGS("Avatar") << "torso pos " << torso << " torso_scale " << torso_scale << LL_ENDL; + +	LLVector3 hip = mHipLeftp->getPosition(); +	LLVector3 hip_scale = mHipLeftp->getScale(); +    LL_DEBUGS("Avatar") << "hip pos " << hip << " hip_scale " << hip_scale << LL_ENDL; + +	LLVector3 knee = mKneeLeftp->getPosition(); +	LLVector3 knee_scale = mKneeLeftp->getScale(); +    LL_DEBUGS("Avatar") << "knee pos " << knee << " knee_scale " << knee_scale << LL_ENDL; + +	LLVector3 ankle = mAnkleLeftp->getPosition(); +	LLVector3 ankle_scale = mAnkleLeftp->getScale(); +    LL_DEBUGS("Avatar") << "ankle pos " << ankle << " ankle_scale " << ankle_scale << LL_ENDL; + +	LLVector3 foot  = mFootLeftp->getPosition(); +    LL_DEBUGS("Avatar") << "foot pos " << foot << LL_ENDL; + +	F32 new_offset = (const_cast<LLVOAvatar*>(this))->getVisualParamWeight(AVATAR_HOVER); +    LL_DEBUGS("Avatar") << "new_offset " << new_offset << LL_ENDL; + +	F32 new_pelvis_to_foot = hip.mV[VZ] * pelvis_scale.mV[VZ] - +        knee.mV[VZ] * hip_scale.mV[VZ] - +        ankle.mV[VZ] * knee_scale.mV[VZ] - +        foot.mV[VZ] * ankle_scale.mV[VZ]; +    LL_DEBUGS("Avatar") << "new_pelvis_to_foot " << new_pelvis_to_foot << LL_ENDL; + +	LLVector3 new_body_size; +	new_body_size.mV[VZ] = new_pelvis_to_foot + +					   // the sqrt(2) correction below is an approximate +					   // correction to get to the top of the head +					   F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) +  +					   head.mV[VZ] * neck_scale.mV[VZ] +  +					   neck.mV[VZ] * chest_scale.mV[VZ] +  +					   chest.mV[VZ] * torso_scale.mV[VZ] +  +					   torso.mV[VZ] * pelvis_scale.mV[VZ];  + +	// TODO -- measure the real depth and width +	new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH; +	new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH; + +    LL_DEBUGS("Avatar") << "new_body_size " << new_body_size << LL_ENDL; +} +     //------------------------------------------------------------------------  // postPelvisSetRecalc  //------------------------------------------------------------------------ -void LLVOAvatar::postPelvisSetRecalc( void ) +void LLVOAvatar::postPelvisSetRecalc()  {		  	mRoot->updateWorldMatrixChildren();			  	computeBodySize(); @@ -8313,6 +8385,12 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara  			}  		} +        // Root joint +        const LLVector3& pos = mRoot->getPosition(); +        const LLVector3& scale = mRoot->getScale(); +        apr_file_printf( file, "\t\t<root name=\"%s\" position=\"%f %f %f\" scale=\"%f %f %f\"/>\n",  +                         mRoot->getName().c_str(), pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]); +          // Bones  		avatar_joint_list_t::iterator iter = mSkeleton.begin();  		avatar_joint_list_t::iterator end  = mSkeleton.end(); @@ -8896,7 +8974,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity()  				   && (all_textures.find(image_id) == all_textures.end()))  				{  					// attachment texture not previously seen. -					LL_INFOS() << "attachment_texture: " << image_id.asString() << LL_ENDL; +					LL_DEBUGS("ARCdetail") << "attachment_texture: " << image_id.asString() << LL_ENDL;  					all_textures.insert(image_id);  				}  			} @@ -8916,7 +8994,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity()  					continue;  				if (all_textures.find(image_id) == all_textures.end())  				{ -					LL_INFOS() << "local_texture: " << texture_dict->mName << ": " << image_id << LL_ENDL; +					LL_DEBUGS("ARCdetail") << "local_texture: " << texture_dict->mName << ": " << image_id << LL_ENDL;  					all_textures.insert(image_id);  				}  			} diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 32a30c3aa8..b67aa62b06 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -367,6 +367,7 @@ protected:  	/*virtual*/ LLAvatarJointMesh*	createAvatarJointMesh(); // Returns LLViewerJointMesh  public:  	void				updateHeadOffset(); +    void				debugBodySize() const;  	void				postPelvisSetRecalc( void );  	/*virtual*/ BOOL	loadSkeletonNode(); diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index a4869b5503..e7d4491e0f 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2669,8 +2669,8 @@ This feature is currently in Beta. Please add your name to this [http://goo.gl/f  	<string name="ATTACH_LULEG">Left Upper Leg</string>  	<string name="ATTACH_LLLEG">Left Lower Leg</string>  	<string name="ATTACH_BELLY">Belly</string> -	<string name="ATTACH_RPEC">Right Pec</string> -	<string name="ATTACH_LPEC">Left Pec</string> +	<string name="ATTACH_LEFT_PEC">Left Pec</string> +	<string name="ATTACH_RIGHT_PEC">Right Pec</string>  	<string name="ATTACH_HUD_CENTER_2">HUD Center 2</string>  	<string name="ATTACH_HUD_TOP_RIGHT">HUD Top Right</string>  	<string name="ATTACH_HUD_TOP_CENTER">HUD Top Center</string> | 
