diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index 9e0a079fd9162ad76d13bc0f8fdf5ab442f27b1e..6df7111a4741ca6aaf74fe7736734d36805f7435 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -1700,7 +1700,7 @@ BOOL LLNetworkData::isValid(U16 param_type, U32 size)
     case PARAMS_EXTENDED_MESH:
         return (size == 4);
     case PARAMS_RENDER_MATERIAL:
-        return (size == 16);
+        return (size > 1);
 	}
 	
 	return FALSE;
@@ -2312,18 +2312,32 @@ LLRenderMaterialParams::LLRenderMaterialParams()
     mType = PARAMS_RENDER_MATERIAL;
 }
 
-BOOL LLRenderMaterialParams::pack(LLDataPacker &dp) const
+BOOL LLRenderMaterialParams::pack(LLDataPacker& dp) const
 {
-    return dp.packUUID(mMaterial, "material");
+    U8 count = (U8)llmin((S32)mEntries.size(), 14); //limited to 255 bytes, no more than 14 material ids
 
-//    return TRUE;
+    dp.packU8(count, "count");
+    for (auto& entry : mEntries)
+    {
+        dp.packU8(entry.te_idx, "te_idx");
+        dp.packUUID(entry.id, "id");
+    }
+
+    return TRUE;
 }
 
-BOOL LLRenderMaterialParams::unpack(LLDataPacker &dp)
+BOOL LLRenderMaterialParams::unpack(LLDataPacker& dp)
 {
-    return dp.unpackUUID(mMaterial, "material");
+    U8 count;
+    dp.unpackU8(count, "count");
+    mEntries.resize(count);
+    for (auto& entry : mEntries)
+    {
+        dp.unpackU8(entry.te_idx, "te_idx");
+        dp.unpackUUID(entry.id, "te_id");
+    }
 
-//    return TRUE;
+    return TRUE;
 }
 
 bool LLRenderMaterialParams::operator==(const LLNetworkData& data) const
@@ -2333,40 +2347,99 @@ bool LLRenderMaterialParams::operator==(const LLNetworkData& data) const
         return false;
     }
 
-    const LLRenderMaterialParams &param = static_cast<const LLRenderMaterialParams&>(data);
+    const LLRenderMaterialParams& param = static_cast<const LLRenderMaterialParams&>(data);
+
+    if (param.mEntries.size() != mEntries.size())
+    {
+        return false;
+    }
+
+    for (auto& entry : mEntries)
+    {
+        if (param.getMaterial(entry.te_idx) != entry.id)
+        {
+            return false;
+        }
+    }
 
-    return param.mMaterial == mMaterial;
+    return true;
 }
 
 void LLRenderMaterialParams::copy(const LLNetworkData& data)
 {
     llassert_always(data.mType == PARAMS_RENDER_MATERIAL);
-    const LLRenderMaterialParams &param = static_cast<const LLRenderMaterialParams&>(data);
-    mMaterial = param.mMaterial;
+    const LLRenderMaterialParams& param = static_cast<const LLRenderMaterialParams&>(data);
+    mEntries = param.mEntries;
 }
 
 LLSD LLRenderMaterialParams::asLLSD() const
 {
-    return llsd::map("material", mMaterial);
+    LLSD ret;
+
+    for (int i = 0; i < mEntries.size(); ++i)
+    {
+        ret[i]["te_idx"] = mEntries[i].te_idx;
+        ret[i]["id"] = mEntries[i].id;
+    }
+
+    return ret;
 }
 
 bool LLRenderMaterialParams::fromLLSD(LLSD& sd)
 {
-    if (sd.has("material"))
+    if (sd.isArray())
     {
-        setMaterial(sd["material"]);
+        mEntries.resize(sd.size());
+        for (int i = 0; i < sd.size(); ++i)
+        {
+            if (sd[i].has("te_idx") && sd.has("id"))
+            {
+                mEntries[i].te_idx = sd[i]["te_idx"].asInteger();
+                mEntries[i].id = sd[i]["id"].asUUID();
+            }
+            else
+            {
+                return false;
+            }
+        }
+
         return true;
     }
 
     return false;
 }
 
-void LLRenderMaterialParams::setMaterial(const LLUUID & id)
+void LLRenderMaterialParams::setMaterial(U8 te, const LLUUID& id)
 {
-    mMaterial = id;
+    for (int i = 0; i < mEntries.size(); ++i)
+    {
+        if (mEntries[i].te_idx == te)
+        {
+            if (id.isNull())
+            {
+                mEntries.erase(mEntries.begin() + i);
+            }
+            else
+            {
+                mEntries[i].id = id;
+            }
+            return;
+        }
+    }
+
+    mEntries.push_back({ te, id });
 }
 
-LLUUID LLRenderMaterialParams::getMaterial() const
+LLUUID LLRenderMaterialParams::getMaterial(U8 te) const
 {
-    return mMaterial;
+    for (int i = 0; i < mEntries.size(); ++i)
+    {
+        if (mEntries[i].te_idx == te)
+        {
+            return mEntries[i].id;
+        }
+    }
+
+    return LLUUID::null;
 }
+
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index 25196fb894abbf9ff36e8f1a7e266e1fb9b922be..1c290185b0fae90f8179eaac9ee5a92084cc7b39 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -369,22 +369,30 @@ class LLExtendedMeshParams : public LLNetworkData
 class LLRenderMaterialParams : public LLNetworkData
 {
 private:
-    LLUUID mMaterial;
+    struct Entry
+    {
+        U8 te_idx;
+        LLUUID id;
+    };
+    std::vector< Entry > mEntries;
 
 public:
     LLRenderMaterialParams();
-    BOOL pack(LLDataPacker &dp) const override;
-    BOOL unpack(LLDataPacker &dp) override;
+    BOOL pack(LLDataPacker& dp) const override;
+    BOOL unpack(LLDataPacker& dp) override;
     bool operator==(const LLNetworkData& data) const override;
     void copy(const LLNetworkData& data) override;
     LLSD asLLSD() const;
     operator LLSD() const { return asLLSD(); }
     bool fromLLSD(LLSD& sd);
 
-    void setMaterial(const LLUUID & id);
-    LLUUID getMaterial() const;
+    void setMaterial(U8 te_idx, const LLUUID& id);
+    LLUUID getMaterial(U8 te_idx) const;
+
+    bool isEmpty() { return mEntries.empty(); }
 };
 
+
 // This code is not naming-standards compliant. Leaving it like this for
 // now to make the connection to code in
 // 	BOOL packTEMessage(LLDataPacker &dp) const;
@@ -480,12 +488,12 @@ class LLPrimitive : public LLXform
 	virtual S32 setTEMediaFlags(const U8 te, const U8 flags);
 	virtual S32 setTEGlow(const U8 te, const F32 glow);
 	virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
-	virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams);
+    virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams);
 	virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed
 	virtual void setTESelected(const U8 te, bool sel);
 
 	LLMaterialPtr getTEMaterialParams(const U8 index);
-
+    
 	void copyTEs(const LLPrimitive *primitive);
 	S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const;
 	BOOL packTEMessage(LLMessageSystem *mesgsys) const;
@@ -563,6 +571,8 @@ class LLPrimitive : public LLXform
 	static LLPCode legacyToPCode(const U8 legacy);
 	static U8 pCodeToLegacy(const LLPCode pcode);
 	static bool getTESTAxes(const U8 face, U32* s_axis, U32* t_axis);
+
+    BOOL hasRenderMaterialParams() const;
 	
 	inline static BOOL isPrimitive(const LLPCode pcode);
 	inline static BOOL isApp(const LLPCode pcode);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 2bb2c9676b596aa63329bcfed8b21546fcbb9045..d325831c8faade11247ad53cbc795765806e39a4 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -4403,6 +4403,7 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
 		case DAD_GESTURE:
 		case DAD_MESH:
         case DAD_SETTINGS:
+        case DAD_MATERIAL:
 			accept = dragItemIntoFolder(inv_item, drop, tooltip_msg);
 			break;
 		case DAD_LINK:
@@ -6032,6 +6033,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
 			case DAD_GESTURE:
 			case DAD_MESH:
             case DAD_SETTINGS:
+            case DAD_MATERIAL:
 			{
 				LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
 				const LLPermissions& perm = inv_item->getPermissions();
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp
index ab32ea39563fa217c87375c739f27ed27711c3ba..82f880c9ee8ed9f8958b29699ae7faf3d54876b5 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -156,6 +156,7 @@ BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 		case DAD_CALLINGCARD:
 		case DAD_MESH:
         case DAD_SETTINGS:
+        case DAD_MATERIAL:
 		{
 			LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
 			if(gInventory.getItem(inv_item->getUUID())
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index defd7025b8dc8ba49174403af429e2bf43162175..998cffef4a7fc655f0717d0561fff241e44445cd 100644
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -704,6 +704,7 @@ BOOL LLTaskCategoryBridge::dragOrDrop(MASK mask, BOOL drop,
 		case DAD_CALLINGCARD:
 		case DAD_MESH:
         case DAD_SETTINGS:
+        case DAD_MATERIAL:
 			accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data);
 			if(accept && drop)
 			{
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 50868d0fa5aaa29b6501fff756fb3d8a14b83b4c..a4b34bb5b660f00319521917d93a31f11e2d1eb3 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -256,7 +256,8 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary()
 	//      										|-------------------------------|----------------------------------------------|-----------------------------------------------|---------------------------------------------------|--------------------------------|
 	addEntry(DAD_NONE, 			new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,	&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dNULL,						&LLToolDragAndDrop::dad3dNULL));
 	addEntry(DAD_TEXTURE, 		new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,	&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dGiveInventory,			&LLToolDragAndDrop::dad3dTextureObject,				&LLToolDragAndDrop::dad3dNULL));
-	addEntry(DAD_SOUND, 		new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,	&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dGiveInventory,			&LLToolDragAndDrop::dad3dUpdateInventory,			&LLToolDragAndDrop::dad3dNULL));
+    addEntry(DAD_MATERIAL,      new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL,                  &LLToolDragAndDrop::dad3dGiveInventory,         &LLToolDragAndDrop::dad3dMaterialObject,            &LLToolDragAndDrop::dad3dNULL));
+    addEntry(DAD_SOUND, 		new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,	&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dGiveInventory,			&LLToolDragAndDrop::dad3dUpdateInventory,			&LLToolDragAndDrop::dad3dNULL));
 	addEntry(DAD_CALLINGCARD, 	new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,	&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dGiveInventory, 		&LLToolDragAndDrop::dad3dUpdateInventory, 			&LLToolDragAndDrop::dad3dNULL));
 	addEntry(DAD_LANDMARK, 		new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, 					&LLToolDragAndDrop::dad3dGiveInventory, 		&LLToolDragAndDrop::dad3dUpdateInventory, 			&LLToolDragAndDrop::dad3dNULL));
 	addEntry(DAD_SCRIPT, 		new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, 					&LLToolDragAndDrop::dad3dGiveInventory, 		&LLToolDragAndDrop::dad3dRezScript, 				&LLToolDragAndDrop::dad3dNULL));
@@ -271,6 +272,7 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary()
 	addEntry(DAD_LINK, 			new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,	&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dNULL,						&LLToolDragAndDrop::dad3dNULL));
 	addEntry(DAD_MESH, 			new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,	&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dGiveInventory,			&LLToolDragAndDrop::dad3dMeshObject,				&LLToolDragAndDrop::dad3dNULL));
     addEntry(DAD_SETTINGS,      new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL,                  &LLToolDragAndDrop::dad3dGiveInventory,         &LLToolDragAndDrop::dad3dUpdateInventory,           &LLToolDragAndDrop::dad3dNULL));
+    
     // TODO: animation on self could play it?  edit it?
 	// TODO: gesture on self could play it?  edit it?
 };
@@ -1062,6 +1064,66 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj,
 	hit_obj->sendTEUpdate();
 }
 
+
+void LLToolDragAndDrop::dropMaterialOneFace(LLViewerObject* hit_obj,
+    S32 hit_face,
+    LLInventoryItem* item,
+    LLToolDragAndDrop::ESource source,
+    const LLUUID& src_id)
+{
+    if (hit_face == -1) return;
+    if (!item || item->getInventoryType() != LLInventoryType::IT_MATERIAL)
+    {
+        LL_WARNS() << "LLToolDragAndDrop::dropTextureOneFace no material item." << LL_ENDL;
+        return;
+    }
+    LLUUID asset_id = item->getAssetUUID();
+    BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
+    if (!success)
+    {
+        return;
+    }
+    
+    LLTextureEntry* tep = hit_obj ? (hit_obj->getTE(hit_face)) : NULL;
+
+    hit_obj->setRenderMaterialID(hit_face, asset_id);
+
+    dialog_refresh_all();
+
+    // send the update to the simulator
+    hit_obj->sendTEUpdate();
+}
+
+
+void LLToolDragAndDrop::dropMaterialAllFaces(LLViewerObject* hit_obj,
+    LLInventoryItem* item,
+    LLToolDragAndDrop::ESource source,
+    const LLUUID& src_id)
+{
+    if (!item || item->getInventoryType() != LLInventoryType::IT_MATERIAL)
+    {
+        LL_WARNS() << "LLToolDragAndDrop::dropTextureAllFaces no material item." << LL_ENDL;
+        return;
+    }
+    LLUUID asset_id = item->getAssetUUID();
+    BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
+    if (!success)
+    {
+        return;
+    }
+    
+    S32 num_faces = hit_obj->getNumTEs();
+    for (S32 face = 0; face < num_faces; face++)
+    {
+        // update viewer side material in anticipation of update from simulator
+        hit_obj->setRenderMaterialID(face, asset_id);
+        dialog_refresh_all();
+    }
+    // send the update to the simulator
+    hit_obj->sendTEUpdate();
+}
+
+
 void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj,
 								 LLInventoryItem* item,
 								 LLToolDragAndDrop::ESource source,
@@ -1628,6 +1690,7 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_
 	case DAD_MESH:
 	case DAD_CATEGORY:
     case DAD_SETTINGS:
+    case DAD_MATERIAL:
 	{
 		LLInventoryObject* inv_obj = (LLInventoryObject*)cargo_data;
 		if(gInventory.getCategory(inv_obj->getUUID()) || (gInventory.getItem(inv_obj->getUUID())
@@ -1982,6 +2045,17 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject(
 				dropTextureOneFace(obj, face, item, mSource, mSourceID);
 			}
 		}
+        else if (cargo_type == DAD_MATERIAL)
+        {
+            if ((mask & MASK_SHIFT))
+            {
+                dropMaterialAllFaces(obj, item, mSource, mSourceID);
+            }
+            else
+            {
+                dropMaterialOneFace(obj, face, item, mSource, mSourceID);
+            }
+        }
 		else if (cargo_type == DAD_MESH)
 		{
 			dropMesh(obj, item, mSource, mSourceID);
@@ -2010,6 +2084,12 @@ EAcceptance LLToolDragAndDrop::dad3dTextureObject(
 	return dad3dApplyToObject(obj, face, mask, drop, DAD_TEXTURE);
 }
 
+EAcceptance LLToolDragAndDrop::dad3dMaterialObject(
+    LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
+{
+    return dad3dApplyToObject(obj, face, mask, drop, DAD_MATERIAL);
+}
+
 EAcceptance LLToolDragAndDrop::dad3dMeshObject(
 	LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
 {
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index 24a712029c9e30ed735f8e75335be0382a3a434e..2f6423080e0ace0bf8a6ad9cdbecf0cf632b586b 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -168,6 +168,8 @@ class LLToolDragAndDrop : public LLTool, public LLSingleton<LLToolDragAndDrop>
 							   MASK mask, BOOL drop);
 	EAcceptance dad3dTextureObject(LLViewerObject* obj, S32 face,
 								   MASK mask, BOOL drop);
+    EAcceptance dad3dMaterialObject(LLViewerObject* obj, S32 face,
+        MASK mask, BOOL drop);
 	EAcceptance dad3dMeshObject(LLViewerObject* obj, S32 face,
 								   MASK mask, BOOL drop);
 //	EAcceptance dad3dTextureSelf(LLViewerObject* obj, S32 face,
@@ -249,6 +251,14 @@ class LLToolDragAndDrop : public LLTool, public LLSingleton<LLToolDragAndDrop>
 									LLInventoryItem* item,
 									ESource source,
 									const LLUUID& src_id);
+    static void dropMaterialOneFace(LLViewerObject* hit_obj, S32 hit_face,
+                                    LLInventoryItem* item,
+                                    ESource source,
+                                    const LLUUID& src_id);
+    static void dropMaterialAllFaces(LLViewerObject* hit_obj,
+                                    LLInventoryItem* item,
+                                    ESource source,
+                                    const LLUUID& src_id);
 	static void dropMesh(LLViewerObject* hit_obj,
 						 LLInventoryItem* item,
 						 ESource source,
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 16479e02a276a083fc75560baf2dccd119bc6eb6..232e51896eb7e131089abdbfe1bd77bc1eb3b66b 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -6991,6 +6991,61 @@ LLVOAvatar* LLViewerObject::getAvatar() const
 	return NULL;
 }
 
+bool LLViewerObject::hasRenderMaterialParams() const
+{
+    return getParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL);
+}
+
+void LLViewerObject::setHasRenderMaterialParams(bool has_materials)
+{
+    bool had_materials = hasRenderMaterialParams();
+
+    if (had_materials != has_materials)
+    {
+        if (has_materials)
+        {
+            setParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL, TRUE, true);
+        }
+        else
+        {
+            setParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL, FALSE, true);
+        }
+    }
+}
+
+const LLUUID& LLViewerObject::getRenderMaterialID(U8 te) const
+{
+    LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
+    if (param_block)
+    {
+        return param_block->getMaterial(te);
+    }
+
+    return LLUUID::null;
+}
+
+void LLViewerObject::setRenderMaterialID(U8 te, const LLUUID& id)
+{
+    if (id.notNull())
+    {
+        setHasRenderMaterialParams(true);
+    }
+
+    LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
+    if (param_block)
+    {
+        param_block->setMaterial(te, id);
+
+        if (param_block->isEmpty())
+        { // might be empty if id is null
+            setHasRenderMaterialParams(false);
+        }
+        else
+        {
+            parameterChanged(LLNetworkData::PARAMS_RENDER_MATERIAL, true);
+        }
+    }
+}
 
 class ObjectPhysicsProperties : public LLHTTPNode
 {
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 5136a7e5ee741623dcba250e9ad313f5c878fc02..1392caa85505287fea730da3fbed19bbe0b51f6a 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -179,6 +179,13 @@ class LLViewerObject
 	const std::string& getAttachmentItemName() const;
 
 	virtual LLVOAvatar* getAvatar() const;  //get the avatar this object is attached to, or NULL if object is not an attachment
+    
+    bool hasRenderMaterialParams() const;
+    void setHasRenderMaterialParams(bool has_params);
+
+    const LLUUID& getRenderMaterialID(U8 te) const;
+    void setRenderMaterialID(U8 te, const LLUUID& id);
+
 	virtual BOOL	isHUDAttachment() const { return FALSE; }
 	virtual BOOL	isTempAttachment() const;
 
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index e2de7ac825e7e5f76b2e4f1bf7097b7438a3f621..7c860936a52e18b21d8870ada0c572a75ae0f97c 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -879,6 +879,7 @@ BOOL LLViewerTextEditor::handleDragAndDrop(S32 x, S32 y, MASK mask,
 			case DAD_ANIMATION:
 			case DAD_GESTURE:
 			case DAD_MESH:
+            case DAD_MATERIAL:
 			{
 				supported = true;
 				break;
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 0706e26fb181ab47e1491f8240a0f08a5df69f5a..f220547499cc99b53fbef0af2a9d2088b7c8d3b4 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -2162,6 +2162,7 @@ void LLVOVolume::setNumTEs(const U8 num_tes)
 	return ;
 }
 
+
 //virtual
 void LLVOVolume::changeTEImage(S32 index, LLViewerTexture* imagep)
 {
@@ -3501,6 +3502,11 @@ F32 LLVOVolume::getLightCutoff() const
 	}
 }
 
+BOOL LLVOVolume::isReflectionProbe() const
+{
+    return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE);
+}
+
 void LLVOVolume::setIsReflectionProbe(BOOL is_probe)
 {
     BOOL was_probe = isReflectionProbe();
@@ -3571,25 +3577,6 @@ void LLVOVolume::setReflectionProbeIsDynamic(bool is_dynamic)
     }
 }
 
-
-BOOL LLVOVolume::isReflectionProbe() const
-{
-    // HACK - make this object a Reflection Probe if a certain UUID is detected
-    static LLCachedControl<std::string> reflection_probe_id(gSavedSettings, "RenderReflectionProbeTextureHackID", "");
-    LLUUID probe_id(reflection_probe_id);
-
-    for (U8 i = 0; i < getNumTEs(); ++i)
-    {
-        if (getTE(i)->getID() == probe_id)
-        {
-            return true;
-        }
-    }
-    // END HACK
-
-    return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE);
-}
-
 F32 LLVOVolume::getReflectionProbeAmbiance() const
 {
     const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index f0a4fd427e9f163e8fcb87a2310b9cedebe4df64..79049851b48252240fee9d7b19ef6d54a3af1378 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -284,7 +284,7 @@ class LLVOVolume : public LLViewerObject
 	F32 getLightRadius() const;
 	F32 getLightFalloff(const F32 fudge_factor = 1.f) const;
 	F32 getLightCutoff() const;
-	
+
     // Reflection Probes
     void setIsReflectionProbe(BOOL is_probe);
     void setReflectionProbeAmbiance(F32 ambiance);