Commits

Vadim Savchuk committed 28c5818 Merge

Merge from default branch

Comments (0)

Files changed (18)

indra/newview/llappearancemgr.cpp

 	}
 }
 
-void LLAppearanceMgr::enforceItemCountLimits()
+S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id,
+												 LLAssetType::EType type,
+												 S32 max_items,
+												 LLInventoryModel::item_array_t& items_to_kill)
+{
+	S32 to_kill_count = 0;
+
+	LLInventoryModel::item_array_t items;
+	getDescendentsOfAssetType(cat_id, items, type, false);
+	LLInventoryModel::item_array_t curr_items = items;
+	removeDuplicateItems(items);
+	if (max_items > 0)
+	{
+		filterWearableItems(items, max_items);
+	}
+	LLInventoryModel::item_array_t kill_items;
+	item_array_diff(curr_items,items,kill_items);
+	for (LLInventoryModel::item_array_t::iterator it = kill_items.begin();
+		 it != kill_items.end();
+		 ++it)
+	{
+		items_to_kill.push_back(*it);
+		to_kill_count++;
+	}
+	return to_kill_count;
+}
+	
+												 
+void LLAppearanceMgr::enforceItemRestrictions()
 {
 	S32 purge_count = 0;
-	
-	LLInventoryModel::item_array_t body_items;
-	getDescendentsOfAssetType(getCOF(), body_items, LLAssetType::AT_BODYPART, false);
-	LLInventoryModel::item_array_t curr_body_items = body_items;
-	removeDuplicateItems(body_items);
-	filterWearableItems(body_items, 1);
-	LLInventoryModel::item_array_t kill_body_items;
-	item_array_diff(curr_body_items,body_items,kill_body_items);
-	for (LLInventoryModel::item_array_t::iterator it = kill_body_items.begin();
-		 it != kill_body_items.end();
-		 ++it)
+	LLInventoryModel::item_array_t items_to_kill;
+
+	purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_BODYPART,
+											  1, items_to_kill);
+	purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_CLOTHING,
+											  LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill);
+	purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_OBJECT,
+											  -1, items_to_kill);
+
+	if (items_to_kill.size()>0)
 	{
-		LLViewerInventoryItem *item = *it;
-		llinfos << "purging dup body part " << item->getName() << llendl;
-		gInventory.purgeObject(item->getUUID());
-		purge_count++;
-	}
-	
-	LLInventoryModel::item_array_t wear_items;
-	getDescendentsOfAssetType(getCOF(), wear_items, LLAssetType::AT_CLOTHING, false);
-	LLInventoryModel::item_array_t curr_wear_items = wear_items;
-	removeDuplicateItems(wear_items);
-	filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE);
-	LLInventoryModel::item_array_t kill_wear_items;
-	item_array_diff(curr_wear_items,wear_items,kill_wear_items);
-	for (LLInventoryModel::item_array_t::iterator it = kill_wear_items.begin();
-		 it != kill_wear_items.end();
-		 ++it)
-	{
-		LLViewerInventoryItem *item = *it;
-		llinfos << "purging excess clothing item " << item->getName() << llendl;
-		gInventory.purgeObject(item->getUUID());
-		purge_count++;
-	}
-
-	if (purge_count>0)
-	{
+		for (LLInventoryModel::item_array_t::iterator it = items_to_kill.begin();
+			 it != items_to_kill.end();
+			 ++it)
+		{
+			LLViewerInventoryItem *item = *it;
+			llinfos << "purging duplicate or excess item " << item->getName() << llendl;
+			gInventory.purgeObject(item->getUUID());
+		}
 		gInventory.notifyObservers();
 	}
 }
 
 	// Remove duplicate or excess wearables. Should normally be enforced at the UI level, but
 	// this should catch anything that gets through.
-	enforceItemCountLimits();
+	enforceItemRestrictions();
 	
 	// update dirty flag to see if the state of the COF matches
 	// the saved outfit stored as a folder link
 
 	switch (item_to_remove->getType())
 	{
-	case LLAssetType::AT_CLOTHING:
-		if (get_is_item_worn(id_to_remove))
-		{
-			//*TODO move here the exact removing code from LLWearableBridge::removeItemFromAvatar in the future
-			LLWearableBridge::removeItemFromAvatar(item_to_remove);
-		}
-		break;
-	case LLAssetType::AT_OBJECT:
-		gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
-		gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
-		gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-		gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_to_remove->getLinkedUUID());
-		gMessageSystem->sendReliable( gAgent.getRegion()->getHost());
-
-		{
-			// this object might have been selected, so let the selection manager know it's gone now
-			LLViewerObject *found_obj = gObjectList.findObject(item_to_remove->getLinkedUUID());
-			if (found_obj)
+		case LLAssetType::AT_CLOTHING:
+			if (get_is_item_worn(id_to_remove))
 			{
-				LLSelectMgr::getInstance()->remove(found_obj);
-			};
-		}
-	default: break;
+				//*TODO move here the exact removing code from LLWearableBridge::removeItemFromAvatar in the future
+				LLWearableBridge::removeItemFromAvatar(item_to_remove);
+			}
+			break;
+		case LLAssetType::AT_OBJECT:
+			LLVOAvatarSelf::detachAttachmentIntoInventory(item_to_remove->getLinkedUUID());
+		default:
+			break;
 	}
 
 	// *HACK: Force to remove garbage from COF.
 	mAttachmentInvLinkEnabled = val;
 }
 
-// BAP TODO - mRegisteredAttachments is currently maintained but not used for anything.  Consider yanking.
 void dumpAttachmentSet(const std::set<LLUUID>& atts, const std::string& msg)
 {
        llinfos << msg << llendl;
 
 void LLAppearanceMgr::registerAttachment(const LLUUID& item_id)
 {
-       mRegisteredAttachments.insert(item_id);
 	   gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
 
 	   if (mAttachmentInvLinkEnabled)
 
 void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id)
 {
-       mRegisteredAttachments.erase(item_id);
 	   gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
 
 	   if (mAttachmentInvLinkEnabled)
 	   }
 }
 
-void LLAppearanceMgr::linkRegisteredAttachments()
-{
-	for (std::set<LLUUID>::iterator it = mRegisteredAttachments.begin();
-		 it != mRegisteredAttachments.end();
-		 ++it)
-	{
-		LLUUID item_id = *it;
-		addCOFItemLink(item_id, false);
-	}
-	mRegisteredAttachments.clear();
-}
-
 BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const
 {
 	return gInventory.isObjectDescendentOf(obj_id, getCOF());
 	 LLInventoryModel::item_array_t items;
 	 LLLinkedItemIDMatches find_links(gInventory.getLinkedItemID(obj_id));
 	 gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(),
-	 cats,
-	 items,
+									 cats,
+									 items,
 	 LLInventoryModel::EXCLUDE_TRASH,
 	 find_links);
 

indra/newview/llappearancemgr.h

 	void renameOutfit(const LLUUID& outfit_id);
 	void takeOffOutfit(const LLUUID& cat_id);
 	void addCategoryToCurrentOutfit(const LLUUID& cat_id);
-	void enforceItemCountLimits();
+	S32 findExcessOrDuplicateItems(const LLUUID& cat_id,
+								   LLAssetType::EType type,
+								   S32 max_items,
+								   LLInventoryModel::item_array_t& items_to_kill);
+	void enforceItemRestrictions();
 
 	// Copy all items and the src category itself.
 	void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
 	void unregisterAttachment(const LLUUID& item_id);
 	void registerAttachment(const LLUUID& item_id);
 	void setAttachmentInvLinkEnable(bool val);
-	void linkRegisteredAttachments();
 
 	// utility function for bulk linking.
 	void linkAll(const LLUUID& category,
 
 	void setOutfitLocked(bool locked);
 
-	std::set<LLUUID> mRegisteredAttachments;
 	bool mAttachmentInvLinkEnabled;
 	bool mOutfitIsDirty;
 	bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls.

indra/newview/llinventorybridge.cpp

 		{
 			return FALSE;
 		}
+
+		if (!item->isFinished()) // EXT-8662
+		{
+			return FALSE;
+		}
+
 		return (item->getPermissions().allowModifyBy(gAgent.getID()));
 	}
 	return FALSE;
 		LLInventoryItem* item = gInventory.getItem(mUUID);
 		if(item)
 		{
-			gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
-			gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
-			gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-			gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
-			gMessageSystem->sendReliable( gAgent.getRegion()->getHost());
-
-			// this object might have been selected, so let the selection manager know it's gone now
-			LLViewerObject *found_obj = gObjectList.findObject(item->getLinkedUUID());
-			if (found_obj)
-			{
-				LLSelectMgr::getInstance()->remove(found_obj);
-			}
+			LLVOAvatarSelf::detachAttachmentIntoInventory(item->getLinkedUUID());
 		}
 	}
 	else LLItemBridge::performAction(model, action);
 
 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.
+	const LLUUID& item_id = item->getLinkedUUID();
+
+	// Check for duplicate request.
+	if (isAgentAvatarValid() &&
+		(gAgentAvatarp->attachmentWasRequested(item_id) ||
+		 gAgentAvatarp->isWearingAttachment(item_id)))
+	{
+		llwarns << "duplicate attachment request, ignoring" << llendl;
+		return;
+	}
+	gAgentAvatarp->addAttachmentRequest(item_id);
 
 	S32 attach_pt = 0;
 	if (isAgentAvatarValid() && attachment)
 		attach_pt |= ATTACHMENT_ADD;
 	}
 
+	LLSD payload;
+	payload["item_id"] = item_id; // Wear the base object in case this is a link.
 	payload["attachment_point"] = attach_pt;
 
 	if (replace &&
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 	if (option == 0/*YES*/)
 	{
-		LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID());
+		LLUUID item_id = notification["payload"]["item_id"].asUUID();
+		LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
 
 		if (itemp)
 		{
 			U8 attachment_pt = notification["payload"]["attachment_point"].asInteger();
+			
 
 			LLMessageSystem* msg = gMessageSystem;
 			msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv);
 				LLViewerInventoryItem *obj_item = obj_item_array.get(i);
 				if (get_is_item_worn(obj_item->getUUID()))
 				{
-					gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
-					gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
-					gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
-					gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item->getLinkedUUID() );
-					
-					gMessageSystem->sendReliable( gAgent.getRegion()->getHost() );
-					
-					// this object might have been selected, so let the selection manager know it's gone now
-					LLViewerObject *found_obj = gObjectList.findObject( obj_item->getLinkedUUID());
-					if (found_obj)
-					{
-						LLSelectMgr::getInstance()->remove(found_obj);
-					}
+					LLVOAvatarSelf::detachAttachmentIntoInventory(obj_item->getLinkedUUID());
 				}
 			}
 		}

indra/newview/lloutfitslist.cpp

 
 void LLOutfitsList::onCOFChanged()
 {
-	LLInventoryModel::changed_items_t changed_linked_items;
+	LLInventoryModel::cat_array_t cat_array;
+	LLInventoryModel::item_array_t item_array;
 
-	const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs();
-	for (LLInventoryModel::changed_items_t::const_iterator iter = changed_items.begin();
-		 iter != changed_items.end();
-		 ++iter)
+	// Collect current COF items
+	gInventory.collectDescendents(
+		LLAppearanceMgr::instance().getCOF(),
+		cat_array,
+		item_array,
+		LLInventoryModel::EXCLUDE_TRASH);
+
+	uuid_vec_t vnew;
+	uuid_vec_t vadded;
+	uuid_vec_t vremoved;
+
+	// From gInventory we get the UUIDs of links that are currently in COF.
+	// These links UUIDs are not the same UUIDs that we have in each wearable items list.
+	// So we collect base items' UUIDs to find them or links that point to them in wearable
+	// items lists and update their worn state there.
+	for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
+		iter != item_array.end();
+		++iter)
 	{
-		LLViewerInventoryItem* item = gInventory.getItem(*iter);
-		if (item)
-		{
-			// From gInventory we get the UUIDs of new links added to COF
-			// or removed from COF. These links UUIDs are not the same UUIDs
-			// that we have in each wearable items list. So we collect base items
-			// UUIDs to find all items or links that point to same base items in wearable
-			// items lists and update their worn state there.
-			changed_linked_items.insert(item->getLinkedUUID());
-		}
+		vnew.push_back((*iter)->getLinkedUUID());
 	}
 
+	// We need to update only items that were added or removed from COF.
+	LLCommonUtils::computeDifference(vnew, mCOFLinkedItems, vadded, vremoved);
+
+	// Store the ids of items currently linked from COF.
+	mCOFLinkedItems = vnew;
+
 	for (outfits_map_t::iterator iter = mOutfitsMap.begin();
 			iter != mOutfitsMap.end();
 			++iter)
 		LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView());
 		if (!list) continue;
 
+		// Append removed ids to added ids because we should update all of them.
+		vadded.reserve(vadded.size() + vremoved.size());
+		vadded.insert(vadded.end(), vremoved.begin(), vremoved.end());
+
 		// Every list updates the labels of changed items  or
 		// the links that point to these items.
-		list->updateChangedItems(changed_linked_items);
+		list->updateChangedItems(vadded);
 	}
 }
 

indra/newview/lloutfitslist.h

 	typedef outfits_map_t::value_type					outfits_map_value_t;
 	outfits_map_t					mOutfitsMap;
 
+	// IDs of original items which are worn and linked in COF.
+	// Used to monitor COF changes for updating items worn state. See EXT-8636.
+	uuid_vec_t						mCOFLinkedItems;
+
 	LLOutfitListGearMenu*			mGearMenu;
 	LLListContextMenu*				mOutfitMenu;
 

indra/newview/llviewerjointattachment.cpp

 #include "llviewerjointattachment.h"
 
 #include "llagentconstants.h"
-
 #include "llviewercontrol.h"
 #include "lldrawable.h"
 #include "llgl.h"
 #include "llrender.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
 #include "llvolume.h"
 #include "pipeline.h"
 #include "llspatialpartition.h"
 //-----------------------------------------------------------------------------
 BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
 {
+	object->extractAttachmentItemID();
+
+	// Same object reattached
 	if (isObjectAttached(object))
 	{
 		llinfos << "(same object re-attached)" << llendl;
 		// Pass through anyway to let setupDrawable()
 		// re-connect object to the joint correctly
 	}
+	
+	// Two instances of the same inventory item attached --
+	// Request detach, and kill the object in the meantime.
+	if (getAttachedObject(object->getAttachmentItemID()))
+	{
+		llinfos << "(same object re-attached)" << llendl;
+		object->markDead();
 
-	object->extractAttachmentItemID();
+		// If this happens to be attached to self, then detach.
+		LLVOAvatarSelf::detachAttachmentIntoInventory(object->getAttachmentItemID());
+		return FALSE;
+	}
+
 	mAttachedObjects.push_back(object);
 	setupDrawable(object);
 	
 	}
 	calcLOD();
 	mUpdateXform = TRUE;
-
+	
 	return TRUE;
 }
 

indra/newview/llvoavatarself.cpp

 }
 
 //-----------------------------------------------------------------------------
+BOOL LLVOAvatarSelf::attachmentWasRequested(const LLUUID& inv_item_id) const
+{
+	const F32 REQUEST_EXPIRATION_SECONDS = 5.0;  // any request older than this is ignored/removed.
+	std::map<LLUUID,LLTimer>::iterator it = mAttachmentRequests.find(inv_item_id);
+	if (it != mAttachmentRequests.end())
+	{
+		const LLTimer& request_time = it->second;
+		F32 request_time_elapsed = request_time.getElapsedTimeF32();
+		if (request_time_elapsed > REQUEST_EXPIRATION_SECONDS)
+		{
+			mAttachmentRequests.erase(it);
+			return FALSE;
+		}
+		else
+		{
+			return TRUE;
+		}
+	}
+	else
+	{
+		return FALSE;
+	}
+}
+
+//-----------------------------------------------------------------------------
+void LLVOAvatarSelf::addAttachmentRequest(const LLUUID& inv_item_id)
+{
+	LLTimer current_time;
+	mAttachmentRequests[inv_item_id] = current_time;
+}
+
+//-----------------------------------------------------------------------------
+void LLVOAvatarSelf::removeAttachmentRequest(const LLUUID& inv_item_id)
+{
+	mAttachmentRequests.erase(inv_item_id);
+}
+
+//-----------------------------------------------------------------------------
 // getWornAttachment()
 //-----------------------------------------------------------------------------
 LLViewerObject* LLVOAvatarSelf::getWornAttachment(const LLUUID& inv_item_id)
 	{
 		const LLUUID& attachment_id = viewer_object->getAttachmentItemID();
 		LLAppearanceMgr::instance().registerAttachment(attachment_id);
+		// Clear any pending requests once the attachment arrives.
+		removeAttachmentRequest(attachment_id);
 	}
 
 	return attachment;
 	return FALSE;
 }
 
+// static
+BOOL LLVOAvatarSelf::detachAttachmentIntoInventory(const LLUUID &item_id)
+{
+	LLInventoryItem* item = gInventory.getItem(item_id);
+	if (item)
+	{
+		gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
+		gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+		gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+		gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id);
+		gMessageSystem->sendReliable(gAgent.getRegion()->getHost());
+		
+		// this object might have been selected, so let the selection manager know it's gone now
+		LLViewerObject *found_obj = gObjectList.findObject(item_id);
+		if (found_obj)
+		{
+			LLSelectMgr::getInstance()->remove(found_obj);
+		}
+		return TRUE;
+	}
+	return FALSE;
+}
+
 U32 LLVOAvatarSelf::getNumWearables(LLVOAvatarDefines::ETextureIndex i) const
 {
 	LLWearableType::EType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i);

indra/newview/llvoavatarself.h

 public:
 	void 				updateAttachmentVisibility(U32 camera_mode);
 	BOOL 				isWearingAttachment(const LLUUID& inv_item_id) const;
+	BOOL				attachmentWasRequested(const LLUUID& inv_item_id) const;
+	void				addAttachmentRequest(const LLUUID& inv_item_id);
+	void				removeAttachmentRequest(const LLUUID& inv_item_id);
 	LLViewerObject* 	getWornAttachment(const LLUUID& inv_item_id);
 	const std::string   getAttachedPointName(const LLUUID& inv_item_id) const;
 	/*virtual*/ const LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object);
 	/*virtual*/ BOOL 	detachObject(LLViewerObject *viewer_object);
+	static BOOL			detachAttachmentIntoInventory(const LLUUID& item_id);
+
+private:
+	// Track attachments that have been requested but have not arrived yet.
+	mutable std::map<LLUUID,LLTimer> mAttachmentRequests;
 
 	//--------------------------------------------------------------------
 	// HUDs

indra/newview/llwearableitemslist.cpp

 {
 	std::string search_label = name;
 
-	if (mWornIndicationEnabled && get_is_item_worn(mInventoryItemUUID))
+	// Updating item's worn status depending on whether it is linked in COF or not.
+	// We don't use get_is_item_worn() here because this update is triggered by
+	// an inventory observer upon link in COF beind added or removed so actual
+	// worn status of a linked item may still remain unchanged.
+	if (mWornIndicationEnabled && LLAppearanceMgr::instance().isLinkInCOF(mInventoryItemUUID))
 	{
 		search_label += LLTrans::getString("worn");
 		item_state = IS_WORN;
 	refreshList(item_array);
 }
 
-void LLWearableItemsList::updateChangedItems(const LLInventoryModel::changed_items_t& changed_items_uuids)
+void LLWearableItemsList::updateChangedItems(const uuid_vec_t& changed_items_uuids)
 {
 	// nothing to update
 	if (changed_items_uuids.empty()) return;
 
 		LLUUID linked_uuid = inv_item->getLinkedUUID();
 
-		for (LLInventoryModel::changed_items_t::const_iterator iter = changed_items_uuids.begin();
+		for (uuid_vec_t::const_iterator iter = changed_items_uuids.begin();
 				iter != changed_items_uuids.end();
 				++iter)
 		{

indra/newview/llwearableitemslist.h

 // newview
 #include "llinventoryitemslist.h"
 #include "llinventorylistitem.h"
-#include "llinventorymodel.h"
 #include "lllistcontextmenu.h"
 #include "llwearabletype.h"
 
 	 * Update items that match UUIDs from changed_items_uuids
 	 * or links that point at such items.
 	 */
-	void updateChangedItems(const LLInventoryModel::changed_items_t& changed_items_uuids);
+	void updateChangedItems(const uuid_vec_t& changed_items_uuids);
 
 	bool isStandalone() const { return mIsStandalone; }
 

indra/newview/skins/default/xui/en/floater_preview_gesture.xml

      name="replace_text"
      tool_tip="Replace the trigger word(s) with these words. For example, trigger &apos;hello&apos; replace with &apos;howdy&apos; will turn the chat &apos;I wanted to say hello&apos; into &apos;I wanted to say howdy&apos; as well as playing the gesture!"
      top_pad="10"
-     width="200">
+     width="210">
         Replace with:
     </text>
     <line_editor
      follows="left|top"
      height="20"
      layout="topleft"
-     left_delta="89"
+     left_delta="99"
      max_length="31"
      name="replace_editor"
      tool_tip="Replace the trigger word(s) with these words. For example, trigger &apos;hello&apos; replace with &apos;howdy&apos; will turn the chat &apos;I wanted to say hello&apos; into &apos;I wanted to say howdy&apos; as well as playing the gesture"
      top_delta="-4"
-     width="175" />
+     width="165" />
     <text
      type="string"
      length="1"
      font.style="BOLD"
      name="key_label"
      top_pad="10"
-     width="100">
+     width="150">
         Shortcut Key:
     </text>
     <combo_box
      height="20"
      label="None"
      layout="topleft"
-     left_delta="89"
+     left_delta="154"
      name="modifier_combo"
      top_delta="-4"
-     width="75" />
+     width="55" />
     <combo_box
      height="20"
      label="None"
      layout="topleft"
-     left_pad="10"
+     left_pad="4"
      name="key_combo"
      top_delta="0"
-     width="75" />
+     width="50" />
     <text
      type="string"
      length="1"

indra/newview/skins/default/xui/fr/floater_postcard.xml

 	<check_box label="Contenu adulte" name="mature_check" tool_tip="Cette carte postale est à caractère adulte."/>
 	<button label="?" name="publish_help_btn"/>
 	<text_editor name="msg_form">
-		Saisir ici votre message.
+		Saisir ici votre message
 	</text_editor>
 	<text name="fine_print">
 		Si le destinataire s&apos;inscrit sur [SECOND_LIFE], vous recevrez un bonus.

indra/newview/skins/default/xui/fr/floater_preview_gesture.xml

 		Prévisualiser
 	</floater.string>
 	<floater.string name="none_text">
-		- Aucun choix -
+		-Aucun choix-
 	</floater.string>
 	<floater.string name="Title">
 		Geste : [NAME]

indra/newview/skins/default/xui/fr/floater_tools.xml

 		Glissez pour déplacer, Maj-glissez pour copier.
 	</text>
 	<radio_group name="focus_radio_group">
-		<radio_item label="Zoom" name="radio zoom"/>
-		<radio_item label="Orbite (Ctrl)" name="radio orbit"/>
+		<radio_item label="Zoomer" name="radio zoom"/>
+		<radio_item label="Faire tourner la caméra (Ctrl)" name="radio orbit"/>
 		<radio_item label="Faire un panoramique (Ctrl+Maj)" name="radio pan"/>
 	</radio_group>
 	<radio_group name="move_radio_group">

indra/newview/skins/default/xui/fr/menu_picks.xml

 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <context_menu name="Picks">
 	<menu_item_call label="Infos" name="pick_info"/>
-	<menu_item_call label="Éditer" name="pick_edit"/>
+	<menu_item_call label="Modifier" name="pick_edit"/>
 	<menu_item_call label="Téléporter" name="pick_teleport"/>
 	<menu_item_call label="Carte" name="pick_map"/>
 	<menu_item_call label="Supprimer" name="pick_delete"/>

indra/newview/skins/default/xui/fr/notifications.xml

 	</notification>
 	<notification name="CannotSaveToAssetStore">
 		Impossible de sauvegarder le fichier [NAME] dans la base de données centrale.
-Cette erreur est généralement temporaire. Veuillez éditer et sauvegarder l&apos;élément endossable à nouveau d&apos;ici quelques minutes.
+Cette erreur est généralement temporaire. Veuillez modifier et sauvegarder l&apos;élément endossable à nouveau d&apos;ici quelques minutes.
 	</notification>
 	<notification name="YouHaveBeenLoggedOut">
 		Zut. Vous avez été déconnecté(e) de [SECOND_LIFE]
 		<usetemplate name="okcancelbuttons" notext="Non" yestext="Oui"/>
 	</notification>
 	<notification name="WLNoEditDefault">
-		Vous ne pouvez pas éditer ou supprimer un préréglage par défaut.
+		Vous ne pouvez pas modifier ou supprimer un préréglage par défaut.
 	</notification>
 	<notification name="WLMissingSky">
 		Une dossier semble manquer au Cycle du jour : [SKY].
 		Ce préréglage existe déjà !
 	</notification>
 	<notification name="WaterNoEditDefault">
-		Vous ne pouvez pas éditer ou supprimer un préréglage par défaut.
+		Vous ne pouvez pas modifier ou supprimer un préréglage par défaut.
 	</notification>
 	<notification name="ChatterBoxSessionStartError">
 		Impossible de démarrer une nouvelle session de chat avec [RECIPIENT].

indra/newview/skins/default/xui/fr/panel_pick_info.xml

 	<panel name="buttons">
 		<button label="Téléporter" name="teleport_btn"/>
 		<button label="Carte" name="show_on_map_btn"/>
-		<button label="Éditer" name="edit_btn"/>
+		<button label="Modifier" name="edit_btn"/>
 	</panel>
 </panel>

indra/newview/skins/default/xui/fr/panel_script_ed.xml

 			<menu_item_call label="Enregistrer" name="Save"/>
 			<menu_item_call label="Annuler tous les changements" name="Revert All Changes"/>
 		</menu>
-		<menu label="Éditer" name="Edit">
+		<menu label="Modifier" name="Edit">
 			<menu_item_call label="Annuler" name="Undo"/>
 			<menu_item_call label="Refaire" name="Redo"/>
 			<menu_item_call label="Couper" name="Cut"/>