From 1866bc2af39189c17b636970d4df7edc983c1830 Mon Sep 17 00:00:00 2001
From: McCabe Maxsted
Date: Sat, 9 Oct 2010 03:27:47 -0700
Subject: Applied RLVa-1.1.2-Imprudence.patch by Kitty Barnett
---
linden/indra/newview/rlvhelper.cpp | 649 ++++++++++++++++++++++++++++++-------
1 file changed, 526 insertions(+), 123 deletions(-)
(limited to 'linden/indra/newview/rlvhelper.cpp')
diff --git a/linden/indra/newview/rlvhelper.cpp b/linden/indra/newview/rlvhelper.cpp
index f509a43..9ef74ac 100644
--- a/linden/indra/newview/rlvhelper.cpp
+++ b/linden/indra/newview/rlvhelper.cpp
@@ -1,27 +1,31 @@
#include "llviewerprecompiledheaders.h"
-#include "llagent.h"
#include "llfloaterwindlight.h"
+#include "llgesturemgr.h"
+#include "llinventoryview.h"
+#include "llinventorybridge.h"
#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "llviewerregion.h"
#include "llviewerstats.h"
#include "llviewerwindow.h"
#include "llvoavatar.h"
+#include "llwearablelist.h"
#include "llwlparammanager.h"
#include "rlvhelper.h"
-#include "rlvevent.h"
#include "rlvhandler.h"
-// ============================================================================
-// Static variable initialization
-//
-
-RlvCommand::RlvBhvrTable RlvCommand::m_BhvrMap;
+// Defined in llinventorybridge.cpp
+void wear_attachments_on_avatar(const LLInventoryModel::item_array_t& items, BOOL remove);
+void wear_inventory_category_on_avatar_loop(LLWearable* wearable, void*);
// ============================================================================
// RlvCommmand
//
-// Checked: 2009-09-10 (RLVa-1.0.3a) | Modified: RLVa-1.0.3a
+RlvCommand::RlvBhvrTable RlvCommand::m_BhvrMap;
+
+// Checked: 2009-12-27 (RLVa-1.1.0k) | Modified: RLVa-1.1.0k
RlvCommand::RlvCommand(const std::string& strCommand)
: m_eBehaviour(RLV_BHVR_UNKNOWN), m_fStrict(false), m_eParamType(RLV_TYPE_UNKNOWN)
{
@@ -32,12 +36,12 @@ RlvCommand::RlvCommand(const std::string& strCommand)
m_eParamType = RLV_TYPE_ADD;
else if ( ("y" == m_strParam) || ("rem" == m_strParam) )
m_eParamType = RLV_TYPE_REMOVE;
+ else if (m_strBehaviour == "clear") // clear is the odd one out so just make it its own type
+ m_eParamType = RLV_TYPE_CLEAR;
else if ("force" == m_strParam)
m_eParamType = RLV_TYPE_FORCE;
else if (LLStringUtil::convertToS32(m_strParam, nTemp)) // Assume it's a reply command if we can convert to an S32
m_eParamType = RLV_TYPE_REPLY;
- else if (m_strBehaviour == "clear") // clear is the odd one out so just make it its own type
- m_eParamType = RLV_TYPE_CLEAR;
else
{
m_eParamType = RLV_TYPE_UNKNOWN;
@@ -51,13 +55,7 @@ RlvCommand::RlvCommand(const std::string& strCommand)
return;
}
- // Check if this is the "strict" (aka "secure") variation of a behaviour
- std::string::size_type idxStrict = m_strBehaviour.find("_sec");
- m_fStrict = (std::string::npos != idxStrict) && (idxStrict + 4 == m_strBehaviour.length());
-
- RlvBhvrTable::const_iterator itBhvr = m_BhvrMap.find( (!m_fStrict) ? m_strBehaviour : m_strBehaviour.substr(0, idxStrict));
- if ( (itBhvr != m_BhvrMap.end()) && ((!m_fStrict) || (hasStrictVariant(itBhvr->second))) )
- m_eBehaviour = itBhvr->second;
+ m_eBehaviour = getBehaviourFromString(m_strBehaviour, &m_fStrict);
}
@@ -95,6 +93,20 @@ bool RlvCommand::parseCommand(const std::string& strCommand, std::string& strBeh
return true;
}
+// Checked: 2009-12-05 (RLVa-1.1.0h) | Added: RLVa-1.1.0h
+ERlvBehaviour RlvCommand::getBehaviourFromString(const std::string& strBhvr, bool* pfStrict /*=NULL*/)
+{
+ std::string::size_type idxStrict = strBhvr.find("_sec");
+ bool fStrict = (std::string::npos != idxStrict) && (idxStrict + 4 == strBhvr.length());
+ if (pfStrict)
+ *pfStrict = fStrict;
+
+ RlvBhvrTable::const_iterator itBhvr = m_BhvrMap.find( (!fStrict) ? strBhvr : strBhvr.substr(0, idxStrict));
+ if ( (itBhvr != m_BhvrMap.end()) && ((!fStrict) || (hasStrictVariant(itBhvr->second))) )
+ return itBhvr->second;
+ return RLV_BHVR_UNKNOWN;
+}
+
void RlvCommand::initLookupTable()
{
static bool fInitialized = false;
@@ -103,14 +115,16 @@ void RlvCommand::initLookupTable()
// NOTE: keep this matched with the enumeration at all times
std::string arBehaviours[RLV_BHVR_COUNT] =
{
- "version", "detach", "sendchat", "emote", "chatshout", "chatnormal", "chatwhisper", "redirchat", "rediremote",
- "sendim", "recvchat", "recvemote", "recvim", "tplm", "tploc", "tplure", "sittp", "edit", "rez",
- "addoutfit", "remoutfit", "getoutfit", "addattach", "remattach", "getattach", "showinv", "viewnote", "unsit", "sit",
- "sendchannel", "getstatus", "getstatusall", "getinv", "getinvworn", "findfolder", "findfolders",
- "attach", "attachall", "detachall", "getpath", "attachthis", "attachallthis", "detachthis", "detachallthis",
- "fartouch", "showworldmap", "showminimap", "showloc", "tpto", "accepttp", "acceptpermission", "shownames", "fly",
- "getsitid", "setdebug", "setenv", "detachme", "showhovertextall", "showhovertextworld", "showhovertexthud",
- "showhovertext", "notify", "defaultwear", "versionnum", "permissive", "viewscript", "viewtexture"
+ "detach", "attach", "addattach", "remattach", "addoutfit", "remoutfit", "emote", "sendchat", "recvchat", "recvemote",
+ "redirchat", "rediremote", "chatwhisper", "chatnormal", "chatshout", "sendchannel", "sendim", "recvim", "permissive",
+ "notify", "showinv", "showminimap", "showworldmap", "showloc", "shownames", "showhovertext", "showhovertexthud",
+ "showhovertextworld", "showhovertextall", "tplm", "tploc", "tplure", "viewnote", "viewscript", "viewtexture",
+ "acceptpermission", "accepttp", "defaultwear", "allowidle", "edit", "rez", "fartouch", "interact", "touch",
+ "touchattach", "touchhud", "touchworld", "fly", "unsit", "sit", "sittp", "setdebug", "setenv", "detachme", "detachthis",
+ "detachall", "detachallthis", "attachthis", "attachall", "attachallthis", "tpto", "version", "versionnew", "versionnum",
+ "getattach", "getattachnames", "getaddattachnames", "getremattachnames", "getoutfit", "getoutfitnames",
+ "getaddoutfitnames", "getremoutfitnames", "findfolder", "findfolders", "getpath", "getinv", "getinvworn", "getsitid",
+ "getstatus", "getstatusall"
};
for (int idxBvhr = 0; idxBvhr < RLV_BHVR_COUNT; idxBvhr++)
@@ -133,9 +147,7 @@ RlvObject::RlvObject(const LLUUID& idObj) : m_UUID(idObj), m_nLookupMisses(0)
bool RlvObject::addCommand(const RlvCommand& rlvCmd)
{
- // Sanity checking
- if (RLV_TYPE_ADD != rlvCmd.getParamType())
- return false;
+ RLV_ASSERT(RLV_TYPE_ADD == rlvCmd.getParamType());
// Don't add duplicate commands for this object (ie @detach=n followed by another @detach=n later on)
for (rlv_command_list_t::iterator itCmd = m_Commands.begin(); itCmd != m_Commands.end(); ++itCmd)
@@ -155,9 +167,7 @@ bool RlvObject::addCommand(const RlvCommand& rlvCmd)
bool RlvObject::removeCommand(const RlvCommand& rlvCmd)
{
- // Sanity checking
- if (RLV_TYPE_REMOVE != rlvCmd.getParamType())
- return false;
+ RLV_ASSERT(RLV_TYPE_REMOVE == rlvCmd.getParamType());
for (rlv_command_list_t::iterator itCmd = m_Commands.begin(); itCmd != m_Commands.end(); ++itCmd)
{
@@ -188,7 +198,7 @@ bool RlvObject::hasBehaviour(ERlvBehaviour eBehaviour, const std::string& strOpt
return false;
}
-// Checked: 2009-06-07 (RLVa-0.2.1c)
+// Checked: 2009-11-27 (RLVa-1.1.0f) | Modified: RLVa-1.1.0f
std::string RlvObject::getStatusString(const std::string& strMatch) const
{
std::string strStatus, strCmd;
@@ -198,8 +208,7 @@ std::string RlvObject::getStatusString(const std::string& strMatch) const
strCmd = itCmd->asString();
if ( (strMatch.empty()) || (std::string::npos != strCmd.find(strMatch)) )
{
- if (!strStatus.empty())
- strStatus.push_back('/');
+ strStatus.push_back('/');
strStatus += strCmd;
}
}
@@ -212,7 +221,7 @@ std::string RlvObject::getStatusString(const std::string& strMatch) const
//
// Checked: 2009-10-12 (RLVa-1.0.5b) | Modified: RLVa-1.0.5b
-void RlvAttachmentManager::forceAttach(const LLUUID& idItem, S32 idxAttachPt)
+void RlvAttachmentManager::attach(const LLUUID& idItem, S32 idxAttachPt)
{
#if RLV_TARGET < RLV_MAKE_TARGET(1, 23, 0) // Version: 1.22.11
LLAttachmentRezAction* rez_action = new LLAttachmentRezAction();
@@ -224,18 +233,15 @@ void RlvAttachmentManager::forceAttach(const LLUUID& idItem, S32 idxAttachPt)
LLSD payload;
payload["item_id"] = idItem;
payload["attachment_point"] = idxAttachPt;
-
- LLNotifications::instance().forceResponse(
- LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
+ LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
#endif
}
-// Checked: 2009-10-12 (RLVa-1.0.5b) | Modified: RLVa-1.0.5b
-void RlvAttachmentManager::forceDetach(LLViewerJointAttachment* pAttachPt)
+// Checked: 2009-11-24 (RLVa-1.1.0k) | Added: RLVa-1.1.0e
+void RlvAttachmentManager::detach(LLViewerJointAttachment* pAttachPt)
{
- // Copy/paste from handle_detach_from_avatar()
- LLViewerObject* attached_object = pAttachPt->getObject();
- if (attached_object)
+ // [See handle_detach_from_avatar()]
+ if ( (pAttachPt) && (pAttachPt->getObject()) )
{
gMessageSystem->newMessage("ObjectDetach");
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
@@ -243,7 +249,7 @@ void RlvAttachmentManager::forceDetach(LLViewerJointAttachment* pAttachPt)
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
- gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID());
+ gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, pAttachPt->getObject()->getLocalID());
gMessageSystem->sendReliable( gAgent.getRegionHost() );
}
}
@@ -278,7 +284,7 @@ void RlvAttachmentManager::onAttach(LLViewerJointAttachment* pAttachPt)
// If it was empty we need to force detach the new attachment; if it wasn't we need to reattach the old one
if (itAttachPrev->second.isNull())
{
- forceDetach(pAttachPt);
+ detach(pAttachPt);
m_PendingDetach.insert(std::pair(idxAttachPt, pAttachPt->getItemID()));
}
else if (m_PendingAttach.find(idxAttachPt) == m_PendingAttach.end()) // (only if we're not reattaching something else there)
@@ -321,7 +327,7 @@ void RlvAttachmentManager::onSavedAssetIntoInventory(const LLUUID& idItem)
{
if ( (!itAttach->second.fAssetSaved) && (idItem == itAttach->second.idItem) )
{
- forceAttach(itAttach->second.idItem, itAttach->first);
+ attach(itAttach->second.idItem, itAttach->first);
itAttach->second.tsAttach = LLFrameTimer::getElapsedSeconds();
}
}
@@ -368,7 +374,7 @@ BOOL RlvAttachmentManager::onTimer()
if (fAttach)
{
- forceAttach(itAttach->second.idItem, itAttach->first);
+ attach(itAttach->second.idItem, itAttach->first);
itAttach->second.tsAttach = tsCurrent;
}
@@ -421,7 +427,7 @@ const LLUUID& RlvWearableItemCollector::getFoldedParent(const LLUUID& idFolder)
return (m_Folding.end() == itFolder) ? idFolder : itFolder->second;
}
-// Checked: 2009-07-29 (RLVa-1.0.1b) | Modified: RLVa-1.0.1b
+// Checked: 2009-12-18 (RLVa-1.1.0k) | Modified: RLVa-1.1.0i
bool RlvWearableItemCollector::onCollectFolder(const LLInventoryCategory* pFolder)
{
const LLUUID& idParent = pFolder->getParentUUID();
@@ -437,25 +443,35 @@ bool RlvWearableItemCollector::onCollectFolder(const LLInventoryCategory* pFolde
return false;
#endif // RLV_EXTENSION_FLAG_NOSTRIP
- if (gRlvHandler.isFoldedFolder(pFolder, m_fAttach)) // Check for folder that should get folded under its parent
+ if (gRlvHandler.isFoldedFolder(pFolder, m_fAttach, false)) // Check for folder that should get folded under its parent
{
m_Tentative.push_front(pFolder->getUUID());
m_Folding.insert(std::pair(pFolder->getUUID(), idParent));
}
else if ( (RLV_FOLDER_PREFIX_HIDDEN != strFolder[0]) && (m_fMatchAll) ) // Collect from any non-hidden child folder for *all
{
- m_Wearable.push_front(pFolder->getUUID());
+ #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ if ( (!RlvSettings::getEnableComposites()) || // ... if we're not checking composite folders
+ (!gRlvHandler.isCompositeFolder(pFolder)) || // ... or if it's not a composite folder
+ ((m_fAttach) && (gRlvHandler.canWearComposite(pFolder))) || // ... or if we're attaching and can attach it OR
+ (!m_fAttach) && (gRlvHandler.canTakeOffComposite(pFolder)) ) // ... or if we're detaching and can detach it
+ #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ {
+ m_Wearable.push_front(pFolder->getUUID());
+ }
return (idParent == m_idFolder); // (Convenience for @getinvworn)
}
- #ifdef RLV_EXPERIMENTAL_COMPOSITES
- else if ( (RLV_FOLDER_PREFIX_HIDDEN == strFolder[0]) && // Hidden folder that's a...
+ #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ else if ( (RlvSettings::getEnableComposites()) &&
+ (RLV_FOLDER_PREFIX_HIDDEN == strFolder[0]) && // Hidden folder that's a...
(gRlvHandler.isCompositeFolder(pFolder)) && // ... composite folder which we...
- ((m_fAttach) || (gRlvHandler.canTakeOffComposite(pFolder))) ) // ... attach or can detach (see composite locking)
+ ( ((m_fAttach) && (gRlvHandler.canWearComposite(pFolder))) || // ... are attaching and can attach OR
+ (!m_fAttach) && (gRlvHandler.canTakeOffComposite(pFolder)) ) ) // ... are detaching and can detach
{
m_Wearable.push_front(pFolder->getUUID());
m_Folding.insert(std::pair(pFolder->getUUID(), idParent));
}
- #endif // RLV_EXPERIMENTAL_COMPOSITES
+ #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS
return false;
}
@@ -486,13 +502,13 @@ bool RlvWearableItemCollector::onCollectItem(const LLInventoryItem* pItem)
case LLAssetType::AT_OBJECT:
fRet = ( (m_Wearable.end() != std::find(m_Wearable.begin(), m_Wearable.end(), idParent)) ||
(m_Tentative.end() != std::find(m_Tentative.begin(), m_Tentative.end(), idParent)) ) &&
- ( (!m_fAttach) || (gRlvHandler.hasAttachPointName(pItem, true)) ); // Only care about attach point on attach*
+ ( (!m_fAttach) || (gRlvHandler.hasAttachPointName(pItem, true)) || (RlvSettings::getEnableSharedWear()) );
break;
- #ifdef RLV_EXPERIMENTAL_FORCEWEAR_GESTURES
+ #ifdef RLV_EXTENSION_FORCEWEAR_GESTURES
case LLAssetType::AT_GESTURE:
fRet = (m_Wearable.end() != std::find(m_Wearable.begin(), m_Wearable.end(), idParent));
break;
- #endif // RLV_EXPERIMENTAL_FORCEWEAR_GESTURES
+ #endif // RLV_EXTENSION_FORCEWEAR_GESTURES
default:
break;
}
@@ -507,6 +523,431 @@ bool RlvWearableItemCollector::operator()(LLInventoryCategory* pFolder, LLInvent
}
// ============================================================================
+// RlvForceWear
+//
+
+// Checked: 2010-02-17 (RLVa-1.1.0o) | Modified: RLVa-1.1.0o
+void RlvForceWear::forceFolder(const LLViewerInventoryCategory* pFolder, eWearAction eAction, eWearFlags eFlags)
+{
+ // [See LLWearableBridge::wearOnAvatar(): don't wear anything until initial wearables are loaded, can destroy clothing items]
+ if (!gAgent.areWearablesLoaded())
+ {
+ LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
+ return;
+ }
+ // Sanity check - getAvatarObject() can't be NULL [see RlvForceWear::isWearingItem()]
+ LLVOAvatar* pAvatar = gAgent.getAvatarObject();
+ if (!pAvatar)
+ return;
+
+ LLInventoryModel::cat_array_t folders;
+ LLInventoryModel::item_array_t items;
+ RlvWearableItemCollector functor(pFolder->getUUID(), (ACTION_ATTACH == eAction), (FLAG_MATCHALL & eFlags));
+
+ // Grab a list of all the items we'll be wearing/attaching
+ gInventory.collectDescendentsIf(pFolder->getUUID(), folders, items, FALSE, functor);
+
+ for (S32 idxItem = 0, cntItem = items.count(); idxItem < cntItem; idxItem++)
+ {
+ LLViewerInventoryItem* pItem = items.get(idxItem);
+
+ // If it's wearable it should be worn on detach
+ if ( (ACTION_DETACH == eAction) && (isWearableItem(pItem)) && (!isWearingItem(pItem)) )
+ continue;
+
+ // NOTES: * if there are composite items then RlvWearableItemCollector made sure they can be worn (or taken off depending)
+ // * some scripts issue @remattach=force,attach:worn-items=force so we need to attach items even if they're currently worn
+ switch (pItem->getType())
+ {
+ case LLAssetType::AT_BODYPART:
+ RLV_ASSERT(ACTION_ATTACH == eAction); // RlvWearableItemCollector shouldn't be supplying us with body parts on detach
+ case LLAssetType::AT_CLOTHING:
+ if (ACTION_ATTACH == eAction)
+ {
+ // The check for whether we're replacing a currently worn composite item happens in onWearableArrived()
+ if (std::find(m_addWearables.begin(), m_addWearables.end(), pItem) == m_addWearables.end())
+ m_addWearables.push_back(pItem);
+ }
+ else
+ {
+ LLWearable* pWearable = gAgent.getWearableFromWearableItem(pItem->getUUID());
+ if ( (pWearable) && (isForceRemovable(pWearable->getType(), false)) )
+ {
+ if (std::find(m_remWearables.begin(), m_remWearables.end(), pWearable->getType()) == m_remWearables.end())
+ m_remWearables.push_back(pWearable->getType());
+ }
+ }
+ break;
+
+ case LLAssetType::AT_OBJECT:
+ if (ACTION_ATTACH == eAction)
+ {
+ LLViewerJointAttachment* pAttachPt = gRlvHandler.getAttachPoint(pItem, true);
+ if ( ( (pAttachPt) && // Need a specific attach pt that
+ (!gRlvHandler.isLockedAttachment(pAttachPt->getObject(), RLV_LOCK_REMOVE)) && // doesn't have a locked object
+ (!gRlvHandler.isLockedAttachment(pAttachPt, RLV_LOCK_ADD)) ) || // and that can be attached to
+ (RlvSettings::getEnableSharedWear()) )
+ {
+ if (std::find(m_addAttachments.begin(), m_addAttachments.end(), pItem) == m_addAttachments.end())
+ {
+ #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ // We still need to check whether we're about to replace a currently worn composite item
+ // (which we're not if we're just reattaching an attachment we're already wearing)
+ LLViewerInventoryCategory* pCompositeFolder = NULL;
+ if ( (pAttachPt->getObject()) && (RlvSettings::getEnableComposites()) &&
+ (pAttachPt->getItemID() != pItem->getUUID()) &&
+ (gRlvHandler.getCompositeInfo(pAttachPt->getItemID(), NULL, &pCompositeFolder)) )
+ {
+ // If we can't take off the composite folder this item would replace then don't allow it to get attached
+ if (gRlvHandler.canTakeOffComposite(pCompositeFolder))
+ {
+ forceFolder(pCompositeFolder, ACTION_DETACH, FLAG_DEFAULT);
+ m_addAttachments.push_back(pItem);
+ }
+ }
+ else
+ #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ {
+ m_addAttachments.push_back(pItem);
+ }
+ }
+ }
+ }
+ else
+ {
+ LLViewerJointAttachment* pAttachPt = pAvatar->getWornAttachmentPoint(pItem->getUUID());
+ if ( (pAttachPt) && (isForceDetachable(pAttachPt, false)) )
+ {
+ if (std::find(m_remAttachments.begin(), m_remAttachments.end(), pAttachPt) == m_remAttachments.end())
+ m_remAttachments.push_back(pAttachPt);
+ }
+ }
+ break;
+
+ #ifdef RLV_EXTENSION_FORCEWEAR_GESTURES
+ case LLAssetType::AT_GESTURE:
+ if (ACTION_ATTACH == eAction)
+ {
+ if (std::find(m_addGestures.begin(), m_addGestures.end(), pItem) == m_addGestures.end())
+ m_addGestures.push_back(pItem);
+ }
+ else
+ {
+ if (std::find(m_remGestures.begin(), m_remGestures.end(), pItem) == m_remGestures.end())
+ m_remGestures.push_back(pItem);
+ }
+ break;
+ #endif // RLV_EXTENSION_FORCEWEAR_GESTURES
+
+ default:
+ break;
+ }
+ }
+}
+
+// Checked: 2009-12-18 (RLVa-1.1.0k) | Added: RLVa-1.1.0i
+bool RlvForceWear::isForceDetachable(LLViewerJointAttachment* pAttachPt, bool fCheckComposite /*=true*/, LLViewerObject* pExceptObj /*=NULL*/)
+{
+ // Attachment point can be detached by an RLV command if:
+ // - something is worn on the attachment point
+ // - what's worn isn't "remove locked" by anything (or anything except the object specified by pExceptObj)
+ // - what's worn is strippable
+ // - composite folders are disabled *or* what's worn isn't part of a composite folder that has at least one item locked
+ #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ LLViewerInventoryCategory* pFolder = NULL;
+ #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ return
+ (
+ (pAttachPt) && (pAttachPt->getObject()) &&
+ ( (!pExceptObj) ? (!gRlvHandler.isLockedAttachment(pAttachPt->getObject(), RLV_LOCK_REMOVE))
+ : (!gRlvHandler.isLockedAttachmentExcept(pAttachPt->getObject(), RLV_LOCK_REMOVE, pExceptObj)) )
+ #ifdef RLV_EXTENSION_FLAG_NOSTRIP
+ && (gRlvHandler.isStrippable(pAttachPt->getItemID()))
+ #endif // RLV_EXTENSION_FLAG_NOSTRIP
+ #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ && ( (!fCheckComposite) || (!RlvSettings::getEnableComposites()) ||
+ (!gRlvHandler.getCompositeInfo(pAttachPt->getItemID(), NULL, &pFolder)) || (gRlvHandler.canTakeOffComposite(pFolder)) )
+ #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ );
+}
+
+// Checked: 2009-12-18 (RLVa-1.1.0k) | Added: RLVa-1.1.0i
+void RlvForceWear::forceDetach(LLViewerJointAttachment* pAttachPt)
+{
+ // Sanity check - no need to process duplicate removes
+ if ( (!pAttachPt) || (std::find(m_remAttachments.begin(), m_remAttachments.end(), pAttachPt) != m_remAttachments.end()) )
+ return;
+
+ if (isForceDetachable(pAttachPt))
+ {
+ #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ LLViewerInventoryCategory* pFolder = NULL;
+ if ( (RlvSettings::getEnableComposites()) &&
+ (gRlvHandler.getCompositeInfo(pAttachPt->getItemID(), NULL, &pFolder)) )
+ {
+ // Attachment belongs to a composite folder so detach the entire folder (if we can take it off)
+ if (gRlvHandler.canTakeOffComposite(pFolder))
+ forceFolder(pFolder, ACTION_DETACH, FLAG_DEFAULT);
+ }
+ else
+ #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ {
+ m_remAttachments.push_back(pAttachPt);
+ }
+ }
+}
+
+// Checked: 2009-12-18 (RLVa-1.1.0k) | Added: RLVa-1.1.0i
+bool RlvForceWear::isForceRemovable(EWearableType wtType, bool fCheckComposite /*=true*/, const LLUUID& idExcept /*=LLUUID::null*/)
+{
+ // Wearable type can be removed by an RLV command if:
+ // - something is worn on that layer
+ // - its asset type is AT_CLOTHING
+ // - what's worn isn't "remove locked" by anything (or anything except the object specified by idExcept)
+ // - what's worn is strippable
+ // - composite folders are disabled *or* what's worn isn't part of a composite folder that has at least one item locked
+ LLWearable* pWearable = gAgent.getWearable(wtType);
+ #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ LLViewerInventoryCategory* pFolder = NULL;
+ #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ return
+ (
+ (pWearable) &&
+ (LLAssetType::AT_CLOTHING == LLWearable::typeToAssetType(wtType)) &&
+ ( (idExcept.notNull()) ? (gRlvHandler.isRemovable(wtType))
+ : (gRlvHandler.isRemovableExcept(wtType, idExcept)) )
+ #ifdef RLV_EXTENSION_FLAG_NOSTRIP
+ && (gRlvHandler.isStrippable(gAgent.getWearableItem(wtType)))
+ #endif // RLV_EXTENSION_FLAG_NOSTRIP
+ #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ && ( (!fCheckComposite) || (!RlvSettings::getEnableComposites()) ||
+ (!gRlvHandler.getCompositeInfo(gAgent.getWearableItem(wtType), NULL, &pFolder)) || (gRlvHandler.canTakeOffComposite(pFolder)) )
+ #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ );
+}
+
+// Checked: 2009-12-18 (RLVa-1.1.0k) | Added: RLVa-1.1.0i
+void RlvForceWear::forceRemove(EWearableType wtType)
+{
+ // Sanity check - no need to process duplicate removes
+ if ( (WT_INVALID == wtType) || (std::find(m_remWearables.begin(), m_remWearables.end(), wtType) != m_remWearables.end()) )
+ return;
+
+ if (isForceRemovable(wtType))
+ {
+ #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ LLViewerInventoryCategory* pFolder = NULL;
+ if ( (RlvSettings::getEnableComposites()) &&
+ (gRlvHandler.getCompositeInfo(gAgent.getWearableItem(wtType), NULL, &pFolder)) )
+ {
+ // Wearable belongs to a composite folder so detach the entire folder (if we can take it off)
+ if (gRlvHandler.canTakeOffComposite(pFolder))
+ forceFolder(pFolder, ACTION_DETACH, FLAG_DEFAULT);
+ }
+ else
+ #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ {
+ m_remWearables.push_back(wtType);
+ }
+ }
+}
+
+// Checked: 2009-12-18 (RLVa-1.1.0k) | Added: RLVa-1.1.0i
+void RlvForceWear::processAdd()
+{
+ // Process attachments
+ if (m_addAttachments.size())
+ {
+ // Workaround for RezMultipleAttachmentsFromInv bug (see http://jira.secondlife.com/browse/SVC-5383)
+ #ifndef RLV_WORKAROUND_REZMULTIPLEATTACH
+ wear_attachments_on_avatar(m_addAttachments, FALSE);
+ #else
+ for (S32 idxItem = 0, cntItem = m_addAttachments.count(); idxItem < cntItem; idxItem++)
+ {
+ LLViewerInventoryItem* pItem = m_addAttachments.get(idxItem);
+
+ S32 idxAttachPt = gRlvHandler.getAttachPointIndex(pItem, true);
+ if (0 != idxAttachPt)
+ {
+ #if RLV_TARGET < RLV_MAKE_TARGET(1, 23, 0) // Version: 1.22.11
+ LLAttachmentRezAction* rez_action = new LLAttachmentRezAction();
+ rez_action->mItemID = pItem->getUUID();
+ rez_action->mAttachPt = idxAttachPt;
+
+ confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action); // (Will call delete on rez_action)
+ #else // Version: 1.23.4
+ LLSD payload;
+ payload["item_id"] = pItem->getUUID();
+ payload["attachment_point"] = idxAttachPt;
+
+ LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
+ #endif
+ }
+ }
+ #endif // RLV_WORKAROUND_REZMULTIPLEATTACH
+
+ m_addAttachments.clear();
+ }
+
+ // Process wearables
+ if (m_addWearables.size())
+ {
+ // [See wear_inventory_category_on_avatar_step2()]
+ LLWearableHoldingPattern* pWearData = new LLWearableHoldingPattern(TRUE);
+
+ // We need to populate 'pWearData->mFoundList' before doing anything else because (some of) the assets might already be available
+ for (S32 idxItem = 0, cntItem = m_addWearables.count(); idxItem < cntItem; idxItem++)
+ {
+ LLViewerInventoryItem* pItem = m_addWearables.get(idxItem);
+ if ( (pItem) && ((LLAssetType::AT_BODYPART == pItem->getType()) || (LLAssetType::AT_CLOTHING == pItem->getType())) )
+ {
+ LLFoundData* pFound = new LLFoundData(pItem->getUUID(), pItem->getAssetUUID(), pItem->getName(), pItem->getType());
+ pWearData->mFoundList.push_front(pFound);
+ }
+ }
+
+ if (!pWearData->mFoundList.size())
+ {
+ delete pWearData;
+ return;
+ }
+
+ // If all the assets are available locally then "pWearData" will be freed *before* the last "gWearableList.getAsset()" call returns
+ bool fContinue = true; LLWearableHoldingPattern::found_list_t::const_iterator itWearable = pWearData->mFoundList.begin();
+ while ( (fContinue) && (itWearable != pWearData->mFoundList.end()) )
+ {
+ const LLFoundData* pFound = *itWearable;
+ ++itWearable;
+ fContinue = (itWearable != pWearData->mFoundList.end());
+ gWearableList.getAsset(pFound->mAssetID, pFound->mName, pFound->mAssetType, onWearableArrived, (void*)pWearData);
+ }
+
+ m_addWearables.clear();
+ }
+
+ // Process gestures
+ if (m_addGestures.size())
+ {
+ gGestureManager.activateGestures(m_addGestures);
+ for (S32 idxGesture = 0, cntGesture = m_addGestures.count(); idxGesture < cntGesture; idxGesture++)
+ gInventory.updateItem(m_addGestures.get(idxGesture));
+ gInventory.notifyObservers();
+
+ m_addGestures.clear();
+ }
+}
+
+// Checked: 2009-12-18 (RLVa-1.1.0k) | Added: RLVa-1.1.0i
+void RlvForceWear::processRem()
+{
+ // Process attachments
+ if (m_remAttachments.size())
+ {
+ // [See LLAgent::userRemoveAllAttachments()]
+ gMessageSystem->newMessage("ObjectDetach");
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+ for (std::list::const_iterator itAttachPt = m_remAttachments.begin();
+ itAttachPt != m_remAttachments.end(); ++itAttachPt)
+ {
+ LLViewerJointAttachment* pAttachPt = *itAttachPt;
+ if (pAttachPt->getObject())
+ {
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+ gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, pAttachPt->getObject()->getLocalID());
+ }
+ }
+
+ gMessageSystem->sendReliable(gAgent.getRegionHost());
+
+ m_remAttachments.clear();
+ }
+
+ // Process wearables
+ if (m_remWearables.size())
+ {
+ for (std::list::const_iterator itWearable = m_remWearables.begin(); itWearable != m_remWearables.end(); ++itWearable)
+ gAgent.removeWearable(*itWearable);
+
+ m_remWearables.clear();
+ }
+
+ // Process gestures
+ if (m_remGestures.size())
+ {
+ for (S32 idxGesture = 0, cntGesture = m_remGestures.count(); idxGesture < cntGesture; idxGesture++)
+ {
+ LLViewerInventoryItem* pItem = m_remGestures.get(idxGesture);
+ gGestureManager.deactivateGesture(pItem->getUUID());
+ gInventory.updateItem(pItem);
+ gInventory.notifyObservers();
+ }
+
+ m_remGestures.clear();
+ }
+}
+
+// Checked: 2010-02-17 (RLVa-1.1.0o) | Modified: RLVa-1.1.0o
+void RlvForceWear::onWearableArrived(LLWearable* pWearable, void* pParam)
+{
+ #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+ // If this wearable will end up replacing a currently worn one that belongs to a composite folder then we need to detach the composite
+ LLViewerInventoryCategory* pFolder = NULL;
+ if ( (RlvSettings::getEnableComposites()) && (pWearable) && (gAgent.getWearable(pWearable->getType())) )
+ {
+ // If we're just rewearing the same item we're already wearing then we're not replacing a composite folder
+ LLWearableHoldingPattern* pWearData = (LLWearableHoldingPattern*)pParam; LLUUID idItem;
+ for (LLWearableHoldingPattern::found_list_t::const_iterator itWearable = pWearData->mFoundList.begin();
+ itWearable != pWearData->mFoundList.end(); ++itWearable)
+ {
+ LLFoundData* pFound = *itWearable;
+ if (pWearable->getID() == pFound->mAssetID)
+ {
+ idItem = pFound->mItemID;
+ break;
+ }
+ }
+ if ( (idItem.notNull()) && (idItem != gAgent.getWearableItem(pWearable->getType())) &&
+ (gRlvHandler.getCompositeInfo(gAgent.getWearableItem(pWearable->getType()), NULL, &pFolder)) )
+ {
+ RlvForceWear rlvWear;
+ rlvWear.forceFolder(pFolder, ACTION_DETACH, FLAG_DEFAULT);
+ rlvWear.done();
+ }
+ }
+ #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS
+
+ wear_inventory_category_on_avatar_loop(pWearable, pParam);
+}
+
+// ============================================================================
+// RlvBehaviourNotifyObserver
+//
+
+void RlvBehaviourNotifyObserver::changed(const RlvCommand& rlvCmd, bool fInternal)
+{
+ if (fInternal)
+ return;
+
+ std::string strCmd = rlvCmd.asString(), strNotify; ERlvParamType eCmdType = rlvCmd.getParamType();
+ if ( (RLV_TYPE_ADD == eCmdType) || (RLV_TYPE_REMOVE == eCmdType) )
+ strNotify = llformat("/%s=%s", strCmd.c_str(), rlvCmd.getParam().c_str());
+ else if (RLV_TYPE_CLEAR == eCmdType)
+ strNotify = llformat("/%s", strCmd.c_str());
+ else
+ return;
+
+ for (std::multimap::const_iterator itNotify = m_Notifications.begin();
+ itNotify != m_Notifications.end(); ++itNotify)
+ {
+ if ( (itNotify->second.strFilter.empty()) || (std::string::npos != strCmd.find(itNotify->second.strFilter)) )
+ rlvSendChatReply(itNotify->second.nChannel, strNotify);
+ }
+}
+
+// ============================================================================
// RlvWLSnapshot
//
@@ -546,38 +987,6 @@ RlvWLSnapshot* RlvWLSnapshot::takeSnapshot()
}
// =========================================================================
-// RlvSettings
-//
-
-BOOL RlvSettings::fShowNameTags = FALSE;
-
-BOOL RlvSettings::getEnableWear()
-{
- return
- rlvGetSettingBOOL(RLV_SETTING_ENABLEWEAR, TRUE) && // "Enable Wear" is toggled on and...
- (!gRlvHandler.hasBehaviour(RLV_BHVR_DEFAULTWEAR)) && // not restricted and...
- (!gRlvHandler.hasBehaviour(RLV_BHVR_ADDATTACH)); // we have attach points we can attach to [see RlvHandler::onAddRemAttach()]
-}
-
-#ifdef RLV_EXTENSION_STARTLOCATION
- // Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.1d
- void RlvSettings::updateLoginLastLocation()
- {
- if (gSavedPerAccountSettings.controlExists(RLV_SETTING_LOGINLASTLOCATION))
- {
- BOOL fValue = (gRlvHandler.hasBehaviour(RLV_BHVR_TPLOC)) ||
- ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) &&
- (gAgent.getAvatarObject()) && (!gAgent.getAvatarObject()->mIsSitting) );
- if (gSavedPerAccountSettings.getBOOL(RLV_SETTING_LOGINLASTLOCATION) != fValue)
- {
- gSavedPerAccountSettings.setBOOL(RLV_SETTING_LOGINLASTLOCATION, fValue);
- gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
- }
- }
- }
-#endif // RLV_EXTENSION_STARTLOCATION
-
-// =========================================================================
// Various helper classes/timers/functors
//
@@ -618,39 +1027,40 @@ void RlvCurrentlyWorn::fetchWorn()
f.fetchItems(idItems);
}
-// Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0f
-bool RlvSelectHasLockedAttach::apply(LLSelectNode* pNode)
-{
- return (pNode->getObject()) ? gRlvHandler.isLockedAttachment(pNode->getObject(), m_eLock) : false;
-}
-
-// Checked: 2009-07-05 (RLVa-1.0.0b) | Modified: RLVa-0.2.0f
-bool RlvSelectIsOwnedByOrGroupOwned::apply(LLSelectNode* pNode)
+void RlvGiveToRLVAgentOffer::done()
{
- return (pNode->mPermissions->isGroupOwned()) || (pNode->mPermissions->getOwner() == m_idAgent);
-}
+ LLViewerInventoryCategory* pRlvRoot = gRlvHandler.getSharedRoot();
+ LLViewerInventoryCategory* pFolder = (mCompleteFolders.size()) ? gInventory.getCategory(mCompleteFolders[0]) : NULL;
+ if ( (pRlvRoot) && (pFolder) )
+ {
+ std::string strName = pFolder->getName();
+ if (strName.find(RLV_PUTINV_PREFIX) == 0)
+ {
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate updOldParent(pFolder->getParentUUID(), -1);
+ update.push_back(updOldParent);
+ LLInventoryModel::LLCategoryUpdate updNewParent(pRlvRoot->getUUID(), 1);
+ update.push_back(updNewParent);
+ gInventory.accountForUpdate(update);
+
+ LLPointer pNewFolder = new LLViewerInventoryCategory(pFolder);
+ pNewFolder->setParent(pRlvRoot->getUUID());
+ pNewFolder->updateParentOnServer(FALSE);
+ pNewFolder->rename(strName.erase(0, strName.find(RLV_FOLDER_PREFIX_PUTINV)));
+ pNewFolder->updateServer(FALSE);
+ gInventory.updateCategory(pNewFolder);
+ }
+ }
-// Checked: 2009-05-31 (RLVa-0.2.0f) | Modified: RLVa-0.2.0f
-bool RlvSelectIsSittingOn::apply(LLSelectNode* pNode)
-{
- return (pNode->getObject()) && (pNode->getObject()->getRootEdit() == m_pObject);
+ gInventory.removeObserver(this);
+ gInventory.notifyObservers();
+ delete this;
}
// ============================================================================
// Various helper functions
//
-// Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
-BOOL rlvAttachToEnabler(void* pParam)
-{
- // Disable an option on the "Attach to (HUD)" submenu if:
- // - the attachment point is locked non-detachable with an object attached
- // - the attachment point is locked non-attachable
- return (pParam != NULL) &&
- (!gRlvHandler.isLockedAttachment(((LLViewerJointAttachment*)pParam)->getObject(), RLV_LOCK_REMOVE)) &&
- (!gRlvHandler.isLockedAttachment((LLViewerJointAttachment*)pParam, RLV_LOCK_ADD));
-}
-
// Checked: 2009-07-05 (RLVa-1.0.0b) | Modified: RLVa-0.2.0g
bool rlvCanDeleteOrReturn()
{
@@ -677,13 +1087,6 @@ bool rlvCanDeleteOrReturn()
return fIsAllowed;
}
-// Checked: 2009-10-04 (RLVa-1.0.4b) | Modified: RLVa-1.0.4b
-BOOL rlvEnableWearEnabler(void* pParam)
-{
- // Visually disables the "Enable Wear" option when restricted from toggling it
- return (!gRlvHandler.hasBehaviour(RLV_BHVR_DEFAULTWEAR));
-}
-
// Checked: 2009-05-26 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d
S32 rlvGetDirectDescendentsCount(const LLInventoryCategory* pFolder, LLAssetType::EType type)
{
@@ -712,12 +1115,12 @@ S32 rlvGetDirectDescendentsCount(const LLInventoryCategory* pFolder, LLAssetType
#if RLV_TARGET < RLV_MAKE_TARGET(1, 23, 0) // Version: 1.22.11
LLStringUtil::format_map_t args;
- args["[MESSAGE]"] = llformat("Restrained Life Support will be %s after you restart",
+ args["[MESSAGE]"] = llformat("RestrainedLove Support will be %s after you restart",
(rlv_handler_t::isEnabled()) ? "disabled" : "enabled" );
gViewerWindow->alertXml("GenericAlert", args);
#else // Version: 1.23.4
LLSD args;
- args["MESSAGE"] = llformat("Restrained Life Support will be %s after you restart",
+ args["MESSAGE"] = llformat("RestrainedLove Support will be %s after you restart",
(rlv_handler_t::isEnabled()) ? "disabled" : "enabled" );
LLNotifications::instance().add("GenericAlert", args);
#endif
--
cgit v1.1