Merged with RLVa tip

Kitty Barnett 2012-08-18 00:08:03 +02:00
commit f1ce3fbee9
17 changed files with 494 additions and 105 deletions

View File

@ -335,3 +335,4 @@ fdcc08a4f20ae9bb060f4693c8980d216534efdf 3.3.3-beta2
af5f3e43e6e4424b1da19d9e16f6b853a7b822ed DRTVWR-169
4b3c68199a86cabaa5d9466d7b0f7e141e901d7a 3.3.3-beta3
6428242e124b523813bfaf4c45b3d422f0298c81 3.3.3-release
0c8f23b2c4cf96d1a08bd527b3ccb6339a9fdb60 RLVa-1.4.6

View File

@ -1507,7 +1507,8 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
// pushWearable(type,new_wearable);
// }
// [RLVa:KB] - Checked: 2010-06-08 (RLVa-1.2.0g) | Added: RLVa-1.2.0g
else if ( (!rlv_handler_t::isEnabled()) || (!gRlvWearableLocks.hasLockedWearable(type)) || (!remove) )
else if ( (!rlv_handler_t::isEnabled()) || (!remove) ||
((gRlvWearableLocks.canWear(type)) && (!gRlvWearableLocks.hasLockedWearable(type))) )
{
// Sanity check: there shouldn't be any worn wearables for this type the first time we encounter it
RLV_ASSERT( (!remove) || (0 != idxCurPerType[type]) || (0 == getWearableCount(type)) );
@ -1521,7 +1522,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
{
// Skip adding if @addoutfit=n restricted *unless* the wearable made it into COF [see LLAppMgr::updateAgentWearables()]
if ( (RLV_WEAR_LOCKED == gRlvWearableLocks.canWear(type)) &&
(!gInventory.isObjectDescendentOf(new_item->getUUID(), LLAppearanceMgr::instance().getCOF())) )
(!LLAppearanceMgr::instance().isLinkInCOF(new_wearable->getItemID())) )
{
continue;
}

View File

@ -32,6 +32,10 @@
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
#include "llviewerinventory.h"
// [RLVa:KB] - Checked: 2012-07-08 (RLVa-1.4.7)
#include "rlvcommon.h"
#include "rlvhandler.h"
// [/RLVa:KB]
//virtual
bool LLPanelAppearanceTab::canTakeOffSelected()
@ -46,6 +50,11 @@ bool LLPanelAppearanceTab::canTakeOffSelected()
LLViewerInventoryItem* item = gInventory.getItem(*it);
if (!item) continue;
// [RLVa:KB] - Checked: 2012-07-08 (RLVa-1.4.7)
if ( (rlv_handler_t::isEnabled()) && (rlvPredCanNotRemoveItem(item)) )
return false;
// [/RLVa:KB]
if (is_worn(NULL, item)) return true;
}
return false;

View File

@ -40,6 +40,10 @@
#include "llwearableitemslist.h"
#include "llsdserialize.h"
#include "llclipboard.h"
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
#include "rlvcommon.h"
#include "rlvhandler.h"
// [/RLVa:KB]
// Context menu and Gear menu helper.
static void edit_outfit()
@ -144,6 +148,9 @@ protected:
bool bp_selected = false; // true if body parts selected
bool clothes_selected = false;
bool attachments_selected = false;
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
S32 rlv_locked_count = 0;
// [/RLVa:KB]
// See what types of wearables are selected.
for (uuid_vec_t::const_iterator it = mUUIDs.begin(); it != mUUIDs.end(); ++it)
@ -169,9 +176,18 @@ protected:
{
attachments_selected = true;
}
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
if ( (rlv_handler_t::isEnabled()) && (!rlvPredCanRemoveItem(item)) )
{
rlv_locked_count++;
}
// [/RLVa:KB]
}
// Enable/disable some menu items depending on the selection.
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
bool rlv_blocked = (mUUIDs.size() == rlv_locked_count);
// [/RLVa:KB]
bool allow_detach = !bp_selected && !clothes_selected && attachments_selected;
bool allow_take_off = !bp_selected && clothes_selected && !attachments_selected;
@ -184,6 +200,10 @@ protected:
// [SL:KB] - Patch: Inventory-AttachmentEdit - Checked: 2010-09-04 (Catznip-2.2.0a) | Added: Catznip-2.1.2a
menu->setItemVisible("take_off_or_detach", (!allow_detach) && (!allow_take_off) && (clothes_selected) && (attachments_selected));
// [/SL:KB]
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
menu->setItemEnabled("take_off", !rlv_blocked);
menu->setItemEnabled("detach", !rlv_blocked);
// [/RLVa:KB]
menu->setItemVisible("edit_outfit_separator", allow_take_off || allow_detach);
}
};

View File

@ -6831,7 +6831,11 @@ void notify_cautioned_script_question(const LLSD& notification, const LLSD& resp
std::string perms;
for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++)
{
if ((orig_questions & LSCRIPTRunTimePermissionBits[i]) && SCRIPT_QUESTION_IS_CAUTION[i])
// if ((orig_questions & LSCRIPTRunTimePermissionBits[i]) && SCRIPT_QUESTION_IS_CAUTION[i])
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
if ( (orig_questions & LSCRIPTRunTimePermissionBits[i]) &&
((SCRIPT_QUESTION_IS_CAUTION[i]) || (notification["payload"]["rlv_notify"].asBoolean())) )
// [/RLVa:KB]
{
count++;
caution = TRUE;
@ -6851,11 +6855,25 @@ void notify_cautioned_script_question(const LLSD& notification, const LLSD& resp
// log a chat message as long as at least one requested permission
// is a caution permission
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
if (caution)
{
LLChat chat(notice.getString());
// LLFloaterChat::addChat(chat, FALSE, FALSE);
LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();
if(nearby_chat)
{
LLChat chat_msg(notice.getString());
chat_msg.mFromName = SYSTEM_FROM;
chat_msg.mFromID = LLUUID::null;
chat_msg.mSourceType = CHAT_SOURCE_SYSTEM;
nearby_chat->addMessage(chat_msg);
}
}
// [/RLVa:KB]
// if (caution)
// {
// LLChat chat(notice.getString());
// // LLFloaterChat::addChat(chat, FALSE, FALSE);
// }
}
}
@ -6901,12 +6919,22 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)
msg->sendReliable(LLHost(notification["payload"]["sender"].asString()));
// only log a chat message if caution prompts are enabled
if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
// if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
if ( (gSavedSettings.getBOOL("PermissionsCautionEnabled")) || (notification["payload"]["rlv_notify"].asBoolean()) )
// [/RLVa:KB]
{
// log a chat message, if appropriate
notify_cautioned_script_question(notification, response, orig, allowed);
}
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
if ( (allowed) && (notification["payload"].has("rlv_blocked")) )
{
RlvUtil::notifyBlocked(notification["payload"]["rlv_blocked"], LLSD().with("OBJECT", notification["payload"]["object_name"]));
}
// [/RLVa:KB]
if ( response["Mute"] ) // mute
{
LLMuteList::getInstance()->add(LLMute(item_id, notification["payload"]["object_name"].asString(), LLMute::OBJECT));
@ -7037,42 +7065,44 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
payload["object_name"] = object_name;
payload["owner_name"] = owner_name;
// [RLVa:KB] - Checked: 2011-07-25 (RLVa-1.4.0a) | Added: RLVa-1.4.0a
if ( (rlv_handler_t::isEnabled()) && (!gRlvAttachmentLocks.canAttach()) )
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
if (rlv_handler_t::isEnabled())
{
// If only the attachment permission is requested we'll auto-deny it; otherwise let the user decide over remaining permissions
if (LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_ATTACH] == questions)
if ( (!gRlvAttachmentLocks.canAttach()) && (LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_ATTACH] & questions) )
{
RlvUtil::notifyBlocked(RLV_STRING_BLOCKED_PERMATTACH, LLSD().with("OBJECT", object_name));
LLNotifications::instance().forceResponse(
LLNotification::Params("ScriptQuestion").substitutions(args).payload(payload), 1/*NO*/);
return;
// Notify the user that we blocked it since they're not allowed to wear any new attachments
payload["rlv_blocked"] = RLV_STRING_BLOCKED_PERMATTACH;
// If only attach is requested we'll auto-deny it; otherwise let the user decide over remaining permissions
if (LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_ATTACH] == questions)
{
payload["questions"] = 0;
LLNotifications::instance().forceResponse(
LLNotification::Params("ScriptQuestion").substitutions(args).payload(payload), 0/*YES*/);
return;
}
else
{
questions &= ~LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_ATTACH];
payload["questions"] = questions;
}
}
else
{
questions &= ~LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_ATTACH];
payload["questions"] = questions;
}
}
// [/RLVa:KB]
// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0e
//<FS:TS> FIRE-6762: Automatically grant sit permissions if same owner
S32 questionsOther = questions;
//</FS:TS> FIRE-6762
if (gRlvHandler.hasBehaviour(RLV_BHVR_ACCEPTPERMISSION))
{
const LLViewerObject* pObj = gObjectList.findObject(taskid);
if (pObj)
if (gRlvHandler.hasBehaviour(RLV_BHVR_ACCEPTPERMISSION))
{
// if (pObj->permYouOwner())
// {
// PERMISSION_TAKE_CONTROLS and PERMISSION_ATTACH are only auto-granted to objects this avie owns
//<FS:TS> FIRE-6762: Automatically grant sit permissions if same owner
questionsOther &= ~(LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TAKE_CONTROLS] |
//</FS:TS> FIRE-6762
LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_ATTACH]);
// }
const LLViewerObject* pObj = gObjectList.findObject(taskid);
if (pObj)
{
if ( (pObj->permYouOwner()) && (!pObj->isAttachment()) )
{
questions &= ~(LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TAKE_CONTROLS] |
LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_ATTACH]);
}
else
{
questions &= ~(LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TAKE_CONTROLS]);
}
payload["rlv_notify"] = !pObj->permYouOwner();
}
}
}
// [SA] Same automatic permissions for the objects owned by the owner of the object the avatar is sat on.
@ -7081,7 +7111,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
{
if (gAgentAvatarp->isSitting() && LLCacheName::cleanFullName(owner_name) == gSitOwnerName)
{
questionsOther &= ~(LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TAKE_CONTROLS] |
questions &= ~(LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TAKE_CONTROLS] |
LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TRIGGER_ANIMATION] |
LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TRACK_CAMERA] |
LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_CONTROL_CAMERA]);
@ -7096,7 +7126,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
}
//</FS:TS> FIRE-6762
// [/SA]
if ( (!caution) && (!questionsOther) )
if ( (!caution) && (!questions) )
{
LLNotifications::instance().forceResponse(
LLNotification::Params("ScriptQuestion").substitutions(args).payload(payload), 0/*YES*/);

View File

@ -180,6 +180,9 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id,
const LLPCode pcode,
LLViewerRegion* regionp) :
LLVOAvatar(id, pcode, regionp),
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
mAttachmentSignal(NULL),
// [/RLVa:KB]
mScreenp(NULL),
mLastRegionHandle(0),
mRegionCrossingCount(0),
@ -799,6 +802,10 @@ void LLVOAvatarSelf::cleanup()
LLVOAvatarSelf::~LLVOAvatarSelf()
{
cleanup();
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
delete mAttachmentSignal;
// [/RLVa:KB]
}
/**
@ -1408,6 +1415,14 @@ LLViewerObject* LLVOAvatarSelf::getWornAttachment(const LLUUID& inv_item_id)
return NULL;
}
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
boost::signals2::connection LLVOAvatarSelf::setAttachmentCallback(const attachment_signal_t::slot_type& cb)
{
if (!mAttachmentSignal)
mAttachmentSignal = new attachment_signal_t();
return mAttachmentSignal->connect(cb);
}
// [/RLVa:KB]
// [RLVa:KB] - Checked: 2010-03-14 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a
LLViewerJointAttachment* LLVOAvatarSelf::getWornAttachmentPoint(const LLUUID& idItem) const
{
@ -1474,6 +1489,10 @@ const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *view
// [RLVa:KB] - Checked: 2010-08-22 (RLVa-1.2.1a) | Modified: RLVa-1.2.1a
// NOTE: RLVa event handlers should be invoked *after* LLVOAvatar::attachObject() calls LLViewerJointAttachment::addObject()
if (mAttachmentSignal)
{
(*mAttachmentSignal)(viewer_object, attachment, ACTION_ATTACH);
}
if (rlv_handler_t::isEnabled())
{
RlvAttachmentLockWatchdog::instance().onAttach(viewer_object, attachment);
@ -1515,6 +1534,10 @@ BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object)
RlvAttachmentLockWatchdog::instance().onDetach(viewer_object, pAttachPt);
gRlvHandler.onDetach(viewer_object, pAttachPt);
}
if (mAttachmentSignal)
{
(*mAttachmentSignal)(viewer_object, pAttachPt, ACTION_DETACH);
}
//-TT Client LSL Bridge
if (pAttachPt->getName() == "Bridge" && gSavedSettings.getBOOL("UseLSLBridge"))

View File

@ -313,9 +313,17 @@ public:
/*virtual*/ BOOL detachObject(LLViewerObject *viewer_object);
static BOOL detachAttachmentIntoInventory(const LLUUID& item_id);
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
enum EAttachAction { ACTION_ATTACH, ACTION_DETACH };
typedef boost::signals2::signal<void (LLViewerObject*, const LLViewerJointAttachment*, EAttachAction)> attachment_signal_t;
boost::signals2::connection setAttachmentCallback(const attachment_signal_t::slot_type& cb);
// [/RLVa:KB]
private:
// Track attachments that have been requested but have not arrived yet.
mutable std::map<LLUUID,LLTimer> mAttachmentRequests;
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
attachment_signal_t* mAttachmentSignal;
// [/RLVa:KB]
//--------------------------------------------------------------------
// HUDs

View File

@ -224,6 +224,8 @@ const char* RlvStrings::getStringFromReturnCode(ERlvCmdRet eRet)
return "unset";
case RLV_RET_SUCCESS_DUPLICATE:
return "duplicate";
case RLV_RET_SUCCESS_DELAYED:
return "delayed";
case RLV_RET_FAILED_SYNTAX:
return "thingy error";
case RLV_RET_FAILED_OPTION:

View File

@ -66,7 +66,7 @@ const S32 RLV_VERSION_BUILD = 0;
// Implementation version
const S32 RLVa_VERSION_MAJOR = 1;
const S32 RLVa_VERSION_MINOR = 4;
const S32 RLVa_VERSION_PATCH = 6;
const S32 RLVa_VERSION_PATCH = 7;
const S32 RLVa_VERSION_BUILD = 0;
// Uncomment before a final release
@ -245,6 +245,7 @@ enum ERlvCmdRet {
RLV_RET_SUCCESS = 0x0100, // Command executed succesfully
RLV_RET_SUCCESS_UNSET, // Command executed succesfully (RLV_TYPE_REMOVE for an unrestricted behaviour)
RLV_RET_SUCCESS_DUPLICATE, // Command executed succesfully (RLV_TYPE_ADD for an already restricted behaviour)
RLV_RET_SUCCESS_DELAYED, // Command parsed valid but will execute at a later time
RLV_RET_FAILED = 0x0200, // Command failed (general failure)
RLV_RET_FAILED_SYNTAX, // Command failed (syntax error)
RLV_RET_FAILED_OPTION, // Command failed (invalid option)

View File

@ -15,8 +15,10 @@
*/
#include "llviewerprecompiledheaders.h"
#include "llappearancemgr.h"
#include "llavatarnamecache.h"
#include "llclipboard.h"
#include "llinventoryfunctions.h"
#include "llscrolllistctrl.h"
#include "llviewerjointattachment.h"
#include "llviewerobjectlist.h"
@ -31,6 +33,35 @@
// Helper functions
//
// Checked: 2012-07-14 (RLVa-1.4.7)
std::string rlvGetItemName(const LLViewerInventoryItem* pItem)
{
if ( (pItem) && ((LLAssetType::AT_BODYPART == pItem->getType()) || (LLAssetType::AT_CLOTHING == pItem->getType())) )
return llformat("%s (%s)", pItem->getName().c_str(), LLWearableType::getTypeName(pItem->getWearableType()).c_str());
else if ( (pItem) && (LLAssetType::AT_OBJECT == pItem->getType()) && (isAgentAvatarValid()) )
return llformat("%s (%s)", pItem->getName().c_str(), gAgentAvatarp->getAttachedPointName(pItem->getUUID()).c_str());
return (pItem) ? pItem->getName() : LLStringUtil::null;
}
// Checked: 2012-07-14 (RLVa-1.4.7)
std::string rlvGetItemType(const LLViewerInventoryItem* pItem)
{
if (pItem)
{
switch (pItem->getType())
{
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
return "Wearable";
case LLAssetType::AT_OBJECT:
return "Attachment";
default:
break;
}
}
return "Unknown";
}
// Checked: 2010-03-11 (RLVa-1.2.0a) | Modified: RLVa-1.2.0g
std::string rlvGetItemNameFromObjID(const LLUUID& idObj, bool fIncludeAttachPt = true)
{
@ -66,6 +97,88 @@ bool rlvGetShowException(ERlvBehaviour eBhvr)
}
}
// Checked: 2012-07-29 (RLVa-1.4.7)
std::string rlvLockMaskToString(ERlvLockMask eLockType)
{
switch (eLockType)
{
case RLV_LOCK_ADD:
return "add";
case RLV_LOCK_REMOVE:
return "rem";
default:
return "unknown";
}
}
// Checked: 2012-07-29 (RLVa-1.4.7)
std::string rlvFolderLockPermissionToString(RlvFolderLocks::ELockPermission eLockPermission)
{
switch (eLockPermission)
{
case RlvFolderLocks::PERM_ALLOW:
return "allow";
case RlvFolderLocks::PERM_DENY:
return "deny";
default:
return "unknown";
}
}
// Checked: 2012-07-29 (RLVa-1.4.7)
std::string rlvFolderLockScopeToString(RlvFolderLocks::ELockScope eLockScope)
{
switch (eLockScope)
{
case RlvFolderLocks::SCOPE_NODE:
return "node";
case RlvFolderLocks::SCOPE_SUBTREE:
return "subtree";
default:
return "unknown";
}
}
// Checked: 2012-07-29 (RLVa-1.4.7)
std::string rlvFolderLockSourceToTarget(RlvFolderLocks::folderlock_source_t lockSource)
{
switch (lockSource.first)
{
case RlvFolderLocks::ST_ATTACHMENT:
{
std::string strAttachName = rlvGetItemNameFromObjID(boost::get<LLUUID>(lockSource.second));
return llformat("Attachment (%s)", strAttachName.c_str());
}
case RlvFolderLocks::ST_ATTACHMENTPOINT:
{
const LLViewerJointAttachment* pAttachPt = RlvAttachPtLookup::getAttachPoint(boost::get<S32>(lockSource.second));
return llformat("Attachment point (%s)", (pAttachPt) ? pAttachPt->getName().c_str() : "Unknown");
}
case RlvFolderLocks::ST_FOLDER:
{
return "Folder: <todo>";
}
case RlvFolderLocks::ST_ROOTFOLDER:
{
return "Root folder";
}
case RlvFolderLocks::ST_SHAREDPATH:
{
const std::string& strPath = boost::get<std::string>(lockSource.second);
return llformat("Shared path (#RLV%s%s)", (!strPath.empty()) ? "/" : "", strPath.c_str());
}
case RlvFolderLocks::ST_WEARABLETYPE:
{
const std::string& strTypeName = LLWearableType::getTypeName(boost::get<LLWearableType::EType>(lockSource.second));
return llformat("Wearable type (%s)", strTypeName.c_str());
}
default:
{
return "(Unknown)";
}
}
}
// ============================================================================
// RlvFloaterBehaviours member functions
//
@ -232,7 +345,7 @@ void RlvFloaterBehaviours::refreshAll()
// RlvFloaterLocks member functions
//
// Checked: 2010-03-11 (RLVa-1.2.0a) | Added: RLVa-1.2.0a
// Checked: 2010-03-11 (RLVa-1.2.0)
void RlvFloaterLocks::onOpen(const LLSD& sdKey)
{
m_ConnRlvCommand = gRlvHandler.setCommandCallback(boost::bind(&RlvFloaterLocks::onRlvCommand, this, _1, _2));
@ -240,12 +353,20 @@ void RlvFloaterLocks::onOpen(const LLSD& sdKey)
refreshAll();
}
// Checked: 2010-03-11 (RLVa-1.2.0a) | Added: RLVa-1.2.0a
// Checked: 2010-03-11 (RLVa-1.2.0)
void RlvFloaterLocks::onClose(bool fQuitting)
{
m_ConnRlvCommand.disconnect();
}
// Checked: 2012-07-14 (RLVa-1.4.7)
BOOL RlvFloaterLocks::postBuild()
{
getChild<LLUICtrl>("refresh_btn")->setCommitCallback(boost::bind(&RlvFloaterLocks::refreshAll, this));
return TRUE;
}
// Checked: 2010-03-11 (RLVa-1.2.0a) | Added: RLVa-1.2.0a
void RlvFloaterLocks::onRlvCommand(const RlvCommand& rlvCmd, ERlvCmdRet eRet)
{
@ -267,12 +388,10 @@ void RlvFloaterLocks::onRlvCommand(const RlvCommand& rlvCmd, ERlvCmdRet eRet)
}
}
// Checked: 2010-03-18 (RLVa-1.2.0a) | Added: RLVa-1.2.0a
// Checked: 2010-03-18 (RLVa-1.2.0)
void RlvFloaterLocks::refreshAll()
{
LLCtrlListInterface* pLockList = childGetListInterface("lock_list");
if (!pLockList)
return;
LLScrollListCtrl* pLockList = getChild<LLScrollListCtrl>("lock_list");
pLockList->operateOnAll(LLCtrlListInterface::OP_DELETE);
if (!isAgentAvatarValid())
@ -361,6 +480,76 @@ void RlvFloaterLocks::refreshAll()
pLockList->addElement(sdRow, ADD_BOTTOM);
}
//
// List "nostrip" (soft) locks
//
sdColumns[1]["value"] = "nostrip";
sdColumns[3]["value"] = "(Agent)";
LLInventoryModel::cat_array_t folders; LLInventoryModel::item_array_t items;
LLFindWearablesEx f(true, true);
gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), folders, items, FALSE, f);
for (LLInventoryModel::item_array_t::const_iterator itItem = items.begin(); itItem != items.end(); ++itItem)
{
const LLViewerInventoryItem* pItem = *itItem;
if (!RlvForceWear::instance().isStrippable(pItem->getUUID()))
{
sdColumns[0]["value"] = rlvGetItemType(pItem);
sdColumns[2]["value"] = rlvGetItemName(pItem);
pLockList->addElement(sdRow, ADD_BOTTOM);
}
}
//
// List folder locks
//
{
// Folder lock descriptors
const RlvFolderLocks::folderlock_list_t& folderLocks = RlvFolderLocks::instance().getFolderLocks();
for (RlvFolderLocks::folderlock_list_t::const_iterator itFolderLock = folderLocks.begin();
itFolderLock != folderLocks.end(); ++itFolderLock)
{
const RlvFolderLocks::folderlock_descr_t* pLockDescr = *itFolderLock;
if (pLockDescr)
{
sdColumns[0]["value"] = "Folder Descriptor";
sdColumns[1]["value"] =
rlvLockMaskToString(pLockDescr->eLockType) + "/" +
rlvFolderLockPermissionToString(pLockDescr->eLockPermission) + "/" +
rlvFolderLockScopeToString(pLockDescr->eLockScope);
sdColumns[2]["value"] = rlvFolderLockSourceToTarget(pLockDescr->lockSource);
sdColumns[3]["value"] = rlvGetItemNameFromObjID(pLockDescr->idRlvObj);
pLockList->addElement(sdRow, ADD_BOTTOM);
}
}
}
{
// Folder locked attachments and wearables
uuid_vec_t idItems;
const uuid_vec_t& folderLockAttachmentsIds = RlvFolderLocks::instance().getAttachmentLookups();
idItems.insert(idItems.end(), folderLockAttachmentsIds.begin(), folderLockAttachmentsIds.end());
const uuid_vec_t& folderLockWearabels = RlvFolderLocks::instance().getWearableLookups();
idItems.insert(idItems.end(), folderLockWearabels.begin(), folderLockWearabels.end());
for (uuid_vec_t::const_iterator itItemId = idItems.begin(); itItemId != idItems.end(); ++itItemId)
{
const LLViewerInventoryItem* pItem = gInventory.getItem(*itItemId);
if (pItem)
{
sdColumns[0]["value"] = rlvGetItemType(pItem);
sdColumns[1]["value"] = rlvLockMaskToString(RLV_LOCK_REMOVE);
sdColumns[2]["value"] = rlvGetItemName(pItem);
sdColumns[3]["value"] = "<Folder Lock>";
pLockList->addElement(sdRow, ADD_BOTTOM);
}
}
}
}
// ============================================================================

View File

@ -71,19 +71,15 @@ private:
* LLFloater overrides
*/
public:
virtual void onOpen(const LLSD& sdKey);
virtual void onClose(bool fQuitting);
/*
* Event handlers
*/
protected:
void onRlvCommand(const RlvCommand& rlvCmd, ERlvCmdRet eRet);
/*virtual*/ void onOpen(const LLSD& sdKey);
/*virtual*/ void onClose(bool fQuitting);
/*virtual*/ BOOL postBuild();
/*
* Member functions
*/
protected:
void onRlvCommand(const RlvCommand& rlvCmd, ERlvCmdRet eRet);
void refreshAll();
/*

View File

@ -1645,15 +1645,9 @@ ERlvCmdRet RlvHandler::processForceCommand(const RlvCommand& rlvCmd) const
case RLV_BHVR_ATTACHALLTHISOVER:
case RLV_BHVR_DETACHALLTHIS:
{
RlvCommandOptionGetPath rlvGetPathOption(rlvCmd);
RlvCommandOptionGetPath rlvGetPathOption(rlvCmd, boost::bind(&RlvHandler::onForceWearCallback, this, _1, rlvCmd.getBehaviourType()));
VERIFY_OPTION(rlvGetPathOption.isValid());
LLInventoryModel::cat_array_t folders;
if (RlvInventory::instance().getPath(rlvGetPathOption.getItemIDs(), folders))
{
for (S32 idxFolder = 0, cntFolder = folders.count(); idxFolder < cntFolder; idxFolder++)
onForceWear(folders.get(idxFolder), rlvCmd.getBehaviourType());
}
eRet = (!rlvGetPathOption.isCallback()) ? RLV_RET_SUCCESS : RLV_RET_SUCCESS_DELAYED;
}
break;
case RLV_BHVR_DETACHME: // @detachme=force - Checked: 2010-09-04 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c
@ -1811,6 +1805,20 @@ ERlvCmdRet RlvHandler::onForceWear(const LLViewerInventoryCategory* pFolder, ERl
return RLV_RET_SUCCESS;
}
void RlvHandler::onForceWearCallback(const uuid_vec_t& idItems, ERlvBehaviour eBhvr) const
{
LLInventoryModel::cat_array_t folders;
if (RlvInventory::instance().getPath(idItems, folders))
{
for (S32 idxFolder = 0, cntFolder = folders.count(); idxFolder < cntFolder; idxFolder++)
onForceWear(folders.get(idxFolder), eBhvr);
// If we're not executing a command then we're a delayed callback and need to manually call done()
if ( (!getCurrentCommand()) && (RlvForceWear::instanceExists()) )
RlvForceWear::instance().done();
}
}
// ============================================================================
// Command handlers (RLV_TYPE_REPLY)
//

View File

@ -173,6 +173,7 @@ protected:
ERlvCmdRet onForceGroup(const RlvCommand& rlvCmd) const;
ERlvCmdRet onForceSit(const RlvCommand& rlvCmd) const;
ERlvCmdRet onForceWear(const LLViewerInventoryCategory* pFolder, ERlvBehaviour eBhvr) const;
void onForceWearCallback(const uuid_vec_t& idItems, ERlvBehaviour eBhvr) const;
// Command handlers (RLV_TYPE_REPLY)
ERlvCmdRet processReplyCommand(const RlvCommand& rlvCmd) const;
ERlvCmdRet onFindFolder(const RlvCommand& rlvCmd, std::string& strReply) const;

View File

@ -210,8 +210,52 @@ RlvCommandOptionGeneric::RlvCommandOptionGeneric(const std::string& strOption)
m_fValid = true;
}
// Checked: 2012-07-28 (RLVa-1.4.7)
class RlvCommandOptionGetPathCallback
{
public:
RlvCommandOptionGetPathCallback(const LLUUID& idAttachObj, RlvCommandOptionGetPath::getpath_callback_t cb)
: mObjectId(idAttachObj), mCallback(cb)
{
if (isAgentAvatarValid())
mAttachmentConnection = gAgentAvatarp->setAttachmentCallback(boost::bind(&RlvCommandOptionGetPathCallback::onAttachment, this, _1, _3));
gIdleCallbacks.addFunction(&onIdle, this);
}
~RlvCommandOptionGetPathCallback()
{
if (mAttachmentConnection.connected())
mAttachmentConnection.disconnect();
gIdleCallbacks.deleteFunction(&onIdle, this);
}
void onAttachment(LLViewerObject* pAttachObj, LLVOAvatarSelf::EAttachAction eAction)
{
if ( (LLVOAvatarSelf::ACTION_ATTACH == eAction) && (pAttachObj->getID() == mObjectId) )
{
uuid_vec_t idItems(1, pAttachObj->getAttachmentItemID());
mCallback(idItems);
delete this;
}
}
static void onIdle(void* pData)
{
RlvCommandOptionGetPathCallback* pInstance = reinterpret_cast<RlvCommandOptionGetPathCallback*>(pData);
if (pInstance->mExpirationTimer.getElapsedTimeF32() > 30.0f)
delete pInstance;
}
protected:
LLUUID mObjectId;
RlvCommandOptionGetPath::getpath_callback_t mCallback;
boost::signals2::connection mAttachmentConnection;
LLFrameTimer mExpirationTimer;
};
// Checked: 2010-11-30 (RLVa-1.3.0b) | Modified: RLVa-1.3.0b
RlvCommandOptionGetPath::RlvCommandOptionGetPath(const RlvCommand& rlvCmd)
RlvCommandOptionGetPath::RlvCommandOptionGetPath(const RlvCommand& rlvCmd, getpath_callback_t cb)
: m_fCallback(false)
{
m_fValid = true; // Assume the option will be a valid one until we find out otherwise
@ -228,12 +272,27 @@ RlvCommandOptionGetPath::RlvCommandOptionGetPath(const RlvCommand& rlvCmd)
else if (rlvCmdOption.isEmpty()) // ... or it can be empty (in which case we act on the object that issued the command)
{
const LLViewerObject* pObj = gObjectList.findObject(rlvCmd.getObjectID());
if ( (pObj) || (pObj->isAttachment()) )
m_idItems.push_back(pObj->getAttachmentItemID());
if (pObj)
{
if (pObj->isAttachment())
m_idItems.push_back(pObj->getAttachmentItemID());
}
else if (!cb.empty())
{
new RlvCommandOptionGetPathCallback(rlvCmd.getObjectID(), cb);
m_fCallback = true;
return;
}
}
else // ... but anything else isn't a valid option
{
m_fValid = false;
return;
}
if (!cb.empty())
{
cb(getItemIDs());
}
}
@ -437,6 +496,9 @@ void RlvForceWear::forceFolder(const LLViewerInventoryCategory* pFolder, EWearAc
RlvWearableItemCollector f(pFolder, eAction, eFlags);
gInventory.collectDescendentsIf(pFolder->getUUID(), folders, items, FALSE, f, TRUE);
// TRUE if we've already encountered this LLWearableType::EType (used only on wear actions and only for AT_CLOTHING)
bool fSeenWType[LLWearableType::WT_COUNT] = { false };
EWearAction eCurAction = eAction;
for (S32 idxItem = 0, cntItem = items.count(); idxItem < cntItem; idxItem++)
{
@ -450,6 +512,8 @@ void RlvForceWear::forceFolder(const LLViewerInventoryCategory* pFolder, EWearAc
// Each folder can specify its own EWearAction override
if (isWearAction(eAction))
eCurAction = f.getWearAction(pRlvItem->getParentUUID());
else
eCurAction = eAction;
// 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
@ -460,6 +524,10 @@ void RlvForceWear::forceFolder(const LLViewerInventoryCategory* pFolder, EWearAc
case LLAssetType::AT_CLOTHING:
if (isWearAction(eAction))
{
// The first time we encounter any given clothing type we use 'eCurAction' (replace or add)
// The second time we encounter a given clothing type we'll always add (rather than replace the previous iteration)
eCurAction = (!fSeenWType[pItem->getWearableType()]) ? eCurAction : ACTION_WEAR_ADD;
ERlvWearMask eWearMask = gRlvWearableLocks.canWear(pRlvItem);
if ( ((ACTION_WEAR_REPLACE == eCurAction) && (eWearMask & RLV_WEAR_REPLACE)) ||
((ACTION_WEAR_ADD == eCurAction) && (eWearMask & RLV_WEAR_ADD)) )
@ -467,6 +535,7 @@ void RlvForceWear::forceFolder(const LLViewerInventoryCategory* pFolder, EWearAc
// The check for whether we're replacing a currently worn composite item happens in onWearableArrived()
if (!isAddWearable(pItem))
addWearable(pRlvItem, eCurAction);
fSeenWType[pItem->getWearableType()] = true;
}
}
else
@ -698,13 +767,15 @@ bool RlvForceWear::isStrippable(const LLInventoryItem* pItem)
}
LLViewerInventoryCategory* pFolder = gInventory.getCategory(pItem->getParentUUID());
while ( (pFolder) && (gInventory.getRootFolderID() != pFolder->getParentUUID()) )
while (pFolder)
{
if (std::string::npos != pFolder->getName().find(RLV_FOLDER_FLAG_NOSTRIP))
return false;
// If the item's parent is a folded folder then we need to check its parent as well
pFolder =
(RlvInventory::isFoldedFolder(pFolder, true)) ? gInventory.getCategory(pFolder->getParentUUID()) : NULL;
if ( (gInventory.getRootFolderID() != pFolder->getParentUUID()) && (RlvInventory::isFoldedFolder(pFolder, true)) )
pFolder = gInventory.getCategory(pFolder->getParentUUID());
else
pFolder = NULL;
}
}
return true;

View File

@ -137,8 +137,10 @@ protected:
struct RlvCommandOptionGetPath : public RlvCommandOption
{
RlvCommandOptionGetPath(const RlvCommand& rlvCmd);
typedef boost::function<void(const uuid_vec_t&)> getpath_callback_t;
RlvCommandOptionGetPath(const RlvCommand& rlvCmd, getpath_callback_t cb = NULL);
bool isCallback() const { return m_fCallback; }
/*virtual*/ bool isEmpty() const { return m_idItems.empty(); }
const uuid_vec_t& getItemIDs() const { return m_idItems; }
@ -146,6 +148,7 @@ struct RlvCommandOptionGetPath : public RlvCommandOption
static bool getItemIDs(LLWearableType::EType wtType, uuid_vec_t& idItems, bool fClear = true);
protected:
bool m_fCallback; // TRUE if a callback is schedueled
uuid_vec_t m_idItems;
};

View File

@ -297,7 +297,7 @@ public:
// Specifies options for the folder lock
enum ELockPermission { PERM_ALLOW = 0x1, PERM_DENY = 0x2, PERM_MASK_ANY = 0x3 };
enum ELockScope { SCOPE_NODE, SCOPE_SUBTREE } ;
protected:
struct folderlock_descr_t
{
LLUUID idRlvObj;
@ -360,9 +360,14 @@ protected:
/*
* Member variables
*/
public:
typedef std::list<const folderlock_descr_t*> folderlock_list_t;
// Accessors for RlvFloaterLocks
const folderlock_list_t& getFolderLocks() { return m_FolderLocks; }
const uuid_vec_t& getAttachmentLookups() { return m_LockedAttachmentRem; }
const uuid_vec_t& getWearableLookups() { return m_LockedWearableRem; }
protected:
// Map of folder locks (idRlvObj -> lockDescr)
typedef std::list<const folderlock_descr_t*> folderlock_list_t;
folderlock_list_t m_FolderLocks; // List of add and remove locked folder descriptions
S32 m_cntLockAdd; // Number of RLV_LOCK_ADD locked folders in m_FolderLocks
S32 m_cntLockRem; // Number of RLV_LOCK_REMOVE locked folders in m_FolderLocks

View File

@ -1,43 +1,64 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
can_close="true"
can_drag_on_left="false"
can_minimize="true"
can_resize="true"
height="425"
min_height="200"
min_width="375"
height="400"
min_height="300"
min_width="500"
name="rlvLocks"
title="ACTIVE RLV LOCKS"
width="350"
save_rect="true"
save_visibility="true"
single_instance="true">
<scroll_list
top="0"
draw_border="false"
follows="top|left|bottom|right"
height="400"
multi_select="false"
name="lock_list"
draw_heading="true"
draw_stripes="true"
layout="topleft">
<scroll_list.columns
label="Lock Type"
name="lock_type"
width="110" />
<scroll_list.columns
label="Add / Rem"
name="lock_addrem"
width="75" />
<scroll_list.columns
label="Lock Target"
name="lock_target"
width="150" />
<scroll_list.columns
label="Held By"
name="lock_origin"
width="150" />
</scroll_list>
single_instance="true"
title="Active RLV Locks"
width="500">
<scroll_list
background_visible="false"
draw_border="false"
draw_heading="true"
draw_stripes="true"
follows="all"
height="373"
layout="topleft"
multi_select="false"
name="lock_list"
top="0"
width="500">
<scroll_list.columns label="Lock Type" name="lock_type" width="110" />
<scroll_list.columns label="Add / Rem" name="lock_addrem" width="75" />
<scroll_list.columns label="Lock Target" name="lock_target" width="150" />
<scroll_list.columns label="Held By" name="lock_origin" width="150" />
</scroll_list>
<panel
background_visible="false"
follows="left|right|bottom"
height="27"
layout="topleft"
left="0"
name="bottom_panel"
top_pad="0"
width="500">
<button
follows="bottom|left"
height="25"
image_hover_unselected="Toolbar_Left_Over"
image_overlay="Refresh_Off"
image_overlay_alignment="left"
image_selected="Toolbar_Left_Selected"
image_unselected="Toolbar_Left_Off"
label="Refresh"
layout="topleft"
left="0"
name="refresh_btn"
top="1"
width="74" />
<icon
follows="bottom|left|right"
height="25"
image_name="Toolbar_Right_Off"
layout="topleft"
left_pad="1"
name="dummy_icon"
width="425"/>
</panel>
</floater>