Commits

Vadim Savchuk committed fe7134e Merge

Merge from default branch

  • Participants
  • Parent commits bbf9a1a, d22cf4e
  • Branches product-engine

Comments (0)

Files changed (27)

File indra/llcommon/llassettype.cpp

 {
 	//       												   DESCRIPTION			TYPE NAME	HUMAN NAME			CAN LINK?   CAN FETCH?  CAN KNOW?	
 	//      												  |--------------------|-----------|-------------------|-----------|-----------|---------|
-	addEntry(LLAssetType::AT_TEXTURE, 			new AssetEntry("TEXTURE",			"texture",	"texture",			false,		false,		true));
-	addEntry(LLAssetType::AT_SOUND, 			new AssetEntry("SOUND",				"sound",	"sound",			false,		true,		true));
-	addEntry(LLAssetType::AT_CALLINGCARD, 		new AssetEntry("CALLINGCARD",		"callcard",	"calling card",		false,		false,		false));
-	addEntry(LLAssetType::AT_LANDMARK, 			new AssetEntry("LANDMARK",			"landmark",	"landmark",			false,		true,		true));
-	addEntry(LLAssetType::AT_SCRIPT, 			new AssetEntry("SCRIPT",			"script",	"legacy script",	false,		false,		false));
+	addEntry(LLAssetType::AT_TEXTURE, 			new AssetEntry("TEXTURE",			"texture",	"texture",			true,		false,		true));
+	addEntry(LLAssetType::AT_SOUND, 			new AssetEntry("SOUND",				"sound",	"sound",			true,		true,		true));
+	addEntry(LLAssetType::AT_CALLINGCARD, 		new AssetEntry("CALLINGCARD",		"callcard",	"calling card",		true,		false,		false));
+	addEntry(LLAssetType::AT_LANDMARK, 			new AssetEntry("LANDMARK",			"landmark",	"landmark",			true,		true,		true));
+	addEntry(LLAssetType::AT_SCRIPT, 			new AssetEntry("SCRIPT",			"script",	"legacy script",	true,		false,		false));
 	addEntry(LLAssetType::AT_CLOTHING, 			new AssetEntry("CLOTHING",			"clothing",	"clothing",			true,		true,		true));
 	addEntry(LLAssetType::AT_OBJECT, 			new AssetEntry("OBJECT",			"object",	"object",			true,		false,		false));
-	addEntry(LLAssetType::AT_NOTECARD, 			new AssetEntry("NOTECARD",			"notecard",	"note card",		false,		false,		true));
+	addEntry(LLAssetType::AT_NOTECARD, 			new AssetEntry("NOTECARD",			"notecard",	"note card",		true,		false,		true));
 	addEntry(LLAssetType::AT_CATEGORY, 			new AssetEntry("CATEGORY",			"category",	"folder",			true,		false,		false));
-	addEntry(LLAssetType::AT_LSL_TEXT, 			new AssetEntry("LSL_TEXT",			"lsltext",	"lsl2 script",		false,		false,		false));
-	addEntry(LLAssetType::AT_LSL_BYTECODE, 		new AssetEntry("LSL_BYTECODE",		"lslbyte",	"lsl bytecode",		false,		false,		false));
-	addEntry(LLAssetType::AT_TEXTURE_TGA, 		new AssetEntry("TEXTURE_TGA",		"txtr_tga",	"tga texture",		false,		false,		false));
+	addEntry(LLAssetType::AT_LSL_TEXT, 			new AssetEntry("LSL_TEXT",			"lsltext",	"lsl2 script",		true,		false,		false));
+	addEntry(LLAssetType::AT_LSL_BYTECODE, 		new AssetEntry("LSL_BYTECODE",		"lslbyte",	"lsl bytecode",		true,		false,		false));
+	addEntry(LLAssetType::AT_TEXTURE_TGA, 		new AssetEntry("TEXTURE_TGA",		"txtr_tga",	"tga texture",		true,		false,		false));
 	addEntry(LLAssetType::AT_BODYPART, 			new AssetEntry("BODYPART",			"bodypart",	"body part",		true,		true,		true));
-	addEntry(LLAssetType::AT_SOUND_WAV, 		new AssetEntry("SOUND_WAV",			"snd_wav",	"sound",			false,		false,		false));
-	addEntry(LLAssetType::AT_IMAGE_TGA, 		new AssetEntry("IMAGE_TGA",			"img_tga",	"targa image",		false,		false,		false));
-	addEntry(LLAssetType::AT_IMAGE_JPEG, 		new AssetEntry("IMAGE_JPEG",		"jpeg",		"jpeg image",		false,		false,		false));
-	addEntry(LLAssetType::AT_ANIMATION, 		new AssetEntry("ANIMATION",			"animatn",	"animation",		false,		true,		true));
+	addEntry(LLAssetType::AT_SOUND_WAV, 		new AssetEntry("SOUND_WAV",			"snd_wav",	"sound",			true,		false,		false));
+	addEntry(LLAssetType::AT_IMAGE_TGA, 		new AssetEntry("IMAGE_TGA",			"img_tga",	"targa image",		true,		false,		false));
+	addEntry(LLAssetType::AT_IMAGE_JPEG, 		new AssetEntry("IMAGE_JPEG",		"jpeg",		"jpeg image",		true,		false,		false));
+	addEntry(LLAssetType::AT_ANIMATION, 		new AssetEntry("ANIMATION",			"animatn",	"animation",		true,		true,		true));
 	addEntry(LLAssetType::AT_GESTURE, 			new AssetEntry("GESTURE",			"gesture",	"gesture",			true,		true,		true));
 	addEntry(LLAssetType::AT_SIMSTATE, 			new AssetEntry("SIMSTATE",			"simstate",	"simstate",			false,		false,		false));
 

File indra/llimage/llimage.cpp

 	  mCodec(codec),
 	  mDecoding(0),
 	  mDecoded(0),
-	  mDiscardLevel(0)
+	  mDiscardLevel(-1)
 {
 	mMemType = LLMemType::MTYPE_IMAGEFORMATTED;
 }

File indra/llinventory/llinventorytype.cpp

 bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type,
 									 LLAssetType::EType asset_type)
 {
+	// Links can be of any inventory type.
+	if (LLAssetType::lookupIsLinkType(asset_type))
+		return true;
+
 	const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(inventory_type);
 	if (!entry) return false;
 

File indra/llplugin/llpluginclassmedia.cpp

 		mPlugin->idle();
 	}
 	
-	if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL))
+	if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()))
 	{
 		// Can't process a size change at this time
 	}
 {
 	if(type == MOUSE_EVENT_MOVE)
 	{
+		if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
+		{
+			// Don't queue up mouse move events that can't be delivered.
+			return;
+		}
+
 		if((x == mLastMouseX) && (y == mLastMouseY))
 		{
 			// Don't spam unnecessary mouse move events.

File indra/llplugin/llpluginmessagepipe.cpp

 void LLPluginMessagePipe::processInput(void)
 {
 	// Look for input delimiter(s) in the input buffer.
-	int start = 0;
 	int delim;
-	while((delim = mInput.find(MESSAGE_DELIMITER, start)) != std::string::npos)
+	while((delim = mInput.find(MESSAGE_DELIMITER)) != std::string::npos)
 	{	
 		// Let the owner process this message
 		if (mOwner)
 		{
-			mOwner->receiveMessageRaw(mInput.substr(start, delim - start));
+			// Pull the message out of the input buffer before calling receiveMessageRaw.
+			// It's now possible for this function to get called recursively (in the case where the plugin makes a blocking request)
+			// and this guarantees that the messages will get dequeued correctly.
+			std::string message(mInput, 0, delim);
+			mInput.erase(0, delim + 1);
+			mOwner->receiveMessageRaw(message);
 		}
 		else
 		{
 			LL_WARNS("Plugin") << "!mOwner" << LL_ENDL;
 		}
-		
-		start = delim + 1;
 	}
-	
-	// Remove delivered messages from the input buffer.
-	if(start != 0)
-		mInput = mInput.substr(start);
-	
 }
 

File indra/llplugin/llpluginprocesschild.cpp

 	mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
 	mSleepTime = PLUGIN_IDLE_SECONDS;	// default: send idle messages at 100Hz
 	mCPUElapsed = 0.0f;
+	mBlockingRequest = false;
+	mBlockingResponseReceived = false;
 }
 
 LLPluginProcessChild::~LLPluginProcessChild()
 
 void LLPluginProcessChild::sleep(F64 seconds)
 {
+	deliverQueuedMessages();
 	if(mMessagePipe)
 	{
 		mMessagePipe->pump(seconds);
 
 void LLPluginProcessChild::pump(void)
 {
+	deliverQueuedMessages();
 	if(mMessagePipe)
 	{
 		mMessagePipe->pump(0.0f);
 
 	LL_DEBUGS("Plugin") << "Received from parent: " << message << LL_ENDL;
 
+	// Decode this message
+	LLPluginMessage parsed;
+	parsed.parse(message);
+
+	if(mBlockingRequest)
+	{
+		// We're blocking the plugin waiting for a response.
+
+		if(parsed.hasValue("blocking_response"))
+		{
+			// This is the message we've been waiting for -- fall through and send it immediately. 
+			mBlockingResponseReceived = true;
+		}
+		else
+		{
+			// Still waiting.  Queue this message and don't process it yet.
+			mMessageQueue.push(message);
+			return;
+		}
+	}
+	
 	bool passMessage = true;
 	
 	// FIXME: how should we handle queueing here?
 	
 	{
-		// Decode this message
-		LLPluginMessage parsed;
-		parsed.parse(message);
-		
 		std::string message_class = parsed.getClass();
 		if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
 		{
 void LLPluginProcessChild::receivePluginMessage(const std::string &message)
 {
 	LL_DEBUGS("Plugin") << "Received from plugin: " << message << LL_ENDL;
-
+	
+	if(mBlockingRequest)
+	{
+		// 
+		LL_ERRS("Plugin") << "Can't send a message while already waiting on a blocking request -- aborting!" << LL_ENDL;
+	}
+	
 	// Incoming message from the plugin instance
 	bool passMessage = true;
 
 		// Decode this message
 		LLPluginMessage parsed;
 		parsed.parse(message);
+		
+		if(parsed.hasValue("blocking_request"))
+		{
+			mBlockingRequest = true;
+		}
+
 		std::string message_class = parsed.getClass();
 		if(message_class == "base")
 		{
 		LL_DEBUGS("Plugin") << "Passing through to parent: " << message << LL_ENDL;
 		writeMessageRaw(message);
 	}
+	
+	while(mBlockingRequest)
+	{
+		// The plugin wants to block and wait for a response to this message.
+		sleep(mSleepTime);	// this will pump the message pipe and process messages
+
+		if(mBlockingResponseReceived || mSocketError != APR_SUCCESS || (mMessagePipe == NULL))
+		{
+			// Response has been received, or we've hit an error state.  Stop waiting.
+			mBlockingRequest = false;
+			mBlockingResponseReceived = false;
+		}
+	}
 }
 
 
 	LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL;
 	mState = state; 
 };
+
+void LLPluginProcessChild::deliverQueuedMessages()
+{
+	if(!mBlockingRequest)
+	{
+		while(!mMessageQueue.empty())
+		{
+			receiveMessageRaw(mMessageQueue.front());
+			mMessageQueue.pop();
+		}
+	}
+}

File indra/llplugin/llpluginprocesschild.h

 	LLTimer mHeartbeat;
 	F64		mSleepTime;
 	F64		mCPUElapsed;
+	bool	mBlockingRequest;
+	bool	mBlockingResponseReceived;
+	std::queue<std::string> mMessageQueue;
+	
+	void deliverQueuedMessages();
 	
 };
 

File indra/llplugin/llpluginprocessparent.cpp

 	mCPUUsage = 0.0;
 	mDisableTimeout = false;
 	mDebug = false;
+	mBlocked = false;
 
 	mPluginLaunchTimeout = 60.0f;
 	mPluginLockupTimeout = 15.0f;
 
 void LLPluginProcessParent::sendMessage(const LLPluginMessage &message)
 {
+	if(message.hasValue("blocking_response"))
+	{
+		mBlocked = false;
+
+		// reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked.
+		mHeartbeat.setTimerExpirySec(mPluginLockupTimeout);
+	}
 	
 	std::string buffer = message.generate();
 	LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL;	
 
 void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
 {
+	if(message.hasValue("blocking_request"))
+	{
+		mBlocked = true;
+	}
+
 	std::string message_class = message.getClass();
 	if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
 	{
 {
 	bool result = false;
 	
-	if(!mDisableTimeout && !mDebug)
+	if(!mProcess.isRunning())
 	{
-		if(!mProcess.isRunning())
-		{
-			LL_WARNS("Plugin") << "child exited" << llendl;
-			result = true;
-		}
-		else if(pluginLockedUp())
-		{
-			LL_WARNS("Plugin") << "timeout" << llendl;
-			result = true;
-		}
+		LL_WARNS("Plugin") << "child exited" << llendl;
+		result = true;
+	}
+	else if(pluginLockedUp())
+	{
+		LL_WARNS("Plugin") << "timeout" << llendl;
+		result = true;
 	}
 	
 	return result;
 
 bool LLPluginProcessParent::pluginLockedUp()
 {
+	if(mDisableTimeout || mDebug || mBlocked)
+	{
+		// Never time out a plugin process in these cases.
+		return false;
+	}
+	
 	// If the timer is running and has expired, the plugin has locked up.
 	return (mHeartbeat.getStarted() && mHeartbeat.hasExpired());
 }

File indra/llplugin/llpluginprocessparent.h

 	// returns true if the process has exited or we've had a fatal error
 	bool isDone(void);	
 	
+	// returns true if the process is currently waiting on a blocking request
+	bool isBlocked(void) { return mBlocked; };
+	
 	void killSockets(void);
 	
 	// Go to the proper error state
 	
 	bool mDisableTimeout;
 	bool mDebug;
+	bool mBlocked;
 
 	LLProcessLauncher mDebugger;
 	

File indra/llui/llspinctrl.cpp

 	return FALSE;
 }
 
+BOOL LLSpinCtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+	// just treat a double click as a second click
+	return handleMouseDown(x, y, mask);
+}

File indra/llui/llspinctrl.h

 
 	virtual BOOL	handleScrollWheel(S32 x,S32 y,S32 clicks);
 	virtual BOOL	handleKeyHere(KEY key, MASK mask);
+	virtual BOOL	handleDoubleClick(S32 x, S32 y, MASK mask);
 
 	void			onEditorCommit(const LLSD& data);
 	static void		onEditorGainFocus(LLFocusableElement* caller, void *userdata);

File indra/newview/app_settings/settings.xml

         <key>Value</key>
             <real>1.0</real>
         </map>
-    <key>RecentItemsSortOrder</key>
+  <key>MediaRollOffFactor</key>
+  <map>
+    <key>Comment</key>
+    <string>Multiplier to change rate of media attenuation</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>F32</string>
+    <key>Value</key>
+    <real>10.0</real>
+  </map>
+  <key>RecentItemsSortOrder</key>
     <map>
       <key>Comment</key>
       <string>Specifies sort key for recent inventory items (+0 = name, +1 = date, +2 = folders always by name, +4 = system folders to top)</string>

File indra/newview/llagentwearables.cpp

 		msg->nextBlockFast(_PREHASH_ObjectData );
 		msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
 		msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner());
+#if ENABLE_MULTIATTACHMENTS
+		msg->addU8Fast(_PREHASH_AttachmentPt, 0 | ATTACHMENT_ADD );
+#else
 		msg->addU8Fast(_PREHASH_AttachmentPt, 0 );	// Wear at the previous or default attachment point
+#endif
 		pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
 		msg->addStringFast(_PREHASH_Name, item->getName());
 		msg->addStringFast(_PREHASH_Description, item->getDescription());

File indra/newview/llinventorybridge.cpp

 		return FALSE;
 	}
 
-	// Disable delete from COF folder; have users explicitly choose "detach/take off".
+	// Disable delete from COF folder; have users explicitly choose "detach/take off",
+	// unless the item is not worn but in the COF (i.e. is bugged).
 	if (LLAppearanceMgr::instance().getIsProtectedCOFItem(mUUID))
 	{
-		return FALSE;
+		if (get_is_item_worn(mUUID))
+		{
+			return FALSE;
+		}
 	}
 
 	const LLInventoryObject *obj = model->getItem(mUUID);
 			}
 		}
 		const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i));
-		if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
+		if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
 		{
 			return FALSE;
 		}
 		disabled_items.push_back(std::string("Paste"));
 	}
 
-	if (gAgent.isGodlike())
-	{
-		items.push_back(std::string("Paste As Link"));
-		if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0)
-		{
-			disabled_items.push_back(std::string("Paste As Link"));
-		}
+	items.push_back(std::string("Paste As Link"));
+	if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0)
+	{
+		disabled_items.push_back(std::string("Paste As Link"));
 	}
 
 	items.push_back(std::string("Paste Separator"));
 		{
 			disabled_items.push_back(std::string("Share"));
 		}
-		items.push_back(std::string("Open"));
+		
+		addOpenRightClickMenuOption(items);
 		items.push_back(std::string("Properties"));
 
 		getClipboardEntries(true, items, disabled_items, flags);
 	const LLInventoryObject *obj = getInventoryObject();
 
 	// Don't allow delete as a direct option from COF folder.
-	if (obj && obj->getIsLinkType() && isCOFFolder())
+	if (obj && obj->getIsLinkType() && isCOFFolder() && get_is_item_worn(mUUID))
 	{
 		return;
 	}
 	}
 }
 
+void LLInvFVBridge::addOpenRightClickMenuOption(menuentry_vec_t &items)
+{
+	const LLInventoryObject *obj = getInventoryObject();
+	const BOOL is_link = (obj && obj->getIsLinkType());
+
+	if (is_link)
+		items.push_back(std::string("Open Original"));
+	else
+		items.push_back(std::string("Open"));
+}
+
 // *TODO: remove this
 BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
 {
 		gotoItem();
 	}
 
-	if ("open" == action)
+	if ("open" == action || "open_original" == action)
 	{
 		openItem();
 		return;
 			return FALSE;
 		}
 
-		if (gAgent.isGodlike())
-		{
-			// All items can be copied in god mode since you can
-			// at least paste-as-link the item, though you 
-			// still may not be able paste the item.
-			return TRUE;
-		}
-		else
-		{
-			return (item->getPermissions().allowCopyBy(gAgent.getID()));
-		}
+		// All items can be copied in god mode since you can
+		// at least paste-as-link the item, though you 
+		// still may not be able paste the item.
+		return TRUE;
+		// return (item->getPermissions().allowCopyBy(gAgent.getID()));
 	}
 	return FALSE;
 }
 
 BOOL LLFolderBridge::isItemCopyable() const
 {
-	return FALSE;
+	// Can copy folders to paste-as-link, but not for straight paste.
+	return TRUE;
 }
 
 BOOL LLFolderBridge::copyToClipboard() const
 					else
 					{
 						LLPointer<LLInventoryCallback> cb = NULL;
+						const std::string empty_description = "";
 						link_inventory_item(
 							gAgent.getID(),
 							inv_cat->getUUID(),
 							mUUID,
 							inv_cat->getName(),
+							empty_description,
 							LLAssetType::AT_LINK_FOLDER,
 							cb);
 					}
 			 ++iter)
 		{
 			const LLUUID &object_id = (*iter);
-#if SUPPORT_ENSEMBLES
 			if (LLInventoryCategory *cat = model->getCategory(object_id))
 			{
+				const std::string empty_description = "";
 				link_inventory_item(
 					gAgent.getID(),
 					cat->getUUID(),
 					parent_id,
 					cat->getName(),
+					empty_description,
 					LLAssetType::AT_LINK_FOLDER,
 					LLPointer<LLInventoryCallback>(NULL));
 			}
-			else
-#endif
-				if (LLInventoryItem *item = model->getItem(object_id))
-				{
-					link_inventory_item(
-						gAgent.getID(),
-						item->getLinkedUUID(),
-						parent_id,
-						item->getName(),
-						item->getDescription(),
-						LLAssetType::AT_LINK,
-						LLPointer<LLInventoryCallback>(NULL));
-				}
+			else if (LLInventoryItem *item = model->getItem(object_id))
+			{
+				link_inventory_item(
+					gAgent.getID(),
+					item->getLinkedUUID(),
+					parent_id,
+					item->getName(),
+					item->getDescription(),
+					LLAssetType::AT_LINK,
+					LLPointer<LLInventoryCallback>(NULL));
+			}
 		}
 	}
 }
 			disabled_items.push_back(std::string("Share"));
 		}
 
-		items.push_back(std::string("Open"));
+		addOpenRightClickMenuOption(items);
 		items.push_back(std::string("Properties"));
 
 		getClipboardEntries(true, items, disabled_items, flags);
 		{
 			disabled_items.push_back(std::string("Share"));
 		}
-		items.push_back(std::string("Open"));
+		addOpenRightClickMenuOption(items);
 		items.push_back(std::string("Properties"));
 
 		getClipboardEntries(true, items, disabled_items, flags);
 
 		if (!is_sidepanel)
 		{
-			items.push_back(std::string("Open"));
+			addOpenRightClickMenuOption(items);
 			items.push_back(std::string("Properties"));
 		}
 
 		
 		if (can_open && !is_sidepanel)
 		{
-			items.push_back(std::string("Open"));
+			addOpenRightClickMenuOption(items);
 		}
 
 		if (!is_sidepanel)
 
 // static
 void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
-								   const LLUUID& uuid,LLInventoryModel* model)
-{
-	LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
+								   const LLUUID& uuid,
+								   LLInventoryModel* model)
+{
+	// Perform indirection in case of link.
+	const LLUUID& linked_uuid = gInventory.getLinkedItemID(uuid);
+
+	LLInvFVBridgeAction* action = createAction(asset_type,linked_uuid,model);
 	if(action)
 	{
 		action->doIt();
 
 };
 
-class LLNotecardBridgeAction: public LLInvFVBridgeAction
+class LLNotecardBridgeAction
+: public LLInvFVBridgeAction
 {
 	friend class LLInvFVBridgeAction;
 public:

File indra/newview/llinventorybridge.h

 											menuentry_vec_t &disabled_items);
 	virtual void addDeleteContextMenuOptions(menuentry_vec_t &items,
 											 menuentry_vec_t &disabled_items);
-
+	virtual void addOpenRightClickMenuOption(menuentry_vec_t &items);
 protected:
 	LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid);
 

File indra/newview/llselectmgr.cpp

 		return;
 	}
 
-#if ENABLE_MULTIATTACHMENTS
-	attachment_point |= ATTACHMENT_ADD;
-#endif
 	BOOL build_mode = LLToolMgr::getInstance()->inEdit();
 	// Special case: Attach to default location for this object.
 	if (0 == attachment_point ||
 		get_if_there(gAgentAvatarp->mAttachmentPoints, (S32)attachment_point, (LLViewerJointAttachment*)NULL))
 	{
+#if ENABLE_MULTIATTACHMENTS
+		attachment_point |= ATTACHMENT_ADD;
+#endif
 		sendListToRegions(
 			"ObjectAttach",
 			packAgentIDAndSessionAndAttachment, 

File indra/newview/lltexturefetch.cpp

 	}
 
 protected:
-	LLTextureFetchWorker(LLTextureFetch* fetcher, const LLUUID& id, const LLHost& host,
-						 F32 priority, S32 discard, S32 size);
 	LLTextureFetchWorker(LLTextureFetch* fetcher, const std::string& url, const LLUUID& id, const LLHost& host,
 						 F32 priority, S32 discard, S32 size);
 
 		QUEUED = 1,
 		SENT_SIM = 2
 	};
+	enum e_write_to_cache_state //mWriteToCacheState
+	{
+		NOT_WRITE = 0,
+		CAN_WRITE = 1,
+		SHOULD_WRITE = 2
+	};
 	static const char* sStateDescs[];
 	e_state mState;
+	e_write_to_cache_state mWriteToCacheState;
 	LLTextureFetch* mFetcher;
 	LLPointer<LLImageFormatted> mFormattedImage;
 	LLPointer<LLImageRaw> mRawImage;
 										   S32 size)			// Desired size
 	: LLWorkerClass(fetcher, "TextureFetch"),
 	  mState(INIT),
+	  mWriteToCacheState(NOT_WRITE),
 	  mFetcher(fetcher),
 	  mID(id),
 	  mHost(host),
 	}
 
 	if (mState == INIT)
-	{
+	{		
 		mRawImage = NULL ;
 		mRequestedDiscard = -1;
 		mLoadedDiscard = -1;
 			mFileSize = 0;
 			mLoaded = FALSE;
 			setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
-
-			CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);
+			
 			if (mUrl.compare(0, 7, "file://") == 0)
 			{
 				// read file from local disk
 				std::string filename = mUrl.substr(7, std::string::npos);
+				CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);
 				mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority,
 																		  offset, size, responder);
 			}
 			else if (mUrl.empty())
 			{
+				CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);
 				mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority,
 																		  offset, size, responder);
 			}
 				}
 				setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
 				mState = SEND_HTTP_REQ;
-				delete responder;
-				responder = NULL;
 			}
 		}
 
 			llassert_always(mFormattedImage->getDataSize() > 0);
 			mLoadedDiscard = mDesiredDiscard;
 			mState = DECODE_IMAGE;
+			mWriteToCacheState = NOT_WRITE ;
 			LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize()
 								 << " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight())
 								 << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL;
 				if (!http_url.empty())
 				{
 					mUrl = http_url + "/?texture_id=" + mID.asString().c_str();
+					mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id.
 				}
 			}
 			else
 		{
 			mState = LLTextureFetchWorker::SEND_HTTP_REQ;
 			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
+			if(mWriteToCacheState != NOT_WRITE)
+			{
+				mWriteToCacheState = CAN_WRITE ;
+			}
 			// don't return, fall through to next state
 		}
 		else if (mSentRequest == UNSENT)
 		{
 			// Add this to the network queue and sit here.
 			// LLTextureFetch::update() will send off a request which will change our state
+			mWriteToCacheState = CAN_WRITE ;
 			mRequestedSize = mDesiredSize;
 			mRequestedDiscard = mDesiredDiscard;
 			mSentRequest = QUEUED;
 			}
 			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
 			mState = DECODE_IMAGE;
+			mWriteToCacheState = SHOULD_WRITE ;
 		}
 		else
 		{
 				mState = WAIT_HTTP_REQ;	
 
 				mFetcher->addToHTTPQueue(mID);
-				mSentRequest = QUEUED;
 				// Will call callbackHttpGet when curl request completes
 				std::vector<std::string> headers;
 				headers.push_back("Accept: image/x-j2c");
 			}
 			
 			llassert_always(mBufferSize == cur_size + mRequestedSize);
-			if (mHaveAllData)
+			if (mHaveAllData && mRequestedDiscard == 0) //the image file is fully loaded.
 			{
 				mFileSize = mBufferSize;
 			}
-			else //the file size is unknown
+			else //the file size is unknown.
 			{
-				mFileSize = S32_MAX ; //flag the file is not fully loaded.
+				mFileSize = mBufferSize + 1 ; //flag the file is not fully loaded.
 			}
-
+			
 			U8* buffer = new U8[mBufferSize];
 			if (cur_size > 0)
 			{
 			mBufferSize = 0;
 			mLoadedDiscard = mRequestedDiscard;
 			mState = DECODE_IMAGE;
+			if(mWriteToCacheState != NOT_WRITE)
+			{
+				mWriteToCacheState = SHOULD_WRITE ;
+			}
 			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
 			return false;
 		}
 
 	if (mState == WRITE_TO_CACHE)
 	{
-		if (mInLocalCache || mSentRequest == UNSENT || mFormattedImage.isNull())
+		if (mWriteToCacheState != SHOULD_WRITE || mFormattedImage.isNull())
 		{
 			// If we're in a local cache or we didn't actually receive any new data,
 			// or we failed to load anything, skip
 			return false;
 		}
 		S32 datasize = mFormattedImage->getDataSize();
+		if(mFileSize < datasize)//This could happen when http fetching and sim fetching mixed.
+		{
+			if(mHaveAllData)
+			{
+				mFileSize = datasize ;
+			}
+			else
+			{
+				mFileSize = datasize + 1 ; //flag not fully loaded.
+			}
+		}
 		llassert_always(datasize);
 		setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
 		U32 cache_priority = mWorkPriority;

File indra/newview/llviewermedia.cpp

 {
 	if(mMediaSource)
 	{
-		mMediaSource->setVolume(mRequestedVolume * LLViewerMedia::getVolume());
+		F32 attenuation_multiplier = 1.0;
+
+		if (mProximityDistance > 0)
+		{
+			// the attenuation multiplier should never be more than one since that would increase volume
+			attenuation_multiplier = llmin(1.0, gSavedSettings.getF32("MediaRollOffFactor")/mProximityDistance);
+		}
+
+		mMediaSource->setVolume(mRequestedVolume * LLViewerMedia::getVolume() * attenuation_multiplier);
 	}
 }
 
 	}
 	else
 	{
+		updateVolume();
+
 		// If we didn't just create the impl, it may need to get cookie updates.
 		if(!sUpdatedCookies.empty())
 		{

File indra/newview/llviewermessage.cpp

 
 		////////////////////////////////////////////////////////////////////////////////
 		// Special handling for various types.
-		const LLAssetType::EType asset_type = item->getType();
+		const LLAssetType::EType asset_type = item->getActualType();
 		if (check_offer_throttle(from_name, false)) // If we are throttled, don't display
 		{
 			LL_DEBUGS("Messaging") << "Highlighting inventory item: " << item->getUUID()  << LL_ENDL;

File indra/newview/skins/default/xui/en/menu_inventory.xml

          parameter="open" />
     </menu_item_call>
     <menu_item_call
+     label="Open Original"
+     layout="topleft"
+     name="Open Original">
+        <menu_item_call.on_click
+         function="Inventory.DoToSelected"
+         parameter="open_original" />
+    </menu_item_call>
+    <menu_item_call
      label="Properties"
      layout="topleft"
      name="Properties">

File indra/newview/skins/default/xui/en/panel_main_inventory.xml

  background_visible="true"
  default_tab_group="1"
  follows="all"
- height="408"
+ height="423"
  label="Things"
  layout="topleft"
  min_height="350"
    left="10"
    max_length="300"
    name="inventory search editor"
-   top="3"
+   top="18"
    width="303" />
   <tab_container
      bg_alpha_color="DkGray"

File indra/newview/skins/default/xui/it/menu_participant_list.xml

 		<menu_item_call label="Disattiva audio di questo participante" name="ModerateVoiceMuteSelected"/>
 		<menu_item_call label="Disattiva audio di tutti gli altri" name="ModerateVoiceMuteOthers"/>
 		<menu_item_call label="Riattiva audio di questo participante" name="ModerateVoiceUnMuteSelected"/>
-		<menu_item_call label="Disattiva audio di tutti gli altri" name="ModerateVoiceUnMuteOthers"/>
+		<menu_item_call label="Riattiva audio di tutti gli altri" name="ModerateVoiceUnMuteOthers"/>
 	</context_menu>
 </context_menu>

File indra/newview/skins/default/xui/it/notifications.xml

 In genere si tratta di un problema temporaneo. Attendi alcuni minuti per modificare e salvare nuovamente gli elementi indossabili.
 	</notification>
 	<notification name="YouHaveBeenLoggedOut">
-		Accidenti. Sei stato scollegato da [SECOND_LIFE]
+		Sei stato scollegato da [SECOND_LIFE].
             [MESSAGE]
 		<usetemplate name="okcancelbuttons" notext="Esci" yestext="Vedi IM &amp; Chat"/>
 	</notification>

File indra/newview/skins/default/xui/it/panel_edit_pick.xml

 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel label="Modifica scelta" name="panel_edit_pick">
+<panel label="Modifica preferito" name="panel_edit_pick">
 	<panel.string name="location_notice">
 		(si aggiornerà dopo il salvataggio)
 	</panel.string>
 	<text name="title">
-		Modifica scelta
+		Modifica preferito
 	</text>
 	<scroll_container name="profile_scroll">
 		<panel name="scroll_content_panel">

File indra/newview/skins/default/xui/it/panel_preferences_advanced.xml

 	</text>
 	<check_box label="Costruire/Modificare" name="edit_camera_movement" tool_tip="Utilizza il posizionamento automatico della fotocamera entrando o uscendo dalla modalità modifica"/>
 	<check_box label="Aspetto fisico" name="appearance_camera_movement" tool_tip="Utilizza il posizionamento automatico della camera in modalità modifica"/>
-	<check_box label="Mostra in modalità Mouselook" name="first_person_avatar_visible"/>
+	<check_box label="Visualizzami in modalità soggettiva" name="first_person_avatar_visible"/>
 	<check_box label="Le frecce di direzione mi fanno sempre spostare" name="arrow_keys_move_avatar_check"/>
 	<check_box label="Doppio click e tieni premuto per correre" name="tap_tap_hold_to_run"/>
-	<check_box label="Consente il movimento delle labbra dell&apos;avatar quando parla" name="enable_lip_sync"/>
+	<check_box label="Movimento delle labbra dell&apos;avatar quando parla" name="enable_lip_sync"/>
 	<check_box label="Chat a bolla" name="bubble_text_chat"/>
 	<slider label="Opacità" name="bubble_chat_opacity"/>
 	<color_swatch name="background" tool_tip="Scegli il colore delle vignette della chat"/>

File indra/newview/skins/default/xui/it/strings.xml

 		Alto
 	</string>
 	<string name="LeaveMouselook">
-		Premi ESC per tornare in visulizzazione normale
+		Premi ESC per tornare in visualizzazione normale
 	</string>
 	<string name="InventoryNoMatchingItems">
 		Nessun oggetto corrispondente trovato in inventario.  Prova [secondlife:///app/search/groups &quot;Cerca&quot;].
 	</string>
 	<string name="FavoritesNoMatchingItems">
-		Trascina qui un punto di riferimento per aggiungerlo ai tuoi preferiti.
+		Trascina qui un punto di riferimento per aggiungerlo ai Preferiti.
 	</string>
 	<string name="InventoryNoTexture">
 		Non hai una copia di questa texture nel tuo inventario
 		(si aggiornerà dopo la pubblicazione)
 	</string>
 	<string name="NoPicksClassifiedsText">
-		Non hai creato luoghi preferiti né inserzioni. Clicca il pulsante più qui sotto per creare un luogo preferito o un&apos;inserzione.
+		Non hai creato luoghi preferiti né inserzioni. Clicca il pulsante + qui sotto per creare un luogo preferito o un&apos;inserzione.
 	</string>
 	<string name="NoAvatarPicksClassifiedsText">
 		L&apos;utente non ha luoghi preferiti né inserzioni

File indra/newview/skins/default/xui/it/teleport_strings.xml

 			Elaborazione della destinazione in corso...
 		</message>
 		<message name="contacting">
-			Contattando la nuova regione.
+			Contatto in corso con la nuova regione.
 		</message>
 		<message name="arriving">
 			In arrivo a destinazione...