diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index 33675bd261e15348b1aae04c5e05d7334cc0b4ad..f409db99429ee8347b4692e4fa251dd740c480fa 100755
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -321,10 +321,16 @@ void LLDrawPoolTerrain::renderFullShader()
 	// Hack! Get the region that this draw pool is rendering from!
 	LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
 	LLVLComposition *compp = regionp->getComposition();
-	LLViewerTexture *detail_texture0p = compp->mDetailTextures[0];
-	LLViewerTexture *detail_texture1p = compp->mDetailTextures[1];
-	LLViewerTexture *detail_texture2p = compp->mDetailTextures[2];
-	LLViewerTexture *detail_texture3p = compp->mDetailTextures[3];
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+	LLViewerTexture *detail_texture0p = (LLPipeline::sRenderTextures) ? compp->mDetailTextures[0] : LLViewerFetchedTexture::sDefaultDiffuseImagep;
+	LLViewerTexture *detail_texture1p = (LLPipeline::sRenderTextures) ? compp->mDetailTextures[1] : LLViewerFetchedTexture::sDefaultDiffuseImagep;
+	LLViewerTexture *detail_texture2p = (LLPipeline::sRenderTextures) ? compp->mDetailTextures[2] : LLViewerFetchedTexture::sDefaultDiffuseImagep;
+	LLViewerTexture *detail_texture3p = (LLPipeline::sRenderTextures) ? compp->mDetailTextures[3] : LLViewerFetchedTexture::sDefaultDiffuseImagep;
+// [/SL:KB]
+//	LLViewerTexture *detail_texture0p = compp->mDetailTextures[0];
+//	LLViewerTexture *detail_texture1p = compp->mDetailTextures[1];
+//	LLViewerTexture *detail_texture2p = compp->mDetailTextures[2];
+//	LLViewerTexture *detail_texture3p = compp->mDetailTextures[3];
 
 	LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal();
 	F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale;
@@ -472,10 +478,16 @@ void LLDrawPoolTerrain::renderFull4TU()
 	// Hack! Get the region that this draw pool is rendering from!
 	LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
 	LLVLComposition *compp = regionp->getComposition();
-	LLViewerTexture *detail_texture0p = compp->mDetailTextures[0];
-	LLViewerTexture *detail_texture1p = compp->mDetailTextures[1];
-	LLViewerTexture *detail_texture2p = compp->mDetailTextures[2];
-	LLViewerTexture *detail_texture3p = compp->mDetailTextures[3];
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+	LLViewerTexture *detail_texture0p = (LLPipeline::sRenderTextures) ? compp->mDetailTextures[0] : LLViewerFetchedTexture::sDefaultDiffuseImagep;
+	LLViewerTexture *detail_texture1p = (LLPipeline::sRenderTextures) ? compp->mDetailTextures[1] : LLViewerFetchedTexture::sDefaultDiffuseImagep;
+	LLViewerTexture *detail_texture2p = (LLPipeline::sRenderTextures) ? compp->mDetailTextures[2] : LLViewerFetchedTexture::sDefaultDiffuseImagep;
+	LLViewerTexture *detail_texture3p = (LLPipeline::sRenderTextures) ? compp->mDetailTextures[3] : LLViewerFetchedTexture::sDefaultDiffuseImagep;
+// [/SL:KB]
+//	LLViewerTexture *detail_texture0p = compp->mDetailTextures[0];
+//	LLViewerTexture *detail_texture1p = compp->mDetailTextures[1];
+//	LLViewerTexture *detail_texture2p = compp->mDetailTextures[2];
+//	LLViewerTexture *detail_texture3p = compp->mDetailTextures[3];
 
 	LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal();
 	F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale;
@@ -674,10 +686,16 @@ void LLDrawPoolTerrain::renderFull2TU()
 	// Hack! Get the region that this draw pool is rendering from!
 	LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
 	LLVLComposition *compp = regionp->getComposition();
-	LLViewerTexture *detail_texture0p = compp->mDetailTextures[0];
-	LLViewerTexture *detail_texture1p = compp->mDetailTextures[1];
-	LLViewerTexture *detail_texture2p = compp->mDetailTextures[2];
-	LLViewerTexture *detail_texture3p = compp->mDetailTextures[3];
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+	LLViewerTexture *detail_texture0p = (LLPipeline::sRenderTextures) ? compp->mDetailTextures[0] : LLViewerFetchedTexture::sDefaultDiffuseImagep;
+	LLViewerTexture *detail_texture1p = (LLPipeline::sRenderTextures) ? compp->mDetailTextures[1] : LLViewerFetchedTexture::sDefaultDiffuseImagep;
+	LLViewerTexture *detail_texture2p = (LLPipeline::sRenderTextures) ? compp->mDetailTextures[2] : LLViewerFetchedTexture::sDefaultDiffuseImagep;
+	LLViewerTexture *detail_texture3p = (LLPipeline::sRenderTextures) ? compp->mDetailTextures[3] : LLViewerFetchedTexture::sDefaultDiffuseImagep;
+// [/SL:KB]
+//	LLViewerTexture *detail_texture0p = compp->mDetailTextures[0];
+//	LLViewerTexture *detail_texture1p = compp->mDetailTextures[1];
+//	LLViewerTexture *detail_texture2p = compp->mDetailTextures[2];
+//	LLViewerTexture *detail_texture3p = compp->mDetailTextures[3];
 
 	LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal();
 	F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale;
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index b1f40781f73e5bcdccd50ac111e41d928b8492cc..ecba1dc75db63f0df70b8933f7345010058aa050 100755
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -98,7 +98,10 @@ void LLDrawPoolTree::render(S32 pass)
 	LLGLState test(GL_ALPHA_TEST, LLGLSLShader::sNoFixedFunction ? 0 : 1);
 	LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f);
 
-	gGL.getTexUnit(sDiffTex)->bind(mTexturep);
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+	gGL.getTexUnit(sDiffTex)->bind( (LLPipeline::sRenderTextures) ? mTexturep : LLViewerFetchedTexture::sDefaultDiffuseImagep );
+// [/SL:KB]
+//	gGL.getTexUnit(sDiffTex)->bind(mTexturep);
 				
 	for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
 		 iter != mDrawFace.end(); iter++)
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index de349a03d4cafe9878c5e53bbae42b2335995c00..85d5a30e1ed8bfbc1c0f305af917154b63175e60 100755
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -53,6 +53,9 @@
 #include "llviewershadermgr.h"
 #include "llviewertexture.h"
 #include "llvoavatar.h"
+// [RLVa:KB] - Checked: RLVa-2.0.0
+#include "rlvhandler.h"
+// [/RLVa:KB]
 
 #if LL_LINUX
 // Work-around spurious used before init warning on Vector4a
@@ -166,6 +169,10 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
 	mBoundingSphereRadius = 0.0f ;
 
 	mHasMedia = FALSE ;
+
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+	mShowDiffTexture = true;
+// [/SL:KB]
 }
 
 void LLFace::destroy()
@@ -282,6 +289,14 @@ void LLFace::setTexture(U32 ch, LLViewerTexture* tex)
 		return ;
 	}
 
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+	if ( (LLRender::DIFFUSE_MAP == ch) && (!mShowDiffTexture) )
+	{
+		mOrigDiffTexture = tex;
+		return;
+	}
+// [/SL:KB]
+
 	if(mTexture[ch].notNull())
 	{
 		mTexture[ch]->removeFace(ch, this) ;
@@ -2644,9 +2659,60 @@ LLViewerTexture* LLFace::getTexture(U32 ch) const
 {
 	llassert(ch < LLRender::NUM_TEXTURE_CHANNELS);
 
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+	// Check whether the diffuse texture needs to be obscured or restored
+	if (mShowDiffTexture != LLPipeline::sRenderTextures)
+		setDefaultTexture(LLRender::DIFFUSE_MAP, !LLPipeline::sRenderTextures);
+// [/SL:KB]
+
 	return mTexture[ch] ;
 }
 
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+void LLFace::setDefaultTexture(U32 nChannel, bool fShowDefault) const
+{
+	bool fUpdated = false;
+	if ( (LLRender::DIFFUSE_MAP == nChannel) && (mVObjp) && (!mVObjp->isDead()) && ((LL_PCODE_VOLUME == mVObjp->getPCode()) || (LLViewerObject::LL_VO_PART_GROUP == mVObjp->getPCode())) )
+	{
+		if ( ((mShowDiffTexture) && (fShowDefault)) ||
+		     ((!mShowDiffTexture) && (fShowDefault) && (mOrigDiffTexture.notNull()) && (mTexture[nChannel]) && (mTexture[nChannel]->getID() != LLViewerFetchedTexture::sDefaultDiffuseImagep->getID())) )
+		{
+			if (mOrigDiffTexture.notNull())
+				mShowDiffTexture = true;				// Swap out the default texture
+			else
+				mOrigDiffTexture = mTexture[nChannel];	// Cache the original texture
+
+			if ( (!gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_TEXTURES)) || (!mVObjp->isAttachment()) )
+			{
+				if (LL_PCODE_VOLUME == mVObjp->getPCode())
+					const_cast<LLFace*>(this)->switchTexture(nChannel, LLViewerFetchedTexture::sDefaultDiffuseImagep);
+				else
+					const_cast<LLFace*>(this)->setTexture(nChannel, LLViewerFetchedTexture::sDefaultDiffuseImagep);
+			}
+			mShowDiffTexture = false; fUpdated = true;
+		}
+		else if ( (!mShowDiffTexture) && (!fShowDefault) && (mOrigDiffTexture.notNull()) )
+		{
+			mShowDiffTexture = true;
+			if (LL_PCODE_VOLUME == mVObjp->getPCode())
+				const_cast<LLFace*>(this)->switchTexture(nChannel, mOrigDiffTexture);
+			else
+				const_cast<LLFace*>(this)->setTexture(nChannel, mOrigDiffTexture);
+			mOrigDiffTexture = nullptr; fUpdated = true;
+		}
+
+		if ((fUpdated) && (mDrawablep))
+		{
+			gPipeline.markTextured(mDrawablep);
+			const_cast<LLDrawable*>(mDrawablep.get())->updateTexture();
+		}
+	}
+
+	// Always flip the flag even if we didn't obscure so we don't keep wasting cycles with negative checks
+	mShowDiffTexture = !fShowDefault;
+}
+// [/SL:KB]
+
 void LLFace::setVertexBuffer(LLVertexBuffer* buffer)
 {
 	mVertexBuffer = buffer;
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index ee545acb94104c53bde604d81844acab02e1000f..35cfdc1f8b66f8301f97eecbf965c60acadb1362 100755
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -220,6 +220,10 @@ public:
 
 	BOOL		switchTexture() ;
 
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+	void		setDefaultTexture(U32 nChannel, bool fShowDefault) const;
+// [/SL:KB]
+
 	//vertex buffer tracking
 	void setVertexBuffer(LLVertexBuffer* buffer);
 	void clearVertexBuffer(); //sets mVertexBuffer to NULL
@@ -294,7 +298,11 @@ private:
 	F32         mBoundingSphereRadius ;
 	bool        mHasMedia ;
 
-	
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+	mutable bool                       mShowDiffTexture;
+	mutable LLPointer<LLViewerTexture> mOrigDiffTexture;
+// [/SL:KB]
+
 protected:
 	static BOOL	sSafeRenderSelect;
 	
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 61e918215c1214d69fe1301774ceb0247484453f..543df6c48f07ef68855036cd91729b07a0c89a18 100755
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -719,6 +719,29 @@ void LLViewerObjectList::dirtyAllObjectInventory()
 	}
 }
 
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+void LLViewerObjectList::setAllObjectDefaultTextures(U32 nChannel, bool fShowDefault)
+{
+	LLPipeline::sRenderTextures = !fShowDefault;
+
+	for (LLViewerObject* pObj : mObjects)
+	{
+		LLDrawable* pDrawable = pObj->mDrawable;
+		if ( (pDrawable) && (!pDrawable->isDead()) )
+		{
+			for (int idxFace = 0, cntFace = pDrawable->getNumFaces(); idxFace < cntFace; idxFace++)
+			{
+				if (LLFace* pFace = pDrawable->getFace(idxFace))
+					pFace->setDefaultTexture(nChannel, fShowDefault);
+			}
+
+			if (LLVOVolume* pVoVolume = pDrawable->getVOVolume())
+				pVoVolume->markForUpdate(true);
+		}
+	}
+}
+// [/SL:KB]
+
 void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
 {
 	S32 i;
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index 594317cd9ff2b83829895470fe4b6789b0565b16..568dce0473305c69385af314cf51e43380e68487 100755
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -121,6 +121,9 @@ public:
 	void resetObjectBeacons();
 
 	void dirtyAllObjectInventory();
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+	void setAllObjectDefaultTextures(U32 nChannel, bool fShowDefault);
+// [/SL:KB]
 
 	void removeFromActiveList(LLViewerObject* objectp);
 	void updateActive(LLViewerObject *objectp);
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index e2b8ff8e80152b15365c349595c94f60628500cc..8d73aee63ab394b4332909cce49bbefd58f043b5 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -76,6 +76,9 @@ LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sWhiteImagep = NULL;
 LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL;
 LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sSmokeImagep = NULL;
 LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sFlatNormalImagep = NULL;
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultDiffuseImagep = NULL;
+// [/SL:KB]
 LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap;
 LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL;
 const std::string sTesterName("TextureTester");
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index cedac44633ba95af5739358ad03dce2863dd332d..6ed3bfc9c73bcc9ef191fc43be2bd0fac39dd350 100755
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -521,6 +521,9 @@ public:
 	static LLPointer<LLViewerFetchedTexture> sDefaultImagep; // "Default" texture for error cases, the only case of fetched texture which is generated in local.
 	static LLPointer<LLViewerFetchedTexture> sSmokeImagep; // Old "Default" translucent texture
 	static LLPointer<LLViewerFetchedTexture> sFlatNormalImagep; // Flat normal map denoting no bumpiness on a surface
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+	static LLPointer<LLViewerFetchedTexture> sDefaultDiffuseImagep;
+// [/SL:KB]
 };
 
 //
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 586c803ce58bcbef2d7a458f3ec6c703e50b6e7a..72b75318ddd651b1746e917b4e18244d74f849ea 100755
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -402,6 +402,9 @@ BOOL    LLPipeline::sMemAllocationThrottled = FALSE;
 S32		LLPipeline::sVisibleLightCount = 0;
 F32		LLPipeline::sMinRenderSize = 0.f;
 BOOL	LLPipeline::sRenderingHUDs;
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+bool	LLPipeline::sRenderTextures = true;
+// [/SL:KB]
 
 // EventHost API LLPipeline listener.
 static LLPipelineListener sPipelineListener;
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 97e11a151f2c91dace88b0f1b169d62db769d9ae..4fa1ad15d0afe4e26a5c6b781cdf44e827f1e3f3 100755
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -587,6 +587,9 @@ public:
 	static S32				sVisibleLightCount;
 	static F32				sMinRenderSize;
 	static BOOL				sRenderingHUDs;
+// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
+	static bool				sRenderTextures;
+// [/SL:KB]
 
 	static LLTrace::EventStatHandle<S64> sStatBatchSize;
 
diff --git a/indra/newview/rlvcommon.h b/indra/newview/rlvcommon.h
index 4dde21887db96fc8a34c7cca412eeedf34df9b5c..56aed0d64a66b86176df58cb2c51c95adc71f7fd 100644
--- a/indra/newview/rlvcommon.h
+++ b/indra/newview/rlvcommon.h
@@ -56,7 +56,7 @@ class RlvObject;
 
 struct RlvException;
 typedef boost::variant<std::string, LLUUID, S32, ERlvBehaviour> RlvExceptionOption;
-typedef boost::variant<int, float, LLVector3> RlvBehaviourModifierValue;
+typedef boost::variant<int, float, LLVector3, LLUUID> RlvBehaviourModifierValue;
 
 class RlvGCTimer;
 
diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h
index 847b86d743c67ea2666f6f5023b1ea62cf74f4b8..db6c9845864b801a7b8ebc4f270ba255bb80ae7e 100644
--- a/indra/newview/rlvdefines.h
+++ b/indra/newview/rlvdefines.h
@@ -200,6 +200,7 @@ enum ERlvBehaviour {
 	RLV_BHVR_SETCAM_FOV,			// Changes the current (vertical) field of view
 	RLV_BHVR_SETCAM_FOVMIN,			// Enforces a minimum (vertical) FOV
 	RLV_BHVR_SETCAM_FOVMAX,			// Enforces a maximum (vertical) FOV
+	RLV_BHVR_SETCAM_TEXTURES,		// Replaces all textures with the specified texture (or the default unrezzed one)
 	RLV_BHVR_SETCAM_UNLOCK,			// Forces the camera focus to the user's avatar
 
 	RLV_BHVR_COUNT,
@@ -216,6 +217,7 @@ enum ERlvBehaviourModifier
 	RLV_MODIFIER_SETCAM_FOCUSOFFSET,
 	RLV_MODIFIER_SETCAM_FOVMIN,
 	RLV_MODIFIER_SETCAM_FOVMAX,
+	RLV_MODIFIER_SETCAM_TEXTURE,
 
 	RLV_MODIFIER_COUNT,
 	RLV_MODIFIER_UNKNOWN
diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp
index 5309c8d79b0980d1fdf76313d5fd325f80c0962b..072950200e2bd3cc67668d604369558c5e993d97 100644
--- a/indra/newview/rlvhandler.cpp
+++ b/indra/newview/rlvhandler.cpp
@@ -39,6 +39,7 @@
 #include "lltabcontainer.h"				// @showinv - Tab container control for inventory tabs
 #include "lltoolmgr.h"					// @edit
 #include "llviewercamera.h"				// @setcam and related
+#include "llviewertexturelist.h"		// @setcam_texture
 
 // RLVa includes
 #include "rlvactions.h"
@@ -1419,10 +1420,19 @@ ERlvCmdRet RlvBehaviourGenericHandler<RLV_OPTION_NONE_OR_MODIFIER>::onCommand(co
 	RlvBehaviourModifier* pBhvrModifier = RlvBehaviourDictionary::instance().getModifierFromBehaviour(rlvCmd.getBehaviourType());
 	if ( (pBhvrModifier) && (pBhvrModifier->getAddDefault()) )
 	{
+		// HACK-RLVa: reference counting doesn't happen until control returns to our caller but the modifier callbacks will happen now so we need to adjust the reference counts here
 		if (RLV_TYPE_ADD == rlvCmd.getParamType())
+		{
+			gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]++;
 			pBhvrModifier->addValue(pBhvrModifier->getDefaultValue(), rlvCmd.getObjectID());
+			gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]--;
+		}
 		else
+		{
+			gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]--;
 			pBhvrModifier->removeValue(pBhvrModifier->getDefaultValue(), rlvCmd.getObjectID());
+			gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]++;
+		}
 	}
 
 	fRefCount = true;
@@ -1696,6 +1706,27 @@ void RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_FOVMAX>::onValueChange() co
 	LLViewerCamera::instance().setDefaultFOV(LLViewerCamera::instance().getDefaultFOV());
 }
 
+// Handles: @setcam_textures[:<uuid>=n|y changes
+template<>
+void RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_TEXTURE>::onValueChange() const
+{
+	if (RlvBehaviourModifier* pBhvrModifier = RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_TEXTURE))
+	{
+		if (pBhvrModifier->hasValue())
+		{
+			RLV_INFOS << "Toggling diffuse textures for @setcam_textures" << RLV_ENDL;
+			LLViewerFetchedTexture::sDefaultDiffuseImagep = LLViewerTextureManager::getFetchedTexture(pBhvrModifier->getValue<LLUUID>(), FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+			gObjectList.setAllObjectDefaultTextures(LLRender::DIFFUSE_MAP, true);
+		}
+		else
+		{
+			RLV_INFOS << "Restoring diffuse textures for @setcam_textures" << RLV_ENDL;
+			gObjectList.setAllObjectDefaultTextures(LLRender::DIFFUSE_MAP, false);
+			LLViewerFetchedTexture::sDefaultDiffuseImagep = nullptr;
+		}
+	}
+}
+
 // Handles: @setcam=n|y toggles
 template<> template<>
 void RlvBehaviourToggleHandler<RLV_BHVR_SETCAM>::onCommandToggle(ERlvBehaviour eBhvr, bool fHasBhvr)
diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp
index ffc95be74b786e141ce64eac6fef456cf477d995..83a8949e0dead07c51213e092bf9db92cb525a7a 100644
--- a/indra/newview/rlvhelper.cpp
+++ b/indra/newview/rlvhelper.cpp
@@ -177,6 +177,8 @@ RlvBehaviourDictionary::RlvBehaviourDictionary()
 	addModifier(RLV_BHVR_SETCAM_FOVMIN, RLV_MODIFIER_SETCAM_FOVMIN, new RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_FOVMIN>(DEFAULT_FIELD_OF_VIEW, true, new RlvBehaviourModifier_CompMax()));
 	addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_MODIFIER>("setcam_fovmax", RLV_BHVR_SETCAM_FOVMAX));
 	addModifier(RLV_BHVR_SETCAM_FOVMAX, RLV_MODIFIER_SETCAM_FOVMAX, new RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_FOVMAX>(DEFAULT_FIELD_OF_VIEW, true, new RlvBehaviourModifier_CompMin()));
+	addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_NONE_OR_MODIFIER>("setcam_textures", RLV_BHVR_SETCAM_TEXTURES));
+	addModifier(RLV_BHVR_SETCAM_TEXTURES, RLV_MODIFIER_SETCAM_TEXTURE, new RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_TEXTURE>(IMG_DEFAULT, true, nullptr));
 	addEntry(new RlvBehaviourToggleProcessor<RLV_BHVR_SETCAM_UNLOCK, RLV_OPTION_NONE>("setcam_unlock"));
 
 	//
@@ -468,6 +470,15 @@ bool RlvBehaviourModifier::convertOptionValue(const std::string& optionValue, Rl
 				return true;
 			}
 		}
+		else if (typeid(LLUUID) == m_DefaultValue.type())
+		{
+			LLUUID idOption;
+			if (LLUUID::parseUUID(optionValue, &idOption))
+			{
+				modValue = idOption;
+				return true;
+			}
+		}
 		return false;
 	}
 	catch (const std::invalid_argument&)