diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 6782d83264520dc5b6157f48c131ef11484115e6..e7f8997b9406b4517dc359d8b44b732a7babec46 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -5711,10 +5711,15 @@ void LLPickInfo::fetchResults()
 // [RLVa:KB] - Checked: RLVa-2.2 (@setoverlay)
 	if ( (RlvActions::hasBehaviour(RLV_BHVR_SETOVERLAY)) && (hit_object) && (!hit_object->isHUDAttachment()) )
 	{
-		if (auto* pOverlayEffect = LLVfxManager::instance().getEffect<RlvOverlayEffect>(EVisualEffect::RlvOverlay))
+		std::list<LLVisualEffect*> effects;
+		LLVfxManager::instance().getEffects<RlvOverlayEffect>(effects);
+		for (const LLVisualEffect* pEffect : effects)
 		{
-			if (pOverlayEffect->hitTest(mMousePt))
+			if (pEffect->getEnabled() && static_cast<const RlvOverlayEffect*>(pEffect)->hitTest(mMousePt))
+			{
 				hit_object = nullptr;
+				break;
+			}
 		}
 	}
 // [/RLVa:KB]
diff --git a/indra/newview/rlveffects.cpp b/indra/newview/rlveffects.cpp
index 844d98ff25d7009a64803f70ac093370a7a3b367..70e90301444245b7d616395478b1318fc4dcdc45 100644
--- a/indra/newview/rlveffects.cpp
+++ b/indra/newview/rlveffects.cpp
@@ -40,6 +40,7 @@ RlvOverlayEffect::RlvOverlayEffect(const LLUUID& idRlvObj)
 	, m_fBlockTouch(false)
 	, m_Color(LLColor3(c_DefaultColor))
 {
+	m_fEnabled = false;
 }
 
 RlvOverlayEffect::~RlvOverlayEffect()
diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp
index 69dcb32e5537631b87d50847f25aeba6d322a1c3..de6eb9acac5f211239af45ece3f74bbfe0b3eaaf 100644
--- a/indra/newview/rlvhandler.cpp
+++ b/indra/newview/rlvhandler.cpp
@@ -2050,14 +2050,44 @@ void RlvBehaviourToggleHandler<RLV_BHVR_PAY>::onCommandToggle(ERlvBehaviour eBhv
 	}
 }
 
-// Handles: @setoverlay=n|y toggles
+// Handles: @setoverlay=n|y
 template<> template<>
-void RlvBehaviourToggleHandler<RLV_BHVR_SETOVERLAY>::onCommandToggle(ERlvBehaviour eBhvr, bool fHasBhvr)
+ERlvCmdRet RlvBehaviourHandler<RLV_BHVR_SETOVERLAY>::onCommand(const RlvCommand& rlvCmd, bool& fRefCount)
 {
-	if (fHasBhvr)
-		LLVfxManager::instance().addEffect(new RlvOverlayEffect(gRlvHandler.getCurrentObject()));
-	else
-		LLVfxManager::instance().removeEffect<RlvOverlayEffect>(gRlvHandler.getCurrentObject());
+	ERlvCmdRet eRet = RlvBehaviourGenericHandler<RLV_OPTION_NONE_OR_MODIFIER>::onCommand(rlvCmd, fRefCount);
+	if ( (RLV_RET_SUCCESS == eRet) && (!rlvCmd.isModifier()) )
+	{
+		if (gRlvHandler.hasBehaviour(rlvCmd.getObjectID(), rlvCmd.getBehaviourType()))
+		{
+			LLVfxManager::instance().addEffect(new RlvOverlayEffect(gRlvHandler.getCurrentObject()));
+		}
+		else
+		{
+			LLVfxManager::instance().removeEffect<RlvOverlayEffect>(gRlvHandler.getCurrentObject());
+		}
+	}
+
+	// Refresh overlay effects according to object hierarchy
+	std::list<LLVisualEffect*> effects;
+	if (LLVfxManager::instance().getEffects<RlvOverlayEffect>(effects))
+	{
+		auto itActiveEffect = std::find_if(effects.begin(), effects.end(), [](const LLVisualEffect* pEffect) { return pEffect->getEnabled(); });
+		if (effects.end() == itActiveEffect)
+		{
+			// If nothing is active just pick the first one to activate
+			itActiveEffect = effects.begin();
+		}
+
+		const LLUUID idActiveRootObj = (effects.end() != itActiveEffect) ? Rlv::getObjectRootId((*itActiveEffect)->getId()) : LLUUID::null;
+		for (LLVisualEffect* pEffect : effects)
+		{
+			bool isActive = (idActiveRootObj.isNull() && pEffect == effects.front()) || (Rlv::getObjectRootId(pEffect->getId()) == idActiveRootObj);
+			int nPriority = (isActive) ? 256 - Rlv::getObjectLinkNumber(pEffect->getId()) : pEffect->getPriority();
+			LLVfxManager::instance().updateEffect(pEffect, isActive, nPriority);
+		}
+	}
+
+	return eRet;
 }
 
 // Handles: @setsphere=n|y
diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp
index 33549a311842f8dd6f41f2b05fade73a7d0720db..2e70b3ecd0ba6fc28d969ee97e209536a985b957 100644
--- a/indra/newview/rlvhelper.cpp
+++ b/indra/newview/rlvhelper.cpp
@@ -221,16 +221,16 @@ RlvBehaviourDictionary::RlvBehaviourDictionary()
 	addEntry(new RlvBehaviourGenericToggleProcessor<RLV_BHVR_SETCAM_UNLOCK, RLV_OPTION_NONE>("camunlock", RlvBehaviourInfo::BHVR_SYNONYM | RlvBehaviourInfo::BHVR_DEPRECATED));
 
 	// Overlay
-	RlvBehaviourInfo* pSetOverlayBhvr = new RlvBehaviourGenericToggleProcessor<RLV_BHVR_SETOVERLAY, RLV_OPTION_NONE_OR_MODIFIER>("setoverlay");
+	RlvBehaviourInfo* pSetOverlayBhvr = new RlvBehaviourProcessor<RLV_BHVR_SETOVERLAY>("setoverlay");
 	pSetOverlayBhvr->addModifier(ERlvLocalBhvrModifier::OverlayAlpha, typeid(float), "alpha", &RlvOverlayEffect::onAlphaValueChanged);
 	pSetOverlayBhvr->addModifier(ERlvLocalBhvrModifier::OverlayTexture, typeid(LLUUID), "texture", &RlvOverlayEffect::onTextureChanged);
 	pSetOverlayBhvr->addModifier(ERlvLocalBhvrModifier::OverlayTint, typeid(LLVector3), "tint", &RlvOverlayEffect::onColorValueChanged);
 	pSetOverlayBhvr->addModifier(ERlvLocalBhvrModifier::OverlayTouch, typeid(LLVector3), "touch", &RlvOverlayEffect::onBlockTouchValueChanged);
 	addEntry(pSetOverlayBhvr);
-	addEntry(new RlvForceProcessor<RLV_BHVR_SETOVERLAY_TWEEN>("setoverlay_tween", RlvBehaviourInfo::BHVR_EXPERIMENTAL));
+	addEntry(new RlvForceProcessor<RLV_BHVR_SETOVERLAY_TWEEN>("setoverlay_tween"));
 
 	// Sphere
-	RlvBehaviourInfo* pSetSphereBhvr = new RlvBehaviourProcessor<RLV_BHVR_SETSPHERE>("setsphere", RlvBehaviourInfo::BHVR_EXPERIMENTAL);
+	RlvBehaviourInfo* pSetSphereBhvr = new RlvBehaviourProcessor<RLV_BHVR_SETSPHERE>("setsphere");
 	pSetSphereBhvr->addModifier(ERlvLocalBhvrModifier::SphereMode, typeid(int), "mode", &RlvSphereEffect::onModeChanged);
 	pSetSphereBhvr->addModifier(ERlvLocalBhvrModifier::SphereOrigin, typeid(int), "origin", &RlvSphereEffect::onOriginChanged);
 	pSetSphereBhvr->addModifier(ERlvLocalBhvrModifier::SphereColor, typeid(LLVector3), "color", &RlvSphereEffect::onColorChanged);
@@ -2053,6 +2053,27 @@ namespace Rlv
 			gSavedSettings.setBOOL("WindLightUseAtmosShaders", TRUE);
 		}
 	}
+
+	int getObjectLinkNumber(const LLUUID& idObj)
+	{
+		const LLViewerObject* pObj = gObjectList.findObject(idObj);
+		const LLViewerObject* pRootObj = (pObj) ? pObj->getRootEdit() : nullptr;
+		if ( (!pRootObj) || (pRootObj->getChildren().empty()) )
+			return 0;
+		else if (pRootObj == pObj)
+			return 1;
+		return 2 + std::distance(pRootObj->getChildren().begin(), std::find(pRootObj->getChildren().begin(), pRootObj->getChildren().end(), pObj));
+	}
+
+	const LLUUID& getObjectRootId(const LLUUID& idObj)
+	{
+		if (const LLViewerObject* pObj = gObjectList.findObject(idObj))
+		{
+			pObj = pObj->getRootEdit();
+			return pObj->getID();
+		}
+		return idObj;
+	}
 }
 
 // =========================================================================
diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h
index d6e147df9a89bc72966ba4cf11ec3893bf1f51e6..031b30f5baee13a0449af0b8cd95b766e0b90c5e 100644
--- a/indra/newview/rlvhelper.h
+++ b/indra/newview/rlvhelper.h
@@ -695,6 +695,9 @@ std::string rlvGetLastParenthesisedText(const std::string& strText, std::string:
 namespace Rlv
 {
 	void forceAtmosphericShadersIfAvailable();
+
+	int           getObjectLinkNumber(const LLUUID& idObj);
+	const LLUUID& getObjectRootId(const LLUUID& idObj);
 }
 
 // ============================================================================