aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden
diff options
context:
space:
mode:
Diffstat (limited to 'linden')
-rw-r--r--linden/indra/newview/llagent.cpp4
-rw-r--r--linden/indra/newview/llfloateropenobject.cpp13
-rw-r--r--linden/indra/newview/llinventorybridge.cpp159
-rw-r--r--linden/indra/newview/llpanelcontents.cpp8
-rw-r--r--linden/indra/newview/llpanelinventory.cpp51
-rw-r--r--linden/indra/newview/llpreviewscript.cpp12
-rw-r--r--linden/indra/newview/lltooldraganddrop.cpp10
-rw-r--r--linden/indra/newview/llviewerdisplay.cpp4
-rw-r--r--linden/indra/newview/llviewermenu.cpp106
-rw-r--r--linden/indra/newview/llviewertexteditor.cpp7
-rw-r--r--linden/indra/newview/llvoavatar.cpp31
-rw-r--r--linden/indra/newview/llvovolume.cpp8
-rw-r--r--linden/indra/newview/pipeline.cpp4
-rw-r--r--linden/indra/newview/rlvdefines.h21
-rw-r--r--linden/indra/newview/rlvextensions.cpp2
-rw-r--r--linden/indra/newview/rlvhandler.cpp519
-rw-r--r--linden/indra/newview/rlvhandler.h139
-rw-r--r--linden/indra/newview/rlvhelper.cpp257
-rw-r--r--linden/indra/newview/rlvhelper.h78
19 files changed, 905 insertions, 528 deletions
diff --git a/linden/indra/newview/llagent.cpp b/linden/indra/newview/llagent.cpp
index 8b118e0..a0ab4ab 100644
--- a/linden/indra/newview/llagent.cpp
+++ b/linden/indra/newview/llagent.cpp
@@ -7761,7 +7761,7 @@ void LLAgent::userRemoveAllAttachments( void* userdata )
7761 return; 7761 return;
7762 } 7762 }
7763 7763
7764// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.0c 7764// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
7765 // NOTE-RLVa: This function is called from inside RlvHandler as well, hence the rather heavy modifications 7765 // NOTE-RLVa: This function is called from inside RlvHandler as well, hence the rather heavy modifications
7766 std::list<U32> rlvAttachments; 7766 std::list<U32> rlvAttachments;
7767 // TODO-RLVa: Once we have the improved "removeWearable" logic implemented we can just get rid of the whole "rlvCompFolders" hassle 7767 // TODO-RLVa: Once we have the improved "removeWearable" logic implemented we can just get rid of the whole "rlvCompFolders" hassle
@@ -7779,7 +7779,7 @@ void LLAgent::userRemoveAllAttachments( void* userdata )
7779 { 7779 {
7780 if (rlv_handler_t::isEnabled()) 7780 if (rlv_handler_t::isEnabled())
7781 { 7781 {
7782 if (!gRlvHandler.isDetachable(curiter->first)) 7782 if (gRlvHandler.isLockedAttachment(curiter->first, RLV_LOCK_REMOVE))
7783 continue; 7783 continue;
7784 7784
7785 // Check if we're being called in response to an RLV command (that would be @detach=force) 7785 // Check if we're being called in response to an RLV command (that would be @detach=force)
diff --git a/linden/indra/newview/llfloateropenobject.cpp b/linden/indra/newview/llfloateropenobject.cpp
index fd4f9c6..a83b0c9 100644
--- a/linden/indra/newview/llfloateropenobject.cpp
+++ b/linden/indra/newview/llfloateropenobject.cpp
@@ -207,18 +207,7 @@ void LLFloaterOpenObject::onClickMoveToInventory(void* data)
207void LLFloaterOpenObject::onClickMoveAndWear(void* data) 207void LLFloaterOpenObject::onClickMoveAndWear(void* data)
208{ 208{
209 LLFloaterOpenObject* self = (LLFloaterOpenObject*)data; 209 LLFloaterOpenObject* self = (LLFloaterOpenObject*)data;
210// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Deprecated: RLVa-0.2.2a 210 self->moveToInventory(true);
211 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) )
212 {
213 // TODO-RLVa: once we have "Add to Outfit" and "Replace Outfit" working we don't need this anymore
214 self->moveToInventory(false);
215 }
216 else
217 {
218 self->moveToInventory(true);
219 }
220// [/RLVa:KB]
221// self->moveToInventory(true);
222 self->close(); 211 self->close();
223} 212}
224 213
diff --git a/linden/indra/newview/llinventorybridge.cpp b/linden/indra/newview/llinventorybridge.cpp
index 5060d21..f706ad6 100644
--- a/linden/indra/newview/llinventorybridge.cpp
+++ b/linden/indra/newview/llinventorybridge.cpp
@@ -488,6 +488,20 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
488 items.push_back(std::string("Open")); 488 items.push_back(std::string("Open"));
489 items.push_back(std::string("Properties")); 489 items.push_back(std::string("Properties"));
490 490
491// [RLVa:KB] - Checked: 2009-10-13 (RLVa-1.0.5c) | Modified: RLVa-1.0.5c
492 if (rlv_handler_t::isEnabled())
493 {
494 LLInventoryObject* pItem = (mInventoryPanel->getModel()) ? mInventoryPanel->getModel()->getObject(mUUID) : NULL;
495 if ( (pItem) &&
496 ( ((LLAssetType::AT_NOTECARD == pItem->getType()) && (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWNOTE))) ||
497 ((LLAssetType::AT_LSL_TEXT == pItem->getType()) && (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWSCRIPT))) ||
498 ((LLAssetType::AT_NOTECARD == pItem->getType()) && (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWTEXTURE))) ) )
499 {
500 disabled_items.push_back(std::string("Open"));
501 }
502 }
503// [/RLVa:KB]
504
491 getClipboardEntries(true, items, disabled_items, flags); 505 getClipboardEntries(true, items, disabled_items, flags);
492 } 506 }
493 hideContextEntries(menu, items, disabled_items); 507 hideContextEntries(menu, items, disabled_items);
@@ -2446,6 +2460,13 @@ void open_texture(const LLUUID& item_id,
2446 const LLUUID& source_id, 2460 const LLUUID& source_id,
2447 BOOL take_focus) 2461 BOOL take_focus)
2448{ 2462{
2463// [RLVa:KB] - Checked: 2009-10-13 (RLVa-1.0.5c) | Added: RLVa-1.0.5c
2464 if (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWTEXTURE))
2465 {
2466 return;
2467 }
2468// [/RLVa:KB]
2469
2449 // See if we can bring an exiting preview to the front 2470 // See if we can bring an exiting preview to the front
2450 if( !LLPreview::show( item_id, take_focus ) ) 2471 if( !LLPreview::show( item_id, take_focus ) )
2451 { 2472 {
@@ -3274,11 +3295,11 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model
3274 item = (LLViewerInventoryItem*)gInventory.getItem(object_id); 3295 item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
3275 if(item && gInventory.isObjectDescendentOf(object_id, gAgent.getInventoryRootID())) 3296 if(item && gInventory.isObjectDescendentOf(object_id, gAgent.getInventoryRootID()))
3276 { 3297 {
3277// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 3298// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
3278 // User picked "Wear" so either nothing is locked, or we need to look up the specific attach point from its name 3299 // User picked "Wear" so either nothing is locked, or we need to look up the specific attach point from its name
3279 // (NOTE: rez_attachment will take care of deciding whether or not we *can* attach) 3300 // (NOTE: rez_attachment will take care of deciding whether or not we *can* attach)
3280 rez_attachment(item, 3301 rez_attachment(item,
3281 ((!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedAttachment()) || (RlvSettings::getEnableWear())) 3302 ((!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedAttachment(RLV_LOCK_ANY)) || (RlvSettings::getEnableWear()))
3282 ? NULL : gRlvHandler.getAttachPoint(item, true)); 3303 ? NULL : gRlvHandler.getAttachPoint(item, true));
3283// [/RLVa:KB] 3304// [/RLVa:KB]
3284// rez_attachment(item, NULL); 3305// rez_attachment(item, NULL);
@@ -3301,9 +3322,9 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model
3301 { 3322 {
3302 LLInventoryItem* item = gInventory.getItem(mUUID); 3323 LLInventoryItem* item = gInventory.getItem(mUUID);
3303 3324
3304// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 3325// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
3305 // Fall-through: if there's a "Detach from yourself" code path we missed then we'll still disallow the detach here 3326 // Fall-through: if there's a "Detach from yourself" code path we missed then we'll still disallow the detach here
3306 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(item)) ) 3327 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.isLockedAttachment(item, RLV_LOCK_REMOVE)) )
3307 { 3328 {
3308 return; 3329 return;
3309 } 3330 }
@@ -3398,24 +3419,38 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach
3398 rez_action->mAttachPt = attach_pt; 3419 rez_action->mAttachPt = attach_pt;
3399 if (attachment && attachment->getObject()) 3420 if (attachment && attachment->getObject())
3400 { 3421 {
3401// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) 3422// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
3402 if ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isDetachable(attach_pt)) ) 3423 if ( (rlv_handler_t::isEnabled()) && // Can't replace an existing object if it's undetachable
3403 gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action); 3424 (gRlvHandler.isLockedAttachment(attach_pt, RLV_LOCK_ANY)) ) // or if we're not allowed to attach to that attach point
3404 else 3425 {
3405 delete rez_action; 3426 delete rez_action;
3406// [/RLVa] 3427 return;
3407// gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action); 3428 }
3429// [/RLVa:KB]
3430 gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action);
3408 } 3431 }
3409 else 3432 else
3410 { 3433 {
3411// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) 3434// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-10-10 (RLVa-1.0.5) | Modified: RLVa-1.0.5
3412 // Don't allow wear to default attach point if there are any locked attachments 3435 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_ANY)) )
3413 if ( (!rlv_handler_t::isEnabled()) || (0 != attach_pt) || (!gRlvHandler.hasLockedAttachment()) || (RlvSettings::getEnableWear()) ) 3436 {
3414 confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action); 3437 if (0 == attach_pt) // Can't wear on the default attachment point
3415 else 3438 {
3416 delete rez_action; 3439 if (!RlvSettings::getEnableWear()) // (unless "Enable Wear" is enabled)
3417// [/RLVa] 3440 {
3418// confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action); 3441 delete rez_action;
3442 return;
3443 }
3444 gRlvHandler.onWearAttachment(item->getUUID());
3445 }
3446 else if (gRlvHandler.isLockedAttachment(attach_pt, RLV_LOCK_ADD)) // and we can never wear on a non-attachable attach point
3447 {
3448 delete rez_action;
3449 return;
3450 }
3451 }
3452// [/RLVa:KB]
3453 confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action);
3419 } 3454 }
3420} 3455}
3421 3456
@@ -3485,9 +3520,12 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
3485 { 3520 {
3486 items.push_back(std::string("Detach From Yourself")); 3521 items.push_back(std::string("Detach From Yourself"));
3487 3522
3488// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 3523// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
3489 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(item)) ) 3524 if ( (rlv_handler_t::isEnabled()) &&
3525 (gRlvHandler.hasLockedAttachment(RLV_LOCK_REMOVE)) && (gRlvHandler.isLockedAttachment(item, RLV_LOCK_REMOVE)) )
3526 {
3490 disabled_items.push_back(std::string("Detach From Yourself")); 3527 disabled_items.push_back(std::string("Detach From Yourself"));
3528 }
3491// [/RLVa:KB] 3529// [/RLVa:KB]
3492 } 3530 }
3493 else 3531 else
@@ -3500,13 +3538,16 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
3500 items.push_back(std::string("RestoreToWorld Separator")); 3538 items.push_back(std::string("RestoreToWorld Separator"));
3501 items.push_back(std::string("Restore to Last Position")); 3539 items.push_back(std::string("Restore to Last Position"));
3502 3540
3503// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0c 3541// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
3504 // Only enable "Wear" if there is an attach point name *and* there isn't a worn attachment there that's currently locked 3542 if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getEnableWear()) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_ANY)) )
3505 if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getEnableWear()) && (gRlvHandler.hasLockedAttachment()) )
3506 { 3543 {
3507 LLViewerJointAttachment* pAttachPt = gRlvHandler.getAttachPoint(item, true); 3544 LLViewerJointAttachment* pAttachPt = gRlvHandler.getAttachPoint(item, true); // The item's name should specify
3508 if ( (!pAttachPt) || (!gRlvHandler.isDetachable(pAttachPt)) ) 3545 if ( (!pAttachPt) || // an attachment point that
3546 (gRlvHandler.isLockedAttachment(pAttachPt->getObject(), RLV_LOCK_REMOVE)) || // doesn't have an undetachable object
3547 (gRlvHandler.isLockedAttachment(pAttachPt, RLV_LOCK_ADD)) ) // and that can be attached to
3548 {
3509 disabled_items.push_back(std::string("Object Wear")); 3549 disabled_items.push_back(std::string("Object Wear"));
3550 }
3510 } 3551 }
3511// [/RLVa:KB] 3552// [/RLVa:KB]
3512 3553
@@ -3609,6 +3650,13 @@ LLUIImagePtr LLLSLTextBridge::getIcon() const
3609 3650
3610void LLLSLTextBridge::openItem() 3651void LLLSLTextBridge::openItem()
3611{ 3652{
3653// [RLVa:KB] - Checked: 2009-10-13 (RLVa-1.0.5c) | Modified: RLVa-1.0.5c
3654 if (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWSCRIPT))
3655 {
3656 return;
3657 }
3658// [/RLVa:KB]
3659
3612 // See if we can bring an exiting preview to the front 3660 // See if we can bring an exiting preview to the front
3613 if(!LLPreview::show(mUUID)) 3661 if(!LLPreview::show(mUUID))
3614 { 3662 {
@@ -4050,15 +4098,26 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata )
4050 is_gesture); 4098 is_gesture);
4051 S32 gest_count = gest_item_array.count(); 4099 S32 gest_count = gest_item_array.count();
4052 4100
4053// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-1.0.0c 4101// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
4054 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) && (!RlvSettings::getEnableWear()) ) 4102 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_ANY)) )
4055 { 4103 {
4056 // Filter anything that doesn't specify an attachment point (or that specifies one that's currently locked) 4104 // Filter anything that we shouldn't be attaching
4057 for (S32 idxObj = obj_item_array.count() - 1; idxObj >= 0; idxObj--) 4105 for (S32 idxObj = obj_item_array.count() - 1; idxObj >= 0; idxObj--)
4058 { 4106 {
4059 LLViewerJointAttachment* pAttachPt = gRlvHandler.getAttachPoint(obj_item_array.get(idxObj).get(), true); 4107 if (!RlvSettings::getEnableWear())
4060 if ( ((!pAttachPt) || (!gRlvHandler.isDetachable(pAttachPt))) ) 4108 {
4061 obj_item_array.remove(idxObj); 4109 LLViewerJointAttachment* pAttachPt = gRlvHandler.getAttachPoint(obj_item_array.get(idxObj).get(), true);
4110 if ( (!pAttachPt) || // Item should specify attachpt that
4111 (gRlvHandler.isLockedAttachment(pAttachPt->getObject(), RLV_LOCK_REMOVE)) || // doesn't have an undetachable object
4112 (gRlvHandler.isLockedAttachment(pAttachPt, RLV_LOCK_ADD)) ) // and that is attachable
4113 {
4114 obj_item_array.remove(idxObj);
4115 }
4116 }
4117 else
4118 {
4119 gRlvHandler.onWearAttachment(obj_item_array.get(idxObj)->getUUID());
4120 }
4062 } 4121 }
4063 obj_count = obj_item_array.count(); 4122 obj_count = obj_item_array.count();
4064 } 4123 }
@@ -4241,15 +4300,26 @@ void wear_attachments_on_avatar(const std::set<LLUUID>& item_ids, BOOL remove)
4241 { 4300 {
4242 if ( (gInventory.isObjectDescendentOf(*it, gAgent.getInventoryRootID())) ) 4301 if ( (gInventory.isObjectDescendentOf(*it, gAgent.getInventoryRootID())) )
4243 { 4302 {
4244// items.put(item); 4303// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-10-15 (RLVa-1.0.5e) | Modified: RLVa-1.0.5e
4245// [RLVa:KB] - Checked: 2009-09-11 (RLVa-1.0.2c) | Modified: RLVa-1.0.2c 4304 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_ANY)) )
4246 LLViewerJointAttachment* pAttachPt = NULL;
4247 if ( (!rlv_handler_t::isEnabled()) || (RlvSettings::getEnableWear()) || (!gRlvHandler.hasLockedAttachment()) ||
4248 (((pAttachPt = gRlvHandler.getAttachPoint(item, true)) != NULL) && (gRlvHandler.isDetachable(pAttachPt))) )
4249 { 4305 {
4250 items.put(item); 4306 if (!RlvSettings::getEnableWear())
4307 {
4308 LLViewerJointAttachment* pAttachPt = NULL;
4309 if ( ((pAttachPt = gRlvHandler.getAttachPoint(item, true)) == NULL) || // Item should specify attachpt that
4310 (gRlvHandler.isLockedAttachment(pAttachPt->getObject(), RLV_LOCK_REMOVE)) || // doesn't have an undetachable object
4311 (gRlvHandler.isLockedAttachment(pAttachPt, RLV_LOCK_ADD)) ) // and that is attachable
4312 {
4313 continue;
4314 }
4315 }
4316 else
4317 {
4318 gRlvHandler.onWearAttachment(item->getUUID());
4319 }
4251 } 4320 }
4252// [/RLVa:KB] 4321// [/RLVa:KB]
4322 items.put(item);
4253 } 4323 }
4254 else if ( (item->isComplete()) ) 4324 else if ( (item->isComplete()) )
4255 { 4325 {
@@ -4309,9 +4379,9 @@ void wear_attachments_on_avatar(const LLInventoryModel::item_array_t& items, BOO
4309 msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id ); 4379 msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id );
4310 msg->addU8Fast(_PREHASH_TotalObjects, count ); 4380 msg->addU8Fast(_PREHASH_TotalObjects, count );
4311// msg->addBOOLFast(_PREHASH_FirstDetachAll, remove ); 4381// msg->addBOOLFast(_PREHASH_FirstDetachAll, remove );
4312// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.2a 4382// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
4313 // This really should just *always* be FALSE since TRUE can result in loss of the current asset state 4383 // This really should just *always* be FALSE since TRUE can result in loss of the current asset state
4314 msg->addBOOLFast(_PREHASH_FirstDetachAll, remove && (!gRlvHandler.hasLockedAttachment()) ); 4384 msg->addBOOLFast(_PREHASH_FirstDetachAll, remove && (!gRlvHandler.hasLockedAttachment(RLV_LOCK_ANY)) );
4315// [/RLVa:KB] 4385// [/RLVa:KB]
4316 } 4386 }
4317 4387
@@ -4320,9 +4390,9 @@ void wear_attachments_on_avatar(const LLInventoryModel::item_array_t& items, BOO
4320 msg->addUUIDFast(_PREHASH_ItemID, item->getUUID() ); 4390 msg->addUUIDFast(_PREHASH_ItemID, item->getUUID() );
4321 msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); 4391 msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner());
4322// msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // Wear at the previous or default attachment point 4392// msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // Wear at the previous or default attachment point
4323// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.2a 4393// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
4324 msg->addU8Fast(_PREHASH_AttachmentPt, 4394 msg->addU8Fast(_PREHASH_AttachmentPt,
4325 ( (!rlv_handler_t::isEnabled()) || (RlvSettings::getEnableWear()) || (!gRlvHandler.hasLockedAttachment()) ) 4395 ( (!rlv_handler_t::isEnabled()) || (RlvSettings::getEnableWear()) || (!gRlvHandler.hasLockedAttachment(RLV_LOCK_ANY)) )
4326 ? 0 4396 ? 0
4327 : gRlvHandler.getAttachPointIndex(gRlvHandler.getAttachPoint(item, true))); 4397 : gRlvHandler.getAttachPointIndex(gRlvHandler.getAttachPoint(item, true)));
4328// [/RLVa:KB] 4398// [/RLVa:KB]
@@ -4428,13 +4498,12 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata)
4428 { 4498 {
4429 for(i = 0; i < obj_count; ++i) 4499 for(i = 0; i < obj_count; ++i)
4430 { 4500 {
4431// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.2a 4501// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
4432 // TODO-RLVa: is there a reason why LL doesn't bother checking to see if you're actually wearing the object? 4502 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_REMOVE)) )
4433 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) )
4434 { 4503 {
4435 LLVOAvatar* pAvatar = gAgent.getAvatarObject(); 4504 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
4436 if ( (!pAvatar) || (!pAvatar->isWearingAttachment(obj_item_array.get(i)->getUUID())) || 4505 if ( (!pAvatar) || (!pAvatar->isWearingAttachment(obj_item_array.get(i)->getUUID())) ||
4437 (!gRlvHandler.isDetachable(obj_item_array.get(i).get())) ) // Why does LLPointer have a cast to BOOL aka S32??? 4506 (gRlvHandler.isLockedAttachment(obj_item_array.get(i).get(), RLV_LOCK_REMOVE)) )
4438 { 4507 {
4439 continue; 4508 continue;
4440 } 4509 }
diff --git a/linden/indra/newview/llpanelcontents.cpp b/linden/indra/newview/llpanelcontents.cpp
index e13ec46..6462d44 100644
--- a/linden/indra/newview/llpanelcontents.cpp
+++ b/linden/indra/newview/llpanelcontents.cpp
@@ -121,11 +121,11 @@ void LLPanelContents::getState(LLViewerObject *objectp )
121 && ( objectp->permYouOwner() || ( !group_id.isNull() && gAgent.isInGroup(group_id) ))); // solves SL-23488 121 && ( objectp->permYouOwner() || ( !group_id.isNull() && gAgent.isInGroup(group_id) ))); // solves SL-23488
122 BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ); 122 BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME );
123 123
124// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0g 124// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
125 if ( (rlv_handler_t::isEnabled()) && (editable) ) 125 if ( (rlv_handler_t::isEnabled()) && (editable) )
126 { 126 {
127 // Don't allow creation of new scripts if it's undetachable 127 // Don't allow creation of new scripts if it's undetachable
128 editable = gRlvHandler.isDetachable(objectp); 128 editable = !gRlvHandler.isLockedAttachment(objectp, RLV_LOCK_REMOVE);
129 129
130 // Don't allow creation of new scripts if we're @unsit=n or @sittp=n restricted and we're sitting on the selection 130 // Don't allow creation of new scripts if we're @unsit=n or @sittp=n restricted and we're sitting on the selection
131 if ( (editable) && ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP))) ) 131 if ( (editable) && ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP))) )
@@ -182,10 +182,10 @@ void LLPanelContents::onClickNewScript(void *userdata)
182 LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(children_ok); 182 LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(children_ok);
183 if(object) 183 if(object)
184 { 184 {
185// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 185// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a)
186 if (rlv_handler_t::isEnabled()) // Fallback code [see LLPanelContents::getState()] 186 if (rlv_handler_t::isEnabled()) // Fallback code [see LLPanelContents::getState()]
187 { 187 {
188 if (!gRlvHandler.isDetachable(object)) 188 if (gRlvHandler.isLockedAttachment(object, RLV_LOCK_REMOVE))
189 { 189 {
190 return; // Disallow creating new scripts in a locked attachment 190 return; // Disallow creating new scripts in a locked attachment
191 } 191 }
diff --git a/linden/indra/newview/llpanelinventory.cpp b/linden/indra/newview/llpanelinventory.cpp
index 0ae2aec..d45b9d5 100644
--- a/linden/indra/newview/llpanelinventory.cpp
+++ b/linden/indra/newview/llpanelinventory.cpp
@@ -368,9 +368,9 @@ void LLTaskInvFVBridge::previewItem()
368 368
369BOOL LLTaskInvFVBridge::isItemRenameable() const 369BOOL LLTaskInvFVBridge::isItemRenameable() const
370{ 370{
371// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 371// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
372 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); 372 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
373 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(object)) ) 373 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.isLockedAttachment(object, RLV_LOCK_REMOVE)) )
374 { 374 {
375 return FALSE; 375 return FALSE;
376 } 376 }
@@ -394,8 +394,8 @@ BOOL LLTaskInvFVBridge::isItemRenameable() const
394BOOL LLTaskInvFVBridge::renameItem(const std::string& new_name) 394BOOL LLTaskInvFVBridge::renameItem(const std::string& new_name)
395{ 395{
396 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); 396 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
397// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 397// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
398 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(object)) ) 398 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.isLockedAttachment(object, RLV_LOCK_REMOVE)) )
399 { 399 {
400 return TRUE; // Fallback code [see LLTaskInvFVBridge::isItemRenameable()] 400 return TRUE; // Fallback code [see LLTaskInvFVBridge::isItemRenameable()]
401 } 401 }
@@ -426,13 +426,13 @@ BOOL LLTaskInvFVBridge::isItemMovable()
426 // return TRUE; 426 // return TRUE;
427 //} 427 //}
428 //return FALSE; 428 //return FALSE;
429// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0g 429// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
430 if (rlv_handler_t::isEnabled()) 430 if (rlv_handler_t::isEnabled())
431 { 431 {
432 LLViewerObject* pObj = gObjectList.findObject(mPanel->getTaskUUID()); 432 LLViewerObject* pObj = gObjectList.findObject(mPanel->getTaskUUID());
433 if (pObj) 433 if (pObj)
434 { 434 {
435 if (!gRlvHandler.isDetachable(pObj)) 435 if (gRlvHandler.isLockedAttachment(pObj, RLV_LOCK_REMOVE))
436 { 436 {
437 return FALSE; 437 return FALSE;
438 } 438 }
@@ -451,10 +451,10 @@ BOOL LLTaskInvFVBridge::isItemMovable()
451BOOL LLTaskInvFVBridge::isItemRemovable() 451BOOL LLTaskInvFVBridge::isItemRemovable()
452{ 452{
453 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); 453 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
454// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0g 454// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
455 if ( (object) && (rlv_handler_t::isEnabled()) ) 455 if ( (object) && (rlv_handler_t::isEnabled()) )
456 { 456 {
457 if (!gRlvHandler.isDetachable(object)) 457 if (gRlvHandler.isLockedAttachment(object, RLV_LOCK_REMOVE))
458 { 458 {
459 return FALSE; 459 return FALSE;
460 } 460 }
@@ -611,9 +611,9 @@ BOOL LLTaskInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
611 const LLPermissions& perm = inv->getPermissions(); 611 const LLPermissions& perm = inv->getPermissions();
612 bool can_copy = gAgent.allowOperation(PERM_COPY, perm, 612 bool can_copy = gAgent.allowOperation(PERM_COPY, perm,
613 GP_OBJECT_MANIPULATE); 613 GP_OBJECT_MANIPULATE);
614// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 614// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
615 // Kind of redundant due to the note below, but in case that ever gets fixed 615 // Kind of redundant due to the note below, but in case that ever gets fixed
616 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(object)) ) 616 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.isLockedAttachment(object, RLV_LOCK_REMOVE)) )
617 { 617 {
618 return FALSE; 618 return FALSE;
619 } 619 }
@@ -735,12 +735,16 @@ void LLTaskInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
735 { 735 {
736 disabled_items.push_back(std::string("Task Open")); 736 disabled_items.push_back(std::string("Task Open"));
737 } 737 }
738// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 738// [RLVa:KB] - Checked: 2009-10-13 (RLVa-1.0.5c) | Modified: RLVa-1.0.5c
739 else if ( (rlv_handler_t::isEnabled()) && 739 else if (rlv_handler_t::isEnabled())
740 ((LLAssetType::AT_LSL_TEXT == item->getType()) || (LLAssetType::AT_NOTECARD == item->getType())) &&
741 (!gRlvHandler.isDetachable(gObjectList.findObject(mPanel->getTaskUUID()))) )
742 { 740 {
743 disabled_items.push_back(std::string("Task Open")); 741 bool fLocked = gRlvHandler.isLockedAttachment(gObjectList.findObject(mPanel->getTaskUUID()), RLV_LOCK_REMOVE);
742 if ( ((LLAssetType::AT_LSL_TEXT == item->getType()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_VIEWSCRIPT)) || (fLocked))) ||
743 ((LLAssetType::AT_NOTECARD == item->getType()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_VIEWNOTE)) || (fLocked))) ||
744 ((LLAssetType::AT_NOTECARD == item->getType()) && (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWTEXTURE))) )
745 {
746 disabled_items.push_back(std::string("Task Open"));
747 }
744 } 748 }
745// [/RLVa:KB] 749// [/RLVa:KB]
746 } 750 }
@@ -967,6 +971,13 @@ LLUIImagePtr LLTaskTextureBridge::getIcon() const
967 971
968void LLTaskTextureBridge::openItem() 972void LLTaskTextureBridge::openItem()
969{ 973{
974// [RLVa:KB] - Checked: 2009-10-13 (RLVa-1.0.5c) | Added: RLVa-1.0.5c
975 if (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWTEXTURE))
976 {
977 return;
978 }
979// [/RLVa:KB]
980
970 llinfos << "LLTaskTextureBridge::openItem()" << llendl; 981 llinfos << "LLTaskTextureBridge::openItem()" << llendl;
971 if(!LLPreview::show(mUUID)) 982 if(!LLPreview::show(mUUID))
972 { 983 {
@@ -1248,9 +1259,10 @@ LLTaskLSLBridge::LLTaskLSLBridge(
1248 1259
1249void LLTaskLSLBridge::openItem() 1260void LLTaskLSLBridge::openItem()
1250{ 1261{
1251// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 1262// [RLVa:KB] - Checked: 2009-10-13 (RLVa-1.0.5c) | Modified: RLVa-1.0.5c
1252 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); 1263 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
1253 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(object)) ) 1264 if ( (rlv_handler_t::isEnabled()) &&
1265 ((gRlvHandler.hasBehaviour(RLV_BHVR_VIEWSCRIPT)) || (gRlvHandler.isLockedAttachment(object, RLV_LOCK_REMOVE))) )
1254 { 1266 {
1255 return; 1267 return;
1256 } 1268 }
@@ -1376,8 +1388,9 @@ void LLTaskNotecardBridge::openItem()
1376 { 1388 {
1377 return; 1389 return;
1378 } 1390 }
1379// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 1391// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
1380 if ( (rlv_handler_t::isEnabled()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_VIEWNOTE)) || (!gRlvHandler.isDetachable(object))) ) 1392 if ( (rlv_handler_t::isEnabled()) &&
1393 ( (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWNOTE)) || (gRlvHandler.isLockedAttachment(object, RLV_LOCK_REMOVE)) ) )
1381 { 1394 {
1382 return; 1395 return;
1383 } 1396 }
diff --git a/linden/indra/newview/llpreviewscript.cpp b/linden/indra/newview/llpreviewscript.cpp
index 6273011..69b6864 100644
--- a/linden/indra/newview/llpreviewscript.cpp
+++ b/linden/indra/newview/llpreviewscript.cpp
@@ -1989,8 +1989,8 @@ void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata )
1989 LLCheckBoxCtrl* runningCheckbox = self->getChild<LLCheckBoxCtrl>("running"); 1989 LLCheckBoxCtrl* runningCheckbox = self->getChild<LLCheckBoxCtrl>("running");
1990 BOOL running = runningCheckbox->get(); 1990 BOOL running = runningCheckbox->get();
1991 //self->mRunningCheckbox->get(); 1991 //self->mRunningCheckbox->get();
1992// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 1992// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
1993 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(object)) ) 1993 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.isLockedAttachment(object, RLV_LOCK_REMOVE)) )
1994 { 1994 {
1995 return; 1995 return;
1996 } 1996 }
@@ -2020,8 +2020,8 @@ void LLLiveLSLEditor::onReset(void *userdata)
2020 LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata; 2020 LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata;
2021 2021
2022 LLViewerObject* object = gObjectList.findObject( self->mObjectID ); 2022 LLViewerObject* object = gObjectList.findObject( self->mObjectID );
2023// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 2023// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
2024 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(object)) ) 2024 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.isLockedAttachment(object, RLV_LOCK_REMOVE)) )
2025 { 2025 {
2026 return; 2026 return;
2027 } 2027 }
@@ -2448,8 +2448,8 @@ void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save)
2448{ 2448{
2449 LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; 2449 LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
2450 2450
2451// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 2451// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
2452 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(gObjectList.findObject(self->mObjectID))) ) 2452 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.isLockedAttachment(gObjectList.findObject(self->mObjectID), RLV_LOCK_REMOVE)) )
2453 { 2453 {
2454 return; 2454 return;
2455 } 2455 }
diff --git a/linden/indra/newview/lltooldraganddrop.cpp b/linden/indra/newview/lltooldraganddrop.cpp
index 178bde6..c0fa28c 100644
--- a/linden/indra/newview/lltooldraganddrop.cpp
+++ b/linden/indra/newview/lltooldraganddrop.cpp
@@ -1946,7 +1946,7 @@ EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LL
1946// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 1946// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
1947 if (rlv_handler_t::isEnabled()) 1947 if (rlv_handler_t::isEnabled())
1948 { 1948 {
1949 if (!gRlvHandler.isDetachable(obj)) 1949 if (gRlvHandler.isLockedAttachment(obj, RLV_LOCK_REMOVE))
1950 { 1950 {
1951 return ACCEPT_NO_LOCKED; // Disallow inventory drops on a locked attachment 1951 return ACCEPT_NO_LOCKED; // Disallow inventory drops on a locked attachment
1952 } 1952 }
@@ -2014,10 +2014,12 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv(
2014 return ACCEPT_NO; 2014 return ACCEPT_NO;
2015 } 2015 }
2016 2016
2017// [RLVa:KB] - Checked: 2009-09-08 (RLVa-1.0.2c) | Modified: RLVa-1.0.2c 2017// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5) | Modified: RLVa-1.0.5
2018 LLViewerJointAttachment* pAttachPt = NULL; 2018 LLViewerJointAttachment* pAttachPt = NULL;
2019 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) && (!RlvSettings::getEnableWear()) && 2019 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_ANY)) && (!RlvSettings::getEnableWear()) &&
2020 ( ((pAttachPt = gRlvHandler.getAttachPoint(item, true)) == NULL) || (!gRlvHandler.isDetachable(pAttachPt)) ) ) 2020 ( ((pAttachPt = gRlvHandler.getAttachPoint(item, true)) == NULL) || // Item should specify an attachpt that
2021 (gRlvHandler.isLockedAttachment(pAttachPt->getObject(), RLV_LOCK_REMOVE)) || // doesn't have an undetachable object
2022 (gRlvHandler.isLockedAttachment(pAttachPt, RLV_LOCK_ADD)) ) ) // and that is attachable
2021 { 2023 {
2022 return ACCEPT_NO_LOCKED; 2024 return ACCEPT_NO_LOCKED;
2023 } 2025 }
diff --git a/linden/indra/newview/llviewerdisplay.cpp b/linden/indra/newview/llviewerdisplay.cpp
index 4b352a4..77d2509 100644
--- a/linden/indra/newview/llviewerdisplay.cpp
+++ b/linden/indra/newview/llviewerdisplay.cpp
@@ -676,8 +676,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
676 } 676 }
677 677
678// if(gUseWireframe) 678// if(gUseWireframe)
679// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 679// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
680 if ( (gUseWireframe) && ( (!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedAttachment()) ) ) 680 if ( (gUseWireframe) && ( (!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedAttachment(RLV_LOCK_REMOVE)) ) )
681// [/RLVa:KB] 681// [/RLVa:KB]
682 { 682 {
683 glClearColor(0.5f, 0.5f, 0.5f, 0.f); 683 glClearColor(0.5f, 0.5f, 0.5f, 0.f);
diff --git a/linden/indra/newview/llviewermenu.cpp b/linden/indra/newview/llviewermenu.cpp
index 4732046..ecf6fcb 100644
--- a/linden/indra/newview/llviewermenu.cpp
+++ b/linden/indra/newview/llviewermenu.cpp
@@ -2146,8 +2146,9 @@ class LLSelfEnableRemoveAllAttachments : public view_listener_t
2146 LLVOAvatar::attachment_map_t::iterator curiter = iter++; 2146 LLVOAvatar::attachment_map_t::iterator curiter = iter++;
2147 LLViewerJointAttachment* attachment = curiter->second; 2147 LLViewerJointAttachment* attachment = curiter->second;
2148// if (attachment->getObject()) 2148// if (attachment->getObject())
2149// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0c 2149// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
2150 if ( (attachment->getObject()) && ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isDetachable(curiter->first)) ) ) 2150 if ( (attachment->getObject()) &&
2151 ((!rlv_handler_t::isEnabled()) || (!gRlvHandler.isLockedAttachment(curiter->first, RLV_LOCK_REMOVE))) )
2151// [/RLVa:KB] 2152// [/RLVa:KB]
2152 { 2153 {
2153 new_value = true; 2154 new_value = true;
@@ -2387,7 +2388,7 @@ class LLObjectImportUpload : public view_listener_t
2387bool handle_go_to_confirm() 2388bool handle_go_to_confirm()
2388{ 2389{
2389// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 2390// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
2390 if ( (rlv_handler_t::isEnabled()) && gAgent.forwardGrabbed() && (gRlvHandler.hasLockedAttachment()) ) 2391 if ( (rlv_handler_t::isEnabled()) && (gAgent.forwardGrabbed()) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_REMOVE)) )
2391 { 2392 {
2392 return true; 2393 return true;
2393 } 2394 }
@@ -2410,12 +2411,12 @@ bool handle_go_to_confirm()
2410 2411
2411bool handle_go_to() 2412bool handle_go_to()
2412{ 2413{
2413// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 2414// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
2414 if ( (rlv_handler_t::isEnabled()) && gAgent.forwardGrabbed() && (gRlvHandler.hasLockedAttachment()) ) 2415 if ( (rlv_handler_t::isEnabled()) && (gAgent.forwardGrabbed()) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_REMOVE)) )
2415 { 2416 {
2416 return true; 2417 return true;
2417 } 2418 }
2418// [/RLVa:KB] 2419 // [/RLVa:KB]
2419 2420
2420 handle_go_to_callback( 0, (void*)LLToolPie::getInstance() ); 2421 handle_go_to_callback( 0, (void*)LLToolPie::getInstance() );
2421 2422
@@ -4737,8 +4738,8 @@ class LLToolsReleaseKeys : public view_listener_t
4737{ 4738{
4738 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4739 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4739 { 4740 {
4740// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 4741// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
4741 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) ) 4742 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_REMOVE)) )
4742 { 4743 {
4743 return true; 4744 return true;
4744 } 4745 }
@@ -4754,9 +4755,9 @@ class LLToolsEnableReleaseKeys : public view_listener_t
4754{ 4755{
4755 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4756 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4756 { 4757 {
4757// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 4758// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
4758 gMenuHolder->findControl(userdata["control"].asString())->setValue( 4759 gMenuHolder->findControl(userdata["control"].asString())->setValue(
4759 gAgent.anyControlGrabbed() && ( (!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedAttachment() ) ) ); 4760 gAgent.anyControlGrabbed() && ( (!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedAttachment(RLV_LOCK_REMOVE) ) ) );
4760// [/RLVa:KB] 4761// [/RLVa:KB]
4761 //gMenuHolder->findControl(userdata["control"].asString())->setValue( gAgent.anyControlGrabbed() ); 4762 //gMenuHolder->findControl(userdata["control"].asString())->setValue( gAgent.anyControlGrabbed() );
4762 return true; 4763 return true;
@@ -6070,11 +6071,13 @@ private:
6070 if (index > 0) 6071 if (index > 0)
6071 attachment_point = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL); 6072 attachment_point = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL);
6072 6073
6073// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 6074// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
6074 if ( (rlv_handler_t::isEnabled()) && 6075 if ( (rlv_handler_t::isEnabled()) &&
6075 ( ((index == 0) && (gRlvHandler.hasLockedAttachment())) || // Can't wear on default attach point 6076 ( ((index == 0) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_ANY))) || // Can't wear on default attach point
6076 ((index > 0) && (!gRlvHandler.isDetachable(attachment_point))) || // Can't replace locked attachment 6077 ((index > 0) && // or replace a locked attachment
6077 (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) ) ) // Attach on rezzed object == "Take" 6078 ((gRlvHandler.isLockedAttachment(attachment_point->getObject(), RLV_LOCK_REMOVE)) ||
6079 (gRlvHandler.isLockedAttachment(attachment_point, RLV_LOCK_ADD)) ) ) || // or wear on a non-attachable attach point
6080 (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) ) ) // Attach on rezzed object == "Take"
6078 { 6081 {
6079 setObjectSelection(NULL); // Clear the selection or it'll get stuck 6082 setObjectSelection(NULL); // Clear the selection or it'll get stuck
6080 return true; 6083 return true;
@@ -6188,15 +6191,15 @@ class LLAttachmentDrop : public view_listener_t
6188 return true; 6191 return true;
6189 } 6192 }
6190 6193
6191// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 6194// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
6192 if (rlv_handler_t::isEnabled()) 6195 if (rlv_handler_t::isEnabled())
6193 { 6196 {
6194 if (gRlvHandler.hasLockedAttachment()) 6197 if (gRlvHandler.hasLockedAttachment(RLV_LOCK_REMOVE))
6195 { 6198 {
6196 // NOTE: copy/paste of the code in enable_detach() 6199 // NOTE: copy/paste of the code in enable_detach()
6197 LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection(); 6200 LLObjectSelectionHandle hSelection = LLSelectMgr::getInstance()->getSelection();
6198 RlvSelectHasLockedAttach functor; 6201 RlvSelectHasLockedAttach functor(RLV_LOCK_REMOVE);
6199 if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&functor, FALSE)) ) 6202 if ( (hSelection->isAttachment()) && (hSelection->getFirstRootNode(&functor, FALSE)) )
6200 return true; 6203 return true;
6201 } 6204 }
6202 else if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) 6205 else if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ))
@@ -6224,8 +6227,8 @@ void handle_detach_from_avatar(void* user_data)
6224 6227
6225 if (attached_object) 6228 if (attached_object)
6226 { 6229 {
6227// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0d 6230// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
6228 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(attached_object)) ) 6231 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.isLockedAttachment(attached_object, RLV_LOCK_REMOVE)) )
6229 { 6232 {
6230 return; 6233 return;
6231 } 6234 }
@@ -6313,12 +6316,12 @@ class LLAttachmentDetach : public view_listener_t
6313 return true; 6316 return true;
6314 } 6317 }
6315 6318
6316// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 6319// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5) | Modified: RLVa-1.0.5
6317 // NOTE: copy/paste of the code in enable_detach() 6320 // NOTE: copy/paste of the code in enable_detach()
6318 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) ) 6321 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_REMOVE)) )
6319 { 6322 {
6320 LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection(); 6323 LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection();
6321 RlvSelectHasLockedAttach functor; 6324 RlvSelectHasLockedAttach functor(RLV_LOCK_REMOVE);
6322 if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&functor, FALSE)) ) 6325 if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&functor, FALSE)) )
6323 return FALSE; 6326 return FALSE;
6324 } 6327 }
@@ -6431,16 +6434,16 @@ BOOL enable_detach(void*)
6431 // ...if it's you, good to detach 6434 // ...if it's you, good to detach
6432 if (avatar->getID() == gAgent.getID()) 6435 if (avatar->getID() == gAgent.getID())
6433 { 6436 {
6434// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 6437// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5) | Modified: RLVa-1.0.5
6435 // NOTE: this code is reused as-is in LLAttachmentDetach::handleEvent() and LLAttachmentDrop::handleEvent() 6438 // NOTE: this code is reused as-is in LLAttachmentDetach::handleEvent() and LLAttachmentDrop::handleEvent()
6436 // so any changes here should be reflected there as well (I think it's in a number of other places as well by now) 6439 // so any changes here should be reflected there as well
6437 6440
6438 // RELEASE-RLVa: LLSelectMgr::sendDetach() and LLSelectMgr::sendDropAttachment() call sendListToRegions with 6441 // RELEASE-RLVa: LLSelectMgr::sendDetach() and LLSelectMgr::sendDropAttachment() call sendListToRegions with
6439 // SEND_ONLY_ROOTS so we only need to examine the roots which saves us time 6442 // SEND_ONLY_ROOTS so we only need to examine the roots which saves us time
6440 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) ) 6443 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_REMOVE)) )
6441 { 6444 {
6442 LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection(); 6445 LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection();
6443 RlvSelectHasLockedAttach functor; 6446 RlvSelectHasLockedAttach functor(RLV_LOCK_REMOVE);
6444 if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&functor, FALSE)) ) 6447 if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&functor, FALSE)) )
6445 return FALSE; 6448 return FALSE;
6446 } 6449 }
@@ -6467,7 +6470,7 @@ class LLAttachmentEnableDetach : public view_listener_t
6467// Used to tell if the selected object can be attached to your avatar. 6470// Used to tell if the selected object can be attached to your avatar.
6468BOOL object_selected_and_point_valid(void *user_data) 6471BOOL object_selected_and_point_valid(void *user_data)
6469{ 6472{
6470// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) 6473// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5) | Modified: RLVa-1.0.5
6471 if (rlv_handler_t::isEnabled()) 6474 if (rlv_handler_t::isEnabled())
6472 { 6475 {
6473 // RELEASE-RLVa: look at the caller graph for this function on every new release 6476 // RELEASE-RLVa: look at the caller graph for this function on every new release
@@ -6477,9 +6480,11 @@ BOOL object_selected_and_point_valid(void *user_data)
6477 // - enabler set up in LLVOAvatar::buildCharacter() => Rezzed prim / right-click / "Attach >" [user_data == pAttachPt] 6480 // - enabler set up in LLVOAvatar::buildCharacter() => Rezzed prim / right-click / "Attach >" [user_data == pAttachPt]
6478 // - enabler set up in LLVOAvatar::buildCharacter() => Rezzed prim / Edit menu / "Attach Object" [user_data == pAttachPt] 6481 // - enabler set up in LLVOAvatar::buildCharacter() => Rezzed prim / Edit menu / "Attach Object" [user_data == pAttachPt]
6479 LLViewerJointAttachment* pAttachPt = (LLViewerJointAttachment*)user_data; 6482 LLViewerJointAttachment* pAttachPt = (LLViewerJointAttachment*)user_data;
6480 if ( ((!pAttachPt) && (gRlvHandler.hasLockedAttachment())) || // Don't allow attach to default attach point 6483 if ( ( (!pAttachPt) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_ANY)) ) || // Don't allow attach to default attach point
6481 ((pAttachPt) && (!gRlvHandler.isDetachable(pAttachPt))) || // Don't allow replacing of locked attachment 6484 ( (pAttachPt) && // Don't allow replacing of a locked attachment
6482 (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) ) // Attaching a rezzed object == "Take" 6485 ( (gRlvHandler.isLockedAttachment(pAttachPt->getObject(), RLV_LOCK_REMOVE)) ||
6486 (gRlvHandler.isLockedAttachment(pAttachPt, RLV_LOCK_ADD)) ) ) || // or wear on a non-attachable attach point
6487 (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) ) // Attaching a rezzed object == "Take"
6483 { 6488 {
6484 return FALSE; 6489 return FALSE;
6485 } 6490 }
@@ -6556,7 +6561,7 @@ BOOL object_attached(void *user_data)
6556// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 6561// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6557 return ( 6562 return (
6558 (attachment->getObject() != NULL) && 6563 (attachment->getObject() != NULL) &&
6559 ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isDetachable(attachment->getObject())) ) 6564 ( (!rlv_handler_t::isEnabled()) || (!gRlvHandler.isLockedAttachment(attachment->getObject(), RLV_LOCK_REMOVE)) )
6560 ); 6565 );
6561// [/RLVa:KB] 6566// [/RLVa:KB]
6562// return attachment->getObject() != NULL; 6567// return attachment->getObject() != NULL;
@@ -6708,12 +6713,13 @@ class LLToolsSelectedScriptAction : public view_listener_t
6708{ 6713{
6709 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 6714 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
6710 { 6715 {
6711// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 6716// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
6712 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) ) 6717 // We'll allow resetting the scripts of objects on a non-attachable attach point since they wouldn't be able to circumvent anything
6718 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_REMOVE)) )
6713 { 6719 {
6714 LLObjectSelectionHandle selectHandle = LLSelectMgr::getInstance()->getSelection(); 6720 LLObjectSelectionHandle hSelection = LLSelectMgr::getInstance()->getSelection();
6715 RlvSelectHasLockedAttach functor; 6721 RlvSelectHasLockedAttach functor(RLV_LOCK_REMOVE);
6716 if ( (selectHandle->isAttachment()) && (selectHandle->getFirstNode(&functor)) ) 6722 if ( (hSelection->isAttachment()) && (hSelection->getFirstNode(&functor)) )
6717 return true; 6723 return true;
6718 } 6724 }
6719// [/RLVa:KB] 6725// [/RLVa:KB]
@@ -6802,9 +6808,9 @@ void handle_dump_image_list(void*)
6802 6808
6803void handle_test_male(void*) 6809void handle_test_male(void*)
6804{ 6810{
6805// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 6811// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
6806 if ( (rlv_handler_t::isEnabled()) && 6812 if ( (rlv_handler_t::isEnabled()) &&
6807 ( (gRlvHandler.hasLockedAttachment()) || 6813 ( (gRlvHandler.hasLockedAttachment(RLV_LOCK_ANY)) ||
6808 (gRlvHandler.hasBehaviour(RLV_BHVR_ADDOUTFIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_REMOUTFIT)) ) ) 6814 (gRlvHandler.hasBehaviour(RLV_BHVR_ADDOUTFIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_REMOUTFIT)) ) )
6809 { 6815 {
6810 return; 6816 return;
@@ -6817,9 +6823,9 @@ void handle_test_male(void*)
6817 6823
6818void handle_test_female(void*) 6824void handle_test_female(void*)
6819{ 6825{
6820// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 6826// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
6821 if ( (rlv_handler_t::isEnabled()) && 6827 if ( (rlv_handler_t::isEnabled()) &&
6822 ( (gRlvHandler.hasLockedAttachment()) || 6828 ( (gRlvHandler.hasLockedAttachment(RLV_LOCK_ANY)) ||
6823 (gRlvHandler.hasBehaviour(RLV_BHVR_ADDOUTFIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_REMOUTFIT)) ) ) 6829 (gRlvHandler.hasBehaviour(RLV_BHVR_ADDOUTFIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_REMOUTFIT)) ) )
6824 { 6830 {
6825 return; 6831 return;
@@ -6968,16 +6974,16 @@ BOOL enable_more_than_one_selected(void* )
6968 6974
6969static bool is_editable_selected() 6975static bool is_editable_selected()
6970{ 6976{
6971// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-1.0.0c 6977// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
6972 // RELEASE-RLVa: check that this still isn't called by anything but script actions in the Tools menu 6978 // RELEASE-RLVa: check that this still isn't called by anything but script actions in the Tools menu
6973 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) ) 6979 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_REMOVE)) )
6974 { 6980 {
6975 LLObjectSelectionHandle selectHandle = LLSelectMgr::getInstance()->getSelection(); 6981 LLObjectSelectionHandle hSelection = LLSelectMgr::getInstance()->getSelection();
6976 6982
6977 // NOTE: this is called for 5 different menu items so we'll trade accuracy for efficiency and only 6983 // NOTE: this is called for 5 different menu items so we'll trade accuracy for efficiency and only
6978 // examine root nodes (LLToolsSelectedScriptAction::handleEvent() will catch what we miss) 6984 // examine root nodes (LLToolsSelectedScriptAction::handleEvent() will catch what we miss)
6979 RlvSelectHasLockedAttach functor; 6985 RlvSelectHasLockedAttach functor(RLV_LOCK_REMOVE);
6980 if ( (selectHandle->isAttachment()) && (selectHandle->getFirstRootNode(&functor)) ) 6986 if ( (hSelection->isAttachment()) && (hSelection->getFirstRootNode(&functor)) )
6981 { 6987 {
6982 return false; 6988 return false;
6983 } 6989 }
diff --git a/linden/indra/newview/llviewertexteditor.cpp b/linden/indra/newview/llviewertexteditor.cpp
index 8f4a944..c8b8fec 100644
--- a/linden/indra/newview/llviewertexteditor.cpp
+++ b/linden/indra/newview/llviewertexteditor.cpp
@@ -1364,6 +1364,13 @@ BOOL LLViewerTextEditor::openEmbeddedItem(LLInventoryItem* item)
1364 1364
1365void LLViewerTextEditor::openEmbeddedTexture( LLInventoryItem* item ) 1365void LLViewerTextEditor::openEmbeddedTexture( LLInventoryItem* item )
1366{ 1366{
1367// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-10-13 (RLVa-1.0.5c) | Added: RLVa-1.0.5c
1368 if (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWTEXTURE))
1369 {
1370 return;
1371 }
1372// [/RLVa:KB]
1373
1367 // See if we can bring an existing preview to the front 1374 // See if we can bring an existing preview to the front
1368 // *NOTE: Just for embedded Texture , we should use getAssetUUID(), 1375 // *NOTE: Just for embedded Texture , we should use getAssetUUID(),
1369 // not getUUID(), because LLPreviewTexture pass in AssetUUID into 1376 // not getUUID(), because LLPreviewTexture pass in AssetUUID into
diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp
index 4ab14f4..df07701 100644
--- a/linden/indra/newview/llvoavatar.cpp
+++ b/linden/indra/newview/llvoavatar.cpp
@@ -6451,37 +6451,10 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object)
6451 { 6451 {
6452 updateAttachmentVisibility(gAgent.getCameraMode()); 6452 updateAttachmentVisibility(gAgent.getCameraMode());
6453 6453
6454// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) 6454// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
6455 if (rlv_handler_t::isEnabled()) 6455 if (rlv_handler_t::isEnabled())
6456 { 6456 {
6457 static bool fRlvFullyLoaded = false; 6457 gRlvHandler.onAttach(attachment);
6458 static LLFrameTimer* pRlvFullyLoadedTimer = NULL;
6459
6460 // There's no way to know when we're done reattaching what was attached at log-off but this ugly evil bad hack tries anyway
6461 if (!fRlvFullyLoaded)
6462 {
6463 if (pRlvFullyLoadedTimer)
6464 {
6465 if (pRlvFullyLoadedTimer->getElapsedTimeF32() > 30.0f)
6466 {
6467 fRlvFullyLoaded = true;
6468 delete pRlvFullyLoadedTimer;
6469 pRlvFullyLoadedTimer = NULL;
6470 }
6471 else
6472 {
6473 pRlvFullyLoadedTimer->reset();
6474 }
6475 }
6476 else if ( (!pRlvFullyLoadedTimer) &&
6477 ( (0 == mPendingAttachment.size()) ||
6478 ((1 == mPendingAttachment.size()) && (mPendingAttachment[0] == viewer_object)) ) )
6479 {
6480 pRlvFullyLoadedTimer = new LLFrameTimer();
6481 }
6482 }
6483
6484 gRlvHandler.onAttach(attachment, fRlvFullyLoaded);
6485 } 6458 }
6486// [/RLVa:KB] 6459// [/RLVa:KB]
6487 6460
diff --git a/linden/indra/newview/llvovolume.cpp b/linden/indra/newview/llvovolume.cpp
index adf82cd..7b151e8 100644
--- a/linden/indra/newview/llvovolume.cpp
+++ b/linden/indra/newview/llvovolume.cpp
@@ -1943,9 +1943,9 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
1943{ 1943{
1944 if (!mbCanSelect || 1944 if (!mbCanSelect ||
1945// (gHideSelectedObjects && isSelected()) || 1945// (gHideSelectedObjects && isSelected()) ||
1946// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 1946// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
1947 ( (gHideSelectedObjects && isSelected()) && 1947 ( (gHideSelectedObjects && isSelected()) &&
1948 ((!rlv_handler_t::isEnabled()) || (!isHUDAttachment()) || (gRlvHandler.isDetachable(this))) ) || 1948 ((!rlv_handler_t::isEnabled()) || (!isHUDAttachment()) || (!gRlvHandler.isLockedAttachment(this, RLV_LOCK_REMOVE))) ) ||
1949// [/RLVa:KB] 1949// [/RLVa:KB]
1950 mDrawable->isDead() || 1950 mDrawable->isDead() ||
1951 !gPipeline.hasRenderType(mDrawable->getRenderType())) 1951 !gPipeline.hasRenderType(mDrawable->getRenderType()))
@@ -2092,10 +2092,10 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
2092// { 2092// {
2093// return; 2093// return;
2094// } 2094// }
2095// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 2095// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
2096 LLViewerObject* pObj = facep->getViewerObject(); 2096 LLViewerObject* pObj = facep->getViewerObject();
2097 if ( (pObj->isSelected() && gHideSelectedObjects) && 2097 if ( (pObj->isSelected() && gHideSelectedObjects) &&
2098 ((!rlv_handler_t::isEnabled()) || (!pObj->isHUDAttachment()) || (gRlvHandler.isDetachable(pObj))) ) 2098 ((!rlv_handler_t::isEnabled()) || (!pObj->isHUDAttachment()) || (!gRlvHandler.isLockedAttachment(pObj, RLV_LOCK_REMOVE))) )
2099 { 2099 {
2100 return; 2100 return;
2101 } 2101 }
diff --git a/linden/indra/newview/pipeline.cpp b/linden/indra/newview/pipeline.cpp
index efb5ff6..bf7799c 100644
--- a/linden/indra/newview/pipeline.cpp
+++ b/linden/indra/newview/pipeline.cpp
@@ -1797,10 +1797,10 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
1797 { 1797 {
1798// if (drawablep->getVObj().notNull() && 1798// if (drawablep->getVObj().notNull() &&
1799// drawablep->getVObj()->isSelected()) 1799// drawablep->getVObj()->isSelected())
1800// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) 1800// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
1801 LLViewerObject* pObj = drawablep->getVObj(); 1801 LLViewerObject* pObj = drawablep->getVObj();
1802 if ( (pObj) && (pObj->isSelected()) && 1802 if ( (pObj) && (pObj->isSelected()) &&
1803 ((!rlv_handler_t::isEnabled()) || (!pObj->isHUDAttachment()) || (gRlvHandler.isDetachable(pObj))) ) 1803 ((!rlv_handler_t::isEnabled()) || (!pObj->isHUDAttachment()) || (!gRlvHandler.isLockedAttachment(pObj, RLV_LOCK_REMOVE))) )
1804// [/RVLa:KB] 1804// [/RVLa:KB]
1805 { 1805 {
1806 return; 1806 return;
diff --git a/linden/indra/newview/rlvdefines.h b/linden/indra/newview/rlvdefines.h
index 118ba31..a35d109 100644
--- a/linden/indra/newview/rlvdefines.h
+++ b/linden/indra/newview/rlvdefines.h
@@ -41,14 +41,14 @@
41 41
42// Version of the specifcation we support 42// Version of the specifcation we support
43const S32 RLV_VERSION_MAJOR = 1; 43const S32 RLV_VERSION_MAJOR = 1;
44const S32 RLV_VERSION_MINOR = 21; 44const S32 RLV_VERSION_MINOR = 22;
45const S32 RLV_VERSION_PATCH = 0; 45const S32 RLV_VERSION_PATCH = 0;
46const S32 RLV_VERSION_BUILD = 0; 46const S32 RLV_VERSION_BUILD = 0;
47 47
48// Implementation version 48// Implementation version
49const S32 RLVa_VERSION_MAJOR = 1; 49const S32 RLVa_VERSION_MAJOR = 1;
50const S32 RLVa_VERSION_MINOR = 0; 50const S32 RLVa_VERSION_MINOR = 0;
51const S32 RLVa_VERSION_PATCH = 4; 51const S32 RLVa_VERSION_PATCH = 5;
52const S32 RLVa_VERSION_BUILD = 4; 52const S32 RLVa_VERSION_BUILD = 4;
53 53
54// The official viewer version we're patching against 54// The official viewer version we're patching against
@@ -59,12 +59,15 @@ const S32 RLVa_VERSION_BUILD = 4;
59#define RLV_WARNS LL_WARNS("RLV") 59#define RLV_WARNS LL_WARNS("RLV")
60#define RLV_INFOS LL_INFOS("RLV") 60#define RLV_INFOS LL_INFOS("RLV")
61#define RLV_DEBUGS LL_DEBUGS("RLV") 61#define RLV_DEBUGS LL_DEBUGS("RLV")
62#define RLV_ENDL LL_ENDL
62 63
63#if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG 64#if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
64 // Turn on extended debugging information 65 // Turn on extended debugging information
65 #define RLV_DEBUG 66 #define RLV_DEBUG
66 // Make sure we halt execution on errors 67 // Make sure we halt execution on errors
67 #define RLV_ERRS LL_ERRS("RLV") 68 #define RLV_ERRS LL_ERRS("RLV")
69 // Keep our asserts separate from LL's
70 #define RLV_ASSERT(f) if (!(f)) RLV_ERRS << "ASSERT (" << #f << ")" << RLV_ENDL;
68 // Uncomment to enable the Advanced / RLVa / Unit Tests menu (non-public) 71 // Uncomment to enable the Advanced / RLVa / Unit Tests menu (non-public)
69 //#define RLV_DEBUG_TESTS 72 //#define RLV_DEBUG_TESTS
70#else 73#else
@@ -72,6 +75,8 @@ const S32 RLVa_VERSION_BUILD = 4;
72 //#define RLV_DEBUG 75 //#define RLV_DEBUG
73 // Don't halt execution on errors in release 76 // Don't halt execution on errors in release
74 #define RLV_ERRS LL_WARNS("RLV") 77 #define RLV_ERRS LL_WARNS("RLV")
78 // We don't want to check assertions in release builds
79 #define RLV_ASSERT(f)
75#endif // LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG 80#endif // LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
76 81
77#define RLV_ROOT_FOLDER "#RLV" 82#define RLV_ROOT_FOLDER "#RLV"
@@ -111,6 +116,8 @@ enum ERlvBehaviour {
111 RLV_BHVR_ADDOUTFIT, // "addoutfit" 116 RLV_BHVR_ADDOUTFIT, // "addoutfit"
112 RLV_BHVR_REMOUTFIT, // "remoutfit" 117 RLV_BHVR_REMOUTFIT, // "remoutfit"
113 RLV_BHVR_GETOUTFIT, // "getoutfit" 118 RLV_BHVR_GETOUTFIT, // "getoutfit"
119 RLV_BHVR_ADDATTACH, // "addattach"
120 RLV_BHVR_REMATTACH, // "remattach"
114 RLV_BHVR_GETATTACH, // "getattach" 121 RLV_BHVR_GETATTACH, // "getattach"
115 RLV_BHVR_SHOWINV, // "showinv" 122 RLV_BHVR_SHOWINV, // "showinv"
116 RLV_BHVR_VIEWNOTE, // "viewnote" 123 RLV_BHVR_VIEWNOTE, // "viewnote"
@@ -152,6 +159,8 @@ enum ERlvBehaviour {
152 RLV_BHVR_DEFAULTWEAR, // "defaultwear" 159 RLV_BHVR_DEFAULTWEAR, // "defaultwear"
153 RLV_BHVR_VERSIONNUM, // "versionnum" 160 RLV_BHVR_VERSIONNUM, // "versionnum"
154 RLV_BHVR_PERMISSIVE, // "permissive" 161 RLV_BHVR_PERMISSIVE, // "permissive"
162 RLV_BHVR_VIEWSCRIPT, // "viewscript"
163 RLV_BHVR_VIEWTEXTURE, // "viewtexture"
155 164
156 RLV_BHVR_COUNT, 165 RLV_BHVR_COUNT,
157 RLV_BHVR_UNKNOWN 166 RLV_BHVR_UNKNOWN
@@ -185,6 +194,12 @@ enum ERlvExceptionCheck {
185 RLV_CHECK_DEFAULT // Permissive or strict will be determined by currently enforced restrictions 194 RLV_CHECK_DEFAULT // Permissive or strict will be determined by currently enforced restrictions
186}; 195};
187 196
197enum ERlvLockMask {
198 RLV_LOCK_ADD = 0x01,
199 RLV_LOCK_REMOVE = 0x02,
200 RLV_LOCK_ANY = RLV_LOCK_ADD | RLV_LOCK_REMOVE
201};
202
188// ============================================================================ 203// ============================================================================
189// Settings 204// Settings
190 205
diff --git a/linden/indra/newview/rlvextensions.cpp b/linden/indra/newview/rlvextensions.cpp
index f31c62e..769d3cc 100644
--- a/linden/indra/newview/rlvextensions.cpp
+++ b/linden/indra/newview/rlvextensions.cpp
@@ -97,7 +97,7 @@ BOOL RlvExtGetSet::processCommand(const LLUUID& idObj, const RlvCommand& rlvCmd)
97 F32 nAngle = 0.0f; 97 F32 nAngle = 0.0f;
98 if (LLStringUtil::convertToF32(rlvCmd.getOption(), nAngle)) 98 if (LLStringUtil::convertToF32(rlvCmd.getOption(), nAngle))
99 { 99 {
100 nAngle += RLV_SETROT_OFFSET; 100 nAngle = RLV_SETROT_OFFSET - nAngle;
101 101
102 gAgent.startCameraAnimation(); 102 gAgent.startCameraAnimation();
103 103
diff --git a/linden/indra/newview/rlvhandler.cpp b/linden/indra/newview/rlvhandler.cpp
index 69e2e2f..88cd174 100644
--- a/linden/indra/newview/rlvhandler.cpp
+++ b/linden/indra/newview/rlvhandler.cpp
@@ -31,11 +31,6 @@
31#include "rlvextensions.h" 31#include "rlvextensions.h"
32#include "rlvhandler.h" 32#include "rlvhandler.h"
33 33
34// Only defined in llinventorybridge.cpp
35#if RLV_TARGET < RLV_MAKE_TARGET(1, 23, 0) // Version: 1.22.11
36 #include "llinventorybridge.h"
37 void confirm_replace_attachment_rez(S32 option, void* user_data);
38#endif
39// Only defined in llinventorymodel.cpp 34// Only defined in llinventorymodel.cpp
40extern const char* NEW_CATEGORY_NAME; 35extern const char* NEW_CATEGORY_NAME;
41 36
@@ -66,8 +61,8 @@ const std::string RlvHandler::cstrMsgTpLure =
66const std::string RlvHandler::cstrAnonyms[] = 61const std::string RlvHandler::cstrAnonyms[] =
67{ 62{
68 "A resident", "This resident", "That resident", "An individual", "This individual", "That individual", "A person", 63 "A resident", "This resident", "That resident", "An individual", "This individual", "That individual", "A person",
69 "This person", "That person", "A stranger", "This stranger", "That stranger", "A human being", "This human being", 64 "This person", "That person", "A stranger", "This stranger", "That stranger", "A being", "This being",
70 "That human being", "An agent", "This agent", "That agent", "A soul", "This soul", "That soul", "Somebody", 65 "That being", "An agent", "This agent", "That agent", "A soul", "This soul", "That soul", "Somebody",
71 "Some people", "Someone", "Mysterious one", "An unknown being", "Unidentified one", "An unknown person" 66 "Some people", "Someone", "Mysterious one", "An unknown being", "Unidentified one", "An unknown person"
72}; 67};
73 68
@@ -131,6 +126,7 @@ RlvHandler::~RlvHandler()
131 //delete m_pGCTimer; // <- deletes itself 126 //delete m_pGCTimer; // <- deletes itself
132 delete m_pWLSnapshot; // <- delete on NULL is harmless 127 delete m_pWLSnapshot; // <- delete on NULL is harmless
133 delete m_pBhvrNotify; 128 delete m_pBhvrNotify;
129 delete m_pAttachMgr;
134} 130}
135 131
136// ============================================================================ 132// ============================================================================
@@ -246,7 +242,7 @@ bool RlvHandler::hasLockedHUD() const
246 return false; 242 return false;
247 243
248 LLViewerJointAttachment* pAttachPt; 244 LLViewerJointAttachment* pAttachPt;
249 for (rlv_detach_map_t::const_iterator itAttachPt = m_Attachments.begin(); itAttachPt != m_Attachments.end(); ++itAttachPt) 245 for (rlv_attachlock_map_t::const_iterator itAttachPt = m_AttachRem.begin(); itAttachPt != m_AttachRem.end(); ++itAttachPt)
250 { 246 {
251 pAttachPt = get_if_there(pAvatar->mAttachmentPoints, (S32)itAttachPt->first, (LLViewerJointAttachment*)NULL); 247 pAttachPt = get_if_there(pAvatar->mAttachmentPoints, (S32)itAttachPt->first, (LLViewerJointAttachment*)NULL);
252 if ( (pAttachPt) && (pAttachPt->getIsHUDAttachment()) ) 248 if ( (pAttachPt) && (pAttachPt->getIsHUDAttachment()) )
@@ -255,61 +251,94 @@ bool RlvHandler::hasLockedHUD() const
255 return false; // None of our locked attachments is a HUD 251 return false; // None of our locked attachments is a HUD
256} 252}
257 253
258bool RlvHandler::isDetachable(const LLInventoryItem* pItem) const 254// Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
255bool RlvHandler::isLockedAttachment(const LLInventoryItem* pItem, ERlvLockMask eLock) const
259{ 256{
260 LLVOAvatar* pAvatar = gAgent.getAvatarObject(); 257 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
261 return ( (pItem) && (pAvatar) ) ? isDetachable(pAvatar->getWornAttachment(pItem->getUUID())) : true; 258 return (pItem) && (pAvatar) && (isLockedAttachment(pAvatar->getWornAttachment(pItem->getUUID()), eLock));
262} 259}
263 260
264// Checked: 2009-08-11 (RLVa-1.0.1h) | Added: RLVa-1.0.1h 261// Checked: 2009-10-13 (RLVa-1.0.5b) | Added: RLVa-1.0.5b
265bool RlvHandler::isDetachableExcept(S32 idxAttachPt, LLViewerObject *pObj) const 262bool RlvHandler::isLockedAttachmentExcept(S32 idxAttachPt, ERlvLockMask eLock, LLViewerObject *pObj) const
266{ 263{
267 // Loop over every object that marked the specific attachment point undetachable (but ignore pObj and any of its children) 264 // Loop over every object that marked the specific attachment point eLock type locked (but ignore pObj and any of its children)
268 for (rlv_detach_map_t::const_iterator itAttach = m_Attachments.lower_bound(idxAttachPt), 265 LLViewerObject* pTempObj;
269 endAttach = m_Attachments.upper_bound(idxAttachPt); itAttach != endAttach; ++itAttach) 266 if (eLock & RLV_LOCK_REMOVE)
270 { 267 {
271 LLViewerObject* pTempObj = gObjectList.findObject(itAttach->second); 268 for (rlv_attachlock_map_t::const_iterator itAttach = m_AttachRem.lower_bound(idxAttachPt),
272 if ( (!pTempObj) || (pTempObj->getRootEdit()->getID() != pObj->getID()) ) 269 endAttach = m_AttachRem.upper_bound(idxAttachPt); itAttach != endAttach; ++itAttach)
273 return false; 270 {
271 if ( ((pTempObj = gObjectList.findObject(itAttach->second)) == NULL) || (pTempObj->getRootEdit()->getID() != pObj->getID()) )
272 return true;
273 }
274 } 274 }
275 return true; 275 if (eLock & RLV_LOCK_ADD)
276 {
277 for (rlv_attachlock_map_t::const_iterator itAttach = m_AttachAdd.lower_bound(idxAttachPt),
278 endAttach = m_AttachAdd.upper_bound(idxAttachPt); itAttach != endAttach; ++itAttach)
279 {
280 if ( ((pTempObj = gObjectList.findObject(itAttach->second)) == NULL) || (pTempObj->getRootEdit()->getID() != pObj->getID()) )
281 return true;
282 }
283 }
284 return false;
276} 285}
277 286
278// Checked: 2009-09-06 (RLVa-1.0.2b) | Modified: RLVa-1.0.2b 287// Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
279bool RlvHandler::setDetachable(S32 idxAttachPt, const LLUUID& idRlvObj, bool fDetachable) 288void RlvHandler::addAttachmentLock(S32 idxAttachPt, const LLUUID &idRlvObj, ERlvLockMask eLock)
280{ 289{
281 // Sanity check - make sure it's an object we know about 290 // Sanity check - make sure it's an object we know about
282 rlv_object_map_t::const_iterator itObj = m_Objects.find(idRlvObj); 291 if ( (m_Objects.find(idRlvObj) == m_Objects.end()) || (!idxAttachPt) )
283 if ( (itObj == m_Objects.end()) || (!idxAttachPt) ) 292 return; // If (idxAttachPt) == 0 then: (pObj == NULL) || (pObj->isAttachment() == FALSE)
284 return false; // If (idxAttachPt) == 0 then: (pObj == NULL) || (pObj->isAttachment() == FALSE)
285 293
286 if (!fDetachable) 294 // NOTE: m_AttachXXX can contain duplicate <idxAttachPt, idRlvObj> pairs (ie @detach:spine=n,detach=n from an attachment on spine)
295 if (eLock & RLV_LOCK_REMOVE)
287 { 296 {
288 #ifdef RLV_EXPERIMENTAL_FIRSTUSE 297 #ifdef RLV_EXPERIMENTAL_FIRSTUSE
289 //LLFirstUse::useRlvDetach(); 298 //LLFirstUse::useRlvDetach();
290 #endif // RLV_EXPERIMENTAL_FIRSTUSE 299 #endif // RLV_EXPERIMENTAL_FIRSTUSE
291 300
292 // NOTE: m_Attachments can contain duplicate <idxAttachPt, idRlvObj> pairs (ie @detach:spine=n,detach=n from an attachment on spine) 301 m_AttachRem.insert(std::pair<S32, LLUUID>(idxAttachPt, idRlvObj));
293 m_Attachments.insert(std::pair<S32, LLUUID>(idxAttachPt, itObj->second.m_UUID));
294 return true;
295 } 302 }
296 else 303 if (eLock & RLV_LOCK_ADD)
297 { 304 {
298 for (rlv_detach_map_t::iterator itAttach = m_Attachments.lower_bound(idxAttachPt), 305 m_AttachAdd.insert(std::pair<S32, LLUUID>(idxAttachPt, idRlvObj));
299 endAttach = m_Attachments.upper_bound(idxAttachPt); itAttach != endAttach; ++itAttach) 306 }
307}
308
309// Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
310void RlvHandler::removeAttachmentLock(S32 idxAttachPt, const LLUUID &idRlvObj, ERlvLockMask eLock)
311{
312 // Sanity check - make sure it's an object we know about
313 if ( (m_Objects.find(idRlvObj) == m_Objects.end()) || (!idxAttachPt) )
314 return; // If (idxAttachPt) == 0 then: (pObj == NULL) || (pObj->isAttachment() == FALSE)
315
316 if (eLock & RLV_LOCK_REMOVE)
317 {
318 for (rlv_attachlock_map_t::iterator itAttach = m_AttachRem.lower_bound(idxAttachPt),
319 endAttach = m_AttachRem.upper_bound(idxAttachPt); itAttach != endAttach; ++itAttach)
300 { 320 {
301 if (itObj->second.m_UUID == itAttach->second) 321 if (idRlvObj == itAttach->second)
302 { 322 {
303 m_Attachments.erase(itAttach); 323 m_AttachRem.erase(itAttach);
304 return true; 324 break;
325 }
326 }
327 }
328 if (eLock & RLV_LOCK_ADD)
329 {
330 for (rlv_attachlock_map_t::iterator itAttach = m_AttachAdd.lower_bound(idxAttachPt),
331 endAttach = m_AttachAdd.upper_bound(idxAttachPt); itAttach != endAttach; ++itAttach)
332 {
333 if (idRlvObj == itAttach->second)
334 {
335 m_AttachAdd.erase(itAttach);
336 break;
305 } 337 }
306 } 338 }
307 } 339 }
308 return false; // Fall-through for (fDetachable == TRUE) - if the object wasn't undetachable then we consider it a failure
309} 340}
310 341
311
312
313#ifdef RLV_EXTENSION_FLAG_NOSTRIP 342#ifdef RLV_EXTENSION_FLAG_NOSTRIP
314 // Checked: 2009-05-26 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d 343 // Checked: 2009-05-26 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d
315 bool RlvHandler::isStrippable(const LLUUID& idItem) const 344 bool RlvHandler::isStrippable(const LLUUID& idItem) const
@@ -413,10 +442,10 @@ void RlvHandler::notifyBehaviourObservers(const RlvCommand& rlvCmd, bool fIntern
413} 442}
414 443
415// Checked: 444// Checked:
416BOOL RlvHandler::processCommand(const LLUUID& uuid, const std::string& strCmd, bool fFromObj) 445BOOL RlvHandler::processCommand(const LLUUID& idObj, const std::string& strCmd, bool fFromObj)
417{ 446{
418 #ifdef RLV_DEBUG 447 #ifdef RLV_DEBUG
419 RLV_INFOS << "[" << uuid << "]: " << strCmd << LL_ENDL; 448 RLV_INFOS << "[" << idObj << "]: " << strCmd << LL_ENDL;
420 #endif // RLV_DEBUG 449 #endif // RLV_DEBUG
421 450
422 RlvCommand rlvCmd(strCmd); 451 RlvCommand rlvCmd(strCmd);
@@ -427,7 +456,10 @@ BOOL RlvHandler::processCommand(const LLUUID& uuid, const std::string& strCmd, b
427 #endif // RLV_DEBUG 456 #endif // RLV_DEBUG
428 return FALSE; 457 return FALSE;
429 } 458 }
430 m_pCurCommand = &rlvCmd; m_idCurObject = uuid; 459
460 // NOTE: if we pass RlvObject::m_UUID for idObj somewhere and process a @clear then it will point to invalid/cleared memory at the end
461 // so make sure to *always* pass our private copy to other functions
462 m_pCurCommand = &rlvCmd; m_idCurObject = idObj;
431 463
432 BOOL fRet = FALSE; 464 BOOL fRet = FALSE;
433 switch (rlvCmd.getParamType()) 465 switch (rlvCmd.getParamType())
@@ -444,7 +476,7 @@ BOOL RlvHandler::processCommand(const LLUUID& uuid, const std::string& strCmd, b
444 break; 476 break;
445 } 477 }
446 478
447 rlv_object_map_t::iterator itObj = m_Objects.find(uuid); 479 rlv_object_map_t::iterator itObj = m_Objects.find(m_idCurObject);
448 if (itObj != m_Objects.end()) 480 if (itObj != m_Objects.end())
449 { 481 {
450 RlvObject& rlvObj = itObj->second; 482 RlvObject& rlvObj = itObj->second;
@@ -452,9 +484,9 @@ BOOL RlvHandler::processCommand(const LLUUID& uuid, const std::string& strCmd, b
452 } 484 }
453 else 485 else
454 { 486 {
455 RlvObject rlvObj(uuid); 487 RlvObject rlvObj(m_idCurObject);
456 fRet = rlvObj.addCommand(rlvCmd); 488 fRet = rlvObj.addCommand(rlvCmd);
457 m_Objects.insert(std::pair<LLUUID, RlvObject>(uuid, rlvObj)); 489 m_Objects.insert(std::pair<LLUUID, RlvObject>(m_idCurObject, rlvObj));
458 } 490 }
459 491
460 #ifdef RLV_DEBUG 492 #ifdef RLV_DEBUG
@@ -464,14 +496,14 @@ BOOL RlvHandler::processCommand(const LLUUID& uuid, const std::string& strCmd, b
464 if (fRet) { // If FALSE then this was a duplicate, there's no need to handle those 496 if (fRet) { // If FALSE then this was a duplicate, there's no need to handle those
465 if (!m_pGCTimer) 497 if (!m_pGCTimer)
466 m_pGCTimer = new RlvGCTimer(); 498 m_pGCTimer = new RlvGCTimer();
467 processAddCommand(uuid, rlvCmd); 499 processAddCommand(m_idCurObject, rlvCmd);
468 notifyBehaviourObservers(rlvCmd, !fFromObj); 500 notifyBehaviourObservers(rlvCmd, !fFromObj);
469 } 501 }
470 } 502 }
471 break; 503 break;
472 case RLV_TYPE_REMOVE: // Checked: 504 case RLV_TYPE_REMOVE: // Checked:
473 { 505 {
474 rlv_object_map_t::iterator itObj = m_Objects.find(uuid); 506 rlv_object_map_t::iterator itObj = m_Objects.find(m_idCurObject);
475 if (itObj != m_Objects.end()) 507 if (itObj != m_Objects.end())
476 fRet = itObj->second.removeCommand(rlvCmd); 508 fRet = itObj->second.removeCommand(rlvCmd);
477 509
@@ -481,13 +513,13 @@ BOOL RlvHandler::processCommand(const LLUUID& uuid, const std::string& strCmd, b
481 #endif // RLV_DEBUG 513 #endif // RLV_DEBUG
482 514
483 if (fRet) { // Don't handle non-sensical removes 515 if (fRet) { // Don't handle non-sensical removes
484 processRemoveCommand(uuid, rlvCmd); 516 processRemoveCommand(m_idCurObject, rlvCmd);
485 notifyBehaviourObservers(rlvCmd, !fFromObj); 517 notifyBehaviourObservers(rlvCmd, !fFromObj);
486 518
487 if (0 == itObj->second.m_Commands.size()) 519 if (0 == itObj->second.m_Commands.size())
488 { 520 {
489 #ifdef RLV_DEBUG 521 #ifdef RLV_DEBUG
490 RLV_INFOS << "\t- command list empty => removing " << uuid << LL_ENDL; 522 RLV_INFOS << "\t- command list empty => removing " << m_idCurObject << LL_ENDL;
491 #endif // RLV_DEBUG 523 #endif // RLV_DEBUG
492 m_Objects.erase(itObj); 524 m_Objects.erase(itObj);
493 } 525 }
@@ -495,14 +527,14 @@ BOOL RlvHandler::processCommand(const LLUUID& uuid, const std::string& strCmd, b
495 } 527 }
496 break; 528 break;
497 case RLV_TYPE_CLEAR: 529 case RLV_TYPE_CLEAR:
498 fRet = processClearCommand(uuid, rlvCmd); 530 fRet = processClearCommand(m_idCurObject, rlvCmd);
499 notifyBehaviourObservers(rlvCmd, !fFromObj); 531 notifyBehaviourObservers(rlvCmd, !fFromObj);
500 break; 532 break;
501 case RLV_TYPE_FORCE: // Checked: 533 case RLV_TYPE_FORCE: // Checked:
502 fRet = processForceCommand(uuid, rlvCmd); 534 fRet = processForceCommand(m_idCurObject, rlvCmd);
503 break; 535 break;
504 case RLV_TYPE_REPLY: // Checked: 536 case RLV_TYPE_REPLY: // Checked:
505 fRet = processReplyCommand(uuid, rlvCmd); 537 fRet = processReplyCommand(m_idCurObject, rlvCmd);
506 break; 538 break;
507 case RLV_TYPE_UNKNOWN: // Checked: 539 case RLV_TYPE_UNKNOWN: // Checked:
508 break; 540 break;
@@ -535,35 +567,15 @@ BOOL RlvHandler::processAddCommand(const LLUUID& uuid, const RlvCommand& rlvCmd)
535 m_Behaviours[eBehaviour]++; 567 m_Behaviours[eBehaviour]++;
536 } 568 }
537 569
570 bool fRefCount = false; // Unused for the moment
538 switch (eBehaviour) 571 switch (eBehaviour)
539 { 572 {
540 case RLV_BHVR_DETACH: // @detach[:<option>]=n - Checked: 2009-08-04 (RLVa-1.0.1d) | Modified: RLVa-1.0.1d 573 case RLV_BHVR_DETACH: // @detach[:<option>]=n - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
541 { 574 onAddRemDetach(uuid, rlvCmd, fRefCount);
542 LLViewerObject* pObj = NULL; S32 idxAttachPt = 0; 575 break;
543 if (strOption.empty()) // @detach=n 576 case RLV_BHVR_ADDATTACH: // @addattach[:<option>]=n - Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
544 { 577 case RLV_BHVR_REMATTACH: // @addattach[:<option>]=n - Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
545 // If the object rezzed before we received @detach=n from it then we can just do our thing here 578 onAddRemAttach(uuid, rlvCmd, fRefCount);
546 // If the object hasn't rezzed yet then we need to wait until RlvHandler::onAttach()
547 // If @detach=n were possible for non-attachments another copy/paste would be needed in RlvHandler::onGC()
548 if ((pObj = gObjectList.findObject(uuid)) != NULL)
549 setDetachable(pObj, uuid, false);
550 }
551 else if ((idxAttachPt = getAttachPointIndex(strOption, true)) != 0) // @detach:<attachpt>=n
552 {
553 setDetachable(idxAttachPt, uuid, false);
554
555 // (See below)
556 LLViewerJointAttachment* pAttachPt = getAttachPoint(strOption, true);
557 if (pAttachPt)
558 pObj = pAttachPt->getObject();
559 }
560
561 // When at least one HUD attachment is locked we want to make sure they're all visible (ie prevent hiding a blindfold HUD)
562 // However, since @detach:<attachpt>=n might lock a HUD attachment point that doesn't currently have an object we
563 // have to do this here *and* in RlvHandler::onAttach()
564 if ( (pObj) && (pObj->isHUDAttachment()) )
565 LLPipeline::sShowHUDAttachments = TRUE;
566 }
567 break; 579 break;
568 case RLV_BHVR_REDIRCHAT: // @redirchat:<option>=n - Checked: 2009-07-07 (RLVa-1.0.0d) 580 case RLV_BHVR_REDIRCHAT: // @redirchat:<option>=n - Checked: 2009-07-07 (RLVa-1.0.0d)
569 case RLV_BHVR_REDIREMOTE: // @rediremote:<option>=n - Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.2a 581 case RLV_BHVR_REDIREMOTE: // @rediremote:<option>=n - Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.2a
@@ -797,25 +809,15 @@ BOOL RlvHandler::processRemoveCommand(const LLUUID& uuid, const RlvCommand& rlvC
797 m_Behaviours[eBehaviour]--; 809 m_Behaviours[eBehaviour]--;
798 } 810 }
799 811
812 bool fRefCount = false; // Unused for the moment
800 switch (eBehaviour) 813 switch (eBehaviour)
801 { 814 {
802 case RLV_BHVR_DETACH: // @detach[:<option>]=y - Checked: 2009-08-04 (RLVa-1.0.1d) | Modified: RLVa-1.0.1d 815 case RLV_BHVR_DETACH: // @detach[:<option>]=y - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
803 { 816 onAddRemDetach(uuid, rlvCmd, fRefCount);
804 S32 idxAttachPt = 0; 817 break;
805 if (strOption.empty()) // @detach=y 818 case RLV_BHVR_ADDATTACH: // @addattach[:<option>]=y - Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
806 { 819 case RLV_BHVR_REMATTACH: // @addattach[:<option>]=y - Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
807 // The object may or may not (if it got detached) still exist 820 onAddRemAttach(uuid, rlvCmd, fRefCount);
808 rlv_object_map_t::const_iterator itObj = m_Objects.find(uuid);
809 if (itObj != m_Objects.end())
810 idxAttachPt = itObj->second.m_idxAttachPt;
811 if (idxAttachPt)
812 setDetachable(idxAttachPt, uuid, true);
813 }
814 else if ((idxAttachPt = getAttachPointIndex(strOption, true))) // @detach:<attachpt>=y
815 {
816 setDetachable(idxAttachPt, uuid, true);
817 }
818 }
819 break; 821 break;
820 case RLV_BHVR_REDIRCHAT: // @redirchat:<option>=y - Checked: 2009-07-07 (RLVa-1.0.0d) 822 case RLV_BHVR_REDIRCHAT: // @redirchat:<option>=y - Checked: 2009-07-07 (RLVa-1.0.0d)
821 case RLV_BHVR_REDIREMOTE: // @rediremote:<option>=y - Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.2a 823 case RLV_BHVR_REDIREMOTE: // @rediremote:<option>=y - Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.2a
@@ -940,7 +942,7 @@ BOOL RlvHandler::processRemoveCommand(const LLUUID& uuid, const RlvCommand& rlvC
940 return TRUE; // Remove commands don't fail, doesn't matter what we return here 942 return TRUE; // Remove commands don't fail, doesn't matter what we return here
941} 943}
942 944
943BOOL RlvHandler::processClearCommand(const LLUUID& idObj, const RlvCommand& rlvCmd) 945BOOL RlvHandler::processClearCommand(const LLUUID idObj, const RlvCommand& rlvCmd)
944{ 946{
945 const std::string& strFilter = rlvCmd.getParam(); std::string strCmdRem; 947 const std::string& strFilter = rlvCmd.getParam(); std::string strCmdRem;
946 948
@@ -976,8 +978,11 @@ BOOL RlvHandler::processForceCommand(const LLUUID& idObj, const RlvCommand& rlvC
976 978
977 switch (rlvCmd.getBehaviourType()) 979 switch (rlvCmd.getBehaviourType())
978 { 980 {
979 case RLV_BHVR_DETACH: // @detach[:<option>]=force - Checked: 981 case RLV_BHVR_DETACH: // @detach[:<option>]=force - Checked: 2009-10-12 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
980 onForceDetach(idObj, strOption); 982 onForceDetach(idObj, rlvCmd);
983 break;
984 case RLV_BHVR_REMATTACH: // @remattach[:<option>]=force - Checked: 2009-10-12 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
985 onForceRemAttach(idObj, rlvCmd);
981 break; 986 break;
982 case RLV_BHVR_REMOUTFIT: // @remoutfit:<option>=force - Checked: 987 case RLV_BHVR_REMOUTFIT: // @remoutfit:<option>=force - Checked:
983 onForceRemOutfit(idObj, strOption); 988 onForceRemOutfit(idObj, strOption);
@@ -1125,7 +1130,7 @@ BOOL RlvHandler::processReplyCommand(const LLUUID& uuid, const RlvCommand& rlvCm
1125 #endif // RLV_EXPERIMENTAL_COMPOSITE_FOLDING 1130 #endif // RLV_EXPERIMENTAL_COMPOSITE_FOLDING
1126 } 1131 }
1127 break; 1132 break;
1128 case RLV_BHVR_GETATTACH: // @getattach[:<layer>]=<channel> - Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-0.2.0d 1133 case RLV_BHVR_GETATTACH: // @getattach[:<layer>]=<channel> - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
1129 { 1134 {
1130 // If we're fetching all worn attachments then the reply should start with 0 1135 // If we're fetching all worn attachments then the reply should start with 0
1131 if (strOption.empty()) 1136 if (strOption.empty())
@@ -1155,9 +1160,9 @@ BOOL RlvHandler::processReplyCommand(const LLUUID& uuid, const RlvCommand& rlvCm
1155 { 1160 {
1156 bool fWorn = (pAttachment->getItemID().notNull()) && 1161 bool fWorn = (pAttachment->getItemID().notNull()) &&
1157 ( (!RlvSettings::getHideLockedAttach()) || 1162 ( (!RlvSettings::getHideLockedAttach()) ||
1158 ( (isDetachable(itAttach->first)) && (isStrippable(pAttachment->getItemID())) ) ); 1163 ( (!isLockedAttachmentExcept(itAttach->first, RLV_LOCK_REMOVE, gObjectList.findObject(uuid))) &&
1164 (isStrippable(pAttachment->getItemID())) ) );
1159 strReply.push_back( (fWorn) ? '1' : '0' ); 1165 strReply.push_back( (fWorn) ? '1' : '0' );
1160 //strReply.push_back( (pAttachment->getItemID().notNull()) ? '1' : '0' );
1161 } 1166 }
1162 #endif // RLV_EXPERIMENTAL_COMPOSITE_FOLDING 1167 #endif // RLV_EXPERIMENTAL_COMPOSITE_FOLDING
1163 } 1168 }
@@ -1327,7 +1332,7 @@ void RlvHandler::initLookupTables()
1327} 1332}
1328 1333
1329// Checked: 2009-08-11 (RLVa-1.0.1h) | Modified: RLVa-1.0.1h 1334// Checked: 2009-08-11 (RLVa-1.0.1h) | Modified: RLVa-1.0.1h
1330void RlvHandler::onAttach(LLViewerJointAttachment* pAttachPt, bool fFullyLoaded) 1335void RlvHandler::onAttach(LLViewerJointAttachment* pAttachPt)
1331{ 1336{
1332 // Sanity check - LLVOAvatar::attachObject() should call us *after* calling LLViewerJointAttachment::addObject() 1337 // Sanity check - LLVOAvatar::attachObject() should call us *after* calling LLViewerJointAttachment::addObject()
1333 LLViewerObject* pObj = pAttachPt->getObject(); 1338 LLViewerObject* pObj = pAttachPt->getObject();
@@ -1338,30 +1343,8 @@ void RlvHandler::onAttach(LLViewerJointAttachment* pAttachPt, bool fFullyLoaded)
1338 return; 1343 return;
1339 } 1344 }
1340 1345
1341 // Check if this attachment point has a pending "reattach-on-detach" 1346 // Let the attachment manager know
1342 rlv_reattach_map_t::iterator itReattach = m_AttachPending.find(idxAttachPt); 1347 m_pAttachMgr->onAttach(pAttachPt);
1343 if (itReattach != m_AttachPending.end())
1344 {
1345 if (itReattach->second == pAttachPt->getItemID())
1346 {
1347 RLV_INFOS << "Reattached " << pAttachPt->getItemID().asString() << " to " << idxAttachPt << LL_ENDL;
1348 m_AttachPending.erase(itReattach);
1349 }
1350 }
1351 else if ( (fFullyLoaded) && (!isDetachableExcept(idxAttachPt, pObj)) )
1352 {
1353 // We're fully loaded with no pending reattach on this attach point but it's "undetachable" -> force detach the new attachment
1354
1355 // Assertion: the only way the attachment point could be locked at this point is if some object locked it with @detach:attachpt=n
1356 // - previous attachments on this attachment point might have issued @detach=n but those were all cleaned up at detach
1357 // - the new attachment might have issued @detach=n but that won't actually lock down the attachment point until further down
1358 // NOTE 1: "some object" may no longer exist if it was not an attachment and the GC hasn't cleaned it up yet (informative)
1359 // NOTE 2: "some object" may refer to the new attachment - ie @detach:spine=n from object on spine (problematic, causes reattach)
1360 // -> solved by using isDetachableExcept(idxAttachPt, pObj) instead of isDetachable(idxAttachPt)
1361
1362 m_DetachPending.insert(std::pair<S32, LLUUID>(idxAttachPt, pObj->getID()));
1363 rlvForceDetach(pAttachPt);
1364 }
1365 1348
1366 // Check if we already have an RlvObject instance for this object (rezzed prim attached from in-world, or an attachment that rezzed in) 1349 // Check if we already have an RlvObject instance for this object (rezzed prim attached from in-world, or an attachment that rezzed in)
1367 rlv_object_map_t::iterator itObj = m_Objects.find(pObj->getID()); 1350 rlv_object_map_t::iterator itObj = m_Objects.find(pObj->getID());
@@ -1378,7 +1361,7 @@ void RlvHandler::onAttach(LLViewerJointAttachment* pAttachPt, bool fFullyLoaded)
1378 if (itObj->second.hasBehaviour(RLV_BHVR_DETACH, false)) 1361 if (itObj->second.hasBehaviour(RLV_BHVR_DETACH, false))
1379 { 1362 {
1380 // (Copy/paste from processAddCommand) 1363 // (Copy/paste from processAddCommand)
1381 setDetachable(idxAttachPt, pObj->getID(), false); 1364 addAttachmentLock(idxAttachPt, itObj->second.m_UUID, RLV_LOCK_REMOVE);
1382 1365
1383 if (pObj->isHUDAttachment()) 1366 if (pObj->isHUDAttachment())
1384 LLPipeline::sShowHUDAttachments = TRUE; // Prevents hiding of locked HUD attachments 1367 LLPipeline::sShowHUDAttachments = TRUE; // Prevents hiding of locked HUD attachments
@@ -1469,44 +1452,19 @@ void RlvHandler::onDetach(LLViewerJointAttachment* pAttachPt)
1469 //RLV_INFOS << "Clean up for '" << pDbgAttachmentPt->getName() << "'" << LL_ENDL; 1452 //RLV_INFOS << "Clean up for '" << pDbgAttachmentPt->getName() << "'" << LL_ENDL;
1470 #endif // RLV_DEBUG 1453 #endif // RLV_DEBUG
1471 1454
1472 // If the attachment was locked then we should reattach it (unless we're already trying to reattach to this attachment point) 1455 // Let the attachment manager know
1473 // (unless we forcefully detached it else in which case we do not want to reattach it) 1456 m_pAttachMgr->onDetach(pAttachPt);
1474 rlv_reattach_map_t::iterator itDetach = m_DetachPending.find(idxAttachPt);
1475 if (itDetach != m_DetachPending.end())
1476 {
1477 // RLVa-TODO: we should really be comparing item UUIDs but is it even possible to end up here and not have them match?
1478 m_DetachPending.erase(itDetach);
1479 }
1480 else if ( (!isDetachable(idxAttachPt)) && (m_AttachPending.find(idxAttachPt) == m_AttachPending.end()) )
1481 {
1482 // In an ideal world we would simply set up an LLInventoryObserver but there's no specific "asset updated" changed flag *sighs*
1483 // NOTE: attachments *always* know their "inventory item UUID" so we don't have to worry about fetched vs unfetched inventory
1484 m_AttachPending.insert(std::pair<S32, LLUUID>(idxAttachPt, pAttachPt->getItemID()));
1485 }
1486 1457
1487 // We can't - easily - clean up child prims that never issued @detach=n but the GC will get those eventually 1458 // Clean up any restriction this object (or one of its child prims) may have
1488 rlv_detach_map_t::iterator itAttach = m_Attachments.find(idxAttachPt); 1459 rlv_object_map_t::iterator itObj = m_Objects.begin(), itCurrent;
1489 while ( (itAttach != m_Attachments.upper_bound(idxAttachPt)) && (itAttach != m_Attachments.end()) ) 1460 while (itObj != m_Objects.end())
1490 { 1461 {
1491 LLViewerObject* pTempObj = gObjectList.findObject(itAttach->second); 1462 itCurrent = itObj++; // @clear will invalidate our iterator so point it ahead now
1492 if ( (pTempObj) && (pTempObj->getRootEdit()->getID() == pObj->getID()) )
1493 {
1494 // Iterator points to the object (or to a child prim) so issue a clear on behalf of the object (there's the
1495 // possibility of going into an eternal loop, but that's ok since it indicates a bug in @clear that needs fixing)
1496 processCommand(itAttach->second, "clear", true);
1497 1463
1498 itAttach = m_Attachments.find(idxAttachPt); // @clear will invalidate all iterators so we have to start anew 1464 // NOTE: ObjectKill seems to happen in reverse (child prims are killed before the root is) so we can't use gObjectList here
1499 } 1465 if (itCurrent->second.m_idxAttachPt == idxAttachPt)
1500 else 1466 processCommand(itCurrent->second.m_UUID, "clear", true);
1501 {
1502 itAttach++;
1503 }
1504 } 1467 }
1505
1506 // Clean up in case there was never a @detach=n (only works for the root prim - see above)
1507 rlv_object_map_t::iterator itObj = m_Objects.find(pObj->getID());
1508 if (itObj != m_Objects.end())
1509 processCommand(itObj->second.m_UUID, "clear", true);
1510} 1468}
1511 1469
1512// Checked: 2009-07-30 (RLVa-1.0.1c) | Modified: RLVa-1.0.1c 1470// Checked: 2009-07-30 (RLVa-1.0.1c) | Modified: RLVa-1.0.1c
@@ -1548,32 +1506,6 @@ bool RlvHandler::onGC()
1548 return (0 != m_Objects.size()); // GC will kill itself if it has nothing to do 1506 return (0 != m_Objects.size()); // GC will kill itself if it has nothing to do
1549} 1507}
1550 1508
1551// Checked: 2009-08-08 (RLVa-1.0.1g) | Modified: RLVa-1.0.1g
1552void RlvHandler::onSavedAssetIntoInventory(const LLUUID& idItem)
1553{
1554 for (rlv_reattach_map_t::iterator itAttach = m_AttachPending.begin(); itAttach != m_AttachPending.end(); ++itAttach)
1555 {
1556 if (idItem == itAttach->second)
1557 {
1558 RLV_INFOS << "Reattaching " << idItem.asString() << " to " << itAttach->first << LL_ENDL;
1559
1560 #if RLV_TARGET < RLV_MAKE_TARGET(1, 23, 0) // Version: 1.22.11
1561 LLAttachmentRezAction* rez_action = new LLAttachmentRezAction;
1562 rez_action->mItemID = itAttach->second;
1563 rez_action->mAttachPt = itAttach->first;
1564
1565 confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action); // (Will call delete on rez_action)
1566 #else // Version: 1.23.4
1567 LLSD payload;
1568 payload["item_id"] = itAttach->second;
1569 payload["attachment_point"] = itAttach->first;
1570
1571 LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
1572 #endif
1573 }
1574 }
1575}
1576
1577// ============================================================================ 1509// ============================================================================
1578// String/chat censoring functions 1510// String/chat censoring functions
1579// 1511//
@@ -2099,47 +2031,6 @@ std::string RlvHandler::getSharedPath(const LLViewerInventoryCategory* pFolder)
2099// 2031//
2100 2032
2101// Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-0.2.0d 2033// Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-0.2.0d
2102void RlvHandler::onForceDetach(const LLUUID& idObj, const std::string& strOption) const
2103{
2104 U16 nParam;
2105 if (strOption.empty())
2106 {
2107 // Simulate right-click / Take Off > Detach All
2108 LLAgent::userRemoveAllAttachments(NULL);
2109 }
2110 else if (m_AttachLookup.getExactMatchParam(strOption, nParam))
2111 {
2112 // Simulate right-click / Take Off > Detach > ...
2113 LLVOAvatar* pAvatar; LLViewerJointAttachment* pAttachmentPt;
2114 if ( ((pAvatar = gAgent.getAvatarObject()) != NULL) && // Make sure we're actually wearing something on the attachment point
2115 ((pAttachmentPt = get_if_there(pAvatar->mAttachmentPoints, (S32)nParam, (LLViewerJointAttachment*)NULL)) != NULL) &&
2116 (isStrippable(pAttachmentPt->getItemID())) ) // ... and that it's not marked as "nostrip"
2117 {
2118 #ifdef RLV_EXPERIMENTAL_COMPOSITES
2119 // If we're stripping something that's part of a composite folder then we should @detachthis instead
2120 if (isCompositeDescendent(pAttachmentPt->getItemID()))
2121 {
2122 std::string strCmd = "detachthis:" + strOption + "=force";
2123 #ifdef RLV_DEBUG
2124 RLV_INFOS << "\t- '" << strOption << "' belongs to composite folder: @" << strCmd << LL_ENDL;
2125 #endif // RLV_DEBUG
2126 processForceCommand(idObj, RlvCommand(strCmd));
2127 }
2128 else
2129 #endif // RLV_EXPERIMENTAL_COMPOSITES
2130 {
2131 handle_detach_from_avatar(pAttachmentPt);
2132 }
2133 }
2134 }
2135 else
2136 {
2137 // Force detach single folder
2138 onForceWear(strOption, false, false);
2139 }
2140}
2141
2142// Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-0.2.0d
2143void RlvHandler::onForceRemOutfit(const LLUUID& idObj, const std::string& strOption) const 2034void RlvHandler::onForceRemOutfit(const LLUUID& idObj, const std::string& strOption) const
2144{ 2035{
2145 EWearableType typeOption = LLWearable::typeNameToType(strOption), type; 2036 EWearableType typeOption = LLWearable::typeNameToType(strOption), type;
@@ -2209,6 +2100,7 @@ bool RlvHandler::onForceSit(const LLUUID& idObj, const std::string& strOption) c
2209 return true; 2100 return true;
2210} 2101}
2211 2102
2103// Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
2212void RlvHandler::onForceWear(const std::string& strPath, bool fAttach, bool fMatchAll) const 2104void RlvHandler::onForceWear(const std::string& strPath, bool fAttach, bool fMatchAll) const
2213{ 2105{
2214 // See LLWearableBridge::wearOnAvatar(): don't wear anything until initial wearables are loaded, can destroy clothing items 2106 // See LLWearableBridge::wearOnAvatar(): don't wear anything until initial wearables are loaded, can destroy clothing items
@@ -2281,22 +2173,11 @@ void RlvHandler::onForceWear(const std::string& strPath, bool fAttach, bool fMat
2281 // Simulate wearing an object to a specific attachment point (copy/paste to suppress replacement dialog) 2173 // Simulate wearing an object to a specific attachment point (copy/paste to suppress replacement dialog)
2282 // LLAttachObject::handleEvent() => rez_attachment() 2174 // LLAttachObject::handleEvent() => rez_attachment()
2283 LLViewerJointAttachment* pAttachPt = getAttachPoint(pItem, true); 2175 LLViewerJointAttachment* pAttachPt = getAttachPoint(pItem, true);
2284 if ( (pAttachPt) && (isDetachable(pAttachPt)) ) 2176 if ( (pAttachPt) && // Need a specific attach pt that
2177 ( (!isLockedAttachment(pAttachPt->getObject(), RLV_LOCK_REMOVE)) && // doesn't have locked object
2178 (!isLockedAttachment(pAttachPt, RLV_LOCK_ADD)) ) ) // and that can be attached to
2285 { 2179 {
2286 #if RLV_TARGET < RLV_MAKE_TARGET(1, 23, 0) // Version: 1.22.11 2180 RlvAttachmentManager::forceAttach(pItem->getUUID(), getAttachPointIndex(pAttachPt->getName(), true));
2287 LLAttachmentRezAction* rez_action = new LLAttachmentRezAction;
2288 rez_action->mItemID = pItem->getUUID();
2289 rez_action->mAttachPt = getAttachPointIndex(pAttachPt->getName(), true);
2290
2291 confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action); // (Will call delete on rez_action)
2292 #else // Version: 1.23.4
2293 LLSD payload;
2294 payload["item_id"] = pItem->getUUID();
2295 payload["attachment_point"] = getAttachPointIndex(pAttachPt->getName(), true);
2296
2297 LLNotifications::instance().forceResponse(
2298 LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
2299 #endif
2300 } 2181 }
2301 } 2182 }
2302 else 2183 else
@@ -2504,6 +2385,7 @@ BOOL RlvHandler::setEnabled(BOOL fEnable)
2504 RlvSettings::fShowNameTags = gSavedSettings.getBOOL(RLV_SETTING_SHOWNAMETAGS); 2385 RlvSettings::fShowNameTags = gSavedSettings.getBOOL(RLV_SETTING_SHOWNAMETAGS);
2505 2386
2506 RlvCommand::initLookupTable(); 2387 RlvCommand::initLookupTable();
2388 gRlvHandler.m_pAttachMgr = new RlvAttachmentManager();
2507 gRlvHandler.addObserver(new RlvExtGetSet()); 2389 gRlvHandler.addObserver(new RlvExtGetSet());
2508 2390
2509 if (LLStartUp::getStartupState() >= STATE_CLEANUP) 2391 if (LLStartUp::getStartupState() >= STATE_CLEANUP)
@@ -2553,7 +2435,7 @@ void RlvHandler::clearState()
2553 while (m_Objects.size()) 2435 while (m_Objects.size())
2554 { 2436 {
2555 idObj = m_Objects.begin()->first; // Need a copy since after @clear the data it points to will no longer exist 2437 idObj = m_Objects.begin()->first; // Need a copy since after @clear the data it points to will no longer exist
2556 fDetachable = ((pObj = gObjectList.findObject(idObj)) != NULL) ? isDetachable(pObj) : true; 2438 fDetachable = ((pObj = gObjectList.findObject(idObj)) != NULL) ? isLockedAttachment(pObj, RLV_LOCK_REMOVE) : true;
2557 2439
2558 processCommand(idObj, "clear", false); 2440 processCommand(idObj, "clear", false);
2559 if (!fDetachable) 2441 if (!fDetachable)
@@ -2561,32 +2443,165 @@ void RlvHandler::clearState()
2561 } 2443 }
2562 2444
2563 // Sanity check - these should all be empty after we issue @clear on the last object 2445 // Sanity check - these should all be empty after we issue @clear on the last object
2564 if ( (!m_Objects.empty()) || !(m_Exceptions.empty()) || (!m_Attachments.empty()) ) 2446 if ( (!m_Objects.empty()) || !(m_Exceptions.empty()) || (!m_AttachAdd.empty()) || (!m_AttachRem.empty()) )
2565 { 2447 {
2566 RLV_ERRS << "Object, exception or attachment map not empty after clearing state!" << LL_ENDL; 2448 RLV_ERRS << "Object, exception or attachment map not empty after clearing state!" << LL_ENDL;
2567 m_Objects.clear(); 2449 m_Objects.clear();
2568 m_Exceptions.clear(); 2450 m_Exceptions.clear();
2569 m_Attachments.clear(); 2451 m_AttachAdd.clear();
2452 m_AttachRem.clear();
2570 } 2453 }
2571 2454
2572 // These all need manual clearing 2455 // These all need manual clearing
2573 memset(m_LayersAdd, 0, sizeof(S16) * WT_COUNT); 2456 memset(m_LayersAdd, 0, sizeof(S16) * WT_COUNT);
2574 memset(m_LayersRem, 0, sizeof(S16) * WT_COUNT); 2457 memset(m_LayersRem, 0, sizeof(S16) * WT_COUNT);
2575 memset(m_Behaviours, 0, sizeof(S16) * RLV_BHVR_COUNT); 2458 memset(m_Behaviours, 0, sizeof(S16) * RLV_BHVR_COUNT);
2576 m_AttachPending.clear(); 2459 m_Retained.clear();
2577 m_Emitter.clearObservers(); // <- calls delete on all active observers 2460 m_Emitter.clearObservers(); // <- calls delete on all active observers
2578 2461
2579 // Clear dynamically allocated memory 2462 // Clear dynamically allocated memory
2580 if (m_pGCTimer) 2463 delete m_pGCTimer;
2464 m_pGCTimer = NULL;
2465 delete m_pWLSnapshot;
2466 m_pWLSnapshot = NULL;
2467 delete m_pAttachMgr;
2468 m_pAttachMgr = NULL;
2469}
2470
2471// ============================================================================
2472// Command handlers (RLV_TYPE_ADD and RLV_TYPE_REMOVE)
2473//
2474
2475// Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
2476ERlvCmdRet RlvHandler::onAddRemAttach(const LLUUID& idObj, const RlvCommand& rlvCmd, bool& fRefCount)
2477{
2478 // Sanity check - if there's an option it should specify a valid attachment point name
2479 S32 idxAttachPt = getAttachPointIndex(rlvCmd.getOption(), true);
2480 if ( (!idxAttachPt) && (!rlvCmd.getOption().empty()) )
2481 return RLV_RET_FAILED_OPTION;
2482
2483 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
2484 if (!pAvatar)
2485 return RLV_RET_FAILED;
2486
2487 ERlvLockMask eLock = (RLV_BHVR_REMATTACH == rlvCmd.getBehaviourType()) ? RLV_LOCK_REMOVE : RLV_LOCK_ADD;
2488 for (LLVOAvatar::attachment_map_t::const_iterator itAttach = pAvatar->mAttachmentPoints.begin();
2489 itAttach != pAvatar->mAttachmentPoints.end(); ++itAttach)
2581 { 2490 {
2582 delete m_pGCTimer; 2491 if ( (0 == idxAttachPt) || (itAttach->first == idxAttachPt) )
2583 m_pGCTimer = NULL; 2492 {
2493 if (RLV_TYPE_ADD == rlvCmd.getParamType())
2494 addAttachmentLock(itAttach->first, idObj, eLock);
2495 else
2496 removeAttachmentLock(itAttach->first, idObj, eLock);
2497 }
2584 } 2498 }
2585 if (m_pWLSnapshot) 2499
2500 // Refresh HUD visibility if needed
2501 if ( (RLV_BHVR_REMATTACH == rlvCmd.getBehaviourType()) && (hasLockedHUD()) )
2502 LLPipeline::sShowHUDAttachments = TRUE;
2503
2504 fRefCount = rlvCmd.getOption().empty(); // Only reference count global locks
2505 return RLV_RET_NOERROR;
2506}
2507
2508// Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
2509ERlvCmdRet RlvHandler::onAddRemDetach(const LLUUID& idObj, const RlvCommand& rlvCmd, bool& fRefCount)
2510{
2511 S32 idxAttachPt = 0;
2512 if (rlvCmd.getOption().empty()) // @detach=n|y
2586 { 2513 {
2587 delete m_pWLSnapshot; 2514 // The object may or may not exist (it may not have rezzed yet, or it may have already been killed):
2588 m_pWLSnapshot = NULL; 2515 // * @detach=n: - if it has rezzed then we'll already have its attachment point
2516 // - if it hasn't rezzed yet then it's a @detach=n from a non-attachment and RlvHandler::onAttach() takes care of it
2517 // * @detach=y: - if it ever rezzed as an attachment we'll have cached its attach point
2518 // - if it never rezzed as an attachment there won't be a lock to remove
2519 rlv_object_map_t::const_iterator itObj = m_Objects.find(idObj);
2520 if (itObj != m_Objects.end())
2521 idxAttachPt = itObj->second.m_idxAttachPt;
2522 }
2523 else // @detach:<attachpt>=n|y
2524 {
2525 idxAttachPt = getAttachPointIndex(rlvCmd.getOption(), true);
2526 }
2527
2528 // The attach point can be zero for @detach=n|y (i.e. non-attachment) but should always be non-zero for @detach:<attachpt>=n|y
2529 if (0 == idxAttachPt)
2530 return (rlvCmd.getOption().empty()) ? RLV_RET_NOERROR : RLV_RET_FAILED_OPTION;
2531
2532 // Actually lock the attachment point (@detach=n locks remove only; @detach:<attachpt>=n locks both remove and add)
2533 ERlvLockMask eLock = (rlvCmd.getOption().empty()) ? RLV_LOCK_REMOVE : (ERlvLockMask)(RLV_LOCK_ADD | RLV_LOCK_REMOVE);
2534 if (RLV_TYPE_ADD == rlvCmd.getParamType())
2535 addAttachmentLock(idxAttachPt, idObj, eLock);
2536 else
2537 removeAttachmentLock(idxAttachPt, idObj, eLock);
2538
2539 // Refresh HUD visibility if needed
2540 if ( (RLV_TYPE_ADD == rlvCmd.getParamType()) && (hasLockedHUD()) )
2541 LLPipeline::sShowHUDAttachments = TRUE;
2542
2543 fRefCount = false; // Don't reference count @detach[:<option>]=n
2544 return RLV_RET_NOERROR;
2545}
2546
2547// ============================================================================
2548// Command handlers (RLV_TYPE_FORCE)
2549//
2550
2551// Checked: 2009-10-12 (RLVa-1.0.5b) | Modified: RLVa-1.0.5b
2552ERlvCmdRet RlvHandler::onForceDetach(const LLUUID& idObj, const RlvCommand& rlvCmd) const
2553{
2554 // TODO-RLVA: this still needs a rewrite to conform to the new event handler system
2555 if ( (rlvCmd.getOption().empty()) || (getAttachPointIndex(rlvCmd.getOption(), true)) )
2556 {
2557 onForceRemAttach(idObj, rlvCmd);
2558 }
2559 else
2560 {
2561 // Force detach single folder
2562 onForceWear(rlvCmd.getOption(), false, false);
2563 }
2564
2565 return RLV_RET_NOERROR;
2566}
2567
2568// Checked: 2009-10-12 (RLVa-1.0.5b) | Added: RLVa-1.0.5b
2569ERlvCmdRet RlvHandler::onForceRemAttach(const LLUUID& idObj, const RlvCommand& rlvCmd) const
2570{
2571 S32 idxAttachPt = 0;
2572 if (rlvCmd.getOption().empty())
2573 {
2574 // Simulate right-click / Take Off > Detach All
2575 LLAgent::userRemoveAllAttachments(NULL);
2576 return RLV_RET_NOERROR;
2577 }
2578 else if ((idxAttachPt = getAttachPointIndex(rlvCmd.getOption(), true)) != 0)
2579 {
2580 // Simulate right-click / Take Off > Detach > ...
2581 LLVOAvatar* pAvatar; LLViewerJointAttachment* pAttachmentPt;
2582 if ( ((pAvatar = gAgent.getAvatarObject()) != NULL) && // Make sure we're actually wearing something on the attachment point
2583 ((pAttachmentPt = get_if_there(pAvatar->mAttachmentPoints, (S32)idxAttachPt, (LLViewerJointAttachment*)NULL)) != NULL) &&
2584 (isStrippable(pAttachmentPt->getItemID())) ) // ... and that it's not marked as "nostrip"
2585 {
2586 #ifdef RLV_EXPERIMENTAL_COMPOSITES
2587 // If we're stripping something that's part of a composite folder then we should @detachthis instead
2588 if (isCompositeDescendent(pAttachmentPt->getItemID()))
2589 {
2590 std::string strCmd = "detachthis:" + strOption + "=force";
2591 #ifdef RLV_DEBUG
2592 RLV_INFOS << "\t- '" << strOption << "' belongs to composite folder: @" << strCmd << LL_ENDL;
2593 #endif // RLV_DEBUG
2594 processForceCommand(idObj, RlvCommand(strCmd));
2595 }
2596 else
2597 #endif // RLV_EXPERIMENTAL_COMPOSITES
2598 {
2599 handle_detach_from_avatar(pAttachmentPt);
2600 }
2601 }
2602 return RLV_RET_NOERROR;
2589 } 2603 }
2604 return RLV_RET_FAILED_OPTION;
2590} 2605}
2591 2606
2592// ============================================================================ 2607// ============================================================================
diff --git a/linden/indra/newview/rlvhandler.h b/linden/indra/newview/rlvhandler.h
index 5295a72..6821149 100644
--- a/linden/indra/newview/rlvhandler.h
+++ b/linden/indra/newview/rlvhandler.h
@@ -16,9 +16,8 @@
16// ============================================================================ 16// ============================================================================
17 17
18typedef std::map<LLUUID, RlvObject> rlv_object_map_t; 18typedef std::map<LLUUID, RlvObject> rlv_object_map_t;
19typedef std::multimap<S32, LLUUID> rlv_detach_map_t;
20typedef std::map<S32, LLUUID> rlv_reattach_map_t;
21typedef std::multimap<ERlvBehaviour, RlvException> rlv_exception_map_t; 19typedef std::multimap<ERlvBehaviour, RlvException> rlv_exception_map_t;
20typedef std::map<S32, LLUUID> rlv_attachlock_map_t;
22 21
23class RlvHandler 22class RlvHandler
24{ 23{
@@ -47,7 +46,9 @@ public:
47 /* 46 /*
48 * Rule checking functions 47 * Rule checking functions
49 */ 48 */
50 // NOTE: - to check @detach=n -> hasLockedAttachment() / hasLockedHUD() / isDetachable() 49 // NOTE: - to check @detach=n -> hasLockedAttachment(RLV_LOCK_REMOVE) / hasLockedHUD() / isLockedAttachment(.., RLV_LOCK_REMOVE)
50 // - to check @addattach=n -> hasLockedAttachment(RLV_LOCK_ADD) / isLockedAttachment(.., RLV_LOCK_ADD)
51 // - to check @remattach=n -> (see @detach=n)
51 // - to check exceptions -> isException() 52 // - to check exceptions -> isException()
52 // - to check @addoutfit=n -> isWearable() 53 // - to check @addoutfit=n -> isWearable()
53 // - to check @remoutfit=n -> isRemovable() 54 // - to check @remoutfit=n -> isRemovable()
@@ -59,20 +60,21 @@ public:
59 bool hasBehaviourExcept(ERlvBehaviour eBehaviour, const LLUUID& idObj) const; 60 bool hasBehaviourExcept(ERlvBehaviour eBehaviour, const LLUUID& idObj) const;
60 bool hasBehaviourExcept(ERlvBehaviour eBehaviour, const std::string& strOption, const LLUUID& idObj) const; 61 bool hasBehaviourExcept(ERlvBehaviour eBehaviour, const std::string& strOption, const LLUUID& idObj) const;
61 62
62 // Returns TRUE if there is at least 1 non-detachable attachment 63 // Adds an eLock type lock (held by idRlvObj) for the specified attachment point
63 bool hasLockedAttachment() const { return (0 != m_Attachments.size()); } 64 void addAttachmentLock(S32 idxAttachPt, const LLUUID& idRlvObj, ERlvLockMask eLock);
65 // Returns TRUE if there is at least 1 eLock type locked attachment (RLV_LOCK_ANY = RLV_LOCK_ADD *or* RLV_LOCK_REMOVE)
66 bool hasLockedAttachment(ERlvLockMask eLock) const;
64 // Returns TRUE if there is at least 1 non-detachable HUD attachment 67 // Returns TRUE if there is at least 1 non-detachable HUD attachment
65 bool hasLockedHUD() const; 68 bool hasLockedHUD() const;
66 // Returns TRUE if the specified attachment point is detachable 69 // Returns TRUE if the specified attachment point is eLock type locked (RLV_LOCK_ANY = RLV_LOCK_ADD *or* RLV_LOCK_REMOVE)
67 bool isDetachable(S32 idxAttachPt) const { return (idxAttachPt) && (m_Attachments.find(idxAttachPt) == m_Attachments.end()); } 70 bool isLockedAttachment(S32 idxAttachPt, ERlvLockMask eLock) const;
68 bool isDetachable(const LLInventoryItem* pItem) const; 71 bool isLockedAttachment(const LLInventoryItem* pItem, ERlvLockMask eLock) const;
69 bool isDetachable(LLViewerJointAttachment* pAttachPt) const; 72 bool isLockedAttachment(LLViewerJointAttachment* pAttachPt, ERlvLockMask eLock) const;
70 bool isDetachable(LLViewerObject* pObj) const; 73 bool isLockedAttachment(LLViewerObject* pObj, ERlvLockMask eLock) const;
71 // Returns TRUE if the specified attachment point is set non-detachable by anything other than pObj (or one of its children) 74 // Returns TRUE if the specified attachment point is eLock type locked by anything other than pObj (or one of its children)
72 bool isDetachableExcept(S32 idxAttachPt, LLViewerObject* pObj) const; 75 bool isLockedAttachmentExcept(S32 idxAttachPt, ERlvLockMask eLock, LLViewerObject* pObj) const;
73 // Marks the specified attachment point as (non-)detachable (return value indicates success ; used by unit tests) 76 // Adds an eLock type lock (held by idRlvObj) for the specified attachment point
74 bool setDetachable(S32 idxAttachPt, const LLUUID& idRlvObj, bool fDetachable); 77 void removeAttachmentLock(S32 idxAttachPt, const LLUUID& idRlovObj, ERlvLockMask eLock);
75 bool setDetachable(LLViewerObject* pObj, const LLUUID& idRlvObj, bool fDetachable);
76 78
77 // Adds or removes an exception for the specified behaviour 79 // Adds or removes an exception for the specified behaviour
78 void addException(const LLUUID& idObj, ERlvBehaviour eBhvr, const RlvExceptionOption& varOption); 80 void addException(const LLUUID& idObj, ERlvBehaviour eBhvr, const RlvExceptionOption& varOption);
@@ -183,19 +185,28 @@ public:
183 void notifyBehaviourObservers(const RlvCommand& rlvCmd, bool fInternal); 185 void notifyBehaviourObservers(const RlvCommand& rlvCmd, bool fInternal);
184 186
185 // Externally invoked event handlers 187 // Externally invoked event handlers
186 void onAttach(LLViewerJointAttachment* pAttachPt, bool fFullyLoaded); // LLVOAvatar::attachObject() 188 void onAttach(LLViewerJointAttachment* pAttachPt); // LLVOAvatar::attachObject()
187 void onDetach(LLViewerJointAttachment* pAttachPt); // LLVOAvatar::detachObject() 189 void onDetach(LLViewerJointAttachment* pAttachPt); // LLVOAvatar::detachObject()
188 bool onGC(); // RlvGCTimer::tick() 190 bool onGC(); // RlvGCTimer::tick()
189 void onSavedAssetIntoInventory(const LLUUID& idItem); // LLInventoryModel::processSaveAssetIntoInventory() 191 void onSavedAssetIntoInventory(const LLUUID& idItem) { if (m_pAttachMgr) m_pAttachMgr->onSavedAssetIntoInventory(idItem); }
192 void onWearAttachment(const LLUUID& idItem) { if (m_pAttachMgr) m_pAttachMgr->onWearAttachment(idItem); }
190protected: 193protected:
191 BOOL processAddCommand(const LLUUID& uuid, const RlvCommand& rlvCmd); 194 BOOL processAddCommand(const LLUUID& uuid, const RlvCommand& rlvCmd);
192 BOOL processRemoveCommand(const LLUUID& uuid, const RlvCommand& rlvCmd); 195 BOOL processRemoveCommand(const LLUUID& uuid, const RlvCommand& rlvCmd);
193 BOOL processClearCommand(const LLUUID& idObj, const RlvCommand& rlvCmd); 196 BOOL processClearCommand(const LLUUID idObj, const RlvCommand& rlvCmd);
194 BOOL processReplyCommand(const LLUUID& uuid, const RlvCommand& rlvCmd) const; 197 BOOL processReplyCommand(const LLUUID& uuid, const RlvCommand& rlvCmd) const;
195 BOOL processForceCommand(const LLUUID& uuid, const RlvCommand& rlvCmd) const; 198 BOOL processForceCommand(const LLUUID& uuid, const RlvCommand& rlvCmd) const;
196 199
197 // Command handlers (exist for no other reason than to keep the length of the processXXX functions down) 200 // Command handlers (exist for no other reason than to keep the length of the processXXX functions down)
198 void onForceDetach(const LLUUID& idObj, const std::string& strOption) const; 201 ERlvCmdRet onAddRemAttach(const LLUUID& idObj, const RlvCommand& rlvCmd, bool& fRefCount);
202 ERlvCmdRet onAddRemDetach(const LLUUID& idObj, const RlvCommand& rlvCmd, bool& fRefCount);
203 ERlvCmdRet onAddRemOutfit(const LLUUID& idObj, const RlvCommand& rlvCmd, bool& fRefCount);
204 ERlvCmdRet onForceDetach(const LLUUID& idObj, const RlvCommand& rlvCmd) const;
205 ERlvCmdRet onForceRemAttach(const LLUUID& idObj, const RlvCommand& rlvCmd) const;
206 ERlvCmdRet onForceRemOutfit(const LLUUID& idObj, const RlvCommand& rlvCmd) const;
207 ERlvCmdRet onGetAttach(const LLUUID& idObj, const RlvCommand& rlvCmd, std::string& strReply);
208 ERlvCmdRet onGetOutfit(const LLUUID& idObj, const RlvCommand& rlvCmd, std::string& strReply);
209 // Old style command handlers (need to be updated to return ERlvCmdRet)
199 void onForceRemOutfit(const LLUUID& idObj, const std::string& strOption) const; 210 void onForceRemOutfit(const LLUUID& idObj, const std::string& strOption) const;
200 bool onForceSit(const LLUUID& uuid, const std::string& strOption) const; 211 bool onForceSit(const LLUUID& uuid, const std::string& strOption) const;
201 void onForceWear(const std::string& strPath, bool fAttach, bool fMatchAll) const; 212 void onForceWear(const std::string& strPath, bool fAttach, bool fMatchAll) const;
@@ -221,29 +232,29 @@ public:
221 static const std::string cstrMsgTpLure; // Message sent to tplure sender when tplure restricted 232 static const std::string cstrMsgTpLure; // Message sent to tplure sender when tplure restricted
222 static const std::string cstrAnonyms[28]; 233 static const std::string cstrAnonyms[28];
223protected: 234protected:
224 rlv_object_map_t m_Objects; // Map of objects that have active restrictions (by UUID) 235 rlv_object_map_t m_Objects; // Map of objects that have active restrictions (idObj -> RlvObject)
225 rlv_exception_map_t m_Exceptions; // Map of UUIDs that are exempt from the associated ERlvBehaviour 236 rlv_exception_map_t m_Exceptions; // Map of currently active restriction exceptions (ERlvBehaviour -> RlvException)
226 rlv_detach_map_t m_Attachments; // Map of locked attachments (attachment point index -> object that issued @detach=n) 237 rlv_attachlock_map_t m_AttachAdd; // Map of attachment points that can't be attached (idxAttachPt -> idObj)
227 S16 m_LayersAdd[WT_COUNT]; // Array of locked layers (reference counted) 238 rlv_attachlock_map_t m_AttachRem; // Map of attachment points that can't be detached (idxAttachPt -> idObj)
228 S16 m_LayersRem[WT_COUNT]; // Array of locked layers (reference counted) 239 S16 m_LayersAdd[WT_COUNT]; // Array of layers that can't be worn (reference counted)
229 S16 m_Behaviours[RLV_BHVR_COUNT]; 240 S16 m_LayersRem[WT_COUNT]; // Array of layers that can't be removed (reference counted)
230 241 S16 m_Behaviours[RLV_BHVR_COUNT];
231 rlv_retained_list_t m_Retained; 242
232 rlv_reattach_map_t m_AttachPending; 243 rlv_retained_list_t m_Retained;
233 rlv_reattach_map_t m_DetachPending; 244 RlvGCTimer* m_pGCTimer;
234 RlvGCTimer* m_pGCTimer; 245 RlvWLSnapshot* m_pWLSnapshot;
235 RlvWLSnapshot* m_pWLSnapshot; 246 RlvAttachmentManager* m_pAttachMgr;
236 247
237 RlvCommand* m_pCurCommand; // Convenience (see @tpto) 248 RlvCommand* m_pCurCommand; // Convenience (see @tpto)
238 LLUUID m_idCurObject; // Convenience (see @tpto) 249 LLUUID m_idCurObject; // Convenience (see @tpto)
239 250
240 mutable RlvEventEmitter<RlvObserver> m_Emitter; 251 mutable RlvEventEmitter<RlvObserver> m_Emitter;
241 mutable std::list<RlvBehaviourObserver*> m_BhvrObservers; 252 mutable std::list<RlvBehaviourObserver*> m_BhvrObservers;
242 RlvBehaviourNotifyObserver* m_pBhvrNotify; 253 RlvBehaviourNotifyObserver* m_pBhvrNotify;
243 254
244 static BOOL m_fEnabled; // Use setEnabled() to toggle this 255 static BOOL m_fEnabled; // Use setEnabled() to toggle this
245 static BOOL m_fFetchStarted; // TRUE if we fired off an inventory fetch 256 static BOOL m_fFetchStarted; // TRUE if we fired off an inventory fetch
246 static BOOL m_fFetchComplete; // TRUE if everything was fetched 257 static BOOL m_fFetchComplete; // TRUE if everything was fetched
247 static RlvMultiStringSearch m_AttachLookup; // Lookup table for attachment names (lower case) 258 static RlvMultiStringSearch m_AttachLookup; // Lookup table for attachment names (lower case)
248 259
249 bool m_fCanCancelTp; 260 bool m_fCanCancelTp;
@@ -258,8 +269,8 @@ protected:
258 */ 269 */
259public: 270public:
260 const rlv_object_map_t* getObjectMap() const { return &m_Objects; } 271 const rlv_object_map_t* getObjectMap() const { return &m_Objects; }
261 const rlv_exception_map_t* getExceptionMap() const { return &m_Exceptions; } 272 //const rlv_exception_map_t* getExceptionMap() const { return &m_Exceptions; }
262 const rlv_detach_map_t* getDetachMap() const { return &m_Attachments; } 273 //const rlv_detach_map_t* getDetachMap() const { return &m_Attachments; }
263 #ifdef RLV_DEBUG_TESTS 274 #ifdef RLV_DEBUG_TESTS
264 const S16* getAddLayers() const { return m_LayersAdd; } 275 const S16* getAddLayers() const { return m_LayersAdd; }
265 const S16* getRemLayers() const { return m_LayersRem; } 276 const S16* getRemLayers() const { return m_LayersRem; }
@@ -345,6 +356,13 @@ inline bool RlvHandler::hasBehaviourExcept(ERlvBehaviour eBehaviour, const LLUUI
345 return hasBehaviourExcept(eBehaviour, std::string(), idObj); 356 return hasBehaviourExcept(eBehaviour, std::string(), idObj);
346} 357}
347 358
359// Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
360inline bool RlvHandler::hasLockedAttachment(ERlvLockMask eLock) const
361{
362 // Remove locks are more common so check those first
363 return ( (eLock & RLV_LOCK_REMOVE) && (!m_AttachRem.empty()) ) || ( (eLock & RLV_LOCK_ADD) && (!m_AttachAdd.empty()) );
364}
365
348#ifdef RLV_EXPERIMENTAL_COMPOSITES 366#ifdef RLV_EXPERIMENTAL_COMPOSITES
349 // Checked: 367 // Checked:
350 inline bool RlvHandler::isCompositeFolder(const LLInventoryCategory* pFolder) const 368 inline bool RlvHandler::isCompositeFolder(const LLInventoryCategory* pFolder) const
@@ -359,20 +377,6 @@ inline bool RlvHandler::hasBehaviourExcept(ERlvBehaviour eBehaviour, const LLUUI
359 } 377 }
360#endif // RLV_EXPERIMENTAL_COMPOSITES 378#endif // RLV_EXPERIMENTAL_COMPOSITES
361 379
362// Checked: 2009-09-08 (RLVa-1.0.2c) | Added: RLVa-1.0.2c
363inline bool RlvHandler::isDetachable(LLViewerJointAttachment *pAttachPt) const
364{
365 // If there's an attached object it's faster to just use that; otherwise look up the attachment index because it might be locked empty
366 return (pAttachPt == NULL) ||
367 ( (pAttachPt->getObject() != NULL) && isDetachable(pAttachPt->getObject()) ) || (isDetachable(getAttachPointIndex(pAttachPt)));
368}
369
370// Checked: 2009-05-23 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d
371inline bool RlvHandler::isDetachable(LLViewerObject* pObj) const
372{
373 return (pObj == NULL) || (!pObj->isAttachment()) || (isDetachable(getAttachPointIndex(pObj)));
374}
375
376inline bool RlvHandler::isPermissive(ERlvBehaviour eBhvr) const 380inline bool RlvHandler::isPermissive(ERlvBehaviour eBhvr) const
377{ 381{
378 return (RlvCommand::hasStrictVariant(eBhvr)) 382 return (RlvCommand::hasStrictVariant(eBhvr))
@@ -395,6 +399,29 @@ inline bool RlvHandler::isFoldedFolder(const LLInventoryCategory* pFolder, bool
395 ); 399 );
396} 400}
397 401
402// Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
403inline bool RlvHandler::isLockedAttachment(S32 idxAttachPt, ERlvLockMask eLock) const
404{
405 return ( (eLock & RLV_LOCK_REMOVE) && (m_AttachRem.find(idxAttachPt) != m_AttachRem.end()) ) ||
406 ( (eLock & RLV_LOCK_ADD) && (m_AttachAdd.find(idxAttachPt) != m_AttachAdd.end()) );
407}
408
409
410// Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
411inline bool RlvHandler::isLockedAttachment(LLViewerJointAttachment *pAttachPt, ERlvLockMask eLock) const
412{
413 // If there's an attached object it's faster to just use that; otherwise look up the attachment index because it might be locked empty
414 return (pAttachPt != NULL) &&
415 ( ( (pAttachPt->getObject() != NULL) && (isLockedAttachment(pAttachPt->getObject(), eLock)) ) ||
416 (isLockedAttachment(getAttachPointIndex(pAttachPt), eLock)) );
417}
418
419// Checked: 2009-10-10 (RLVa-1.0.5a) | Added: RLVa-1.0.5a
420inline bool RlvHandler::isLockedAttachment(LLViewerObject* pObj, ERlvLockMask eLock) const
421{
422 return (pObj != NULL) && (pObj->isAttachment()) && (isLockedAttachment(getAttachPointIndex(pObj), eLock));
423}
424
398// Checked: 2009-05-23 (RLVa-0.2.0d) | Added: RLVa-0.2.0d 425// Checked: 2009-05-23 (RLVa-0.2.0d) | Added: RLVa-0.2.0d
399inline bool RlvHandler::isRemovableExcept(EWearableType type, const LLUUID& idObj) const 426inline bool RlvHandler::isRemovableExcept(EWearableType type, const LLUUID& idObj) const
400{ 427{
@@ -434,12 +461,6 @@ inline void RlvHandler::retainCommand(const std::string& strObj, const LLUUID& i
434 m_Retained.push_back(RlvRetainedCommand(strObj, idObj, strCmd)); 461 m_Retained.push_back(RlvRetainedCommand(strObj, idObj, strCmd));
435} 462}
436 463
437// Checked: 2009-05-23 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d
438inline bool RlvHandler::setDetachable(LLViewerObject* pObj, const LLUUID& idRlvObj, bool fDetachable)
439{
440 return setDetachable(getAttachPointIndex(pObj), idRlvObj, fDetachable); // getAttachPointIndex() has a NULL pointer check
441}
442
443// ============================================================================ 464// ============================================================================
444 465
445#endif // RLV_HANDLER_H 466#endif // RLV_HANDLER_H
diff --git a/linden/indra/newview/rlvhelper.cpp b/linden/indra/newview/rlvhelper.cpp
index c8d430d..67ffbe2 100644
--- a/linden/indra/newview/rlvhelper.cpp
+++ b/linden/indra/newview/rlvhelper.cpp
@@ -1,6 +1,7 @@
1#include "llviewerprecompiledheaders.h" 1#include "llviewerprecompiledheaders.h"
2#include "llagent.h" 2#include "llagent.h"
3#include "llfloaterwindlight.h" 3#include "llfloaterwindlight.h"
4#include "llinventoryview.h"
4#include "llviewerobject.h" 5#include "llviewerobject.h"
5#include "llviewerstats.h" 6#include "llviewerstats.h"
6#include "llviewerwindow.h" 7#include "llviewerwindow.h"
@@ -11,6 +12,12 @@
11#include "rlvevent.h" 12#include "rlvevent.h"
12#include "rlvhandler.h" 13#include "rlvhandler.h"
13 14
15// Only defined in llinventorybridge.cpp
16#if RLV_TARGET < RLV_MAKE_TARGET(1, 23, 0) // Version: 1.22.11
17 #include "llinventorybridge.h"
18 void confirm_replace_attachment_rez(S32 option, void* user_data);
19#endif
20
14// ============================================================================ 21// ============================================================================
15// Static variable initialization 22// Static variable initialization
16// 23//
@@ -104,12 +111,13 @@ void RlvCommand::initLookupTable()
104 std::string arBehaviours[RLV_BHVR_COUNT] = 111 std::string arBehaviours[RLV_BHVR_COUNT] =
105 { 112 {
106 "version", "detach", "sendchat", "emote", "chatshout", "chatnormal", "chatwhisper", "redirchat", "rediremote", 113 "version", "detach", "sendchat", "emote", "chatshout", "chatnormal", "chatwhisper", "redirchat", "rediremote",
107 "sendim", "recvchat", "recvemote", "recvim", "tplm", "tploc", "tplure", "sittp", "edit", "rez", "addoutfit", 114 "sendim", "recvchat", "recvemote", "recvim", "tplm", "tploc", "tplure", "sittp", "edit", "rez",
108 "remoutfit", "getoutfit", "getattach", "showinv", "viewnote", "unsit", "sit", "sendchannel", "getstatus", "getstatusall", 115 "addoutfit", "remoutfit", "getoutfit", "addattach", "remattach", "getattach", "showinv", "viewnote", "unsit", "sit",
109 "getinv", "getinvworn", "findfolder", "findfolders", "attach", "attachall", "detachall", "getpath", "attachthis", 116 "sendchannel", "getstatus", "getstatusall", "getinv", "getinvworn", "findfolder", "findfolders",
110 "attachallthis", "detachthis", "detachallthis", "fartouch", "showworldmap", "showminimap", "showloc", "tpto", "accepttp", 117 "attach", "attachall", "detachall", "getpath", "attachthis", "attachallthis", "detachthis", "detachallthis",
111 "acceptpermission", "shownames", "fly", "getsitid", "setdebug", "setenv", "detachme", "showhovertextall", 118 "fartouch", "showworldmap", "showminimap", "showloc", "tpto", "accepttp", "acceptpermission", "shownames", "fly",
112 "showhovertextworld", "showhovertexthud", "showhovertext", "notify", "defaultwear", "versionnum", "permissive" 119 "getsitid", "setdebug", "setenv", "detachme", "showhovertextall", "showhovertextworld", "showhovertexthud",
120 "showhovertext", "notify", "defaultwear", "versionnum", "permissive", "viewscript", "viewtexture"
113 }; 121 };
114 122
115 for (int idxBvhr = 0; idxBvhr < RLV_BHVR_COUNT; idxBvhr++) 123 for (int idxBvhr = 0; idxBvhr < RLV_BHVR_COUNT; idxBvhr++)
@@ -207,6 +215,204 @@ std::string RlvObject::getStatusString(const std::string& strMatch) const
207} 215}
208 216
209// ============================================================================ 217// ============================================================================
218// RlvAttachmentManager
219//
220
221// Checked: 2009-10-12 (RLVa-1.0.5b) | Modified: RLVa-1.0.5b
222void RlvAttachmentManager::forceAttach(const LLUUID& idItem, S32 idxAttachPt)
223{
224 #if RLV_TARGET < RLV_MAKE_TARGET(1, 23, 0) // Version: 1.22.11
225 LLAttachmentRezAction* rez_action = new LLAttachmentRezAction();
226 rez_action->mItemID = idItem;
227 rez_action->mAttachPt = idxAttachPt;
228
229 confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action); // (Will call delete on rez_action)
230 #else // Version: 1.23.4
231 LLSD payload;
232 payload["item_id"] = idItem;
233 payload["attachment_point"] = idxAttachPt;
234
235 LLNotifications::instance().forceResponse(
236 LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
237 #endif
238}
239
240// Checked: 2009-10-12 (RLVa-1.0.5b) | Modified: RLVa-1.0.5b
241void RlvAttachmentManager::forceDetach(LLViewerJointAttachment* pAttachPt)
242{
243 // Copy/paste from handle_detach_from_avatar()
244 LLViewerObject* attached_object = pAttachPt->getObject();
245 if (attached_object)
246 {
247 gMessageSystem->newMessage("ObjectDetach");
248 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
249 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
250 gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
251
252 gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
253 gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID());
254 gMessageSystem->sendReliable( gAgent.getRegionHost() );
255 }
256}
257
258// Checked: 2009-10-12 (RLVa-1.0.5b) | Modified: RLVa-1.0.5b
259void RlvAttachmentManager::onAttach(LLViewerJointAttachment* pAttachPt)
260{
261 S32 idxAttachPt = gRlvHandler.getAttachPointIndex(pAttachPt->getObject());
262 if (!idxAttachPt)
263 return;
264
265 // If the attachment point has a pending "reattach" then we don't want to do anything
266 rlv_attach_map_t::iterator itAttach = m_PendingAttach.find(idxAttachPt);
267 if (itAttach != m_PendingAttach.end())
268 {
269 if (pAttachPt->getItemID() == itAttach->second.idItem)
270 m_PendingAttach.erase(itAttach);
271 return;
272 }
273
274 // Check if the attach is the result of a user action (="Wear")
275 rlv_wear_map_t::iterator itWear = m_PendingWear.find(pAttachPt->getItemID());
276 if (itWear != m_PendingWear.end())
277 {
278 // We need to return the attachment point to its previous state if it's non-attachable
279 if (gRlvHandler.isLockedAttachment(idxAttachPt, RLV_LOCK_ADD))
280 {
281 // Get the state of the attachment point at the time the user picked "Wear" (if we don't have one it wasn't "add locked" then)
282 std::map<S32, LLUUID>::iterator itAttachPrev = itWear->second.attachPts.find(idxAttachPt);
283 if ( (itAttachPrev != itWear->second.attachPts.end()) && (pAttachPt->getItemID() != itAttachPrev->second) )
284 {
285 // If it was empty we need to force detach the new attachment; if it wasn't we need to reattach the old one
286 if (itAttachPrev->second.isNull())
287 {
288 forceDetach(pAttachPt);
289 m_PendingDetach.insert(std::pair<S32, LLUUID>(idxAttachPt, pAttachPt->getItemID()));
290 }
291 else if (m_PendingAttach.find(idxAttachPt) == m_PendingAttach.end()) // (only if we're not reattaching something else there)
292 {
293 m_PendingAttach.insert(std::pair<S32, RlvReattachInfo>(idxAttachPt, RlvReattachInfo(itAttachPrev->second)));
294 }
295 }
296 }
297 m_PendingWear.erase(itWear); // No need to start the timer since it should be running already if '!m_PendingWear.empty()'
298 }
299}
300
301// Checked: 2009-10-12 (RLVa-1.0.5b) | Modified: RLVa-1.0.5b
302void RlvAttachmentManager::onDetach(LLViewerJointAttachment* pAttachPt)
303{
304 S32 idxAttachPt = gRlvHandler.getAttachPointIndex(pAttachPt->getObject());
305 if (!idxAttachPt)
306 return;
307
308 // If this is an attachment that we force-detached then we don't want to do anything (even if it is "remove locked")
309 rlv_detach_map_t::iterator itDetach = m_PendingDetach.find(idxAttachPt);
310 if ( (itDetach != m_PendingDetach.end()) && (itDetach->second == pAttachPt->getItemID()) )
311 {
312 m_PendingDetach.erase(itDetach);
313 return;
314 }
315
316 // If the attachment is currently "remove locked" and we're not already trying to reattach something there we should reattach it
317 if ( (m_PendingAttach.find(idxAttachPt) == m_PendingAttach.end()) && (gRlvHandler.isLockedAttachment(idxAttachPt, RLV_LOCK_REMOVE)) )
318 {
319 m_PendingAttach.insert(std::pair<S32, RlvReattachInfo>(idxAttachPt, RlvReattachInfo(pAttachPt->getItemID())));
320 startTimer();
321 }
322}
323
324// Checked: 2009-10-12 (RLVa-1.0.5b) | Modified: RLVa-1.0.5b
325void RlvAttachmentManager::onSavedAssetIntoInventory(const LLUUID& idItem)
326{
327 for (rlv_attach_map_t::iterator itAttach = m_PendingAttach.begin(); itAttach != m_PendingAttach.end(); ++itAttach)
328 {
329 if ( (!itAttach->second.fAssetSaved) && (idItem == itAttach->second.idItem) )
330 {
331 forceAttach(itAttach->second.idItem, itAttach->first);
332 itAttach->second.tsAttach = LLFrameTimer::getElapsedSeconds();
333 }
334 }
335}
336
337// Checked: 2009-10-12 (RLVa-1.0.5b) | Modified: RLVa-1.0.5b
338BOOL RlvAttachmentManager::onTimer()
339{
340 F64 tsCurrent = LLFrameTimer::getElapsedSeconds();
341
342 // Garbage collect (failed) wear requests older than 60 seconds
343 rlv_wear_map_t::iterator itWear = m_PendingWear.begin();
344 while (itWear != m_PendingWear.end())
345 {
346 if (itWear->second.tsWear + 60 < tsCurrent)
347 m_PendingWear.erase(itWear++);
348 else
349 ++itWear;
350 }
351
352 // Walk over the pending reattach list
353 rlv_attach_map_t::iterator itAttach = m_PendingAttach.begin();
354 while (itAttach != m_PendingAttach.end())
355 {
356 // Sanity check - make sure the item is still in the user's inventory
357 if (gInventory.getItem(itAttach->second.idItem) == NULL)
358 {
359 m_PendingAttach.erase(itAttach++);
360 continue;
361 }
362
363 // Force an attach if we haven't gotten an SavedAssetIntoInventory message after 15 seconds
364 // (or if it's been 30 seconds since we last tried to reattach the item)
365 bool fAttach = false;
366 if ( (!itAttach->second.fAssetSaved) && (itAttach->second.tsDetach + 15 < tsCurrent) )
367 {
368 itAttach->second.fAssetSaved = true;
369 fAttach = true;
370 }
371 else if ( (itAttach->second.fAssetSaved) && (itAttach->second.tsAttach + 30 < tsCurrent) )
372 {
373 fAttach = true;
374 }
375
376 if (fAttach)
377 {
378 forceAttach(itAttach->second.idItem, itAttach->first);
379 itAttach->second.tsAttach = tsCurrent;
380 }
381
382 ++itAttach;
383 }
384
385 return ( (m_PendingAttach.empty()) && (m_PendingDetach.empty()) && (m_PendingWear.empty()) );
386}
387
388// Checked: 2009-10-12 (RLVa-1.0.5b) | Modified: RLVa-1.0.5b
389void RlvAttachmentManager::onWearAttachment(const LLUUID& idItem)
390{
391 // We only need to keep track of wears if there are non-attachable attachment points
392 if (!gRlvHandler.hasLockedAttachment(RLV_LOCK_ADD))
393 return;
394
395 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
396 if (!pAvatar)
397 return;
398
399 // If the attachment point this will end up being attached to is:
400 // - unlocked : nothing should happen (from RLVa's point of view)
401 // - RLV_LOCK_ADD: the new attachment should get detached and the current one reattached (unless it's currently empty)
402 // - RLV_LOCK_REM: the current attachment will get reattached on ObjectKill (if there is no current one then nothing should happen)
403 RlvWearInfo infoWear(idItem);
404 for (LLVOAvatar::attachment_map_t::const_iterator itAttach = pAvatar->mAttachmentPoints.begin();
405 itAttach != pAvatar->mAttachmentPoints.end(); ++itAttach)
406 {
407 if (gRlvHandler.isLockedAttachment(itAttach->first, RLV_LOCK_ADD)) // We only need to keep track of these (see above)
408 infoWear.attachPts.insert(std::pair<S32, LLUUID>(itAttach->first, itAttach->second->getItemID()));
409 }
410
411 m_PendingWear.insert(std::pair<LLUUID, RlvWearInfo>(idItem, infoWear));
412 startTimer();
413}
414
415// ============================================================================
210// RlvWearableItemCollector 416// RlvWearableItemCollector
211// 417//
212 418
@@ -354,7 +560,10 @@ BOOL RlvSettings::fShowNameTags = FALSE;
354 560
355BOOL RlvSettings::getEnableWear() 561BOOL RlvSettings::getEnableWear()
356{ 562{
357 return rlvGetSettingBOOL(RLV_SETTING_ENABLEWEAR, TRUE) && (!gRlvHandler.hasBehaviour(RLV_BHVR_DEFAULTWEAR)); 563 return
564 rlvGetSettingBOOL(RLV_SETTING_ENABLEWEAR, TRUE) && // "Enable Wear" is toggled on and...
565 (!gRlvHandler.hasBehaviour(RLV_BHVR_DEFAULTWEAR)) && // not restricted and...
566 (!gRlvHandler.hasBehaviour(RLV_BHVR_ADDATTACH)); // we have attach points we can attach to [see RlvHandler::onAddRemAttach()]
358} 567}
359 568
360#ifdef RLV_EXTENSION_STARTLOCATION 569#ifdef RLV_EXTENSION_STARTLOCATION
@@ -419,7 +628,7 @@ void RlvCurrentlyWorn::fetchWorn()
419// Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0f 628// Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0f
420bool RlvSelectHasLockedAttach::apply(LLSelectNode* pNode) 629bool RlvSelectHasLockedAttach::apply(LLSelectNode* pNode)
421{ 630{
422 return (pNode->getObject()) ? !gRlvHandler.isDetachable(pNode->getObject()) : false; 631 return (pNode->getObject()) ? gRlvHandler.isLockedAttachment(pNode->getObject(), m_eLock) : false;
423} 632}
424 633
425// Checked: 2009-07-05 (RLVa-1.0.0b) | Modified: RLVa-0.2.0f 634// Checked: 2009-07-05 (RLVa-1.0.0b) | Modified: RLVa-0.2.0f
@@ -438,11 +647,15 @@ bool RlvSelectIsSittingOn::apply(LLSelectNode* pNode)
438// Various helper functions 647// Various helper functions
439// 648//
440 649
441// Checked: 2009-09-08 (RLVa-1.0.2c) | Modified: RLVa-1.0.2c 650// Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a
442BOOL rlvAttachToEnabler(void* pParam) 651BOOL rlvAttachToEnabler(void* pParam)
443{ 652{
444 // Enables/disables an option on the "Attach to (HUD)" submenu depending on whether it is (un)detachable 653 // Disable an option on the "Attach to (HUD)" submenu if:
445 return gRlvHandler.isDetachable((LLViewerJointAttachment*)pParam); 654 // - the attachment point is locked non-detachable with an object attached
655 // - the attachment point is locked non-attachable
656 return (pParam != NULL) &&
657 (!gRlvHandler.isLockedAttachment(((LLViewerJointAttachment*)pParam)->getObject(), RLV_LOCK_REMOVE)) &&
658 (!gRlvHandler.isLockedAttachment((LLViewerJointAttachment*)pParam, RLV_LOCK_ADD));
446} 659}
447 660
448// Checked: 2009-07-05 (RLVa-1.0.0b) | Modified: RLVa-0.2.0g 661// Checked: 2009-07-05 (RLVa-1.0.0b) | Modified: RLVa-0.2.0g
@@ -527,24 +740,6 @@ S32 rlvGetDirectDescendentsCount(const LLInventoryCategory* pFolder, LLAssetType
527// Message sending functions 740// Message sending functions
528// 741//
529 742
530// Checked: 2009-08-11 (RLVa-1.0.1h) | Added: RLVa-1.0.1h
531void rlvForceDetach(LLViewerJointAttachment* pAttachPt)
532{
533 // Copy/paste from handle_detach_from_avatar()
534 LLViewerObject* attached_object = pAttachPt->getObject();
535 if (attached_object)
536 {
537 gMessageSystem->newMessage("ObjectDetach");
538 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
539 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
540 gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
541
542 gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
543 gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID());
544 gMessageSystem->sendReliable( gAgent.getRegionHost() );
545 }
546}
547
548void rlvSendBusyMessage(const LLUUID& idTo, const std::string& strMsg, const LLUUID& idSession) 743void rlvSendBusyMessage(const LLUUID& idTo, const std::string& strMsg, const LLUUID& idSession)
549{ 744{
550 // (See process_improved_im) 745 // (See process_improved_im)
@@ -662,7 +857,3 @@ std::string rlvGetLastParenthesisedText(const std::string& strText, std::string:
662} 857}
663 858
664// ========================================================================= 859// =========================================================================
665// Debug helper functions
666//
667
668// =========================================================================
diff --git a/linden/indra/newview/rlvhelper.h b/linden/indra/newview/rlvhelper.h
index 42d10b8..25d8174 100644
--- a/linden/indra/newview/rlvhelper.h
+++ b/linden/indra/newview/rlvhelper.h
@@ -109,6 +109,80 @@ protected:
109}; 109};
110 110
111// ============================================================================ 111// ============================================================================
112// RlvAttachmentManager - Self contained helper class that automagically takes care of the nitty gritty of force detaching/reattaching
113//
114
115class RlvAttachmentManager
116{
117public:
118 RlvAttachmentManager() : m_pTimer(NULL) {}
119 ~RlvAttachmentManager() { delete m_pTimer; }
120
121 /*
122 * Member functions
123 */
124public:
125 static void forceAttach(const LLUUID& idItem, S32 idxAttachPt);
126 static void forceDetach(LLViewerJointAttachment* pAttachPt);
127protected:
128 void startTimer() { if (!m_pTimer) m_pTimer = new RlvAttachmentManagerTimer(this); }
129
130 /*
131 * Event handlers
132 */
133public:
134 void onAttach(LLViewerJointAttachment* pAttachPt);
135 void onDetach(LLViewerJointAttachment* pAttachPt);
136 void onSavedAssetIntoInventory(const LLUUID& idItem);
137 BOOL onTimer();
138 void onWearAttachment(const LLUUID& idItem);
139
140 /*
141 * Member variables
142 */
143protected:
144 typedef std::map<S32, LLUUID> rlv_detach_map_t;
145 rlv_detach_map_t m_PendingDetach;
146
147 struct RlvReattachInfo
148 {
149 RlvReattachInfo(const LLUUID& itemid) : idItem(itemid), fAssetSaved(false), tsAttach(0)
150 { tsDetach = LLFrameTimer::getElapsedSeconds(); }
151
152 LLUUID idItem;
153 bool fAssetSaved;
154 F64 tsDetach;
155 F64 tsAttach;
156 protected:
157 RlvReattachInfo();
158 };
159 typedef std::map<S32, RlvReattachInfo> rlv_attach_map_t;
160 rlv_attach_map_t m_PendingAttach;
161
162 struct RlvWearInfo
163 {
164 RlvWearInfo(LLUUID itemid) : idItem(itemid) { tsWear = LLFrameTimer::getElapsedSeconds(); }
165
166 LLUUID idItem;
167 F64 tsWear;
168 std::map<S32, LLUUID> attachPts;
169 protected:
170 RlvWearInfo();
171 };
172 typedef std::map<LLUUID, RlvWearInfo> rlv_wear_map_t;
173 rlv_wear_map_t m_PendingWear;
174
175 class RlvAttachmentManagerTimer : public LLEventTimer
176 {
177 public:
178 RlvAttachmentManagerTimer(RlvAttachmentManager* pMgr) : LLEventTimer(10), m_pMgr(pMgr) {}
179 virtual ~RlvAttachmentManagerTimer() { m_pMgr->m_pTimer = NULL; }
180 virtual BOOL tick() { return m_pMgr->onTimer(); }
181 RlvAttachmentManager* m_pMgr;
182 } *m_pTimer;
183};
184
185// ============================================================================
112// RlvCriteriaCategoryCollector - Criteria based folder matching filter used by @findfolder and @findfolders 186// RlvCriteriaCategoryCollector - Criteria based folder matching filter used by @findfolder and @findfolders
113// 187//
114 188
@@ -295,7 +369,10 @@ public:
295 369
296struct RlvSelectHasLockedAttach : public LLSelectedNodeFunctor 370struct RlvSelectHasLockedAttach : public LLSelectedNodeFunctor
297{ 371{
372 RlvSelectHasLockedAttach(ERlvLockMask eLock) : m_eLock(eLock) {}
298 virtual bool apply(LLSelectNode* pNode); 373 virtual bool apply(LLSelectNode* pNode);
374protected:
375 ERlvLockMask m_eLock;
299}; 376};
300 377
301struct RlvSelectIsOwnedByOrGroupOwned : public LLSelectedNodeFunctor 378struct RlvSelectIsOwnedByOrGroupOwned : public LLSelectedNodeFunctor
@@ -324,7 +401,6 @@ bool rlvIsEmote(const std::string& strUTF8Text);
324bool rlvIsValidReplyChannel(S32 nChannel); 401bool rlvIsValidReplyChannel(S32 nChannel);
325bool rlvIsWearingItem(const LLInventoryItem* pItem); 402bool rlvIsWearingItem(const LLInventoryItem* pItem);
326 403
327void rlvForceDetach(LLViewerJointAttachment* pAttachPt);
328void rlvSendBusyMessage(const LLUUID& idTo, const std::string& strMsg, const LLUUID& idSession = LLUUID::null); 404void rlvSendBusyMessage(const LLUUID& idTo, const std::string& strMsg, const LLUUID& idSession = LLUUID::null);
329bool rlvSendChatReply(const std::string& strChannel, const std::string& strReply); 405bool rlvSendChatReply(const std::string& strChannel, const std::string& strReply);
330bool rlvSendChatReply(S32 nChannel, const std::string& strReply); 406bool rlvSendChatReply(S32 nChannel, const std::string& strReply);