aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra')
-rw-r--r--linden/indra/llcommon/llchat.h8
-rw-r--r--linden/indra/newview/CMakeLists.txt11
-rw-r--r--linden/indra/newview/app_settings/settings.xml101
-rw-r--r--linden/indra/newview/app_settings/settings_per_account.xml13
-rw-r--r--linden/indra/newview/llagent.cpp186
-rw-r--r--linden/indra/newview/llagent.h4
-rw-r--r--linden/indra/newview/llappviewer.cpp17
-rw-r--r--linden/indra/newview/llchatbar.cpp76
-rw-r--r--linden/indra/newview/llfloaterabout.cpp10
-rw-r--r--linden/indra/newview/llfloateractivespeakers.cpp19
-rw-r--r--linden/indra/newview/llfloaterbeacons.cpp10
-rw-r--r--linden/indra/newview/llfloaterchat.cpp60
-rw-r--r--linden/indra/newview/llfloaterinspect.cpp24
-rw-r--r--linden/indra/newview/llfloaterland.cpp44
-rw-r--r--linden/indra/newview/llfloaterland.h4
-rw-r--r--linden/indra/newview/llfloatermap.cpp10
-rw-r--r--linden/indra/newview/llfloatermap.h4
-rw-r--r--linden/indra/newview/llfloateropenobject.cpp13
-rw-r--r--linden/indra/newview/llfloaterproperties.cpp16
-rw-r--r--linden/indra/newview/llfloaterregioninfo.cpp19
-rw-r--r--linden/indra/newview/llfloaterregioninfo.h3
-rw-r--r--linden/indra/newview/llfloaterreporter.cpp35
-rw-r--r--linden/indra/newview/llfloatersettingsdebug.cpp31
-rw-r--r--linden/indra/newview/llfloaterwindlight.cpp9
-rw-r--r--linden/indra/newview/llfloaterworldmap.cpp28
-rw-r--r--linden/indra/newview/llglsandbox.cpp28
-rw-r--r--linden/indra/newview/llhoverview.cpp38
-rw-r--r--linden/indra/newview/llhudtext.cpp39
-rw-r--r--linden/indra/newview/llhudtext.h8
-rw-r--r--linden/indra/newview/llimpanel.cpp36
-rw-r--r--linden/indra/newview/llimview.cpp13
-rw-r--r--linden/indra/newview/llinventorybridge.cpp137
-rw-r--r--linden/indra/newview/llinventorymodel.cpp25
-rw-r--r--linden/indra/newview/llinventoryview.cpp19
-rw-r--r--linden/indra/newview/llinventoryview.h28
-rw-r--r--linden/indra/newview/llmaniptranslate.cpp11
-rw-r--r--linden/indra/newview/llnetmap.cpp38
-rw-r--r--linden/indra/newview/llnotify.cpp11
-rw-r--r--linden/indra/newview/lloverlaybar.cpp12
-rw-r--r--linden/indra/newview/llpanelavatar.cpp20
-rw-r--r--linden/indra/newview/llpanelclassified.cpp11
-rw-r--r--linden/indra/newview/llpanelcontents.cpp38
-rw-r--r--linden/indra/newview/llpaneldisplay.cpp14
-rw-r--r--linden/indra/newview/llpanelinventory.cpp86
-rw-r--r--linden/indra/newview/llpanelland.cpp6
-rw-r--r--linden/indra/newview/llpanellogin.cpp16
-rw-r--r--linden/indra/newview/llpanelobject.cpp13
-rw-r--r--linden/indra/newview/llpanelpermissions.cpp27
-rw-r--r--linden/indra/newview/llpanelpick.cpp16
-rw-r--r--linden/indra/newview/llprefsim.cpp6
-rw-r--r--linden/indra/newview/llpreviewscript.cpp20
-rw-r--r--linden/indra/newview/llselectmgr.cpp12
-rw-r--r--linden/indra/newview/llstartup.cpp22
-rw-r--r--linden/indra/newview/llstatusbar.cpp15
-rw-r--r--linden/indra/newview/lltoolbar.cpp22
-rw-r--r--linden/indra/newview/lltooldraganddrop.cpp85
-rw-r--r--linden/indra/newview/lltoolface.cpp10
-rw-r--r--linden/indra/newview/lltoolgrab.cpp24
-rw-r--r--linden/indra/newview/lltoolpie.cpp61
-rw-r--r--linden/indra/newview/lltoolplacer.cpp20
-rw-r--r--linden/indra/newview/lltoolselect.cpp49
-rw-r--r--linden/indra/newview/lltracker.cpp24
-rw-r--r--linden/indra/newview/llviewercontrol.cpp21
-rw-r--r--linden/indra/newview/llviewerdisplay.cpp12
-rw-r--r--linden/indra/newview/llviewermenu.cpp602
-rw-r--r--linden/indra/newview/llviewermessage.cpp403
-rw-r--r--linden/indra/newview/llviewerobject.cpp17
-rw-r--r--linden/indra/newview/llviewertexteditor.cpp7
-rw-r--r--linden/indra/newview/llviewerwindow.cpp10
-rw-r--r--linden/indra/newview/llvoavatar.cpp115
-rw-r--r--linden/indra/newview/llvovolume.cpp16
-rw-r--r--linden/indra/newview/llworldmapview.cpp19
-rw-r--r--linden/indra/newview/pipeline.cpp9
-rw-r--r--linden/indra/newview/rlvevent.h224
-rw-r--r--linden/indra/newview/rlvextensions.cpp454
-rw-r--r--linden/indra/newview/rlvextensions.h43
-rw-r--r--linden/indra/newview/rlvfloaterbehaviour.cpp152
-rw-r--r--linden/indra/newview/rlvfloaterbehaviour.h49
-rw-r--r--linden/indra/newview/rlvhandler.cpp2549
-rw-r--r--linden/indra/newview/rlvhandler.h462
-rw-r--r--linden/indra/newview/rlvhelper.cpp674
-rw-r--r--linden/indra/newview/rlvhelper.h579
-rw-r--r--linden/indra/newview/rlvmultistringsearch.cpp196
-rw-r--r--linden/indra/newview/rlvmultistringsearch.h191
-rw-r--r--linden/indra/newview/skins/default/xui/en-us/floater_rlv_behaviour.xml11
85 files changed, 8502 insertions, 128 deletions
diff --git a/linden/indra/llcommon/llchat.h b/linden/indra/llcommon/llchat.h
index 1bb3f3b..aa4469c 100644
--- a/linden/indra/llcommon/llchat.h
+++ b/linden/indra/llcommon/llchat.h
@@ -72,6 +72,10 @@ public:
72 : mText(text), 72 : mText(text),
73 mFromName(), 73 mFromName(),
74 mFromID(), 74 mFromID(),
75// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
76 mRlvLocFiltered(FALSE),
77 mRlvNamesFiltered(FALSE),
78// [/RLVa:KB]
75 mSourceType(CHAT_SOURCE_AGENT), 79 mSourceType(CHAT_SOURCE_AGENT),
76 mChatType(CHAT_TYPE_NORMAL), 80 mChatType(CHAT_TYPE_NORMAL),
77 mAudible(CHAT_AUDIBLE_FULLY), 81 mAudible(CHAT_AUDIBLE_FULLY),
@@ -83,6 +87,10 @@ public:
83 std::string mText; // UTF-8 line of text 87 std::string mText; // UTF-8 line of text
84 std::string mFromName; // agent or object name 88 std::string mFromName; // agent or object name
85 LLUUID mFromID; // agent id or object id 89 LLUUID mFromID; // agent id or object id
90// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
91 BOOL mRlvLocFiltered;
92 BOOL mRlvNamesFiltered;
93// [/RLVa:KB]
86 EChatSourceType mSourceType; 94 EChatSourceType mSourceType;
87 EChatType mChatType; 95 EChatType mChatType;
88 EChatAudible mAudible; 96 EChatAudible mAudible;
diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt
index 34aa29f..1fc7549 100644
--- a/linden/indra/newview/CMakeLists.txt
+++ b/linden/indra/newview/CMakeLists.txt
@@ -431,6 +431,11 @@ set(viewer_SOURCE_FILES
431 llxmlrpctransaction.cpp 431 llxmlrpctransaction.cpp
432 noise.cpp 432 noise.cpp
433 pipeline.cpp 433 pipeline.cpp
434 rlvhandler.cpp
435 rlvhelper.cpp
436 rlvmultistringsearch.cpp
437 rlvextensions.cpp
438 rlvfloaterbehaviour.cpp
434 ) 439 )
435 440
436set(VIEWER_BINARY_NAME "imprudence-bin" CACHE STRING 441set(VIEWER_BINARY_NAME "imprudence-bin" CACHE STRING
@@ -834,6 +839,12 @@ set(viewer_HEADER_FILES
834 randgauss.h 839 randgauss.h
835 VertexCache.h 840 VertexCache.h
836 VorbisFramework.h 841 VorbisFramework.h
842 rlvevent.h
843 rlvhandler.h
844 rlvhelper.h
845 rlvmultistringsearch.h
846 rlvextensions.h
847 rlvfloaterbehaviour.h
837 ) 848 )
838 849
839source_group("CMake Rules" FILES ViewerInstall.cmake) 850source_group("CMake Rules" FILES ViewerInstall.cmake)
diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml
index 5c76185..628936c 100644
--- a/linden/indra/newview/app_settings/settings.xml
+++ b/linden/indra/newview/app_settings/settings.xml
@@ -1,7 +1,106 @@
1<?xml version="1.0" ?> 1<?xml version="1.0" ?>
2<llsd> 2<llsd>
3<map> 3<map>
4 <key>AFKTimeout</key> 4 <key>RestrainedLife</key>
5 <map>
6 <key>Comment</key>
7 <string>Toggles the RestrainedLife features (BDSM lockable toys support). Needs a restart of the viewer.</string>
8 <key>Persist</key>
9 <integer>1</integer>
10 <key>Type</key>
11 <string>Boolean</string>
12 <key>Value</key>
13 <integer>0</integer>
14 </map>
15 <key>RestrainedLifeDebug</key>
16 <map>
17 <key>Comment</key>
18 <string>Toggles the RestrainedLife debug mode (displays the commands when in debug mode).</string>
19 <key>Persist</key>
20 <integer>1</integer>
21 <key>Type</key>
22 <string>Boolean</string>
23 <key>Value</key>
24 <integer>0</integer>
25 </map>
26 <key>RestrainedLifeNoSetEnv</key>
27 <map>
28 <key>Comment</key>
29 <string>When TRUE, forbids to set the environment (time of day and Windlight settings) via RestrainedLife. Needs a restart of the viewer.</string>
30 <key>Persist</key>
31 <integer>1</integer>
32 <key>Type</key>
33 <string>Boolean</string>
34 <key>Value</key>
35 <integer>0</integer>
36 </map>
37 <key>RestrainedLifeForbidGiveToRLV</key>
38 <map>
39 <key>Comment</key>
40 <string>When FALSE, allows to give sub-folders to the #RLV RestrainedLife folder.</string>
41 <key>Persist</key>
42 <integer>1</integer>
43 <key>Type</key>
44 <string>Boolean</string>
45 <key>Value</key>
46 <integer>1</integer>
47 </map>
48 <key>RLVaEnableLegacyNaming</key>
49 <map>
50 <key>Comment</key>
51 <string>Enables legacy naming convention for folders</string>
52 <key>Persist</key>
53 <integer>1</integer>
54 <key>Type</key>
55 <string>Boolean</string>
56 <key>Value</key>
57 <integer>1</integer>
58 </map>
59 <key>RLVaEnableWear</key>
60 <map>
61 <key>Comment</key>
62 <string>When TRUE, enables the "Wear" option on the inventory item context menu for attachments.</string>
63 <key>Persist</key>
64 <integer>1</integer>
65 <key>Type</key>
66 <string>Boolean</string>
67 <key>Value</key>
68 <integer>0</integer>
69 </map>
70 <key>RLVaHideLockedLayers</key>
71 <map>
72 <key>Comment</key>
73 <string>When TRUE, hides worn but "remove outfit" restricted clothing layers from @getoufit</string>
74 <key>Persist</key>
75 <integer>1</integer>
76 <key>Type</key>
77 <string>Boolean</string>
78 <key>Value</key>
79 <integer>0</integer>
80 </map>
81 <key>RLVaHideLockedAttachments</key>
82 <map>
83 <key>Comment</key>
84 <string>When TRUE, hides worn but "no detach" restricted attachments from @getattach</string>
85 <key>Persist</key>
86 <integer>1</integer>
87 <key>Type</key>
88 <string>Boolean</string>
89 <key>Value</key>
90 <integer>0</integer>
91 </map>
92 <key>RLVaShowNameTags</key>
93 <map>
94 <key>Comment</key>
95 <string>Display of names above avatars is subject to the general "Show Names" setting when @shownames=n restricted</string>
96 <key>Persist</key>
97 <integer>1</integer>
98 <key>Type</key>
99 <string>Boolean</string>
100 <key>Value</key>
101 <integer>0</integer>
102 </map>
103 <key>AFKTimeout</key>
5 <map> 104 <map>
6 <key>Comment</key> 105 <key>Comment</key>
7 <string>Time before automatically setting AFK (away from keyboard) mode (seconds)</string> 106 <string>Time before automatically setting AFK (away from keyboard) mode (seconds)</string>
diff --git a/linden/indra/newview/app_settings/settings_per_account.xml b/linden/indra/newview/app_settings/settings_per_account.xml
index 90c7b11..59caac4 100644
--- a/linden/indra/newview/app_settings/settings_per_account.xml
+++ b/linden/indra/newview/app_settings/settings_per_account.xml
@@ -1,6 +1,17 @@
1<llsd> 1<llsd>
2 <map> 2 <map>
3 <key>BusyModeResponse</key> 3 <key>RLVaLoginLastLocation</key>
4 <map>
5 <key>Comment</key>
6 <string>Determines whether the next login will be forced to the last logoff location (set by the viewer)</string>
7 <key>Persist</key>
8 <integer>1</integer>
9 <key>Type</key>
10 <string>Boolean</string>
11 <key>Value</key>
12 <integer>1</integer>
13 </map>
14 <key>BusyModeResponse</key>
4 <map> 15 <map>
5 <key>Comment</key> 16 <key>Comment</key>
6 <string>Auto response to instant messages while in busy mode.</string> 17 <string>Auto response to instant messages while in busy mode.</string>
diff --git a/linden/indra/newview/llagent.cpp b/linden/indra/newview/llagent.cpp
index 5f0a875..e71f1b7 100644
--- a/linden/indra/newview/llagent.cpp
+++ b/linden/indra/newview/llagent.cpp
@@ -757,6 +757,9 @@ void LLAgent::movePitch(S32 direction)
757// Does this parcel allow you to fly? 757// Does this parcel allow you to fly?
758BOOL LLAgent::canFly() 758BOOL LLAgent::canFly()
759{ 759{
760// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0c)
761 if (gRlvHandler.hasBehaviour(RLV_BHVR_FLY)) return FALSE;
762// [/RLVa:KB]
760 if (isGodlike()) return TRUE; 763 if (isGodlike()) return TRUE;
761 764
762 LLViewerRegion* regionp = getRegion(); 765 LLViewerRegion* regionp = getRegion();
@@ -796,6 +799,13 @@ void LLAgent::setFlying(BOOL fly)
796 799
797 if (fly) 800 if (fly)
798 { 801 {
802// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0c)
803 if (gRlvHandler.hasBehaviour(RLV_BHVR_FLY))
804 {
805 return;
806 }
807// [/RLVa:KB]
808
799 BOOL was_flying = getFlying(); 809 BOOL was_flying = getFlying();
800 if (!canFly() && !was_flying) 810 if (!canFly() && !was_flying)
801 { 811 {
@@ -4213,6 +4223,13 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_ani
4213 return; 4223 return;
4214 } 4224 }
4215 4225
4226// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
4227 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (mAvatarObject.notNull()) && (mAvatarObject->mIsSitting) )
4228 {
4229 return;
4230 }
4231// [/RLVa:KB]
4232
4216 setControlFlags(AGENT_CONTROL_STAND_UP); // force stand up 4233 setControlFlags(AGENT_CONTROL_STAND_UP); // force stand up
4217 gViewerWindow->getWindow()->resetBusyCount(); 4234 gViewerWindow->getWindow()->resetBusyCount();
4218 4235
@@ -5007,6 +5024,14 @@ BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOO
5007// utility to build a location string 5024// utility to build a location string
5008void LLAgent::buildLocationString(std::string& str) 5025void LLAgent::buildLocationString(std::string& str)
5009{ 5026{
5027// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
5028 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
5029 {
5030 str = rlv_handler_t::cstrHidden;
5031 return;
5032 }
5033// [/RLVa:KB]
5034
5010 const LLVector3& agent_pos_region = getPositionAgent(); 5035 const LLVector3& agent_pos_region = getPositionAgent();
5011 S32 pos_x = S32(agent_pos_region.mV[VX]); 5036 S32 pos_x = S32(agent_pos_region.mV[VX]);
5012 S32 pos_y = S32(agent_pos_region.mV[VY]); 5037 S32 pos_y = S32(agent_pos_region.mV[VY]);
@@ -5889,6 +5914,15 @@ void LLAgent::teleportRequest(
5889// Landmark ID = LLUUID::null means teleport home 5914// Landmark ID = LLUUID::null means teleport home
5890void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) 5915void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id)
5891{ 5916{
5917// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d)
5918 if ( (rlv_handler_t::isEnabled()) &&
5919 ( (gRlvHandler.hasBehaviour("tplm")) ||
5920 ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (mAvatarObject.notNull()) && (mAvatarObject->mIsSitting)) ))
5921 {
5922 return;
5923 }
5924// [/RLVa:KB]
5925
5892 LLViewerRegion *regionp = getRegion(); 5926 LLViewerRegion *regionp = getRegion();
5893 if(regionp && teleportCore()) 5927 if(regionp && teleportCore())
5894 { 5928 {
@@ -5953,6 +5987,17 @@ void LLAgent::teleportCancel()
5953 5987
5954void LLAgent::teleportViaLocation(const LLVector3d& pos_global) 5988void LLAgent::teleportViaLocation(const LLVector3d& pos_global)
5955{ 5989{
5990// [RLVa:KB] - Alternate: Snowglobe-1.0 | Checked: 2009-07-07 (RLVa-1.0.0d)
5991 // If we're getting teleported due to @tpto we should disregard any @tploc=n or @unsit=n restrictions from the same object
5992 if ( (rlv_handler_t::isEnabled()) &&
5993 ( (gRlvHandler.hasBehaviourExcept("tploc", gRlvHandler.getCurrentObject())) ||
5994 ( (mAvatarObject.notNull()) && (mAvatarObject->mIsSitting) &&
5995 (gRlvHandler.hasBehaviourExcept(RLV_BHVR_UNSIT, gRlvHandler.getCurrentObject()))) ) )
5996 {
5997 return;
5998 }
5999// [/RLVa:KB]
6000
5956 LLViewerRegion* regionp = getRegion(); 6001 LLViewerRegion* regionp = getRegion();
5957 LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); 6002 LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global);
5958 if(regionp && info) 6003 if(regionp && info)
@@ -6027,6 +6072,13 @@ void LLAgent::setTeleportState(ETeleportState state)
6027 // We're outa here. Save "back" slurl. 6072 // We're outa here. Save "back" slurl.
6028 mTeleportSourceSLURL = getSLURL(); 6073 mTeleportSourceSLURL = getSLURL();
6029 } 6074 }
6075
6076// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.0b
6077 if ( (rlv_handler_t::isEnabled()) && (TELEPORT_NONE == mTeleportState) )
6078 {
6079 gRlvHandler.setCanCancelTp(true);
6080 }
6081// [/RLVa:KB]
6030} 6082}
6031 6083
6032void LLAgent::stopCurrentAnimations() 6084void LLAgent::stopCurrentAnimations()
@@ -6654,10 +6706,17 @@ void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void
6654 } 6706 }
6655 6707
6656 // now that we have the asset ids...request the wearable assets 6708 // now that we have the asset ids...request the wearable assets
6709// [RLVa:KB] - Checked: 2009-08-08 (RLVa-1.0.1g) | Added: RLVa-1.0.1g
6710 LLInventoryFetchObserver::item_ref_t rlvItems;
6711// [/RLVa:KB]
6657 for( i = 0; i < WT_COUNT; i++ ) 6712 for( i = 0; i < WT_COUNT; i++ )
6658 { 6713 {
6659 if( !gAgent.mWearableEntry[i].mItemID.isNull() ) 6714 if( !gAgent.mWearableEntry[i].mItemID.isNull() )
6660 { 6715 {
6716// [RLVa:KB] - Checked: 2009-08-08 (RLVa-1.0.1g) | Added: RLVa-1.0.1g
6717 if (rlv_handler_t::isEnabled())
6718 rlvItems.push_back(gAgent.mWearableEntry[i].mItemID);
6719// [/RLVa:KB]
6661 gWearableList.getAsset( 6720 gWearableList.getAsset(
6662 asset_id_array[i], 6721 asset_id_array[i],
6663 LLStringUtil::null, 6722 LLStringUtil::null,
@@ -6665,6 +6724,15 @@ void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void
6665 LLAgent::onInitialWearableAssetArrived, (void*)(intptr_t)i ); 6724 LLAgent::onInitialWearableAssetArrived, (void*)(intptr_t)i );
6666 } 6725 }
6667 } 6726 }
6727
6728// [RLVa:KB] - Checked: 2009-08-08 (RLVa-1.0.1g) | Added: RLVa-1.0.1g
6729 // TODO-RLVa: checking that we're in STATE_STARTED is probably not needed, but leave it until we can be absolutely sure
6730 if ( (rlv_handler_t::isEnabled()) && (LLStartUp::getStartupState() == STATE_STARTED) )
6731 {
6732 RlvCurrentlyWorn f;
6733 f.fetchItems(rlvItems);
6734 }
6735// [/RLVa:KB]
6668 } 6736 }
6669} 6737}
6670 6738
@@ -7162,6 +7230,13 @@ void LLAgent::removeWearable( EWearableType type )
7162 return; 7230 return;
7163 } 7231 }
7164 7232
7233// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d)
7234 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isRemovable(type)) )
7235 {
7236 return;
7237 }
7238// [/RLVa:KB]
7239
7165 if( old_wearable ) 7240 if( old_wearable )
7166 { 7241 {
7167 if( old_wearable->isDirty() ) 7242 if( old_wearable->isDirty() )
@@ -7284,15 +7359,17 @@ void LLAgent::setWearableOutfit(
7284 wearables_to_remove[WT_SKIN] = FALSE; 7359 wearables_to_remove[WT_SKIN] = FALSE;
7285 wearables_to_remove[WT_HAIR] = FALSE; 7360 wearables_to_remove[WT_HAIR] = FALSE;
7286 wearables_to_remove[WT_EYES] = FALSE; 7361 wearables_to_remove[WT_EYES] = FALSE;
7287 wearables_to_remove[WT_SHIRT] = remove; 7362// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.2a
7288 wearables_to_remove[WT_PANTS] = remove; 7363 wearables_to_remove[WT_SHIRT] = remove && gRlvHandler.isRemovable(WT_SHIRT);
7289 wearables_to_remove[WT_SHOES] = remove; 7364 wearables_to_remove[WT_PANTS] = remove && gRlvHandler.isRemovable(WT_PANTS);
7290 wearables_to_remove[WT_SOCKS] = remove; 7365 wearables_to_remove[WT_SHOES] = remove && gRlvHandler.isRemovable(WT_SHOES);
7291 wearables_to_remove[WT_JACKET] = remove; 7366 wearables_to_remove[WT_SOCKS] = remove && gRlvHandler.isRemovable(WT_SOCKS);
7292 wearables_to_remove[WT_GLOVES] = remove; 7367 wearables_to_remove[WT_JACKET] = remove && gRlvHandler.isRemovable(WT_JACKET);
7293 wearables_to_remove[WT_UNDERSHIRT] = (!gAgent.isTeen()) & remove; 7368 wearables_to_remove[WT_GLOVES] = remove && gRlvHandler.isRemovable(WT_GLOVES);
7294 wearables_to_remove[WT_UNDERPANTS] = (!gAgent.isTeen()) & remove; 7369 wearables_to_remove[WT_UNDERSHIRT] = (!gAgent.isTeen()) && remove && gRlvHandler.isRemovable(WT_UNDERSHIRT);
7295 wearables_to_remove[WT_SKIRT] = remove; 7370 wearables_to_remove[WT_UNDERPANTS] = (!gAgent.isTeen()) && remove && gRlvHandler.isRemovable(WT_UNDERPANTS);
7371 wearables_to_remove[WT_SKIRT] = remove && gRlvHandler.isRemovable(WT_SKIRT);
7372// [/RLVa:KB]
7296 7373
7297 S32 count = wearables.count(); 7374 S32 count = wearables.count();
7298 llassert( items.count() == count ); 7375 llassert( items.count() == count );
@@ -7384,6 +7461,15 @@ void LLAgent::setWearable( LLInventoryItem* new_item, LLWearable* new_wearable )
7384 EWearableType type = new_wearable->getType(); 7461 EWearableType type = new_wearable->getType();
7385 7462
7386 LLWearable* old_wearable = mWearableEntry[ type ].mWearable; 7463 LLWearable* old_wearable = mWearableEntry[ type ].mWearable;
7464
7465// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d)
7466 // Block if: we can't wear on that layer; or we're already wearing something there we can't take off
7467 if ( (rlv_handler_t::isEnabled()) && ((!gRlvHandler.isWearable(type)) || ((old_wearable) && (!gRlvHandler.isRemovable(type)))) )
7468 {
7469 return;
7470 }
7471// [/RLVa:KB]
7472
7387 if( old_wearable ) 7473 if( old_wearable )
7388 { 7474 {
7389 const LLUUID& old_item_id = mWearableEntry[ type ].mItemID; 7475 const LLUUID& old_item_id = mWearableEntry[ type ].mItemID;
@@ -7592,10 +7678,13 @@ void LLAgent::userRemoveAllAttachments( void* userdata )
7592 return; 7678 return;
7593 } 7679 }
7594 7680
7595 gMessageSystem->newMessage("ObjectDetach"); 7681// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.0c
7596 gMessageSystem->nextBlockFast(_PREHASH_AgentData); 7682 // NOTE-RLVa: This function is called from inside RlvHandler as well, hence the rather heavy modifications
7597 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); 7683 std::list<U32> rlvAttachments;
7598 gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); 7684 // TODO-RLVa: Once we have the improved "removeWearable" logic implemented we can just get rid of the whole "rlvCompFolders" hassle
7685 #ifdef RLV_EXPERIMENTAL_COMPOSITES
7686 std::list<LLUUID> rlvCompFolders;
7687 #endif // RLV_EXPERIMENTAL_COMPOSITES
7599 7688
7600 for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); 7689 for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
7601 iter != avatarp->mAttachmentPoints.end(); ) 7690 iter != avatarp->mAttachmentPoints.end(); )
@@ -7605,11 +7694,78 @@ void LLAgent::userRemoveAllAttachments( void* userdata )
7605 LLViewerObject* objectp = attachment->getObject(); 7694 LLViewerObject* objectp = attachment->getObject();
7606 if (objectp) 7695 if (objectp)
7607 { 7696 {
7697 if (rlv_handler_t::isEnabled())
7698 {
7699 if (!gRlvHandler.isDetachable(curiter->first))
7700 continue;
7701
7702 // Check if we're being called in response to an RLV command (that would be @detach=force)
7703 if ( (gRlvHandler.getCurrentCommand()) && (attachment->getItemID().notNull()) )
7704 {
7705 if (!gRlvHandler.isStrippable(attachment->getItemID())) // "nostrip" can be taken off by the user but not @detach
7706 continue;
7707
7708 #ifdef RLV_EXPERIMENTAL_COMPOSITES
7709 LLViewerInventoryCategory* pFolder;
7710 if (gRlvHandler.getCompositeInfo(attachment->getItemID(), NULL, &pFolder))
7711 {
7712 #ifdef RLV_EXPERIMENTAL_COMPOSITE_LOCKING
7713 if (!gRlvHandler.canTakeOffComposite(pFolder))
7714 continue;
7715 #endif // RLV_EXPERIMENTAL_COMPOSITE_LOCKING
7716
7717 // The attachment belongs to a composite folder so there may be additional things we need to take off
7718 if (std::find(rlvCompFolders.begin(), rlvCompFolders.end(), pFolder->getUUID()) != rlvCompFolders.end())
7719 rlvCompFolders.push_back(pFolder->getUUID());
7720 }
7721 #endif // RLV_EXPERIMENTAL_COMPOSITES
7722 }
7723 }
7724 rlvAttachments.push_back(objectp->getLocalID());
7725 }
7726 }
7727
7728 // Only send the message if we actually have something to detach
7729 if (rlvAttachments.size() > 0)
7730 {
7731 gMessageSystem->newMessage("ObjectDetach");
7732 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
7733 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
7734 gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
7735
7736 for (std::list<U32>::const_iterator itAttach = rlvAttachments.begin(); itAttach != rlvAttachments.end(); ++itAttach)
7737 {
7608 gMessageSystem->nextBlockFast(_PREHASH_ObjectData); 7738 gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
7609 gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID()); 7739 gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, *itAttach);
7610 } 7740 }
7741
7742 gMessageSystem->sendReliable( gAgent.getRegionHost() );
7611 } 7743 }
7612 gMessageSystem->sendReliable( gAgent.getRegionHost() ); 7744
7745 #ifdef RLV_EXPERIMENTAL_COMPOSITES
7746 if (rlv_handler_t::isEnabled)
7747 {
7748 // If we encountered any composite folders then we need to @detach all of them
7749 for (std::list<LLUUID>::const_iterator itFolder = rlvCompFolders.begin(); itFolder != rlvCompFolders.end(); ++itFolder)
7750 {
7751 std::string strFolder = gRlvHandler.getSharedPath(*itFolder);
7752
7753 // It shouldn't happen but make absolutely sure that we don't issue @detach:=force and reenter this function
7754 if (!strFolder.empty())
7755 {
7756 std::string strCmd = "detach:" + strFolder + "=force";
7757 #ifdef RLV_DEBUG
7758 RLV_INFOS << "\t- detaching composite folder: @" << strCmd << LL_ENDL;
7759 #endif // RLV_DEBUG
7760
7761 // HACK-RLV: executing a command while another command is currently executing isn't the best thing to do, however
7762 // in this specific case it is safe (and still better than making processForceCommand public)
7763 gRlvHandler.processCommand(gRlvHandler.getCurrentObject(), strCmd);
7764 }
7765 }
7766 }
7767 #endif // RLV_EXPERIMENTAL_COMPOSITES
7768// [/RLVa:KB]
7613} 7769}
7614 7770
7615void LLAgent::observeFriends() 7771void LLAgent::observeFriends()
diff --git a/linden/indra/newview/llagent.h b/linden/indra/newview/llagent.h
index a4a930f..f64bf95 100644
--- a/linden/indra/newview/llagent.h
+++ b/linden/indra/newview/llagent.h
@@ -67,6 +67,10 @@
67#include "llfollowcam.h" 67#include "llfollowcam.h"
68// end Ventrella 68// end Ventrella
69 69
70// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d)
71#include "rlvhandler.h"
72// [/RLVa:KB]
73
70const U8 AGENT_STATE_TYPING = 0x04; // Typing indication 74const U8 AGENT_STATE_TYPING = 0x04; // Typing indication
71const U8 AGENT_STATE_EDITING = 0x10; // Set when agent has objects selected 75const U8 AGENT_STATE_EDITING = 0x10; // Set when agent has objects selected
72 76
diff --git a/linden/indra/newview/llappviewer.cpp b/linden/indra/newview/llappviewer.cpp
index 4d53c88..81c3f92 100644
--- a/linden/indra/newview/llappviewer.cpp
+++ b/linden/indra/newview/llappviewer.cpp
@@ -3829,4 +3829,21 @@ void LLAppViewer::handleLoginComplete()
3829 gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState(); 3829 gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
3830 } 3830 }
3831 writeDebugInfo(); 3831 writeDebugInfo();
3832
3833// [RLVa:KB] - Alternate: Snowglobe-1.0 | Checked: 2009-08-05 (RLVa-1.0.1e) | Modified: RLVa-1.0.1e
3834 // TODO-RLVa: find some way to initialize the lookup table when we need them *and* support toggling RLVa at runtime
3835 gRlvHandler.initLookupTables();
3836
3837 if (rlv_handler_t::isEnabled())
3838 {
3839 RlvCurrentlyWorn::fetchWorn();
3840 rlv_handler_t::fetchSharedInventory();
3841
3842 #ifdef RLV_EXTENSION_STARTLOCATION
3843 RlvSettings::updateLoginLastLocation();
3844 #endif // RLV_EXTENSION_STARTLOCATION
3845
3846 gRlvHandler.processRetainedCommands();
3847 }
3848// [/RLVa:KB]
3832} 3849}
diff --git a/linden/indra/newview/llchatbar.cpp b/linden/indra/newview/llchatbar.cpp
index 59aa572..eb1da05 100644
--- a/linden/indra/newview/llchatbar.cpp
+++ b/linden/indra/newview/llchatbar.cpp
@@ -78,7 +78,10 @@ LLChatBar *gChatBar = NULL;
78 78
79// legacy calllback glue 79// legacy calllback glue
80void toggleChatHistory(void* user_data); 80void toggleChatHistory(void* user_data);
81void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); 81//void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel);
82// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.2a
83void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channel);
84// [/RLVa:KB]
82 85
83 86
84class LLChatBarGestureObserver : public LLGestureManagerObserver 87class LLChatBarGestureObserver : public LLGestureManagerObserver
@@ -482,7 +485,10 @@ void LLChatBar::onInputEditorKeystroke( LLLineEditor* caller, void* userdata )
482 485
483 S32 length = raw_text.length(); 486 S32 length = raw_text.length();
484 487
485 if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences 488 //if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences
489// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d)
490 if ( (length > 0) && (raw_text[0] != '/') && (!gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT)) )
491// [/RLVa:KB]
486 { 492 {
487 gAgent.startTyping(); 493 gAgent.startTyping();
488 } 494 }
@@ -586,6 +592,21 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL
586 utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); 592 utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1);
587 } 593 }
588 594
595// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.0b
596 if ( (0 == channel) && (rlv_handler_t::isEnabled()) )
597 {
598 // Adjust the (public) chat "volume" on chat and gestures (also takes care of playing the proper animation)
599 if ( ((CHAT_TYPE_SHOUT == type) || (CHAT_TYPE_NORMAL == type)) && (gRlvHandler.hasBehaviour("chatnormal")) )
600 type = CHAT_TYPE_WHISPER;
601 else if ( (CHAT_TYPE_SHOUT == type) && (gRlvHandler.hasBehaviour("chatshout")) )
602 type = CHAT_TYPE_NORMAL;
603 else if ( (CHAT_TYPE_WHISPER == type) && (gRlvHandler.hasBehaviour("chatwhisper")) )
604 type = CHAT_TYPE_NORMAL;
605
606 animate &= !gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT);
607 }
608// [/RLVa:KB]
609
589 // Don't animate for chats people can't hear (chat to scripts) 610 // Don't animate for chats people can't hear (chat to scripts)
590 if (animate && (channel == 0)) 611 if (animate && (channel == 0))
591 { 612 {
@@ -621,8 +642,57 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL
621 send_chat_from_viewer(utf8_out_text, type, channel); 642 send_chat_from_viewer(utf8_out_text, type, channel);
622} 643}
623 644
624void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) 645// void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel)
646// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.2a
647void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channel)
648// [/RLVa:KB]
625{ 649{
650// [RLVa:KB] - Checked: 2009-08-05 (RLVa-1.0.1e) | Modified: RLVa-1.0.1e
651 // Only process chat messages (ie not CHAT_TYPE_START, CHAT_TYPE_STOP, etc)
652 if ( (rlv_handler_t::isEnabled()) && ( (CHAT_TYPE_WHISPER == type) || (CHAT_TYPE_NORMAL == type) || (CHAT_TYPE_SHOUT == type) ) )
653 {
654 if (0 == channel)
655 {
656 // (We already did this before, but LLChatHandler::handle() calls this directly)
657 if ( ((CHAT_TYPE_SHOUT == type) || (CHAT_TYPE_NORMAL == type)) && (gRlvHandler.hasBehaviour("chatnormal")) )
658 type = CHAT_TYPE_WHISPER;
659 else if ( (CHAT_TYPE_SHOUT == type) && (gRlvHandler.hasBehaviour("chatshout")) )
660 type = CHAT_TYPE_NORMAL;
661 else if ( (CHAT_TYPE_WHISPER == type) && (gRlvHandler.hasBehaviour("chatwhisper")) )
662 type = CHAT_TYPE_NORMAL;
663
664 // Redirect chat if needed
665 if ( ( (gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT) || (gRlvHandler.hasBehaviour(RLV_BHVR_REDIREMOTE)) ) &&
666 (gRlvHandler.redirectChatOrEmote(utf8_out_text)) ) )
667 {
668 return;
669 }
670
671 // Filter public chat if sendchat restricted (and filter anything that redirchat didn't redirect)
672 if ( (gRlvHandler.hasBehaviour("sendchat")) || (gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT)) )
673 gRlvHandler.filterChat(utf8_out_text, true);
674 }
675 else
676 {
677 // Don't allow chat on a non-public channel if sendchannel restricted (unless the channel is an exception)
678 if ( (gRlvHandler.hasBehaviour("sendchannel")) && (!gRlvHandler.hasBehaviour("sendchannel", llformat("%d", channel))) )
679 return;
680
681 // Don't allow chat on debug channel if @sendchat, @redirchat or @rediremote restricted (shows as public chat on viewers)
682 if (channel >= CHAT_CHANNEL_DEBUG)
683 {
684 bool fIsEmote = rlvIsEmote(utf8_out_text);
685 if ( (gRlvHandler.hasBehaviour("sendchat")) ||
686 ((!fIsEmote) && (gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT))) ||
687 ((fIsEmote) && (gRlvHandler.hasBehaviour(RLV_BHVR_REDIREMOTE))) )
688 {
689 return;
690 }
691 }
692 }
693 }
694// [/RLVa:KB]
695
626 LLMessageSystem* msg = gMessageSystem; 696 LLMessageSystem* msg = gMessageSystem;
627 msg->newMessageFast(_PREHASH_ChatFromViewer); 697 msg->newMessageFast(_PREHASH_ChatFromViewer);
628 msg->nextBlockFast(_PREHASH_AgentData); 698 msg->nextBlockFast(_PREHASH_AgentData);
diff --git a/linden/indra/newview/llfloaterabout.cpp b/linden/indra/newview/llfloaterabout.cpp
index 37e9c54..63f72af 100644
--- a/linden/indra/newview/llfloaterabout.cpp
+++ b/linden/indra/newview/llfloaterabout.cpp
@@ -126,7 +126,15 @@ LLFloaterAbout::LLFloaterAbout()
126 126
127 // Position 127 // Position
128 LLViewerRegion* region = gAgent.getRegion(); 128 LLViewerRegion* region = gAgent.getRegion();
129 if (region) 129// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-04 (RLVa-1.0.0a)
130 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
131 {
132 support.append(rlv_handler_t::cstrHidden);
133 support.append("\n\n");
134 }
135 else if (region)
136// [/RLVa:KB]
137// if (region)
130 { 138 {
131 LLStyleSP server_link_style(new LLStyle); 139 LLStyleSP server_link_style(new LLStyle);
132 server_link_style->setVisible(true); 140 server_link_style->setVisible(true);
diff --git a/linden/indra/newview/llfloateractivespeakers.cpp b/linden/indra/newview/llfloateractivespeakers.cpp
index a8f3f91..b4d402a 100644
--- a/linden/indra/newview/llfloateractivespeakers.cpp
+++ b/linden/indra/newview/llfloateractivespeakers.cpp
@@ -98,6 +98,11 @@ void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const std::string& first, c
98 if (speaker_ptr) 98 if (speaker_ptr)
99 { 99 {
100 speaker_ptr->mDisplayName = first + " " + last; 100 speaker_ptr->mDisplayName = first + " " + last;
101// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-1.0.0g
102 // TODO-RLVa: this seems to get called per frame which is very likely an LL bug that will eventuall get fixed
103 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
104 speaker_ptr->mDisplayName = gRlvHandler.getAnonym(speaker_ptr->mDisplayName);
105// [/RLVa:KB]
101 } 106 }
102} 107}
103 108
@@ -710,6 +715,13 @@ void LLPanelActiveSpeakers::onVolumeChange(LLUICtrl* source, void* user_data)
710//static 715//static
711void LLPanelActiveSpeakers::onClickProfile(void* user_data) 716void LLPanelActiveSpeakers::onClickProfile(void* user_data)
712{ 717{
718// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-1.0.0g
719 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
720 {
721 return;
722 }
723// [/RLVa:KB]
724
713 LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data; 725 LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data;
714 LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID(); 726 LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID();
715 727
@@ -719,6 +731,13 @@ void LLPanelActiveSpeakers::onClickProfile(void* user_data)
719//static 731//static
720void LLPanelActiveSpeakers::onDoubleClickSpeaker(void* user_data) 732void LLPanelActiveSpeakers::onDoubleClickSpeaker(void* user_data)
721{ 733{
734// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-1.0.0g
735 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
736 {
737 return;
738 }
739// [/RLVa:KB]
740
722 LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data; 741 LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data;
723 LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID(); 742 LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID();
724 743
diff --git a/linden/indra/newview/llfloaterbeacons.cpp b/linden/indra/newview/llfloaterbeacons.cpp
index d636776..7403df2 100644
--- a/linden/indra/newview/llfloaterbeacons.cpp
+++ b/linden/indra/newview/llfloaterbeacons.cpp
@@ -37,6 +37,9 @@
37#include "llcheckboxctrl.h" 37#include "llcheckboxctrl.h"
38#include "pipeline.h" 38#include "pipeline.h"
39 39
40// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d)
41#include "llagent.h"
42// [/RLVa:KB]
40 43
41LLFloaterBeacons::LLFloaterBeacons(const LLSD& seed) 44LLFloaterBeacons::LLFloaterBeacons(const LLSD& seed)
42{ 45{
@@ -72,6 +75,13 @@ BOOL LLFloaterBeacons::postBuild()
72// Too bad we can't just add control_name="BeaconsEnabled" to the XML. 75// Too bad we can't just add control_name="BeaconsEnabled" to the XML.
73void LLFloaterBeacons::open() 76void LLFloaterBeacons::open()
74{ 77{
78// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b)
79 if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT))
80 {
81 return;
82 }
83// [/RLVa:KB]
84
75 LLFloater::open(); 85 LLFloater::open();
76 gSavedSettings.setBOOL( "BeaconsEnabled", TRUE); 86 gSavedSettings.setBOOL( "BeaconsEnabled", TRUE);
77} 87}
diff --git a/linden/indra/newview/llfloaterchat.cpp b/linden/indra/newview/llfloaterchat.cpp
index 5117b8d..4cc721e 100644
--- a/linden/indra/newview/llfloaterchat.cpp
+++ b/linden/indra/newview/llfloaterchat.cpp
@@ -202,7 +202,11 @@ void add_timestamped_line(LLViewerTextEditor* edit, const LLChat &chat, const LL
202 // extract out the sender name and replace it with the hotlinked name. 202 // extract out the sender name and replace it with the hotlinked name.
203 if (chat.mSourceType == CHAT_SOURCE_AGENT && 203 if (chat.mSourceType == CHAT_SOURCE_AGENT &&
204 chat.mFromID != LLUUID::null && 204 chat.mFromID != LLUUID::null &&
205 (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0)) 205// (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0))
206 (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0) &&
207// [RLVa] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e)
208 (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) )
209// [/RLVa]
206 { 210 {
207 std::string start_line = line.substr(0, chat.mFromName.length() + 1); 211 std::string start_line = line.substr(0, chat.mFromName.length() + 1);
208 line = line.substr(chat.mFromName.length() + 1); 212 line = line.substr(chat.mFromName.length() + 1);
@@ -226,6 +230,30 @@ void log_chat_text(const LLChat& chat)
226// static 230// static
227void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) 231void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
228{ 232{
233// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
234 if (rlv_handler_t::isEnabled())
235 {
236 // TODO-RLVa: we might cast too broad a net by filtering here, needs testing
237 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) && (!chat.mRlvLocFiltered) && (CHAT_SOURCE_AGENT != chat.mSourceType) )
238 {
239 LLChat& rlvChat = const_cast<LLChat&>(chat);
240 gRlvHandler.filterLocation(rlvChat.mText);
241 rlvChat.mRlvLocFiltered = TRUE;
242 }
243 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!chat.mRlvNamesFiltered) )
244 {
245 // NOTE: this will also filter inventory accepted/declined text in the chat history
246 LLChat& rlvChat = const_cast<LLChat&>(chat);
247 if (CHAT_SOURCE_AGENT != chat.mSourceType)
248 {
249 // Filter object and system chat (names are filtered elsewhere to save ourselves an gObjectList lookup)
250 gRlvHandler.filterNames(rlvChat.mText);
251 }
252 rlvChat.mRlvNamesFiltered = TRUE;
253 }
254 }
255// [/RLVa:KB]
256
229 if ( gSavedPerAccountSettings.getBOOL("LogChat") && log_to_file) 257 if ( gSavedPerAccountSettings.getBOOL("LogChat") && log_to_file)
230 { 258 {
231 log_chat_text(chat); 259 log_chat_text(chat);
@@ -356,6 +384,30 @@ void LLFloaterChat::addChat(const LLChat& chat,
356 chat.mChatType == CHAT_TYPE_DEBUG_MSG 384 chat.mChatType == CHAT_TYPE_DEBUG_MSG
357 && !gSavedSettings.getBOOL("ScriptErrorsAsChat"); 385 && !gSavedSettings.getBOOL("ScriptErrorsAsChat");
358 386
387// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
388 if (rlv_handler_t::isEnabled())
389 {
390 // TODO-RLVa: we might cast too broad a net by filtering here, needs testing
391 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) && (!chat.mRlvLocFiltered) && (CHAT_SOURCE_AGENT != chat.mSourceType) )
392 {
393 LLChat& rlvChat = const_cast<LLChat&>(chat);
394 if (!from_instant_message)
395 gRlvHandler.filterLocation(rlvChat.mText);
396 rlvChat.mRlvLocFiltered = TRUE;
397 }
398 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!chat.mRlvNamesFiltered) )
399 {
400 LLChat& rlvChat = const_cast<LLChat&>(chat);
401 if ( (!from_instant_message) && (CHAT_SOURCE_AGENT != chat.mSourceType) )
402 {
403 // Filter object and system chat (names are filtered elsewhere to save ourselves an gObjectList lookup)
404 gRlvHandler.filterNames(rlvChat.mText);
405 }
406 rlvChat.mRlvNamesFiltered = TRUE;
407 }
408 }
409// [/RLVa:KB]
410
359#if LL_LCD_COMPILE 411#if LL_LCD_COMPILE
360 // add into LCD displays 412 // add into LCD displays
361 if (!invisible_script_debug_chat) 413 if (!invisible_script_debug_chat)
@@ -513,7 +565,11 @@ void LLFloaterChat::onClickToggleActiveSpeakers(void* userdata)
513{ 565{
514 LLFloaterChat* self = (LLFloaterChat*)userdata; 566 LLFloaterChat* self = (LLFloaterChat*)userdata;
515 567
516 self->childSetVisible("active_speakers_panel", !self->childIsVisible("active_speakers_panel")); 568// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
569 self->childSetVisible("active_speakers_panel",
570 (!self->childIsVisible("active_speakers_panel")) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) );
571// [/RLVa:KB]
572 //self->childSetVisible("active_speakers_panel", !self->childIsVisible("active_speakers_panel"));
517} 573}
518 574
519//static 575//static
diff --git a/linden/indra/newview/llfloaterinspect.cpp b/linden/indra/newview/llfloaterinspect.cpp
index e1d3c4a..2367b48 100644
--- a/linden/indra/newview/llfloaterinspect.cpp
+++ b/linden/indra/newview/llfloaterinspect.cpp
@@ -42,6 +42,10 @@
42#include "llviewerobject.h" 42#include "llviewerobject.h"
43#include "lluictrlfactory.h" 43#include "lluictrlfactory.h"
44 44
45// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
46#include "rlvhandler.h"
47// [/RLVa:KB]
48
45LLFloaterInspect* LLFloaterInspect::sInstance = NULL; 49LLFloaterInspect* LLFloaterInspect::sInstance = NULL;
46 50
47LLFloaterInspect::LLFloaterInspect(void) : 51LLFloaterInspect::LLFloaterInspect(void) :
@@ -145,7 +149,13 @@ void LLFloaterInspect::onClickOwnerProfile(void* ctrl)
145 if(node) 149 if(node)
146 { 150 {
147 const LLUUID& owner_id = node->mPermissions->getOwner(); 151 const LLUUID& owner_id = node->mPermissions->getOwner();
148 LLFloaterAvatarInfo::showFromDirectory(owner_id); 152// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
153 if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
154 {
155 LLFloaterAvatarInfo::showFromDirectory(owner_id);
156 }
157// [/RLVa:KB]
158// LLFloaterAvatarInfo::showFromDirectory(owner_id);
149 } 159 }
150 } 160 }
151} 161}
@@ -163,7 +173,10 @@ void LLFloaterInspect::onSelectObject(LLUICtrl* ctrl, void* user_data)
163{ 173{
164 if(LLFloaterInspect::getSelectedUUID() != LLUUID::null) 174 if(LLFloaterInspect::getSelectedUUID() != LLUUID::null)
165 { 175 {
166 sInstance->childSetEnabled("button owner", true); 176 //sInstance->childSetEnabled("button owner", true);
177// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-1.0.0e
178 sInstance->childSetEnabled("button owner", !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES));
179// [/RLVa:KB]
167 sInstance->childSetEnabled("button creator", true); 180 sInstance->childSetEnabled("button creator", true);
168 } 181 }
169} 182}
@@ -223,6 +236,13 @@ void LLFloaterInspect::refresh()
223 LLStringUtil::copy(time, ctime(&timestamp), MAX_STRING); 236 LLStringUtil::copy(time, ctime(&timestamp), MAX_STRING);
224 time[24] = '\0'; 237 time[24] = '\0';
225 gCacheName->getFullName(obj->mPermissions->getOwner(), owner_name); 238 gCacheName->getFullName(obj->mPermissions->getOwner(), owner_name);
239// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
240 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
241 {
242 // TODO-RLVa: shouldn't filter if this is a group-owned prim (will show "(nobody)")
243 owner_name = gRlvHandler.getAnonym(owner_name);
244 }
245// [/RLVa:KB]
226 gCacheName->getFullName(obj->mPermissions->getCreator(), creator_name); 246 gCacheName->getFullName(obj->mPermissions->getCreator(), creator_name);
227 row["id"] = obj->getObject()->getID(); 247 row["id"] = obj->getObject()->getID();
228 row["columns"][0]["column"] = "object_name"; 248 row["columns"][0]["column"] = "object_name";
diff --git a/linden/indra/newview/llfloaterland.cpp b/linden/indra/newview/llfloaterland.cpp
index 9707184..75c5782 100644
--- a/linden/indra/newview/llfloaterland.cpp
+++ b/linden/indra/newview/llfloaterland.cpp
@@ -813,6 +813,12 @@ void LLPanelLandGeneral::setGroup(const LLUUID& group_id)
813// static 813// static
814void LLPanelLandGeneral::onClickBuyLand(void* data) 814void LLPanelLandGeneral::onClickBuyLand(void* data)
815{ 815{
816// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
817 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) )
818 {
819 return;
820 }
821// [/RLVa:KB]
816 BOOL* for_group = (BOOL*)data; 822 BOOL* for_group = (BOOL*)data;
817 LLViewerParcelMgr::getInstance()->startBuyLand(*for_group); 823 LLViewerParcelMgr::getInstance()->startBuyLand(*for_group);
818} 824}
@@ -2779,3 +2785,41 @@ void LLPanelLandCovenant::updateEstateOwnerName(const std::string& name)
2779 if (editor) editor->setText(name); 2785 if (editor) editor->setText(name);
2780 } 2786 }
2781} 2787}
2788
2789// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
2790void LLFloaterLand::open()
2791{
2792 // We'll allow "About Land" as long as you have the ability to return prims (through ownership or through group powers)
2793 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
2794 {
2795 LLParcelSelection* pParcelSel = LLViewerParcelMgr::getInstance()->getFloatingParcelSelection();
2796 if ( (!pParcelSel) || (pParcelSel->hasOthersSelected()) )
2797 return;
2798 LLParcel* pParcel = pParcelSel->getParcel();
2799 if (!pParcel)
2800 return;
2801
2802 // Ideally we could just use LLViewerParcelMgr::isParcelOwnedByAgent(), but that has that sneaky exemption
2803 // for fake god like (aka View Admin Options)
2804 const LLUUID& idOwner = pParcel->getOwnerID();
2805 if ( (idOwner != gAgent.getID()) )
2806 {
2807 // *sighs* LLAgent::hasPowerInGroup() has it too so copy/paste from there
2808 S32 count = gAgent.mGroups.count(); bool fShow = false;
2809 for (S32 i = 0; i < count; ++i)
2810 {
2811 if (gAgent.mGroups.get(i).mID == idOwner)
2812 {
2813 fShow |= ((gAgent.mGroups.get(i).mPowers & GP_LAND_RETURN) > 0);
2814 break;
2815 }
2816 }
2817
2818 if (!fShow)
2819 return;
2820 }
2821 }
2822
2823 LLFloater::open();
2824}
2825// [/RLVa:KB]
diff --git a/linden/indra/newview/llfloaterland.h b/linden/indra/newview/llfloaterland.h
index 5f2b970..6e26b93 100644
--- a/linden/indra/newview/llfloaterland.h
+++ b/linden/indra/newview/llfloaterland.h
@@ -82,6 +82,10 @@ public:
82 virtual void onOpen(); 82 virtual void onOpen();
83 virtual BOOL postBuild(); 83 virtual BOOL postBuild();
84 84
85// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
86 virtual void open();
87// [/RLVa:KB]
88
85protected: 89protected:
86 90
87 // Does its own instance management, so clients not allowed 91 // Does its own instance management, so clients not allowed
diff --git a/linden/indra/newview/llfloatermap.cpp b/linden/indra/newview/llfloatermap.cpp
index 6115404..8714d4f 100644
--- a/linden/indra/newview/llfloatermap.cpp
+++ b/linden/indra/newview/llfloatermap.cpp
@@ -122,3 +122,13 @@ void LLFloaterMap::draw()
122 } 122 }
123} 123}
124 124
125
126// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-05 (RLVa-1.0.0c)
127void LLFloaterMap::open()
128{
129 if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWMINIMAP))
130 {
131 LLFloater::open();
132 }
133}
134// [/RLVa:KB]
diff --git a/linden/indra/newview/llfloatermap.h b/linden/indra/newview/llfloatermap.h
index dd1cba8..857b1ed 100644
--- a/linden/indra/newview/llfloatermap.h
+++ b/linden/indra/newview/llfloatermap.h
@@ -52,6 +52,10 @@ public:
52 /*virtual*/ void onOpen(); 52 /*virtual*/ void onOpen();
53 /*virtual*/ void onClose(bool app_quitting); 53 /*virtual*/ void onClose(bool app_quitting);
54 /*virtual*/ BOOL canClose(); 54 /*virtual*/ BOOL canClose();
55// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-05 (RLVa-1.0.0c)
56 /*virtual*/ void open();
57// [/RLVa:KB]
58
55 59
56private: 60private:
57 LLFloaterMap(const LLSD& key = LLSD()); 61 LLFloaterMap(const LLSD& key = LLSD());
diff --git a/linden/indra/newview/llfloateropenobject.cpp b/linden/indra/newview/llfloateropenobject.cpp
index a83b0c9..fd4f9c6 100644
--- a/linden/indra/newview/llfloateropenobject.cpp
+++ b/linden/indra/newview/llfloateropenobject.cpp
@@ -207,7 +207,18 @@ 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 self->moveToInventory(true); 210// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Deprecated: RLVa-0.2.2a
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);
211 self->close(); 222 self->close();
212} 223}
213 224
diff --git a/linden/indra/newview/llfloaterproperties.cpp b/linden/indra/newview/llfloaterproperties.cpp
index eddd56a..0af8ec3 100644
--- a/linden/indra/newview/llfloaterproperties.cpp
+++ b/linden/indra/newview/llfloaterproperties.cpp
@@ -354,8 +354,17 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
354 else 354 else
355 { 355 {
356 gCacheName->getFullName(perm.getOwner(), name); 356 gCacheName->getFullName(perm.getOwner(), name);
357// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
358 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
359 {
360 name = gRlvHandler.getAnonym(name);
361 }
362// [/RLVa:KB]
357 } 363 }
358 childSetEnabled("BtnOwner",TRUE); 364 //childSetEnabled("BtnOwner",TRUE);
365// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-1.0.0e
366 childSetEnabled("BtnOwner", !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES));
367// [/RLVa:KB]
359 childSetEnabled("LabelOwnerTitle",TRUE); 368 childSetEnabled("LabelOwnerTitle",TRUE);
360 childSetEnabled("LabelOwnerName",TRUE); 369 childSetEnabled("LabelOwnerName",TRUE);
361 childSetText("LabelOwnerName",name); 370 childSetText("LabelOwnerName",name);
@@ -602,7 +611,10 @@ void LLFloaterProperties::onClickOwner(void* data)
602 } 611 }
603 else 612 else
604 { 613 {
605 if(!item->getPermissions().getOwner().isNull()) 614// if(!item->getPermissions().getOwner().isNull())
615// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
616 if ( (!item->getPermissions().getOwner().isNull()) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) )
617// [/RLVa:KB]
606 { 618 {
607 LLFloaterAvatarInfo::showFromObject(item->getPermissions().getOwner()); 619 LLFloaterAvatarInfo::showFromObject(item->getPermissions().getOwner());
608 } 620 }
diff --git a/linden/indra/newview/llfloaterregioninfo.cpp b/linden/indra/newview/llfloaterregioninfo.cpp
index 6e0dba1..40907eb 100644
--- a/linden/indra/newview/llfloaterregioninfo.cpp
+++ b/linden/indra/newview/llfloaterregioninfo.cpp
@@ -3192,3 +3192,22 @@ bool LLDispatchSetEstateAccess::operator()(
3192 3192
3193 return true; 3193 return true;
3194} 3194}
3195
3196// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
3197void LLFloaterRegionInfo::open()
3198{
3199 // We'll allow access to the estate tools for estate managers (and for the sim owner)
3200 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
3201 {
3202 LLViewerRegion* pRegion = gAgent.getRegion();
3203 if (!pRegion)
3204 return;
3205
3206 // Should be able to call LLRegion::canManageEstate() but then we can fake god like
3207 if ( (!pRegion->isEstateManager()) && (pRegion->getOwner() != gAgent.getID()) )
3208 return;
3209 }
3210
3211 LLFloater::open();
3212}
3213// [/RLVa:KB]
diff --git a/linden/indra/newview/llfloaterregioninfo.h b/linden/indra/newview/llfloaterregioninfo.h
index 41a94ce..7b675de 100644
--- a/linden/indra/newview/llfloaterregioninfo.h
+++ b/linden/indra/newview/llfloaterregioninfo.h
@@ -66,6 +66,9 @@ public:
66 66
67 /*virtual*/ void onOpen(); 67 /*virtual*/ void onOpen();
68 /*virtual*/ BOOL postBuild(); 68 /*virtual*/ BOOL postBuild();
69// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
70 /*virtual*/ void open();
71// [/RLVa:KB]
69 72
70 static void processEstateOwnerRequest(LLMessageSystem* msg, void**); 73 static void processEstateOwnerRequest(LLMessageSystem* msg, void**);
71 74
diff --git a/linden/indra/newview/llfloaterreporter.cpp b/linden/indra/newview/llfloaterreporter.cpp
index d2fcf01..0d3b101 100644
--- a/linden/indra/newview/llfloaterreporter.cpp
+++ b/linden/indra/newview/llfloaterreporter.cpp
@@ -132,6 +132,23 @@ LLFloaterReporter::LLFloaterReporter(
132 132
133 childSetText("abuse_location_edit", gAgent.getSLURL() ); 133 childSetText("abuse_location_edit", gAgent.getSLURL() );
134 134
135// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-1.0.0a
136 if (rlv_handler_t::isEnabled())
137 {
138 // Can't filter these since they get sent as part of the report so just hide them instead
139 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
140 {
141 childSetVisible("abuse_location_edit", false);
142 childSetVisible("pos_field", false);
143 }
144 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
145 {
146 childSetVisible("owner_name", false);
147 childSetVisible("abuser_name_edit", false);
148 }
149 }
150// [/RLVa:KB]
151
135 LLButton* pick_btn = getChild<LLButton>("pick_btn"); 152 LLButton* pick_btn = getChild<LLButton>("pick_btn");
136 if (pick_btn) 153 if (pick_btn)
137 { 154 {
@@ -299,6 +316,12 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
299 if (regionp) 316 if (regionp)
300 { 317 {
301 childSetText("sim_field", regionp->getName()); 318 childSetText("sim_field", regionp->getName());
319// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
320 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) )
321 {
322 childSetText("sim_field", rlv_handler_t::cstrHiddenRegion);
323 }
324// [/RLVa:KB]
302 LLVector3d global_pos; 325 LLVector3d global_pos;
303 global_pos.setVec(objectp->getPositionRegion()); 326 global_pos.setVec(objectp->getPositionRegion());
304 setPosBox(global_pos); 327 setPosBox(global_pos);
@@ -322,6 +345,12 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
322 object_owner.append("Unknown"); 345 object_owner.append("Unknown");
323 } 346 }
324 childSetText("object_name", object_owner); 347 childSetText("object_name", object_owner);
348// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RVLa-1.0.0e
349 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
350 {
351 childSetVisible("object_name", false); // Hide the object name if the picked object represents an avataz
352 }
353// [/RLVa:KB]
325 childSetText("owner_name", object_owner); 354 childSetText("owner_name", object_owner);
326 childSetText("abuser_name_edit", object_owner); 355 childSetText("abuser_name_edit", object_owner);
327 mAbuserID = object_id; 356 mAbuserID = object_id;
@@ -594,6 +623,12 @@ LLFloaterReporter* LLFloaterReporter::createNewBugReporter()
594void LLFloaterReporter::setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id) 623void LLFloaterReporter::setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id)
595{ 624{
596 childSetText("object_name", object_name); 625 childSetText("object_name", object_name);
626// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RVLa-1.0.0e
627 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
628 {
629 childSetVisible("object_name", true); // Show the object name if the picked object is actually an object
630 }
631// [/RLVa:KB]
597 childSetText("owner_name", owner_name); 632 childSetText("owner_name", owner_name);
598 childSetText("abuser_name_edit", owner_name); 633 childSetText("abuser_name_edit", owner_name);
599 mAbuserID = owner_id; 634 mAbuserID = owner_id;
diff --git a/linden/indra/newview/llfloatersettingsdebug.cpp b/linden/indra/newview/llfloatersettingsdebug.cpp
index e440c4a..58f37c5 100644
--- a/linden/indra/newview/llfloatersettingsdebug.cpp
+++ b/linden/indra/newview/llfloatersettingsdebug.cpp
@@ -39,6 +39,11 @@
39#include "llcolorswatch.h" 39#include "llcolorswatch.h"
40#include "llviewercontrol.h" 40#include "llviewercontrol.h"
41 41
42// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0g)
43#include "rlvhandler.h"
44#include "rlvextensions.h"
45// [/RLVa:KB]
46
42LLFloaterSettingsDebug* LLFloaterSettingsDebug::sInstance = NULL; 47LLFloaterSettingsDebug* LLFloaterSettingsDebug::sInstance = NULL;
43 48
44LLFloaterSettingsDebug::LLFloaterSettingsDebug() : LLFloater(std::string("Configuration Editor")) 49LLFloaterSettingsDebug::LLFloaterSettingsDebug() : LLFloater(std::string("Configuration Editor"))
@@ -239,6 +244,32 @@ void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp)
239 244
240 if (controlp) 245 if (controlp)
241 { 246 {
247// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.1d
248 if (rlv_handler_t::isEnabled())
249 {
250 // Don't allow changing DBG_WRITE debug settings under @setdebug=n
251 bool fEnable = !( (gRlvHandler.hasBehaviour(RLV_BHVR_SETDEBUG)) &&
252 (RlvExtGetSet::getDebugSettingFlags(controlp->getName()) & RlvExtGetSet::DBG_WRITE) );
253 // Don't allow toggling "Basic Shaders" and/or "Atmopsheric Shaders" through the debug settings under @setenv=n
254 fEnable &= !((gRlvHandler.hasBehaviour(RLV_BHVR_SETENV)) &&
255 (("VertexShaderEnable" == controlp->getName()) || ("WindLightUseAtmosShaders" == controlp->getName())));
256 #ifdef RLV_EXTENSION_STARTLOCATION
257 // Don't allow toggling RestrainedLifeLoginLastLocation
258 fEnable &= !(RLV_SETTING_LOGINLASTLOCATION == controlp->getName());
259 #endif // RLV_EXTENSION_STARTLOCATION
260
261 // NOTE: this runs per-frame so there's no need to explictly handle onCommitSettings() or onClickDefault()
262 spinner1->setEnabled(fEnable);
263 spinner2->setEnabled(fEnable);
264 spinner3->setEnabled(fEnable);
265 spinner4->setEnabled(fEnable);
266 color_swatch->setEnabled(fEnable);
267 childSetEnabled("val_text", fEnable);
268 childSetEnabled("boolean_combo", fEnable);
269 childSetEnabled("default_btn", fEnable);
270 }
271// [/RLVa:KB]
272
242 eControlType type = controlp->type(); 273 eControlType type = controlp->type();
243 274
244 //hide combo box only for non booleans, otherwise this will result in the combo box closing every frame 275 //hide combo box only for non booleans, otherwise this will result in the combo box closing every frame
diff --git a/linden/indra/newview/llfloaterwindlight.cpp b/linden/indra/newview/llfloaterwindlight.cpp
index 37cd4ef..4b0dd04 100644
--- a/linden/indra/newview/llfloaterwindlight.cpp
+++ b/linden/indra/newview/llfloaterwindlight.cpp
@@ -317,6 +317,15 @@ void LLFloaterWindLight::syncMenu()
317 LLWLParamSet& currentParams = param_mgr->mCurParams; 317 LLWLParamSet& currentParams = param_mgr->mCurParams;
318 //std::map<std::string, LLVector4> & currentParams = param_mgr->mCurParams.mParamValues; 318 //std::map<std::string, LLVector4> & currentParams = param_mgr->mCurParams.mParamValues;
319 319
320// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
321 // Fixes LL "bug" (preset name isn't kept synchronized)
322 LLComboBox* comboBox = getChild<LLComboBox>("WLPresetsCombo");
323 if (comboBox->getSelectedItemLabel() != currentParams.mName)
324 {
325 comboBox->setSimple(currentParams.mName);
326 }
327// [/RLVa:KB]
328
320 // blue horizon 329 // blue horizon
321 param_mgr->mBlueHorizon = currentParams.getVector(param_mgr->mBlueHorizon.mName, err); 330 param_mgr->mBlueHorizon = currentParams.getVector(param_mgr->mBlueHorizon.mName, err);
322 childSetValue("WLBlueHorizonR", param_mgr->mBlueHorizon.r / 2.0); 331 childSetValue("WLBlueHorizonR", param_mgr->mBlueHorizon.r / 2.0);
diff --git a/linden/indra/newview/llfloaterworldmap.cpp b/linden/indra/newview/llfloaterworldmap.cpp
index bc61d8a..a31dde5 100644
--- a/linden/indra/newview/llfloaterworldmap.cpp
+++ b/linden/indra/newview/llfloaterworldmap.cpp
@@ -280,6 +280,13 @@ void LLFloaterWorldMap::onClose(bool app_quitting)
280// static 280// static
281void LLFloaterWorldMap::show(void*, BOOL center_on_target) 281void LLFloaterWorldMap::show(void*, BOOL center_on_target)
282{ 282{
283// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0c)
284 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWWORLDMAP))
285 {
286 return;
287 }
288// [/RLVa:KB]
289
283 BOOL was_visible = gFloaterWorldMap->getVisible(); 290 BOOL was_visible = gFloaterWorldMap->getVisible();
284 291
285 gFloaterWorldMap->mIsClosing = FALSE; 292 gFloaterWorldMap->mIsClosing = FALSE;
@@ -641,7 +648,10 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
641 F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS ); 648 F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS );
642 F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS ); 649 F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS );
643 std::string full_name = llformat("%s (%d, %d, %d)", 650 std::string full_name = llformat("%s (%d, %d, %d)",
644 sim_name.c_str(), 651// sim_name.c_str(),
652// [RLVa:KB] - Alternate: Snowglobe-1.0 | Checked: 2009-07-04 (RLVa-1.0.0a)
653 (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? sim_name.c_str() : rlv_handler_t::cstrHiddenRegion.c_str(),
654// [/RLVa:KB]
645 llround(region_x), 655 llround(region_x),
646 llround(region_y), 656 llround(region_y),
647 llround((F32)pos_global.mdV[VZ])); 657 llround((F32)pos_global.mdV[VZ]));
@@ -695,6 +705,14 @@ void LLFloaterWorldMap::updateLocation()
695 705
696 // Set the current SLURL 706 // Set the current SLURL
697 mSLURL = LLURLDispatcher::buildSLURL(agent_sim_name, agent_x, agent_y, agent_z); 707 mSLURL = LLURLDispatcher::buildSLURL(agent_sim_name, agent_x, agent_y, agent_z);
708
709// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
710 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
711 {
712 childSetValue("location", rlv_handler_t::cstrHiddenRegion);
713 mSLURL.clear();
714 }
715// [/RLVa:KB]
698 } 716 }
699 } 717 }
700 718
@@ -737,6 +755,14 @@ void LLFloaterWorldMap::updateLocation()
737 { // Empty SLURL will disable the "Copy SLURL to clipboard" button 755 { // Empty SLURL will disable the "Copy SLURL to clipboard" button
738 mSLURL = ""; 756 mSLURL = "";
739 } 757 }
758
759// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
760 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
761 {
762 childSetValue("location", rlv_handler_t::cstrHiddenRegion);
763 mSLURL.clear();
764 }
765// [/RLVa:KB]
740 } 766 }
741} 767}
742 768
diff --git a/linden/indra/newview/llglsandbox.cpp b/linden/indra/newview/llglsandbox.cpp
index 2b51948..296cdaa 100644
--- a/linden/indra/newview/llglsandbox.cpp
+++ b/linden/indra/newview/llglsandbox.cpp
@@ -166,6 +166,13 @@ extern BOOL gDebugSelect;
166// Returns true if you got at least one object 166// Returns true if you got at least one object
167void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask) 167void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask)
168{ 168{
169// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b)
170 if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT))
171 {
172 return;
173 }
174// [/RLVa:KB]
175
169 LLVector3 av_pos = gAgent.getPositionAgent(); 176 LLVector3 av_pos = gAgent.getPositionAgent();
170 F32 select_dist_squared = gSavedSettings.getF32("MaxSelectDistance"); 177 F32 select_dist_squared = gSavedSettings.getF32("MaxSelectDistance");
171 select_dist_squared = select_dist_squared * select_dist_squared; 178 select_dist_squared = select_dist_squared * select_dist_squared;
@@ -230,6 +237,27 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask)
230 LLViewerCamera::getInstance()->setFar(new_far); 237 LLViewerCamera::getInstance()->setFar(new_far);
231 LLViewerCamera::getInstance()->setNear(new_near); 238 LLViewerCamera::getInstance()->setNear(new_near);
232 } 239 }
240// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
241 if (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH))
242 {
243 // We'll allow drag selection under fartouch, but only within the fartouch range
244 // (just copy/paste the code above us to make that work, thank you Lindens!)
245 LLVector3 relative_av_pos = av_pos;
246 relative_av_pos -= LLViewerCamera::getInstance()->getOrigin();
247
248 F32 new_far = relative_av_pos * LLViewerCamera::getInstance()->getAtAxis() + 1.5f;
249 F32 new_near = relative_av_pos * LLViewerCamera::getInstance()->getAtAxis() - 1.5f;
250
251 new_near = llmax(new_near, 0.1f);
252
253 LLViewerCamera::getInstance()->setFar(new_far);
254 LLViewerCamera::getInstance()->setNear(new_near);
255
256 // Usurp these two
257 limit_select_distance = TRUE;
258 select_dist_squared = 1.5f * 1.5f;
259 }
260// [/RLVa:KB]
233 LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, 261 LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION,
234 center_x-width/2, center_y-height/2, width, height, 262 center_x-width/2, center_y-height/2, width, height,
235 limit_select_distance); 263 limit_select_distance);
diff --git a/linden/indra/newview/llhoverview.cpp b/linden/indra/newview/llhoverview.cpp
index 8d033b2..e40ae10 100644
--- a/linden/indra/newview/llhoverview.cpp
+++ b/linden/indra/newview/llhoverview.cpp
@@ -244,14 +244,25 @@ void LLHoverView::updateText()
244 LLNameValue* lastname = hit_object->getNVPair("LastName"); 244 LLNameValue* lastname = hit_object->getNVPair("LastName");
245 if (firstname && lastname) 245 if (firstname && lastname)
246 { 246 {
247 if (title) 247// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
248 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
248 { 249 {
249 line.append(title->getString()); 250 line = gRlvHandler.getAnonym(line.append(firstname->getString()).append(1, ' ').append(lastname->getString()));
251 }
252 else
253 {
254// [/RLVa:KB]
255 if (title)
256 {
257 line.append(title->getString());
258 line.append(1, ' ');
259 }
260 line.append(firstname->getString());
250 line.append(1, ' '); 261 line.append(1, ' ');
262 line.append(lastname->getString());
263// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
251 } 264 }
252 line.append(firstname->getString()); 265// [/RLVa:KB]
253 line.append(1, ' ');
254 line.append(lastname->getString());
255 } 266 }
256 else 267 else
257 { 268 {
@@ -307,6 +318,13 @@ void LLHoverView::updateText()
307 } 318 }
308 else if(gCacheName->getFullName(owner, name)) 319 else if(gCacheName->getFullName(owner, name))
309 { 320 {
321// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
322 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
323 {
324 name = gRlvHandler.getAnonym(name);
325 }
326// [/RLVa:KB]
327
310 line.append(name); 328 line.append(name);
311 } 329 }
312 else 330 else
@@ -468,7 +486,10 @@ void LLHoverView::updateText()
468 line.append(LLTrans::getString("TooltipLand")); 486 line.append(LLTrans::getString("TooltipLand"));
469 if (hover_parcel) 487 if (hover_parcel)
470 { 488 {
471 line.append(hover_parcel->getName()); 489// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-0.2.0b
490 line.append( (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? hover_parcel->getName() : rlv_handler_t::cstrHiddenParcel );
491// [/RLVa:KB]
492 //line.append(hover_parcel->getName());
472 } 493 }
473 mText.push_back(line); 494 mText.push_back(line);
474 495
@@ -497,7 +518,10 @@ void LLHoverView::updateText()
497 } 518 }
498 else if(gCacheName->getFullName(owner, name)) 519 else if(gCacheName->getFullName(owner, name))
499 { 520 {
500 line.append(name); 521// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b
522 line.append( (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? name : gRlvHandler.getAnonym(name));
523// [/RLVa:KB]
524 //line.append(name);
501 } 525 }
502 else 526 else
503 { 527 {
diff --git a/linden/indra/newview/llhudtext.cpp b/linden/indra/newview/llhudtext.cpp
index 32323dc..ac48c6b 100644
--- a/linden/indra/newview/llhudtext.cpp
+++ b/linden/indra/newview/llhudtext.cpp
@@ -565,6 +565,30 @@ void LLHUDText::renderText(BOOL for_select)
565 565
566void LLHUDText::setStringUTF8(const std::string &wtext) 566void LLHUDText::setStringUTF8(const std::string &wtext)
567{ 567{
568// [RLVa:KB] - Checked: 2009-07-09 (RLVa-1.0.0f)
569 // NOTE: setString() is only called for debug beacons and the floating name tags (which we don't want to censor
570 // because you'd see "(Region hidden) LastName" if you happen to go to a sim who's name is your first name :p
571 if (rlv_handler_t::isEnabled())
572 {
573 std::string text(wtext);
574
575 if (gRlvHandler.canShowHoverText(mSourceObject))
576 {
577 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
578 gRlvHandler.filterLocation(text);
579 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
580 gRlvHandler.filterNames(text);
581 }
582 else
583 {
584 text = "";
585 }
586
587 setString(utf8str_to_wstring(text));
588 return;
589 }
590// [/RLVa:KB]
591
568 setString(utf8str_to_wstring(wtext)); 592 setString(utf8str_to_wstring(wtext));
569} 593}
570 594
@@ -1147,3 +1171,18 @@ F32 LLHUDText::LLHUDTextSegment::getWidth(const LLFontGL* font)
1147 return width; 1171 return width;
1148 } 1172 }
1149} 1173}
1174
1175// [RLVa:KB] - Checked: 2009-07-09 (RLVa-1.0.0f) | Added: RLVa-1.0.0f
1176void LLHUDText::refreshAllObjectText()
1177{
1178 for (TextObjectIterator itText = sTextObjects.begin(); itText != sTextObjects.end(); itText++)
1179 {
1180 LLHUDText* pText = *itText;
1181 if ( (pText) && (!pText->mObjText.empty() && ("" != pText->mObjText) ) &&
1182 (pText->mSourceObject) && (LL_PCODE_VOLUME == pText->mSourceObject->getPCode()) )
1183 {
1184 pText->setStringUTF8(pText->mObjText);
1185 }
1186 }
1187}
1188// [/RLVa:KB]
diff --git a/linden/indra/newview/llhudtext.h b/linden/indra/newview/llhudtext.h
index 6e29d9d..c68a975 100644
--- a/linden/indra/newview/llhudtext.h
+++ b/linden/indra/newview/llhudtext.h
@@ -130,6 +130,11 @@ public:
130 static void addPickable(std::set<LLViewerObject*> &pick_list); 130 static void addPickable(std::set<LLViewerObject*> &pick_list);
131 static void reshape(); 131 static void reshape();
132 static void setDisplayText(BOOL flag) { sDisplayText = flag ; } 132 static void setDisplayText(BOOL flag) { sDisplayText = flag ; }
133// [RLVa:KB] - Checked: 2009-07-09 (RLVa-1.0.0f) | Added: RLVa-1.0.0f
134 const std::string& getObjectText() const { return mObjText; }
135 void setObjectText(const std::string &utf8string) { mObjText = utf8string; }
136 static void refreshAllObjectText();
137// [/RLVa:KB]
133protected: 138protected:
134 LLHUDText(const U8 type); 139 LLHUDText(const U8 type);
135 140
@@ -175,6 +180,9 @@ private:
175 EVertAlignment mVertAlignment; 180 EVertAlignment mVertAlignment;
176 S32 mLOD; 181 S32 mLOD;
177 BOOL mHidden; 182 BOOL mHidden;
183// [RLVa:KB] - Checked: 2009-07-09 (RLVa-1.0.0f) | Added: RLVa-1.0.0f
184 std::string mObjText;
185// [/RLVa:KB]
178 186
179 static BOOL sDisplayText ; 187 static BOOL sDisplayText ;
180 static std::set<LLPointer<LLHUDText> > sTextObjects; 188 static std::set<LLPointer<LLHUDText> > sTextObjects;
diff --git a/linden/indra/newview/llimpanel.cpp b/linden/indra/newview/llimpanel.cpp
index f30ae8c..7e4ed19 100644
--- a/linden/indra/newview/llimpanel.cpp
+++ b/linden/indra/newview/llimpanel.cpp
@@ -2009,6 +2009,42 @@ void LLFloaterIMPanel::sendMsg()
2009 std::string utf8_text = wstring_to_utf8str(text); 2009 std::string utf8_text = wstring_to_utf8str(text);
2010 utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); 2010 utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1);
2011 2011
2012// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-1.0.0g
2013 if (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIM))
2014 {
2015 if (IM_NOTHING_SPECIAL == mDialog) // One-on-one IM: allow if recipient is a sendim exception
2016 {
2017 if (!gRlvHandler.isException(RLV_BHVR_SENDIM, mOtherParticipantUUID))
2018 utf8_text = rlv_handler_t::cstrBlockedSendIM;
2019 }
2020 else if (gAgent.isInGroup(mSessionUUID)) // Group chat: allow if recipient is a sendim exception
2021 {
2022 if (!gRlvHandler.isException(RLV_BHVR_SENDIM, mSessionUUID))
2023 utf8_text = rlv_handler_t::cstrBlockedSendIM;
2024 }
2025 else if (mSpeakers) // Conference chat: allow if all participants are sendim exceptions
2026 {
2027 LLSpeakerMgr::speaker_list_t speakers;
2028 mSpeakers->getSpeakerList(&speakers, TRUE);
2029
2030 for (LLSpeakerMgr::speaker_list_t::const_iterator itSpeaker = speakers.begin();
2031 itSpeaker != speakers.end(); ++itSpeaker)
2032 {
2033 LLSpeaker* pSpeaker = *itSpeaker;
2034 if ( (gAgent.getID() != pSpeaker->mID) && (!gRlvHandler.isException(RLV_BHVR_SENDIM, pSpeaker->mID)) )
2035 {
2036 utf8_text = rlv_handler_t::cstrBlockedSendIM;
2037 break;
2038 }
2039 }
2040 }
2041 else // Catch all fall-through
2042 {
2043 utf8_text = rlv_handler_t::cstrBlockedSendIM;
2044 }
2045 }
2046// [/RLVa:KB]
2047
2012 if ( mSessionInitialized ) 2048 if ( mSessionInitialized )
2013 { 2049 {
2014 deliver_message(utf8_text, 2050 deliver_message(utf8_text,
diff --git a/linden/indra/newview/llimview.cpp b/linden/indra/newview/llimview.cpp
index 1072b21..20de43e 100644
--- a/linden/indra/newview/llimview.cpp
+++ b/linden/indra/newview/llimview.cpp
@@ -1550,6 +1550,19 @@ public:
1550 { 1550 {
1551 return; 1551 return;
1552 } 1552 }
1553// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
1554 // TODO-RLVa: duplicate from process_improved_im()?
1555 if (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM))
1556 {
1557 if (gAgent.isInGroup(session_id))
1558 {
1559 if (!gRlvHandler.isException(RLV_BHVR_RECVIM, session_id))
1560 return;
1561 }
1562 else if (!gRlvHandler.isException(RLV_BHVR_RECVIM, from_id))
1563 message = message.substr(0, message_offset) + rlv_handler_t::cstrBlockedRecvIM;
1564 }
1565// [/RLVa:KB]
1553 1566
1554 // standard message, not from system 1567 // standard message, not from system
1555 std::string saved; 1568 std::string saved;
diff --git a/linden/indra/newview/llinventorybridge.cpp b/linden/indra/newview/llinventorybridge.cpp
index 52b15cb..dc1e0a1 100644
--- a/linden/indra/newview/llinventorybridge.cpp
+++ b/linden/indra/newview/llinventorybridge.cpp
@@ -1921,6 +1921,12 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
1921 LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); 1921 LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
1922 LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); 1922 LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
1923 1923
1924// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
1925 // Fixes LL bug
1926 mItems.clear();
1927 mDisabledItems.clear();
1928// [/RLVa:KB]
1929
1924 if (lost_and_found_id == mUUID) 1930 if (lost_and_found_id == mUUID)
1925 { 1931 {
1926 // This is the lost+found folder. 1932 // This is the lost+found folder.
@@ -2934,6 +2940,13 @@ void open_notecard(LLViewerInventoryItem* inv_item,
2934 const LLUUID& source_id, 2940 const LLUUID& source_id,
2935 BOOL take_focus) 2941 BOOL take_focus)
2936{ 2942{
2943// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
2944 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour("viewnote")) )
2945 {
2946 return;
2947 }
2948// [/RLVa:KB]
2949
2937 // See if we can bring an existing preview to the front 2950 // See if we can bring an existing preview to the front
2938 if(!LLPreview::show(inv_item->getUUID(), take_focus)) 2951 if(!LLPreview::show(inv_item->getUUID(), take_focus))
2939 { 2952 {
@@ -3259,7 +3272,14 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model
3259 item = (LLViewerInventoryItem*)gInventory.getItem(object_id); 3272 item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
3260 if(item && gInventory.isObjectDescendentOf(object_id, gAgent.getInventoryRootID())) 3273 if(item && gInventory.isObjectDescendentOf(object_id, gAgent.getInventoryRootID()))
3261 { 3274 {
3262 rez_attachment(item, NULL); 3275// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
3276 // User picked "Wear" so either nothing is locked, or we need to look up the specific attach point from its name
3277 // (NOTE: rez_attachment will take care of deciding whether or not we *can* attach)
3278 rez_attachment(item,
3279 ((!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedAttachment()) || (RlvSettings::getEnableWear()))
3280 ? NULL : gRlvHandler.getAttachPoint(item, true));
3281// [/RLVa:KB]
3282// rez_attachment(item, NULL);
3263 } 3283 }
3264 else if(item && item->isComplete()) 3284 else if(item && item->isComplete())
3265 { 3285 {
@@ -3278,6 +3298,15 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model
3278 else if ("detach" == action) 3298 else if ("detach" == action)
3279 { 3299 {
3280 LLInventoryItem* item = gInventory.getItem(mUUID); 3300 LLInventoryItem* item = gInventory.getItem(mUUID);
3301
3302// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
3303 // Fall-through: if there's a "Detach from yourself" code path we missed then we'll still disallow the detach here
3304 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(item)) )
3305 {
3306 return;
3307 }
3308// [/RLVa:KB]
3309
3281 if( item ) 3310 if( item )
3282 { 3311 {
3283 gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); 3312 gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
@@ -3367,11 +3396,24 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach
3367 rez_action->mAttachPt = attach_pt; 3396 rez_action->mAttachPt = attach_pt;
3368 if (attachment && attachment->getObject()) 3397 if (attachment && attachment->getObject())
3369 { 3398 {
3370 gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action); 3399// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c)
3400 if ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isDetachable(attach_pt)) )
3401 gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action);
3402 else
3403 delete rez_action;
3404// [/RLVa]
3405// gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action);
3371 } 3406 }
3372 else 3407 else
3373 { 3408 {
3374 confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action); 3409// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c)
3410 // Don't allow wear to default attach point if there are any locked attachments
3411 if ( (!rlv_handler_t::isEnabled()) || (0 != attach_pt) || (!gRlvHandler.hasLockedAttachment()) || (RlvSettings::getEnableWear()) )
3412 confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action);
3413 else
3414 delete rez_action;
3415// [/RLVa]
3416// confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action);
3375 } 3417 }
3376} 3418}
3377 3419
@@ -3440,6 +3482,11 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
3440 if( avatarp->isWearingAttachment( mUUID ) ) 3482 if( avatarp->isWearingAttachment( mUUID ) )
3441 { 3483 {
3442 items.push_back(std::string("Detach From Yourself")); 3484 items.push_back(std::string("Detach From Yourself"));
3485
3486// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
3487 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(item)) )
3488 disabled_items.push_back(std::string("Detach From Yourself"));
3489// [/RLVa:KB]
3443 } 3490 }
3444 else 3491 else
3445 if( !isInTrash() ) 3492 if( !isInTrash() )
@@ -3451,6 +3498,16 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
3451 items.push_back(std::string("RestoreToWorld Separator")); 3498 items.push_back(std::string("RestoreToWorld Separator"));
3452 items.push_back(std::string("Restore to Last Position")); 3499 items.push_back(std::string("Restore to Last Position"));
3453 3500
3501// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0c
3502 // Only enable "Wear" if there is an attach point name *and* there isn't a worn attachment there that's currently locked
3503 if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getEnableWear()) && (gRlvHandler.hasLockedAttachment()) )
3504 {
3505 LLViewerJointAttachment* pAttachPt = gRlvHandler.getAttachPoint(item, true);
3506 if ( (!pAttachPt) || (!gRlvHandler.isDetachable(pAttachPt->getObject())) )
3507 disabled_items.push_back(std::string("Object Wear"));
3508 }
3509// [/RLVa:KB]
3510
3454 LLMenuGL* attach_menu = menu.getChildMenuByName("Attach To", TRUE); 3511 LLMenuGL* attach_menu = menu.getChildMenuByName("Attach To", TRUE);
3455 LLMenuGL* attach_hud_menu = menu.getChildMenuByName("Attach To HUD", TRUE); 3512 LLMenuGL* attach_hud_menu = menu.getChildMenuByName("Attach To HUD", TRUE);
3456 LLVOAvatar *avatarp = gAgent.getAvatarObject(); 3513 LLVOAvatar *avatarp = gAgent.getAvatarObject();
@@ -3466,15 +3523,27 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
3466 LLMenuItemCallGL *new_item; 3523 LLMenuItemCallGL *new_item;
3467 if (attachment->getIsHUDAttachment()) 3524 if (attachment->getIsHUDAttachment())
3468 { 3525 {
3526// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
3469 attach_hud_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(), 3527 attach_hud_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(),
3470 NULL, //&LLObjectBridge::attachToAvatar, 3528 NULL, //&LLObjectBridge::attachToAvatar,
3471 NULL, &attach_label, (void*)attachment)); 3529 (rlv_handler_t::isEnabled()) ? &rlvAttachToEnabler : NULL,
3530 &attach_label, (void*)attachment));
3531// [/RLVa:KB]
3532 //attach_hud_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(),
3533 // NULL, //&LLObjectBridge::attachToAvatar,
3534 // NULL, &attach_label, (void*)attachment));
3472 } 3535 }
3473 else 3536 else
3474 { 3537 {
3538// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
3475 attach_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(), 3539 attach_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(),
3476 NULL, //&LLObjectBridge::attachToAvatar, 3540 NULL, //&LLObjectBridge::attachToAvatar,
3477 NULL, &attach_label, (void*)attachment)); 3541 (rlv_handler_t::isEnabled()) ? &rlvAttachToEnabler : NULL,
3542 &attach_label, (void*)attachment));
3543// [/RLVa:KB]
3544 //attach_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(),
3545 // NULL, //&LLObjectBridge::attachToAvatar,
3546 // NULL, &attach_label, (void*)attachment));
3478 } 3547 }
3479 3548
3480 LLSimpleListener* callback = mInventoryPanel->getListenerByName("Inventory.AttachObject"); 3549 LLSimpleListener* callback = mInventoryPanel->getListenerByName("Inventory.AttachObject");
@@ -3954,6 +4023,20 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata )
3954 is_gesture); 4023 is_gesture);
3955 S32 gest_count = gest_item_array.count(); 4024 S32 gest_count = gest_item_array.count();
3956 4025
4026// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-1.0.0c
4027 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) && (!RlvSettings::getEnableWear()) )
4028 {
4029 // Filter anything that doesn't specify an attachment point (or that specifies one that's currently locked)
4030 for (S32 idxObj = obj_item_array.count() - 1; idxObj >= 0; idxObj--)
4031 {
4032 LLViewerJointAttachment* pAttachPt = gRlvHandler.getAttachPoint(obj_item_array.get(idxObj).get(), true);
4033 if ( ((!pAttachPt) || (!gRlvHandler.isDetachable(pAttachPt->getObject()))) )
4034 obj_item_array.remove(idxObj);
4035 }
4036 obj_count = obj_item_array.count();
4037 }
4038// [/RLVa:KB]
4039
3957 if( !wearable_count && !obj_count && !gest_count) 4040 if( !wearable_count && !obj_count && !gest_count)
3958 { 4041 {
3959 gViewerWindow->alertXml("CouldNotPutOnOutfit"); 4042 gViewerWindow->alertXml("CouldNotPutOnOutfit");
@@ -4058,14 +4141,24 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata )
4058 msg->nextBlockFast(_PREHASH_HeaderData); 4141 msg->nextBlockFast(_PREHASH_HeaderData);
4059 msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id ); 4142 msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id );
4060 msg->addU8Fast(_PREHASH_TotalObjects, obj_count ); 4143 msg->addU8Fast(_PREHASH_TotalObjects, obj_count );
4061 msg->addBOOLFast(_PREHASH_FirstDetachAll, !wear_info->mAppend ); 4144// msg->addBOOLFast(_PREHASH_FirstDetachAll, !wear_info->mAppend );
4145// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.2a
4146 // This really should just *always* be FALSE since TRUE can result in loss of the current asset state
4147 msg->addBOOLFast(_PREHASH_FirstDetachAll, (!wear_info->mAppend) && (!gRlvHandler.hasLockedAttachment()) );
4148// [/RLVa:KB]
4062 } 4149 }
4063 4150
4064 LLInventoryItem* item = obj_item_array.get(i); 4151 LLInventoryItem* item = obj_item_array.get(i);
4065 msg->nextBlockFast(_PREHASH_ObjectData ); 4152 msg->nextBlockFast(_PREHASH_ObjectData );
4066 msg->addUUIDFast(_PREHASH_ItemID, item->getUUID() ); 4153 msg->addUUIDFast(_PREHASH_ItemID, item->getUUID() );
4067 msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); 4154 msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner());
4068 msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // Wear at the previous or default attachment point 4155// msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // Wear at the previous or default attachment point
4156// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.2a
4157 msg->addU8Fast(_PREHASH_AttachmentPt,
4158 ( (!rlv_handler_t::isEnabled()) || (RlvSettings::getEnableWear()) || (!gRlvHandler.hasLockedAttachment()) )
4159 ? 0
4160 : gRlvHandler.getAttachPointIndex(gRlvHandler.getAttachPoint(item, true)));
4161// [/RLVa:KB]
4069 pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); 4162 pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
4070 msg->addStringFast(_PREHASH_Name, item->getName()); 4163 msg->addStringFast(_PREHASH_Name, item->getName());
4071 msg->addStringFast(_PREHASH_Description, item->getDescription()); 4164 msg->addStringFast(_PREHASH_Description, item->getDescription());
@@ -4141,6 +4234,13 @@ void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, B
4141// item->setAssetUUID(wearable->getID()); 4234// item->setAssetUUID(wearable->getID());
4142// item->updateAssetOnServer(); 4235// item->updateAssetOnServer();
4143// } 4236// }
4237// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-1.0.0c
4238 if ( (!gRlvHandler.isWearable(wearable->getType())) ||
4239 ( (!gRlvHandler.isRemovable(wearable->getType())) && (gAgent.getWearable(wearable->getType())) ) )
4240 {
4241 continue;
4242 }
4243// [/RLVa:KB]
4144 items.put(item); 4244 items.put(item);
4145 wearables.put(wearable); 4245 wearables.put(wearable);
4146 } 4246 }
@@ -4229,7 +4329,11 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata)
4229 { 4329 {
4230 for(i = 0; i < wearable_count; ++i) 4330 for(i = 0; i < wearable_count; ++i)
4231 { 4331 {
4232 if( gAgent.isWearingItem (item_array.get(i)->getUUID()) ) 4332// if( gAgent.isWearingItem (item_array.get(i)->getUUID()) )
4333// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.2a
4334 LLWearable* pWearable = gAgent.getWearableFromWearableItem(item_array.get(i)->getUUID());
4335 if ( (pWearable) && ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isRemovable(pWearable->getType()))) )
4336// [/RLVa:KB]
4233 { 4337 {
4234 gWearableList.getAsset(item_array.get(i)->getAssetUUID(), 4338 gWearableList.getAsset(item_array.get(i)->getAssetUUID(),
4235 item_array.get(i)->getName(), 4339 item_array.get(i)->getName(),
@@ -4246,6 +4350,18 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata)
4246 { 4350 {
4247 for(i = 0; i < obj_count; ++i) 4351 for(i = 0; i < obj_count; ++i)
4248 { 4352 {
4353// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.2a
4354 // TODO-RLVa: is there a reason why LL doesn't bother checking to see if you're actually wearing the object?
4355 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) )
4356 {
4357 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
4358 if ( (!pAvatar) || (!pAvatar->isWearingAttachment(obj_item_array.get(i)->getUUID())) ||
4359 (!gRlvHandler.isDetachable(obj_item_array.get(i).get())) ) // Why does LLPointer have a cast to BOOL aka S32???
4360 {
4361 continue;
4362 }
4363 }
4364// [/RVLa:KB]
4249 gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); 4365 gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
4250 gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); 4366 gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
4251 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); 4367 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
@@ -4638,8 +4754,11 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
4638 { 4754 {
4639 EWearableType type = wearable->getType(); 4755 EWearableType type = wearable->getType();
4640 4756
4641 if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR ) ) //&& 4757 //if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR ) ) //&&
4642 //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) ) 4758 //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) )
4759// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.2a | SL big fix
4760 if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES) )
4761// [/RLVa:KB]
4643 { 4762 {
4644 gAgent.removeWearable( type ); 4763 gAgent.removeWearable( type );
4645 } 4764 }
diff --git a/linden/indra/newview/llinventorymodel.cpp b/linden/indra/newview/llinventorymodel.cpp
index 1029a3c..e662058 100644
--- a/linden/indra/newview/llinventorymodel.cpp
+++ b/linden/indra/newview/llinventorymodel.cpp
@@ -2876,6 +2876,14 @@ void LLInventoryModel::processSaveAssetIntoInventory(LLMessageSystem* msg,
2876 llinfos << "LLInventoryModel::processSaveAssetIntoInventory item" 2876 llinfos << "LLInventoryModel::processSaveAssetIntoInventory item"
2877 " not found: " << item_id << llendl; 2877 " not found: " << item_id << llendl;
2878 } 2878 }
2879
2880// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0e
2881 if (rlv_handler_t::isEnabled())
2882 {
2883 gRlvHandler.onSavedAssetIntoInventory(item_id);
2884 }
2885// [/RLVa:KB]
2886
2879 if(gViewerWindow) 2887 if(gViewerWindow)
2880 { 2888 {
2881 gViewerWindow->getWindow()->decBusyCount(); 2889 gViewerWindow->getWindow()->decBusyCount();
@@ -2918,6 +2926,23 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
2918 // << llendl; 2926 // << llendl;
2919 if(tfolder->getUUID().notNull()) 2927 if(tfolder->getUUID().notNull())
2920 { 2928 {
2929// [RLVa:KB] - Checked: 2009-08-07 (RLVa-1.0.1f) | Added: RLVa-1.0.0f
2930 // TODO-RLVa: this really shouldn't go here, but if the inventory offer spans multiple BulkUpdateInventory messages
2931 // then the second message will cause the viewer to show the folder under its original name even though
2932 // it is renamed properly on the inventory server
2933 if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getForbidGiveToRLV()) )
2934 {
2935 LLViewerInventoryCategory* pRlvRoot = gRlvHandler.getSharedRoot();
2936 std::string strName = tfolder->getName();
2937 if ((pRlvRoot) && (pRlvRoot->getUUID() == tfolder->getParentUUID() ) && (strName.find(RLV_PUTINV_PREFIX) == 0))
2938 {
2939 strName.erase(0, strName.find(RLV_FOLDER_PREFIX_PUTINV)); // Strips the prefix while retaining while the '~'
2940 tfolder->rename(strName);
2941 tfolder->updateServer(FALSE);
2942 }
2943 }
2944// [/RLVa:KB]
2945
2921 folders.push_back(tfolder); 2946 folders.push_back(tfolder);
2922 LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID()); 2947 LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID());
2923 if(folderp) 2948 if(folderp)
diff --git a/linden/indra/newview/llinventoryview.cpp b/linden/indra/newview/llinventoryview.cpp
index 0f1eb2b..8e8e894 100644
--- a/linden/indra/newview/llinventoryview.cpp
+++ b/linden/indra/newview/llinventoryview.cpp
@@ -765,7 +765,17 @@ void LLInventoryView::setVisible( BOOL visible )
765// Destroy all but the last floater, which is made invisible. 765// Destroy all but the last floater, which is made invisible.
766void LLInventoryView::onClose(bool app_quitting) 766void LLInventoryView::onClose(bool app_quitting)
767{ 767{
768 S32 count = sActiveViews.count(); 768// S32 count = sActiveViews.count();
769// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
770 // See LLInventoryView::closeAll() on why we're doing it this way
771 S32 count = 0;
772 for (S32 idx = 0, cnt = sActiveViews.count(); idx < cnt; idx++)
773 {
774 if (!sActiveViews.get(idx)->isDead())
775 count++;
776 }
777// [/RLVa:KB]
778
769 if (count > 1) 779 if (count > 1)
770 { 780 {
771 destroy(); 781 destroy();
@@ -843,6 +853,13 @@ LLInventoryView* LLInventoryView::showAgentInventory(BOOL take_keyboard_focus)
843 return NULL; 853 return NULL;
844 } 854 }
845 855
856// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
857 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWINV))
858 {
859 return NULL;
860 }
861// [/RLVa:KB]
862
846 LLInventoryView* iv = LLInventoryView::getActiveInventory(); 863 LLInventoryView* iv = LLInventoryView::getActiveInventory();
847#if 0 && !LL_RELEASE_FOR_DOWNLOAD 864#if 0 && !LL_RELEASE_FOR_DOWNLOAD
848 if (sActiveViews.count() == 1) 865 if (sActiveViews.count() == 1)
diff --git a/linden/indra/newview/llinventoryview.h b/linden/indra/newview/llinventoryview.h
index bdc24e0..1762165 100644
--- a/linden/indra/newview/llinventoryview.h
+++ b/linden/indra/newview/llinventoryview.h
@@ -225,6 +225,34 @@ public:
225 static void toggleVisibility(); 225 static void toggleVisibility();
226 static void toggleVisibility(void*) { toggleVisibility(); } 226 static void toggleVisibility(void*) { toggleVisibility(); }
227 227
228// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
229 static void closeAll()
230 {
231 // If there are mulitple inventory floaters open then clicking the "Inventory" button will close
232 // them one by one (see LLToolBar::onClickInventory() => toggleVisibility() ) until we get to the
233 // last one which will just be hidden instead of closed/destroyed (see LLInventoryView::onClose)
234 //
235 // However the view isn't removed from sActiveViews until its destructor is called and since
236 // 'LLMortician::sDestroyImmediate == FALSE' while the viewer is running the destructor won't be
237 // called right away
238 //
239 // Result: we can't call close() on the last (sActiveViews.count() will still be > 1) because
240 // onClose() would take the wrong branch and destroy() it as well
241 //
242 // Workaround: "fix" onClose() to count only views that aren't marked as "dead"
243
244 LLInventoryView* pView; U8 flagsSound;
245 for (S32 idx = sActiveViews.count() - 1; idx >= 0; idx--)
246 {
247 pView = sActiveViews.get(idx);
248 flagsSound = pView->getSoundFlags();
249 pView->setSoundFlags(LLView::SILENT); // Suppress the window close sound
250 pView->close(); // onClose() protects against closing the last inventory floater
251 pView->setSoundFlags(flagsSound); // One view won't be destroy()'ed so it needs its sound flags restored
252 }
253 }
254// [/RLVa:KB]
255
228 // Final cleanup, destroy all open inventory views. 256 // Final cleanup, destroy all open inventory views.
229 static void cleanup(); 257 static void cleanup();
230 258
diff --git a/linden/indra/newview/llmaniptranslate.cpp b/linden/indra/newview/llmaniptranslate.cpp
index fd02be6..fa66b05 100644
--- a/linden/indra/newview/llmaniptranslate.cpp
+++ b/linden/indra/newview/llmaniptranslate.cpp
@@ -463,8 +463,15 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
463 if (mask == MASK_COPY) 463 if (mask == MASK_COPY)
464 { 464 {
465 // ...we're trying to make a copy 465 // ...we're trying to make a copy
466 LLSelectMgr::getInstance()->selectDuplicate(LLVector3::zero, FALSE); 466// LLSelectMgr::getInstance()->selectDuplicate(LLVector3::zero, FALSE);
467 mCopyMadeThisDrag = TRUE; 467// mCopyMadeThisDrag = TRUE;
468// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
469 if (!gRlvHandler.hasBehaviour(RLV_BHVR_REZ))
470 {
471 LLSelectMgr::getInstance()->selectDuplicate(LLVector3::zero, FALSE);
472 mCopyMadeThisDrag = TRUE;
473 }
474// [/RLVa:KB]
468 475
469 // When we make the copy, we don't want to do any other processing. 476 // When we make the copy, we don't want to do any other processing.
470 // If so, the object will also be moved, and the copy will be offset. 477 // If so, the object will also be moved, and the copy will be offset.
diff --git a/linden/indra/newview/llnetmap.cpp b/linden/indra/newview/llnetmap.cpp
index 6fa6745..8f5d90d 100644
--- a/linden/indra/newview/llnetmap.cpp
+++ b/linden/indra/newview/llnetmap.cpp
@@ -355,6 +355,16 @@ void LLNetMap::draw()
355 glyph_color = avatar_color; 355 glyph_color = avatar_color;
356 } 356 }
357 357
358// [RLVa:KB]
359 if ( !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) )
360 {
361 // User is not allowed to see who it is, or even if it's a friend,
362 // due to RLV settings.
363 glyph_color = avatar_color;
364 }
365// [/RLVa:KB]
366
367
358 LLWorldMapView::drawAvatar( 368 LLWorldMapView::drawAvatar(
359 pos_map.mV[VX], pos_map.mV[VY], 369 pos_map.mV[VX], pos_map.mV[VY],
360 glyph_color, 370 glyph_color,
@@ -551,11 +561,33 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rec
551 std::string fullname; 561 std::string fullname;
552 if(mClosestAgentToCursor.notNull() && gCacheName->getFullName(mClosestAgentToCursor, fullname)) 562 if(mClosestAgentToCursor.notNull() && gCacheName->getFullName(mClosestAgentToCursor, fullname))
553 { 563 {
554 msg.append(fullname); 564// [RLVa:KB]
555 msg.append("\n"); 565 if ( !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) )
566 {
567 // User is not allowed to see who it is, due to RLV settings.
568 msg.append(rlv_handler_t::cstrHidden);
569 }
570 else
571 {
572 msg.append(fullname);
573 msg.append("\n");
574 }
575// [/RLVa:KB]
556 } 576 }
557 msg.append( region->getName() );
558 577
578// [RLVa:KB]
579 if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
580 {
581 // User is not allowed to see where they are, due to RLV settings.
582 msg.append( rlv_handler_t::cstrHidden );
583 }
584 else
585 {
586 msg.append( region->getName() );
587 }
588// [/RLVa:KB]
589
590
559 msg.append("\n"); 591 msg.append("\n");
560 gSavedSettings.getBOOL( "MiniMapTeleport" ) ? 592 gSavedSettings.getBOOL( "MiniMapTeleport" ) ?
561 msg.append(getString("tooltip_tp")) : msg.append(getString("tooltip_map")); 593 msg.append(getString("tooltip_tp")) : msg.append(getString("tooltip_map"));
diff --git a/linden/indra/newview/llnotify.cpp b/linden/indra/newview/llnotify.cpp
index 9e837a6..5590ab1 100644
--- a/linden/indra/newview/llnotify.cpp
+++ b/linden/indra/newview/llnotify.cpp
@@ -54,6 +54,10 @@
54#include "lloverlaybar.h" // for gOverlayBar 54#include "lloverlaybar.h" // for gOverlayBar
55#include "lluictrlfactory.h" 55#include "lluictrlfactory.h"
56 56
57// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0e) | Added: RLVa-0.2.0b
58#include "rlvhandler.h"
59// [/RLVa:KB]
60
57// Globals 61// Globals
58LLNotifyBoxView* gNotifyBoxView = NULL; 62LLNotifyBoxView* gNotifyBoxView = NULL;
59 63
@@ -328,6 +332,13 @@ LLNotifyBox::LLNotifyBox(LLPointer<LLNotifyBoxTemplate> xml_template, const LLSt
328 // TODO: Make a separate archive for these. 332 // TODO: Make a separate archive for these.
329 LLChat chat(mMessage); 333 LLChat chat(mMessage);
330 chat.mSourceType = CHAT_SOURCE_SYSTEM; 334 chat.mSourceType = CHAT_SOURCE_SYSTEM;
335// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0e) | Added: RLVa-0.2.0b
336 if (rlv_handler_t::isEnabled())
337 {
338 // Notices should already have their contents filtered where necessary
339 chat.mRlvLocFiltered = chat.mRlvNamesFiltered = TRUE;
340 }
341// [/RLVa:KB]
331 LLFloaterChat::getInstance(LLSD())->addChatHistory(chat); 342 LLFloaterChat::getInstance(LLSD())->addChatHistory(chat);
332 } 343 }
333 else 344 else
diff --git a/linden/indra/newview/lloverlaybar.cpp b/linden/indra/newview/lloverlaybar.cpp
index 91a7375..91ac440 100644
--- a/linden/indra/newview/lloverlaybar.cpp
+++ b/linden/indra/newview/lloverlaybar.cpp
@@ -256,7 +256,10 @@ void LLOverlayBar::refresh()
256 BOOL sitting = FALSE; 256 BOOL sitting = FALSE;
257 if (gAgent.getAvatarObject()) 257 if (gAgent.getAvatarObject())
258 { 258 {
259 sitting = gAgent.getAvatarObject()->mIsSitting; 259// sitting = gAgent.getAvatarObject()->mIsSitting;
260// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
261 sitting = gAgent.getAvatarObject()->mIsSitting && !gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT);
262// [/RLVa:KB]
260 } 263 }
261 button = getChild<LLButton>("Stand Up"); 264 button = getChild<LLButton>("Stand Up");
262 265
@@ -336,6 +339,13 @@ void LLOverlayBar::onClickMouselook(void*)
336//static 339//static
337void LLOverlayBar::onClickStandUp(void*) 340void LLOverlayBar::onClickStandUp(void*)
338{ 341{
342// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
343 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->mIsSitting) )
344 {
345 return;
346 }
347// [/RLVa:KB]
348
339 LLSelectMgr::getInstance()->deselectAllForStandingUp(); 349 LLSelectMgr::getInstance()->deselectAllForStandingUp();
340 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); 350 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
341} 351}
diff --git a/linden/indra/newview/llpanelavatar.cpp b/linden/indra/newview/llpanelavatar.cpp
index d48237f..8c367fa 100644
--- a/linden/indra/newview/llpanelavatar.cpp
+++ b/linden/indra/newview/llpanelavatar.cpp
@@ -789,6 +789,9 @@ void LLPanelAvatarClassified::refresh()
789 S32 tab_count = tabs ? tabs->getTabCount() : 0; 789 S32 tab_count = tabs ? tabs->getTabCount() : 0;
790 790
791 bool allow_new = tab_count < MAX_CLASSIFIEDS; 791 bool allow_new = tab_count < MAX_CLASSIFIEDS;
792// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
793 allow_new &= !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC);
794// [/RLVa:KB]
792 bool allow_delete = (tab_count > 0); 795 bool allow_delete = (tab_count > 0);
793 bool show_help = (tab_count == 0); 796 bool show_help = (tab_count == 0);
794 797
@@ -924,6 +927,12 @@ void LLPanelAvatarClassified::processAvatarClassifiedReply(LLMessageSystem* msg,
924// static 927// static
925void LLPanelAvatarClassified::onClickNew(void* data) 928void LLPanelAvatarClassified::onClickNew(void* data)
926{ 929{
930// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-04 (RLVa-1.0.0a)
931 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
932 {
933 return;
934 }
935// [/RLVa:KB]
927 LLPanelAvatarClassified* self = (LLPanelAvatarClassified*)data; 936 LLPanelAvatarClassified* self = (LLPanelAvatarClassified*)data;
928 937
929 gViewerWindow->alertXml("AddClassified",callbackNew,self); 938 gViewerWindow->alertXml("AddClassified",callbackNew,self);
@@ -1020,7 +1029,10 @@ void LLPanelAvatarPicks::refresh()
1020 BOOL self = (gAgent.getID() == getPanelAvatar()->getAvatarID()); 1029 BOOL self = (gAgent.getID() == getPanelAvatar()->getAvatarID());
1021 LLTabContainer* tabs = getChild<LLTabContainer>("picks tab"); 1030 LLTabContainer* tabs = getChild<LLTabContainer>("picks tab");
1022 S32 tab_count = tabs ? tabs->getTabCount() : 0; 1031 S32 tab_count = tabs ? tabs->getTabCount() : 0;
1023 childSetEnabled("New...", self && tab_count < MAX_AVATAR_PICKS); 1032// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
1033 childSetEnabled("New...", self && tab_count < MAX_AVATAR_PICKS && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) );
1034// [/RLVa:KB]
1035 //childSetEnabled("New...", self && tab_count < MAX_AVATAR_PICKS);
1024 childSetEnabled("Delete...", self && tab_count > 0); 1036 childSetEnabled("Delete...", self && tab_count > 0);
1025 childSetVisible("New...", self && getPanelAvatar()->isEditable()); 1037 childSetVisible("New...", self && getPanelAvatar()->isEditable());
1026 childSetVisible("Delete...", self && getPanelAvatar()->isEditable()); 1038 childSetVisible("Delete...", self && getPanelAvatar()->isEditable());
@@ -1098,6 +1110,12 @@ void LLPanelAvatarPicks::processAvatarPicksReply(LLMessageSystem* msg, void**)
1098// static 1110// static
1099void LLPanelAvatarPicks::onClickNew(void* data) 1111void LLPanelAvatarPicks::onClickNew(void* data)
1100{ 1112{
1113// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
1114 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
1115 {
1116 return;
1117 }
1118// [/RLVa:KB]
1101 LLPanelAvatarPicks* self = (LLPanelAvatarPicks*)data; 1119 LLPanelAvatarPicks* self = (LLPanelAvatarPicks*)data;
1102 LLPanelPick* panel_pick = new LLPanelPick(FALSE); 1120 LLPanelPick* panel_pick = new LLPanelPick(FALSE);
1103 LLTabContainer* tabs = self->getChild<LLTabContainer>("picks tab"); 1121 LLTabContainer* tabs = self->getChild<LLTabContainer>("picks tab");
diff --git a/linden/indra/newview/llpanelclassified.cpp b/linden/indra/newview/llpanelclassified.cpp
index 4d28be5..3760815 100644
--- a/linden/indra/newview/llpanelclassified.cpp
+++ b/linden/indra/newview/llpanelclassified.cpp
@@ -760,7 +760,10 @@ void LLPanelClassified::refresh()
760 mClickThroughText->setVisible(is_self); 760 mClickThroughText->setVisible(is_self);
761 761
762 mSetBtn->setVisible(is_self); 762 mSetBtn->setVisible(is_self);
763 mSetBtn->setEnabled(is_self); 763 //mSetBtn->setEnabled(is_self);
764// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
765 mSetBtn->setEnabled(is_self && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) );
766// [/RLVa:KB]
764 767
765 mUpdateBtn->setEnabled(is_self && checkDirty()); 768 mUpdateBtn->setEnabled(is_self && checkDirty());
766 mUpdateBtn->setVisible(is_self); 769 mUpdateBtn->setVisible(is_self);
@@ -964,6 +967,12 @@ void LLPanelClassified::onClickLandmark(void* data)
964// static 967// static
965void LLPanelClassified::onClickSet(void* data) 968void LLPanelClassified::onClickSet(void* data)
966{ 969{
970// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
971 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
972 {
973 return;
974 }
975// [/RLVa:KB]
967 LLPanelClassified* self = (LLPanelClassified*)data; 976 LLPanelClassified* self = (LLPanelClassified*)data;
968 977
969 // Save location for later. 978 // Save location for later.
diff --git a/linden/indra/newview/llpanelcontents.cpp b/linden/indra/newview/llpanelcontents.cpp
index d91790e..e13ec46 100644
--- a/linden/indra/newview/llpanelcontents.cpp
+++ b/linden/indra/newview/llpanelcontents.cpp
@@ -66,6 +66,10 @@
66#include "lltoolcomp.h" 66#include "lltoolcomp.h"
67#include "llpanelinventory.h" 67#include "llpanelinventory.h"
68 68
69// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
70#include "llvoavatar.h"
71// [/RLVa:KB]
72
69// 73//
70// Imported globals 74// Imported globals
71// 75//
@@ -117,6 +121,24 @@ void LLPanelContents::getState(LLViewerObject *objectp )
117 && ( 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
118 BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ); 122 BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME );
119 123
124// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0g
125 if ( (rlv_handler_t::isEnabled()) && (editable) )
126 {
127 // Don't allow creation of new scripts if it's undetachable
128 editable = gRlvHandler.isDetachable(objectp);
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
131 if ( (editable) && ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP))) )
132 {
133 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
134 // Only check the first (non-)root object because nothing else would result in enabling the button (see below)
135 LLViewerObject* pObj = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(TRUE);
136
137 editable = (pObj) && (pAvatar) && ((!pAvatar->mIsSitting) || (pAvatar->getRoot() != pObj->getRootEdit()));
138 }
139 }
140// [/RLVa:KB]
141
120 // Edit script button - ok if object is editable and there's an 142 // Edit script button - ok if object is editable and there's an
121 // unambiguous destination for the object. 143 // unambiguous destination for the object.
122 if( editable && 144 if( editable &&
@@ -160,6 +182,22 @@ void LLPanelContents::onClickNewScript(void *userdata)
160 LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(children_ok); 182 LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(children_ok);
161 if(object) 183 if(object)
162 { 184 {
185// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
186 if (rlv_handler_t::isEnabled()) // Fallback code [see LLPanelContents::getState()]
187 {
188 if (!gRlvHandler.isDetachable(object))
189 {
190 return; // Disallow creating new scripts in a locked attachment
191 }
192 else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) )
193 {
194 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
195 if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == object->getRootEdit()) )
196 return; // .. or in a linkset the avie is sitting on under @unsit=n/@sittp=n
197 }
198 }
199// [/RLVa:KB]
200
163 LLPermissions perm; 201 LLPermissions perm;
164 perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); 202 perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null);
165 perm.initMasks( 203 perm.initMasks(
diff --git a/linden/indra/newview/llpaneldisplay.cpp b/linden/indra/newview/llpaneldisplay.cpp
index d510775..14e295c 100644
--- a/linden/indra/newview/llpaneldisplay.cpp
+++ b/linden/indra/newview/llpaneldisplay.cpp
@@ -475,7 +475,12 @@ void LLPanelDisplay::refreshEnabledState()
475 } 475 }
476 476
477 // Vertex Shaders 477 // Vertex Shaders
478 mCtrlShaderEnable->setEnabled(LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable")); 478// mCtrlShaderEnable->setEnabled(LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable"));
479// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0a
480 // "Basic Shaders" can't be disabled - but can be enabled - under @setenv=n
481 bool fCtrlShaderEnable = LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable");
482 mCtrlShaderEnable->setEnabled(fCtrlShaderEnable && (!gRlvHandler.hasBehaviour(RLV_BHVR_SETENV) || !mShaderEnable));
483// [/RLVa:KB]
479 484
480 BOOL shaders = mCtrlShaderEnable->get(); 485 BOOL shaders = mCtrlShaderEnable->get();
481 if (shaders) 486 if (shaders)
@@ -490,7 +495,12 @@ void LLPanelDisplay::refreshEnabledState()
490 495
491 // *HACK just checks to see if we can use shaders... 496 // *HACK just checks to see if we can use shaders...
492 // maybe some cards that use shaders, but don't support windlight 497 // maybe some cards that use shaders, but don't support windlight
493 mCtrlWindLight->setEnabled(mCtrlShaderEnable->getEnabled() && shaders); 498// mCtrlWindLight->setEnabled(mCtrlShaderEnable->getEnabled() && shaders);
499// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0a
500 // "Atmospheric Shaders" can't be disabled - but can be enabled - under @setenv=n
501 bool fCtrlWindLightEnable = fCtrlShaderEnable && shaders;
502 mCtrlWindLight->setEnabled(fCtrlWindLightEnable && (!gRlvHandler.hasBehaviour(RLV_BHVR_SETENV) || !mWindLight));
503// [/RLVa:KB]
494 504
495 // turn off sky detail if atmostpherics isn't on 505 // turn off sky detail if atmostpherics isn't on
496 mCtrlSkyFactor->setEnabled(gSavedSettings.getBOOL("WindLightUseAtmosShaders")); 506 mCtrlSkyFactor->setEnabled(gSavedSettings.getBOOL("WindLightUseAtmosShaders"));
diff --git a/linden/indra/newview/llpanelinventory.cpp b/linden/indra/newview/llpanelinventory.cpp
index c53395d..7ab850f 100644
--- a/linden/indra/newview/llpanelinventory.cpp
+++ b/linden/indra/newview/llpanelinventory.cpp
@@ -81,6 +81,10 @@
81#include "llviewerwindow.h" 81#include "llviewerwindow.h"
82#include "llwearable.h" 82#include "llwearable.h"
83 83
84// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
85#include "llvoavatar.h"
86// [/RLVa:KB]
87
84///---------------------------------------------------------------------------- 88///----------------------------------------------------------------------------
85/// Local function declarations, constants, enums, and typedefs 89/// Local function declarations, constants, enums, and typedefs
86///---------------------------------------------------------------------------- 90///----------------------------------------------------------------------------
@@ -364,8 +368,16 @@ void LLTaskInvFVBridge::previewItem()
364 368
365BOOL LLTaskInvFVBridge::isItemRenameable() const 369BOOL LLTaskInvFVBridge::isItemRenameable() const
366{ 370{
367 if(gAgent.isGodlike()) return TRUE; 371// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
368 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); 372 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
373 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(object)) )
374 {
375 return FALSE;
376 }
377// [/RLVa:KB]
378
379 if(gAgent.isGodlike()) return TRUE;
380// LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
369 if(object) 381 if(object)
370 { 382 {
371 LLInventoryItem* item; 383 LLInventoryItem* item;
@@ -382,6 +394,12 @@ BOOL LLTaskInvFVBridge::isItemRenameable() const
382BOOL LLTaskInvFVBridge::renameItem(const std::string& new_name) 394BOOL LLTaskInvFVBridge::renameItem(const std::string& new_name)
383{ 395{
384 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); 396 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
397// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
398 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(object)) )
399 {
400 return TRUE; // Fallback code [see LLTaskInvFVBridge::isItemRenameable()]
401 }
402// [/RLVa:KB]
385 if(object) 403 if(object)
386 { 404 {
387 LLViewerInventoryItem* item = NULL; 405 LLViewerInventoryItem* item = NULL;
@@ -408,12 +426,47 @@ BOOL LLTaskInvFVBridge::isItemMovable()
408 // return TRUE; 426 // return TRUE;
409 //} 427 //}
410 //return FALSE; 428 //return FALSE;
429// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0g
430 if (rlv_handler_t::isEnabled())
431 {
432 LLViewerObject* pObj = gObjectList.findObject(mPanel->getTaskUUID());
433 if (pObj)
434 {
435 if (!gRlvHandler.isDetachable(pObj))
436 {
437 return FALSE;
438 }
439 else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) )
440 {
441 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
442 if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == pObj->getRootEdit()) )
443 return FALSE;
444 }
445 }
446 }
447// [/RLVa:KB]
411 return TRUE; 448 return TRUE;
412} 449}
413 450
414BOOL LLTaskInvFVBridge::isItemRemovable() 451BOOL LLTaskInvFVBridge::isItemRemovable()
415{ 452{
416 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
455 if ( (object) && (rlv_handler_t::isEnabled()) )
456 {
457 if (!gRlvHandler.isDetachable(object))
458 {
459 return FALSE;
460 }
461 else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) )
462 {
463 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
464 if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == object->getRootEdit()) )
465 return FALSE;
466 }
467 }
468// [/RLVa:KB]
469
417 if(object 470 if(object
418 && (object->permModify() || object->permYouOwner())) 471 && (object->permModify() || object->permYouOwner()))
419 { 472 {
@@ -558,6 +611,13 @@ BOOL LLTaskInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
558 const LLPermissions& perm = inv->getPermissions(); 611 const LLPermissions& perm = inv->getPermissions();
559 bool can_copy = gAgent.allowOperation(PERM_COPY, perm, 612 bool can_copy = gAgent.allowOperation(PERM_COPY, perm,
560 GP_OBJECT_MANIPULATE); 613 GP_OBJECT_MANIPULATE);
614// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
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)) )
617 {
618 return FALSE;
619 }
620// [/RLVa:KB]
561 if (object->isAttachment() && !can_copy) 621 if (object->isAttachment() && !can_copy)
562 { 622 {
563 //RN: no copy contents of attachments cannot be dragged out 623 //RN: no copy contents of attachments cannot be dragged out
@@ -675,6 +735,14 @@ void LLTaskInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
675 { 735 {
676 disabled_items.push_back(std::string("Task Open")); 736 disabled_items.push_back(std::string("Task Open"));
677 } 737 }
738// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
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 {
743 disabled_items.push_back(std::string("Task Open"));
744 }
745// [/RLVa:KB]
678 } 746 }
679 items.push_back(std::string("Task Properties")); 747 items.push_back(std::string("Task Properties"));
680 if(isItemRenameable()) 748 if(isItemRenameable())
@@ -1180,12 +1248,20 @@ LLTaskLSLBridge::LLTaskLSLBridge(
1180 1248
1181void LLTaskLSLBridge::openItem() 1249void LLTaskLSLBridge::openItem()
1182{ 1250{
1251// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
1252 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
1253 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(object)) )
1254 {
1255 return;
1256 }
1257// [/RLVa:KB]
1258
1183 llinfos << "LLTaskLSLBridge::openItem() " << mUUID << llendl; 1259 llinfos << "LLTaskLSLBridge::openItem() " << mUUID << llendl;
1184 if(LLLiveLSLEditor::show(mUUID, mPanel->getTaskUUID())) 1260 if(LLLiveLSLEditor::show(mUUID, mPanel->getTaskUUID()))
1185 { 1261 {
1186 return; 1262 return;
1187 } 1263 }
1188 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); 1264// LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
1189 if(!object || object->isInventoryPending()) 1265 if(!object || object->isInventoryPending())
1190 { 1266 {
1191 return; 1267 return;
@@ -1300,6 +1376,12 @@ void LLTaskNotecardBridge::openItem()
1300 { 1376 {
1301 return; 1377 return;
1302 } 1378 }
1379// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
1380 if ( (rlv_handler_t::isEnabled()) && ((gRlvHandler.hasBehaviour("viewnote")) || (!gRlvHandler.isDetachable(object))) )
1381 {
1382 return;
1383 }
1384// [/RLVa:KB]
1303 if(object->permModify() || gAgent.isGodlike()) 1385 if(object->permModify() || gAgent.isGodlike())
1304 { 1386 {
1305 S32 left, top; 1387 S32 left, top;
diff --git a/linden/indra/newview/llpanelland.cpp b/linden/indra/newview/llpanelland.cpp
index b40450c..c0b8e24 100644
--- a/linden/indra/newview/llpanelland.cpp
+++ b/linden/indra/newview/llpanelland.cpp
@@ -230,6 +230,12 @@ void LLPanelLandInfo::refresh()
230//static 230//static
231void LLPanelLandInfo::onClickClaim(void*) 231void LLPanelLandInfo::onClickClaim(void*)
232{ 232{
233// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
234 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
235 {
236 return;
237 }
238// [/RLVa:KB]
233 LLViewerParcelMgr::getInstance()->startBuyLand(); 239 LLViewerParcelMgr::getInstance()->startBuyLand();
234} 240}
235 241
diff --git a/linden/indra/newview/llpanellogin.cpp b/linden/indra/newview/llpanellogin.cpp
index c26f70f..325fcbc 100644
--- a/linden/indra/newview/llpanellogin.cpp
+++ b/linden/indra/newview/llpanellogin.cpp
@@ -74,6 +74,10 @@
74 74
75#include "llglheaders.h" 75#include "llglheaders.h"
76 76
77// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e)
78#include "rlvhandler.h"
79// [/RLVa:KB]
80
77#define USE_VIEWER_AUTH 0 81#define USE_VIEWER_AUTH 0
78 82
79std::string load_password_from_disk(void); 83std::string load_password_from_disk(void);
@@ -797,6 +801,18 @@ void LLPanelLogin::refreshLocation( bool force_visible )
797 if ( ! force_visible ) 801 if ( ! force_visible )
798 show_start = gSavedSettings.getBOOL("ShowStartLocation"); 802 show_start = gSavedSettings.getBOOL("ShowStartLocation");
799 803
804
805// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
806// TODO-RLVa: figure out some way to make this work with RLV_EXTENSION_STARTLOCATION
807#ifndef RLV_EXTENSION_STARTLOCATION
808 if (rlv_handler_t::isEnabled())
809 {
810 show_start = FALSE;
811 }
812#endif // RLV_EXTENSION_STARTLOCATION
813// [/RLVa:KB]
814
815
800 sInstance->childSetVisible("start_location_combo", show_start); 816 sInstance->childSetVisible("start_location_combo", show_start);
801 sInstance->childSetVisible("start_location_text", show_start); 817 sInstance->childSetVisible("start_location_text", show_start);
802 818
diff --git a/linden/indra/newview/llpanelobject.cpp b/linden/indra/newview/llpanelobject.cpp
index 5c70590..dd71a0e 100644
--- a/linden/indra/newview/llpanelobject.cpp
+++ b/linden/indra/newview/llpanelobject.cpp
@@ -75,6 +75,10 @@
75 75
76#include "lldrawpool.h" 76#include "lldrawpool.h"
77 77
78// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
79#include "llvoavatar.h"
80// [/RLVa:KB]
81
78// 82//
79// Constants 83// Constants
80// 84//
@@ -385,6 +389,15 @@ void LLPanelObject::getState( )
385 enable_rotate = FALSE; 389 enable_rotate = FALSE;
386 } 390 }
387 391
392// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
393 if ( (rlv_handler_t::isEnabled()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP))) )
394 {
395 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
396 if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == objectp->getRootEdit()) )
397 enable_move = enable_scale = enable_rotate = FALSE;
398 }
399// [/RLVa:KB]
400
388 LLVector3 vec; 401 LLVector3 vec;
389 if (enable_move) 402 if (enable_move)
390 { 403 {
diff --git a/linden/indra/newview/llpanelpermissions.cpp b/linden/indra/newview/llpanelpermissions.cpp
index c430922..66c6cdd 100644
--- a/linden/indra/newview/llpanelpermissions.cpp
+++ b/linden/indra/newview/llpanelpermissions.cpp
@@ -322,9 +322,26 @@ void LLPanelPermissions::refresh()
322 } 322 }
323 } 323 }
324 324
325// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
326 bool fRlvEnableOwner = true;
327 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) )
328 {
329 // Only filter the owner name if: the selection is all owned by the same avie and not group owned
330 if ( (owners_identical) && (!LLSelectMgr::getInstance()->selectIsGroupOwned()) )
331 {
332 owner_name = gRlvHandler.getAnonym(owner_name);
333 fRlvEnableOwner = false;
334 }
335 }
336// [/RLVa:KB]
337
325 childSetText("Owner Name",owner_name); 338 childSetText("Owner Name",owner_name);
326 childSetEnabled("Owner Name",TRUE); 339 childSetEnabled("Owner Name",TRUE);
327 childSetEnabled("button owner profile",owners_identical && (mOwnerID.notNull() || LLSelectMgr::getInstance()->selectIsGroupOwned())); 340// childSetEnabled("button owner profile",owners_identical && (mOwnerID.notNull() || LLSelectMgr::getInstance()->selectIsGroupOwned()));
341// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
342 childSetEnabled("button owner profile",
343 fRlvEnableOwner && owners_identical && (mOwnerID.notNull() || LLSelectMgr::getInstance()->selectIsGroupOwned()));
344// [/RLVa:KB]
328 345
329 // update group text field 346 // update group text field
330 childSetEnabled("Group:",true); 347 childSetEnabled("Group:",true);
@@ -861,7 +878,13 @@ void LLPanelPermissions::onClickOwner(void *data)
861 } 878 }
862 else 879 else
863 { 880 {
864 LLFloaterAvatarInfo::showFromObject(self->mOwnerID); 881// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
882 if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
883 {
884 LLFloaterAvatarInfo::showFromObject(self->mOwnerID);
885 }
886// [/RLVa:KB]
887// LLFloaterAvatarInfo::showFromObject(self->mOwnerID);
865 } 888 }
866} 889}
867 890
diff --git a/linden/indra/newview/llpanelpick.cpp b/linden/indra/newview/llpanelpick.cpp
index 480f703..57ce6d5 100644
--- a/linden/indra/newview/llpanelpick.cpp
+++ b/linden/indra/newview/llpanelpick.cpp
@@ -400,7 +400,10 @@ void LLPanelPick::refresh()
400 mEnabledCheck->setEnabled(godlike); 400 mEnabledCheck->setEnabled(godlike);
401 401
402 mSetBtn->setVisible(godlike); 402 mSetBtn->setVisible(godlike);
403 mSetBtn->setEnabled(godlike); 403 //mSetBtn->setEnabled(godlike);
404// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
405 mSetBtn->setEnabled(godlike && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) );
406// [/RLVa:KB]
404 } 407 }
405 else 408 else
406 { 409 {
@@ -417,7 +420,10 @@ void LLPanelPick::refresh()
417 mEnabledCheck->setEnabled(FALSE); 420 mEnabledCheck->setEnabled(FALSE);
418 421
419 mSetBtn->setVisible(is_self); 422 mSetBtn->setVisible(is_self);
420 mSetBtn->setEnabled(is_self); 423 //mSetBtn->setEnabled(is_self);
424// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
425 mSetBtn->setEnabled(is_self && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) );
426// [/RLVa]
421 } 427 }
422} 428}
423 429
@@ -455,6 +461,12 @@ void LLPanelPick::onClickLandmark(void* data)
455// static 461// static
456void LLPanelPick::onClickSet(void* data) 462void LLPanelPick::onClickSet(void* data)
457{ 463{
464// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
465 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
466 {
467 return;
468 }
469// [/RLVa:KB]
458 LLPanelPick* self = (LLPanelPick*)data; 470 LLPanelPick* self = (LLPanelPick*)data;
459 471
460 // Save location for later. 472 // Save location for later.
diff --git a/linden/indra/newview/llprefsim.cpp b/linden/indra/newview/llprefsim.cpp
index 39619b7..429bed9 100644
--- a/linden/indra/newview/llprefsim.cpp
+++ b/linden/indra/newview/llprefsim.cpp
@@ -259,6 +259,12 @@ void LLPrefsIMImpl::setPersonalInfo(const std::string& visibility, bool im_via_e
259 LLWStringUtil::replaceChar(busy_response, '^', '\n'); 259 LLWStringUtil::replaceChar(busy_response, '^', '\n');
260 LLWStringUtil::replaceChar(busy_response, '%', ' '); 260 LLWStringUtil::replaceChar(busy_response, '%', ' ');
261 childSetText("busy_response", wstring_to_utf8str(busy_response)); 261 childSetText("busy_response", wstring_to_utf8str(busy_response));
262// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
263 if (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIM))
264 {
265 childDisable("busy_response");
266 }
267// [/RLVa:KB]
262 268
263 enableHistory(); 269 enableHistory();
264 270
diff --git a/linden/indra/newview/llpreviewscript.cpp b/linden/indra/newview/llpreviewscript.cpp
index af52a4b..1e9def3 100644
--- a/linden/indra/newview/llpreviewscript.cpp
+++ b/linden/indra/newview/llpreviewscript.cpp
@@ -1925,6 +1925,12 @@ void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata )
1925 LLCheckBoxCtrl* runningCheckbox = self->getChild<LLCheckBoxCtrl>("running"); 1925 LLCheckBoxCtrl* runningCheckbox = self->getChild<LLCheckBoxCtrl>("running");
1926 BOOL running = runningCheckbox->get(); 1926 BOOL running = runningCheckbox->get();
1927 //self->mRunningCheckbox->get(); 1927 //self->mRunningCheckbox->get();
1928// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
1929 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(object)) )
1930 {
1931 return;
1932 }
1933// [/RLVa:KB]
1928 if( object ) 1934 if( object )
1929 { 1935 {
1930 LLMessageSystem* msg = gMessageSystem; 1936 LLMessageSystem* msg = gMessageSystem;
@@ -1950,6 +1956,12 @@ void LLLiveLSLEditor::onReset(void *userdata)
1950 LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata; 1956 LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata;
1951 1957
1952 LLViewerObject* object = gObjectList.findObject( self->mObjectID ); 1958 LLViewerObject* object = gObjectList.findObject( self->mObjectID );
1959// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
1960 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(object)) )
1961 {
1962 return;
1963 }
1964// [/RLV:KB]
1953 if(object) 1965 if(object)
1954 { 1966 {
1955 LLMessageSystem* msg = gMessageSystem; 1967 LLMessageSystem* msg = gMessageSystem;
@@ -2371,6 +2383,14 @@ void LLLiveLSLEditor::onLoad(void* userdata)
2371void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save) 2383void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save)
2372{ 2384{
2373 LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; 2385 LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
2386
2387// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
2388 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(gObjectList.findObject(self->mObjectID))) )
2389 {
2390 return;
2391 }
2392// [/RLV:KB]
2393
2374 self->mCloseAfterSave = close_after_save; 2394 self->mCloseAfterSave = close_after_save;
2375 self->saveIfNeeded(); 2395 self->saveIfNeeded();
2376} 2396}
diff --git a/linden/indra/newview/llselectmgr.cpp b/linden/indra/newview/llselectmgr.cpp
index 998cc50..82aeee6 100644
--- a/linden/indra/newview/llselectmgr.cpp
+++ b/linden/indra/newview/llselectmgr.cpp
@@ -3451,12 +3451,20 @@ void LLSelectMgr::deselectAllIfTooFar()
3451 } 3451 }
3452 3452
3453 LLVector3d selectionCenter = getSelectionCenterGlobal(); 3453 LLVector3d selectionCenter = getSelectionCenterGlobal();
3454 if (gSavedSettings.getBOOL("LimitSelectDistance") 3454
3455// if (gSavedSettings.getBOOL("LimitSelectDistance")
3456// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f
3457 BOOL fRlvFartouch = gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH) && gFloaterTools->getVisible();
3458 if ( (gSavedSettings.getBOOL("LimitSelectDistance") || (fRlvFartouch) )
3459// [/RLVa:KB]
3455 && (!mSelectedObjects->getPrimaryObject() || !mSelectedObjects->getPrimaryObject()->isAvatar()) 3460 && (!mSelectedObjects->getPrimaryObject() || !mSelectedObjects->getPrimaryObject()->isAvatar())
3456 && !mSelectedObjects->isAttachment() 3461 && !mSelectedObjects->isAttachment()
3457 && !selectionCenter.isExactlyZero()) 3462 && !selectionCenter.isExactlyZero())
3458 { 3463 {
3459 F32 deselect_dist = gSavedSettings.getF32("MaxSelectDistance"); 3464// F32 deselect_dist = gSavedSettings.getF32("MaxSelectDistance");
3465// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f
3466 F32 deselect_dist = (!fRlvFartouch) ? gSavedSettings.getF32("MaxSelectDistance") : 1.5f;
3467// [/RLVa:KB]
3460 F32 deselect_dist_sq = deselect_dist * deselect_dist; 3468 F32 deselect_dist_sq = deselect_dist * deselect_dist;
3461 3469
3462 LLVector3d select_delta = gAgent.getPositionGlobal() - selectionCenter; 3470 LLVector3d select_delta = gAgent.getPositionGlobal() - selectionCenter;
diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp
index aca3cac..2dc4e74 100644
--- a/linden/indra/newview/llstartup.cpp
+++ b/linden/indra/newview/llstartup.cpp
@@ -384,6 +384,11 @@ bool idle_startup()
384 // Initialize stuff that doesn't need data from simulators 384 // Initialize stuff that doesn't need data from simulators
385 // 385 //
386 386
387// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.1d
388 if ( (gSavedSettings.controlExists(RLV_SETTING_MAIN)) && (gSavedSettings.getBOOL(RLV_SETTING_MAIN)) )
389 rlv_handler_t::setEnabled(TRUE);
390// [/RLVa:KB]
391
387 if (LLFeatureManager::getInstance()->isSafe()) 392 if (LLFeatureManager::getInstance()->isSafe())
388 { 393 {
389 gViewerWindow->alertXml("DisplaySetToSafe"); 394 gViewerWindow->alertXml("DisplaySetToSafe");
@@ -924,6 +929,23 @@ bool idle_startup()
924 // their last location, or some URL "-url //sim/x/y[/z]" 929 // their last location, or some URL "-url //sim/x/y[/z]"
925 // All accounts have both a home and a last location, and we don't support 930 // All accounts have both a home and a last location, and we don't support
926 // more locations than that. Choose the appropriate one. JC 931 // more locations than that. Choose the appropriate one. JC
932// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.1d
933 #ifndef RLV_EXTENSION_STARTLOCATION
934 if (rlv_handler_t::isEnabled())
935 #else
936 if ( (rlv_handler_t::isEnabled()) && (RlvSettings::getLoginLastLocation()) )
937 #endif // RLV_EXTENSION_STARTLOCATION
938 {
939 // Force login at the last location
940 agent_location_id = START_LOCATION_ID_LAST;
941 location_which = START_LOCATION_ID_LAST;
942 gSavedSettings.setBOOL("LoginLastLocation", FALSE);
943
944 // Clear some things that would cause us to divert to a user-specified location
945 LLURLSimString::setString(LLURLSimString::sLocationStringLast);
946 LLStartUp::sSLURLCommand.clear();
947 } else
948// [/RLVa:KB]
927 if (LLURLSimString::parse()) 949 if (LLURLSimString::parse())
928 { 950 {
929 // a startup URL was specified 951 // a startup URL was specified
diff --git a/linden/indra/newview/llstatusbar.cpp b/linden/indra/newview/llstatusbar.cpp
index b0ef61f..012db6f 100644
--- a/linden/indra/newview/llstatusbar.cpp
+++ b/linden/indra/newview/llstatusbar.cpp
@@ -568,6 +568,15 @@ void LLStatusBar::refresh()
568 mRegionDetails.mTraffic = 0.0f; 568 mRegionDetails.mTraffic = 0.0f;
569 } 569 }
570 570
571// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Modified: RLVa-1.0.0a
572 if ( (region) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ) // region == NULL if we loose our connection to the grid
573 {
574 // TODO-RLVa: find out whether the LCD code is still used because if so then we need to filter that as well
575 location_name = llformat("%s (%s) - %s",
576 rlv_handler_t::cstrHiddenRegion.c_str(), region->getSimAccessString().c_str(), rlv_handler_t::cstrHidden.c_str());
577 }
578// [/RLVa:KB]
579
571 mTextParcelName->setText(location_name); 580 mTextParcelName->setText(location_name);
572 581
573 582
@@ -814,6 +823,12 @@ static void onClickScripts(void*)
814 823
815static void onClickBuyLand(void*) 824static void onClickBuyLand(void*)
816{ 825{
826// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
827 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) )
828 {
829 return;
830 }
831// [/RLVa:KB]
817 LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal()); 832 LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal());
818 LLViewerParcelMgr::getInstance()->startBuyLand(); 833 LLViewerParcelMgr::getInstance()->startBuyLand();
819} 834}
diff --git a/linden/indra/newview/lltoolbar.cpp b/linden/indra/newview/lltoolbar.cpp
index 8202191..6d04294 100644
--- a/linden/indra/newview/lltoolbar.cpp
+++ b/linden/indra/newview/lltoolbar.cpp
@@ -307,6 +307,20 @@ void LLToolBar::refresh()
307 } 307 }
308 gSavedSettings.setBOOL("BuildBtnState", build_mode); 308 gSavedSettings.setBOOL("BuildBtnState", build_mode);
309 309
310// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g)
311 // Called per-frame so this really can't be slow
312 if (rlv_handler_t::isEnabled())
313 {
314 // If we're rez-restricted, we can still edit => allow build floater
315 // If we're edit-restricted, we can still rez => allow build floater
316 childSetEnabled("build_btn", !(gRlvHandler.hasBehaviour(RLV_BHVR_REZ) && gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) );
317
318 childSetEnabled("map_btn", !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWWORLDMAP) );
319 childSetEnabled("radar_btn", !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWMINIMAP) );
320 childSetEnabled("inventory_btn", !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWINV) );
321 }
322// [/RLVa:KB]
323
310 updateCommunicateList(); 324 updateCommunicateList();
311} 325}
312 326
@@ -479,6 +493,14 @@ void LLToolBar::onClickSit(void*)
479 } 493 }
480 else 494 else
481 { 495 {
496// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
497 // NOTE-RLVa: dead code?
498 if (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT))
499 {
500 return;
501 }
502// [/RLVa:KB]
503
482 // stand up 504 // stand up
483 gAgent.setFlying(FALSE); 505 gAgent.setFlying(FALSE);
484 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); 506 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
diff --git a/linden/indra/newview/lltooldraganddrop.cpp b/linden/indra/newview/lltooldraganddrop.cpp
index efd8060..c99ccbf 100644
--- a/linden/indra/newview/lltooldraganddrop.cpp
+++ b/linden/indra/newview/lltooldraganddrop.cpp
@@ -1267,6 +1267,15 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target,
1267 return; 1267 return;
1268 } 1268 }
1269 1269
1270
1271// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
1272 // Fallback in case there's a new code path that leads here (see behaviour notes)
1273 if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ))
1274 {
1275 return;
1276 }
1277// [/RLVa:KB]
1278
1270 //llinfos << "Rezzing object" << llendl; 1279 //llinfos << "Rezzing object" << llendl;
1271 make_ui_sound("UISndObjectRezIn"); 1280 make_ui_sound("UISndObjectRezIn");
1272 LLViewerInventoryItem* item; 1281 LLViewerInventoryItem* item;
@@ -1933,6 +1942,23 @@ EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LL
1933 BOOL volume = (LL_PCODE_VOLUME == obj->getPCode()); 1942 BOOL volume = (LL_PCODE_VOLUME == obj->getPCode());
1934 BOOL attached = obj->isAttachment(); 1943 BOOL attached = obj->isAttachment();
1935 BOOL unrestricted = ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) ? TRUE : FALSE; 1944 BOOL unrestricted = ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) ? TRUE : FALSE;
1945
1946// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
1947 if (rlv_handler_t::isEnabled())
1948 {
1949 if (!gRlvHandler.isDetachable(obj))
1950 {
1951 return ACCEPT_NO_LOCKED; // Disallow inventory drops on a locked attachment
1952 }
1953 else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) )
1954 {
1955 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
1956 if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == obj->getRootEdit()) )
1957 return ACCEPT_NO_LOCKED; // ... or on a linkset the avie is sitting on under @unsit=n/@sittp=n
1958 }
1959 }
1960// [/RLVa:KB]
1961
1936 if(attached && !unrestricted) 1962 if(attached && !unrestricted)
1937 { 1963 {
1938 return ACCEPT_NO_LOCKED; 1964 return ACCEPT_NO_LOCKED;
@@ -1988,6 +2014,15 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv(
1988 return ACCEPT_NO; 2014 return ACCEPT_NO;
1989 } 2015 }
1990 2016
2017// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-1.0.0c
2018 LLViewerJointAttachment* pAttachPt = NULL;
2019 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) && (!RlvSettings::getEnableWear()) &&
2020 ( ((pAttachPt = gRlvHandler.getAttachPoint(item, true)) == NULL) || (!gRlvHandler.isDetachable(pAttachPt->getObject())) ) )
2021 {
2022 return ACCEPT_NO_LOCKED;
2023 }
2024// [/RLVa:KB]
2025
1991 if( drop ) 2026 if( drop )
1992 { 2027 {
1993 if(mSource == SOURCE_LIBRARY) 2028 if(mSource == SOURCE_LIBRARY)
@@ -2003,7 +2038,10 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv(
2003 } 2038 }
2004 else 2039 else
2005 { 2040 {
2006 rez_attachment(item, 0); 2041// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-1.0.0c
2042 rez_attachment(item, pAttachPt);
2043// [/RLVa:KB]
2044 //rez_attachment(item, 0);
2007 } 2045 }
2008 } 2046 }
2009 return ACCEPT_YES_SINGLE; 2047 return ACCEPT_YES_SINGLE;
@@ -2013,6 +2051,13 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv(
2013EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand( 2051EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand(
2014 LLViewerObject* obj, S32 face, MASK mask, BOOL drop) 2052 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
2015{ 2053{
2054// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
2055 if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ))
2056 {
2057 return ACCEPT_NO_LOCKED;
2058 }
2059// [/RLVa:KB]
2060
2016 if (mSource == SOURCE_WORLD) 2061 if (mSource == SOURCE_WORLD)
2017 { 2062 {
2018 return dad3dRezFromObjectOnLand(obj, face, mask, drop); 2063 return dad3dRezFromObjectOnLand(obj, face, mask, drop);
@@ -2076,6 +2121,14 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand(
2076EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject( 2121EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject(
2077 LLViewerObject* obj, S32 face, MASK mask, BOOL drop) 2122 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
2078{ 2123{
2124// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
2125 // NOTE: if (mask & MASK_CONTROL) then it's a drop rather than a rez, so we let that pass through
2126 if ( !(mask & MASK_CONTROL) && (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) )
2127 {
2128 return ACCEPT_NO_LOCKED;
2129 }
2130// [/RLVa:KB]
2131
2079 // handle objects coming from object inventory 2132 // handle objects coming from object inventory
2080 if (mSource == SOURCE_WORLD) 2133 if (mSource == SOURCE_WORLD)
2081 { 2134 {
@@ -2281,6 +2334,20 @@ EAcceptance LLToolDragAndDrop::dad3dWearItem(
2281 return ACCEPT_NO; 2334 return ACCEPT_NO;
2282 } 2335 }
2283 2336
2337// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d)
2338 // (See behaviour notes for the "code path", this is just to give a visual indication on whether or not the drop is allowed)
2339 if (rlv_handler_t::isEnabled())
2340 {
2341 EWearableType type = (EWearableType)item->getFlags();
2342
2343 // Block if: 1) we can't wear on that layer; 2) or if we're already wearing something there we can't take off
2344 if ( (!gRlvHandler.isWearable(type)) || ((gAgent.getWearable(type)) && (!gRlvHandler.isRemovable(type))) )
2345 {
2346 return ACCEPT_NO_LOCKED;
2347 }
2348 }
2349// [/RLVa:KB]
2350
2284 if( drop ) 2351 if( drop )
2285 { 2352 {
2286 // Don't wear anything until initial wearables are loaded, can 2353 // Don't wear anything until initial wearables are loaded, can
@@ -2645,6 +2712,14 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventoryCategory(
2645EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnLand( 2712EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnLand(
2646 LLViewerObject* obj, S32 face, MASK mask, BOOL drop) 2713 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
2647{ 2714{
2715// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
2716 // NOTE: it looks like this is only ever called from LLToolDragAndDrop::dad3dRezObjectOnLand() making this a bit redundant
2717 if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ))
2718 {
2719 return ACCEPT_NO_LOCKED;
2720 }
2721// [/RLVa:KB]
2722
2648 lldebugs << "LLToolDragAndDrop::dad3dRezFromObjectOnLand()" << llendl; 2723 lldebugs << "LLToolDragAndDrop::dad3dRezFromObjectOnLand()" << llendl;
2649 LLViewerInventoryItem* item = NULL; 2724 LLViewerInventoryItem* item = NULL;
2650 LLViewerInventoryCategory* cat = NULL; 2725 LLViewerInventoryCategory* cat = NULL;
@@ -2666,6 +2741,14 @@ EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnLand(
2666EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnObject( 2741EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnObject(
2667 LLViewerObject* obj, S32 face, MASK mask, BOOL drop) 2742 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
2668{ 2743{
2744// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
2745 // NOTE: it looks like this is only ever called from LLToolDragAndDrop::dad3dRezObjectOnObject) making this a bit redundant
2746 if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ))
2747 {
2748 return ACCEPT_NO_LOCKED;
2749 }
2750// [/RLVa:KB]
2751
2669 lldebugs << "LLToolDragAndDrop::dad3dRezFromObjectOnObject()" << llendl; 2752 lldebugs << "LLToolDragAndDrop::dad3dRezFromObjectOnObject()" << llendl;
2670 LLViewerInventoryItem* item; 2753 LLViewerInventoryItem* item;
2671 LLViewerInventoryCategory* cat; 2754 LLViewerInventoryCategory* cat;
diff --git a/linden/indra/newview/lltoolface.cpp b/linden/indra/newview/lltoolface.cpp
index d5e4f81..41f2b0d 100644
--- a/linden/indra/newview/lltoolface.cpp
+++ b/linden/indra/newview/lltoolface.cpp
@@ -99,6 +99,16 @@ void LLToolFace::pickCallback(const LLPickInfo& pick_info)
99 return; 99 return;
100 } 100 }
101 101
102// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f
103 if ( (rlv_handler_t::isEnabled()) &&
104 ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) ||
105 ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && ((!hit_obj->isAttachment()) || (!hit_obj->permYouOwner())) &&
106 (dist_vec_squared(gAgent.getPositionAgent(), hit_obj->getPositionRegion() + pick_info.mObjectOffset) > 1.5f * 1.5f) )))
107 {
108 return;
109 }
110// [/RLVa:KB]
111
102 // ...clicked on a world object, try to pick the appropriate face 112 // ...clicked on a world object, try to pick the appropriate face
103 113
104 if (pick_info.mKeyMask & MASK_SHIFT) 114 if (pick_info.mKeyMask & MASK_SHIFT)
diff --git a/linden/indra/newview/lltoolgrab.cpp b/linden/indra/newview/lltoolgrab.cpp
index a6695f9..6c0a557 100644
--- a/linden/indra/newview/lltoolgrab.cpp
+++ b/linden/indra/newview/lltoolgrab.cpp
@@ -185,7 +185,12 @@ BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info)
185 return FALSE; 185 return FALSE;
186 } 186 }
187 187
188 if (objectp->isAvatar()) 188 //if (objectp->isAvatar())
189// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f
190 if ( (objectp->isAvatar()) ||
191 ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && ((!objectp->isAttachment()) || (!objectp->permYouOwner())) &&
192 (dist_vec_squared(gAgent.getPositionAgent(), mGrabPick.mIntersection) > 1.5f * 1.5f) ) )
193// [/RLVa:KB]
189 { 194 {
190 if (gGrabTransientTool) 195 if (gGrabTransientTool)
191 { 196 {
@@ -420,6 +425,23 @@ BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask)
420 return TRUE; 425 return TRUE;
421 } 426 }
422 427
428// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f
429 // Don't allow dragging beyond 1.5m under @fartouch=n
430 LLViewerObject* pObj;
431 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && (GRAB_INACTIVE != mMode) && (hasMouseCapture()) &&
432 ((pObj = mGrabPick.getObject()) != NULL) && (!pObj->isDead()) && (!pObj->isHUDAttachment()) &&
433 (dist_vec_squared(gAgent.getPositionAgent(), pObj->getPositionRegion() + mGrabPick.mObjectOffset) > 1.5f * 1.5f) )
434 {
435 if (gGrabTransientTool)
436 {
437 // Prevent the grab tool from popping up as soon as we kill the drag operation
438 gBasicToolset->selectTool(gGrabTransientTool);
439 gGrabTransientTool = NULL;
440 }
441 setMouseCapture(FALSE);
442 }
443// [/RLVa:KB]
444
423 // Do the right hover based on mode 445 // Do the right hover based on mode
424 switch( mMode ) 446 switch( mMode )
425 { 447 {
diff --git a/linden/indra/newview/lltoolpie.cpp b/linden/indra/newview/lltoolpie.cpp
index 27d1c4c..93f0254 100644
--- a/linden/indra/newview/lltoolpie.cpp
+++ b/linden/indra/newview/lltoolpie.cpp
@@ -165,6 +165,15 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
165 // If it's a left-click, and we have a special action, do it. 165 // If it's a left-click, and we have a special action, do it.
166 if (useClickAction(always_show, mask, object, parent)) 166 if (useClickAction(always_show, mask, object, parent))
167 { 167 {
168// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f
169 // Block left-click special actions (fallback code really since LLToolSelect::handleObjectSelection() wouldn't select it anyway)
170 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) &&
171 (dist_vec_squared(gAgent.getPositionAgent(), mPick.mIntersection) > 1.5f * 1.5f) )
172 {
173 return TRUE;
174 }
175// [/RLVa:KB]
176
168 mClickAction = 0; 177 mClickAction = 0;
169 if (object && object->getClickAction()) 178 if (object && object->getClickAction())
170 { 179 {
@@ -344,7 +353,22 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
344 //gMutePieMenu->setLabel("Mute"); 353 //gMutePieMenu->setLabel("Mute");
345 } 354 }
346 355
347 gPieAvatar->show(x, y, mPieMouseButtonDown); 356// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f
357#ifdef RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK
358 // If we have an empty selection under @fartouch=n don't show the pie menu but play the "operation block" sound
359 if ( (!gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) || (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) )
360 {
361#endif // RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK
362 gPieAvatar->show(x, y, mPieMouseButtonDown);
363#ifdef RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK
364 }
365 else
366 {
367 make_ui_sound("UISndInvalidOp");
368 }
369#endif // RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK
370// [/RLVa:KB]
371
348 } 372 }
349 else if (object->isAttachment() && !object->isHUDAttachment()) 373 else if (object->isAttachment() && !object->isHUDAttachment())
350 { 374 {
@@ -374,15 +398,32 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
374 //gMuteObjectPieMenu->setLabel("Mute"); 398 //gMuteObjectPieMenu->setLabel("Mute");
375 } 399 }
376 400
377 gPieObject->show(x, y, mPieMouseButtonDown); 401// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f
378 402 #ifdef RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK
379 // VEFFECT: ShowPie object 403 // If we have an empty selection under @fartouch=n don't show the pie menu but play the "operation block" sound
380 // Don't show when you click on someone else, it freaks them 404 // (not entirely accurate in case of Tools / Select Only XXX [see LLToolSelect::handleObjectSelection()]
381 // out. 405 if ( (!gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) || (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) )
382 LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE); 406 {
383 effectp->setPositionGlobal(mPick.mPosGlobal); 407 #endif // RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK
384 effectp->setColor(LLColor4U(gAgent.getEffectColor())); 408// [/RLVa:KB]
385 effectp->setDuration(0.25f); 409 gPieObject->show(x, y, mPieMouseButtonDown);
410
411 // VEFFECT: ShowPie object
412 // Don't show when you click on someone else, it freaks them
413 // out.
414 LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE);
415 effectp->setPositionGlobal(mPick.mPosGlobal);
416 effectp->setColor(LLColor4U(gAgent.getEffectColor()));
417 effectp->setDuration(0.25f);
418// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f
419 #ifdef RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK
420 }
421 else
422 {
423 make_ui_sound("UISndInvalidOp");
424 }
425 #endif // RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK
426// [/RLVa:KB]
386 } 427 }
387 } 428 }
388 429
diff --git a/linden/indra/newview/lltoolplacer.cpp b/linden/indra/newview/lltoolplacer.cpp
index 297556e..840de23 100644
--- a/linden/indra/newview/lltoolplacer.cpp
+++ b/linden/indra/newview/lltoolplacer.cpp
@@ -124,6 +124,14 @@ BOOL LLToolPlacer::raycastForNewObjPos( S32 x, S32 y, LLViewerObject** hit_obj,
124 return FALSE; 124 return FALSE;
125 } 125 }
126 126
127// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f
128 // NOTE: don't use surface_pos_global since for prims it will be the center of the prim while we need center + offset
129 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && (dist_vec_squared(gAgent.getPositionGlobal(), pick.mPosGlobal) > 1.5f * 1.5f) )
130 {
131 return FALSE;
132 }
133// [/RLVa:KB]
134
127 // Find the sim where the surface lives. 135 // Find the sim where the surface lives.
128 LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(surface_pos_global); 136 LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(surface_pos_global);
129 if (!regionp) 137 if (!regionp)
@@ -255,7 +263,10 @@ BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics )
255 { 263 {
256 flags |= FLAGS_USE_PHYSICS; 264 flags |= FLAGS_USE_PHYSICS;
257 } 265 }
258 if (create_selected) 266 //if (create_selected)
267// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) | Added: RLVa-1.0.0b
268 if ( (create_selected) && (!gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) )
269// [/RLVa:KB]
259 { 270 {
260 flags |= FLAGS_CREATE_SELECTED; 271 flags |= FLAGS_CREATE_SELECTED;
261 } 272 }
@@ -513,6 +524,13 @@ BOOL LLToolPlacer::placeObject(S32 x, S32 y, MASK mask)
513{ 524{
514 BOOL added = TRUE; 525 BOOL added = TRUE;
515 526
527// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
528 if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ))
529 {
530 return TRUE; // Callers seem to expect a "did you handle it?" so we return TRUE rather than FALSE
531 }
532// [/RLVa:KB]
533
516 if (gSavedSettings.getBOOL("CreateToolCopySelection")) 534 if (gSavedSettings.getBOOL("CreateToolCopySelection"))
517 { 535 {
518 added = addDuplicate(x, y); 536 added = addDuplicate(x, y);
diff --git a/linden/indra/newview/lltoolselect.cpp b/linden/indra/newview/lltoolselect.cpp
index b4e9562..389ae59 100644
--- a/linden/indra/newview/lltoolselect.cpp
+++ b/linden/indra/newview/lltoolselect.cpp
@@ -50,6 +50,10 @@
50#include "llvoavatar.h" 50#include "llvoavatar.h"
51#include "llworld.h" 51#include "llworld.h"
52 52
53// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
54#include "llfloatertools.h"
55// [/RLVa:KB]
56
53// Globals 57// Globals
54extern BOOL gAllowSelectAvatar; 58extern BOOL gAllowSelectAvatar;
55 59
@@ -82,6 +86,51 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi
82 { 86 {
83 object = object->getRootEdit(); 87 object = object->getRootEdit();
84 } 88 }
89
90// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f
91 if (rlv_handler_t::isEnabled())
92 {
93 if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT))
94 {
95 if (!temp_select)
96 {
97 return LLSelectMgr::getInstance()->getSelection();
98 }
99 else
100 {
101 // Temporary selection, but if the build floater is open then it'll be permanent so get rid of the floater
102 if (gFloaterTools->getVisible())
103 {
104 // Copy/paste from toggle_build_mode()
105 gAgent.resetView(false);
106 gFloaterTools->close();
107 gViewerWindow->showCursor();
108 }
109 }
110 }
111
112 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && (object) && ((!object->isAttachment()) || (!object->permYouOwner())) &&
113 (dist_vec_squared(gAgent.getPositionAgent(), object->getPositionRegion()) > 1.5f * 1.5f) )
114 {
115 // NOTE-RLVa: see behaviour notes for a rather lengthy explanation of why we're doing things this way
116 //if (dist_vec_squared(gAgent.getPositionAgent(), object->getPositionRegion() + pick.mObjectOffset) > 1.5f * 1.5f)
117 if (dist_vec_squared(gAgent.getPositionAgent(), pick.mIntersection) > 1.5f * 1.5f)
118 {
119 if ( (gFloaterTools->getVisible()) && (pick.mKeyMask != MASK_SHIFT) && (pick.mKeyMask != MASK_CONTROL) )
120 LLSelectMgr::getInstance()->deselectAll();
121 return LLSelectMgr::getInstance()->getSelection();
122 }
123 else if (gFloaterTools->getVisible())
124 {
125 // Copy/paste from toggle_build_mode()
126 gAgent.resetView(false);
127 gFloaterTools->close();
128 gViewerWindow->showCursor();
129 }
130 }
131 }
132// [/RLVa:KB]
133
85 BOOL select_owned = gSavedSettings.getBOOL("SelectOwnedOnly"); 134 BOOL select_owned = gSavedSettings.getBOOL("SelectOwnedOnly");
86 BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly"); 135 BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly");
87 136
diff --git a/linden/indra/newview/lltracker.cpp b/linden/indra/newview/lltracker.cpp
index bd2f659..cf98c7a 100644
--- a/linden/indra/newview/lltracker.cpp
+++ b/linden/indra/newview/lltracker.cpp
@@ -180,8 +180,12 @@ void LLTracker::render3D()
180 } 180 }
181 else 181 else
182 { 182 {
183 renderBeacon( instance()->mTrackedPositionGlobal, gTrackColor, 183 //renderBeacon( instance()->mTrackedPositionGlobal, gTrackColor,
184 instance()->mBeaconText, instance()->mTrackedLocationName ); 184 // instance()->mBeaconText, instance()->mTrackedLocationName );
185// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-1.0.0a
186 renderBeacon(instance()->mTrackedPositionGlobal, gTrackColor, instance()->mBeaconText,
187 (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? instance()->mTrackedLocationName : rlv_handler_t::cstrHidden);
188// [/RLVa:KB]
185 } 189 }
186 } 190 }
187 191
@@ -222,8 +226,12 @@ void LLTracker::render3D()
222 // and back again 226 // and back again
223 instance()->mHasReachedLandmark = FALSE; 227 instance()->mHasReachedLandmark = FALSE;
224 } 228 }
225 renderBeacon( instance()->mTrackedPositionGlobal, gTrackColor, 229 //renderBeacon( instance()->mTrackedPositionGlobal, gTrackColor,
226 instance()->mBeaconText, instance()->mTrackedLandmarkName ); 230 // instance()->mBeaconText, instance()->mTrackedLandmarkName );
231// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-1.0.0a
232 renderBeacon( instance()->mTrackedPositionGlobal, gTrackColor, instance()->mBeaconText,
233 (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? instance()->mTrackedLandmarkName : rlv_handler_t::cstrHidden);
234// [/RLVa:KB]
227 } 235 }
228 } 236 }
229 else 237 else
@@ -251,8 +259,12 @@ void LLTracker::render3D()
251 } 259 }
252 else 260 else
253 { 261 {
254 renderBeacon( av_tracker.getGlobalPos(), gTrackColor, 262 //renderBeacon( av_tracker.getGlobalPos(), gTrackColor,
255 instance()->mBeaconText, av_tracker.getName() ); 263 // instance()->mBeaconText, av_tracker.getName() );
264// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-1.0.0a
265 renderBeacon( av_tracker.getGlobalPos(), gTrackColor, instance()->mBeaconText,
266 (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? av_tracker.getName() : rlv_handler_t::cstrHidden);
267// [/RLVa:KB]
256 } 268 }
257 } 269 }
258 else 270 else
diff --git a/linden/indra/newview/llviewercontrol.cpp b/linden/indra/newview/llviewercontrol.cpp
index 89ae973..eb8b1d5 100644
--- a/linden/indra/newview/llviewercontrol.cpp
+++ b/linden/indra/newview/llviewercontrol.cpp
@@ -423,6 +423,20 @@ bool handleVoiceClientPrefsChanged(const LLSD& newvalue)
423 return true; 423 return true;
424} 424}
425 425
426// [RLVa:KB] - Checked: 2009-08-11 (RLVa-1.0.1h) | Added: RLVa-1.0.1h
427bool rlvHandleEnableLegacyNamingChanged(const LLSD& newvalue)
428{
429 rlv_handler_t::fLegacyNaming = newvalue.asBoolean();
430 return true;
431}
432
433bool rlvHandleShowNameTagsChanged(const LLSD& newvalue)
434{
435 RlvSettings::fShowNameTags = newvalue.asBoolean();
436 return true;
437}
438// [/RLVa:KB]
439
426bool handleMediaDebugLevelChanged(const LLSD& newvalue) 440bool handleMediaDebugLevelChanged(const LLSD& newvalue)
427{ 441{
428 LLMediaManager *mgr = LLMediaManager::getInstance(); 442 LLMediaManager *mgr = LLMediaManager::getInstance();
@@ -566,6 +580,13 @@ void settings_setup_listeners()
566 gSavedSettings.getControl("AudioLevelMic")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1)); 580 gSavedSettings.getControl("AudioLevelMic")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
567 gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1)); 581 gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
568 gSavedSettings.getControl("MediaDebugLevel")->getSignal()->connect(boost::bind(&handleMediaDebugLevelChanged, _1)); 582 gSavedSettings.getControl("MediaDebugLevel")->getSignal()->connect(boost::bind(&handleMediaDebugLevelChanged, _1));
583
584// [RLVa:KB] - Checked: 2009-08-11 (RLVa-1.0.1h) | Added: RLVa-1.0.1h
585 if (gSavedSettings.controlExists(RLV_SETTING_ENABLELEGACYNAMING))
586 gSavedSettings.getControl(RLV_SETTING_ENABLELEGACYNAMING)->getSignal()->connect(boost::bind(&rlvHandleEnableLegacyNamingChanged, _1));
587 if (gSavedSettings.controlExists(RLV_SETTING_SHOWNAMETAGS))
588 gSavedSettings.getControl(RLV_SETTING_SHOWNAMETAGS)->getSignal()->connect(boost::bind(&rlvHandleShowNameTagsChanged, _1));
589// [/RLVa:KB]
569} 590}
570 591
571template <> eControlType get_control_type<U32>(const U32& in, LLSD& out) 592template <> eControlType get_control_type<U32>(const U32& in, LLSD& out)
diff --git a/linden/indra/newview/llviewerdisplay.cpp b/linden/indra/newview/llviewerdisplay.cpp
index 96591a2..4b352a4 100644
--- a/linden/indra/newview/llviewerdisplay.cpp
+++ b/linden/indra/newview/llviewerdisplay.cpp
@@ -675,7 +675,10 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
675 gSky.updateSky(); 675 gSky.updateSky();
676 } 676 }
677 677
678 if(gUseWireframe) 678// if(gUseWireframe)
679// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
680 if ( (gUseWireframe) && ( (!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedAttachment()) ) )
681// [/RLVa:KB]
679 { 682 {
680 glClearColor(0.5f, 0.5f, 0.5f, 0.f); 683 glClearColor(0.5f, 0.5f, 0.5f, 0.f);
681 glClear(GL_COLOR_BUFFER_BIT); 684 glClear(GL_COLOR_BUFFER_BIT);
@@ -802,7 +805,12 @@ void render_hud_attachments()
802 glh::matrix4f current_mod = glh_get_current_modelview(); 805 glh::matrix4f current_mod = glh_get_current_modelview();
803 806
804 // clamp target zoom level to reasonable values 807 // clamp target zoom level to reasonable values
805 gAgent.mHUDTargetZoom = llclamp(gAgent.mHUDTargetZoom, 0.1f, 1.f); 808// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
809 // TODO-RLVa: while hasLockedHUD() isn't slow this is called per frame so find a better way
810 gAgent.mHUDTargetZoom = llclamp(gAgent.mHUDTargetZoom,
811 ( (!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedHUD()) ) ? 0.1f : 0.85f, 1.f);
812// [/RLVa:KB]
813 //gAgent.mHUDTargetZoom = llclamp(gAgent.mHUDTargetZoom, 0.1f, 1.f);
806 // smoothly interpolate current zoom level 814 // smoothly interpolate current zoom level
807 gAgent.mHUDCurZoom = lerp(gAgent.mHUDCurZoom, gAgent.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f)); 815 gAgent.mHUDCurZoom = lerp(gAgent.mHUDCurZoom, gAgent.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f));
808 816
diff --git a/linden/indra/newview/llviewermenu.cpp b/linden/indra/newview/llviewermenu.cpp
index 2940bdd..6bd38e6 100644
--- a/linden/indra/newview/llviewermenu.cpp
+++ b/linden/indra/newview/llviewermenu.cpp
@@ -219,6 +219,13 @@ void init_debug_ui_menu(LLMenuGL* menu);
219void init_debug_xui_menu(LLMenuGL* menu); 219void init_debug_xui_menu(LLMenuGL* menu);
220void init_debug_avatar_menu(LLMenuGL* menu); 220void init_debug_avatar_menu(LLMenuGL* menu);
221void init_debug_baked_texture_menu(LLMenuGL* menu); 221void init_debug_baked_texture_menu(LLMenuGL* menu);
222// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
223#ifdef RLV_DEBUG_TESTS
224 #include "rlvtest.h"
225#endif // RLV_DEBUG_TESTS
226#include "rlvfloaterbehaviour.h"
227void init_debug_rlva_menu(LLMenuGL* menu);
228// [/RLVa:KB]
222 229
223BOOL enable_land_build(void*); 230BOOL enable_land_build(void*);
224BOOL enable_object_build(void*); 231BOOL enable_object_build(void*);
@@ -825,6 +832,19 @@ void init_client_menu(LLMenuGL* menu)
825 init_debug_world_menu(sub_menu); 832 init_debug_world_menu(sub_menu);
826 menu->appendMenu(sub_menu); 833 menu->appendMenu(sub_menu);
827 834
835// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.1b
836 #ifdef RLV_ADVANCED_MENU
837 if (rlv_handler_t::isEnabled())
838 {
839 sub_menu = new LLMenuGL("RLVa");
840 init_debug_rlva_menu(sub_menu);
841 menu->appendMenu(sub_menu);
842 sub_menu->setVisible(rlv_handler_t::isEnabled());
843 sub_menu->setEnabled(rlv_handler_t::isEnabled());
844 }
845 #endif // RLV_ADVANCED_MENU
846// [/RLVa:KB]
847
828 sub_menu = new LLMenuGL("UI"); 848 sub_menu = new LLMenuGL("UI");
829 init_debug_ui_menu(sub_menu); 849 init_debug_ui_menu(sub_menu);
830 menu->appendMenu(sub_menu); 850 menu->appendMenu(sub_menu);
@@ -919,6 +939,13 @@ void init_client_menu(LLMenuGL* menu)
919 &menu_check_control, 939 &menu_check_control,
920 (void*)"ShowConsoleWindow")); 940 (void*)"ShowConsoleWindow"));
921 941
942// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-1.0.0e
943 #ifdef RLV_ADVANCED_TOGGLE_RLVA
944 if (gSavedSettings.controlExists(RLV_SETTING_MAIN))
945 menu->append(new LLMenuItemCheckGL("Restrained Life API", &rlvDbgToggleEnabled, NULL, &rlvDbgGetEnabled, NULL));
946 #endif // RLV_ADVANCED_TOGGLE_RLVA
947// [/RLVa:KB]
948
922 if(gSavedSettings.getBOOL("QAMode")) 949 if(gSavedSettings.getBOOL("QAMode"))
923 { 950 {
924 LLMenuGL* sub = NULL; 951 LLMenuGL* sub = NULL;
@@ -1366,6 +1393,53 @@ void init_debug_baked_texture_menu(LLMenuGL* menu)
1366 menu->createJumpKeys(); 1393 menu->createJumpKeys();
1367} 1394}
1368 1395
1396// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-1.0.0g
1397void init_debug_rlva_menu(LLMenuGL* menu)
1398{
1399 // Experimental feature toggles
1400 {
1401 /*
1402 #ifdef RLV_EXPERIMENTAL
1403 LLMenuGL* sub_menu = new LLMenuGL("Experimental");
1404
1405 menu->appendMenu(sub_menu);
1406 #endif // RLV_EXPERIMENTAL
1407 */
1408 }
1409
1410 // Unit tests
1411 {
1412 #ifdef RLV_DEBUG_TESTS
1413 init_debug_rlva_tests_menu(menu);
1414 #endif // RLV_DEBUG_TESTS
1415 }
1416
1417 #ifdef RLV_EXTENSION_ENABLE_WEAR
1418 if (gSavedSettings.controlExists(RLV_SETTING_ENABLEWEAR))
1419 {
1420 menu->append(new LLMenuItemCheckGL("Enable Wear", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_ENABLEWEAR));
1421 menu->appendSeparator();
1422 }
1423 #endif // RLV_EXTENSION_ENABLE_WEAR
1424
1425 #ifdef RLV_EXTENSION_HIDELOCKED
1426 if ( (gSavedSettings.controlExists(RLV_SETTING_HIDELOCKEDLAYER)) &&
1427 (gSavedSettings.controlExists(RLV_SETTING_HIDELOCKEDATTACH)) )
1428 {
1429 menu->append(new LLMenuItemCheckGL("Hide locked layers", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_HIDELOCKEDLAYER));
1430 menu->append(new LLMenuItemCheckGL("Hide locked attachments", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_HIDELOCKEDATTACH));
1431 //sub_menu->append(new LLMenuItemToggleGL("Hide locked inventory", &rlv_handler_t::fHideLockedInventory));
1432 menu->appendSeparator();
1433 }
1434 #endif // RLV_EXTENSION_HIDELOCKED
1435
1436 #ifdef RLV_EXTENSION_FLOATER_RESTRICTIONS
1437 // TODO-RLVa: figure out a way to tell if floater_rlv_behaviour.xml exists
1438 menu->append(new LLMenuItemCallGL("Restrictions...", RlvFloaterBehaviour::show, NULL, NULL));
1439 #endif // RLV_EXTENSION_FLOATER_RESTRICTIONS
1440}
1441// [/RLVa:KB]
1442
1369void init_server_menu(LLMenuGL* menu) 1443void init_server_menu(LLMenuGL* menu)
1370{ 1444{
1371 { 1445 {
@@ -1518,6 +1592,16 @@ class LLObjectTouch : public view_listener_t
1518 1592
1519 LLPickInfo pick = LLToolPie::getInstance()->getPick(); 1593 LLPickInfo pick = LLToolPie::getInstance()->getPick();
1520 1594
1595// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f
1596 // TODO-RLVa: this code is rather redundant since we'll never get an active selection to show a pie menu for
1597 // [msg->addVector3("Position", pick.mIntersection) <- see llDetectedTouchPos()]
1598 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && ((!object->isAttachment()) || (!object->permYouOwner())) &&
1599 (dist_vec_squared(gAgent.getPositionAgent(), pick.mIntersection) > 1.5f * 1.5f) )
1600 {
1601 return true; // Can't touch in-world objects (or other avie's attachments) farther than 1.5m away under @fartouch=n
1602 }
1603// [/RLVa:KB]
1604
1521 LLMessageSystem *msg = gMessageSystem; 1605 LLMessageSystem *msg = gMessageSystem;
1522 1606
1523 msg->newMessageFast(_PREHASH_ObjectGrab); 1607 msg->newMessageFast(_PREHASH_ObjectGrab);
@@ -1566,6 +1650,14 @@ class LLObjectEnableTouch : public view_listener_t
1566 { 1650 {
1567 LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); 1651 LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
1568 bool new_value = obj && obj->flagHandleTouch(); 1652 bool new_value = obj && obj->flagHandleTouch();
1653// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f
1654 // TODO-RLVa: this code is rather redundant since we'll never get an active selection to show a pie menu for
1655 if ( (new_value) && (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && ((!obj->isAttachment()) || (!obj->permYouOwner())) &&
1656 (dist_vec_squared(gAgent.getPositionAgent(), LLToolPie::getInstance()->getPick().mIntersection) > 1.5f * 1.5f) )
1657 {
1658 new_value = false; // Can't touch in-world objects (or other avie's attachments) farther than 1.5m away under @fartouch=n
1659 }
1660// [/RLVa:KB]
1569 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 1661 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
1570 1662
1571 // Update label based on the node touch name if available. 1663 // Update label based on the node touch name if available.
@@ -1634,6 +1726,14 @@ class LLObjectOpen : public view_listener_t
1634{ 1726{
1635 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 1727 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
1636 { 1728 {
1729// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b)
1730 // TODO-RLVa: shouldn't we be checking for fartouch here as well?
1731 if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT))
1732 {
1733 return true;
1734 }
1735// [/RLVa:KB]
1736
1637 return handle_object_open(); 1737 return handle_object_open();
1638 } 1738 }
1639}; 1739};
@@ -1652,6 +1752,12 @@ class LLObjectEnableOpen : public view_listener_t
1652 if (!root) new_value = false; 1752 if (!root) new_value = false;
1653 else new_value = root->allowOpen(); 1753 else new_value = root->allowOpen();
1654 } 1754 }
1755
1756// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) | Modified: RLVa-1.0.0b
1757 // TODO-RLV: shouldn't we be checking for fartouch here as well? (and LLViewerObject::allowOpen() makes this redundant?)
1758 new_value &= !gRlvHandler.hasBehaviour(RLV_BHVR_EDIT);
1759// [/RLVa:KB]
1760
1655 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 1761 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
1656 return true; 1762 return true;
1657 } 1763 }
@@ -1713,7 +1819,13 @@ bool toggle_build_mode()
1713 } 1819 }
1714 } 1820 }
1715 1821
1716 1822// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
1823 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (LLSelectMgr::getInstance()) )
1824 {
1825 LLSelectMgr::getInstance()->deselectAll();
1826 }
1827// [/RLVa:KB]
1828
1717 LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); 1829 LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
1718 LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() ); 1830 LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
1719 1831
@@ -1813,6 +1925,23 @@ class LLObjectEdit : public view_listener_t
1813 { 1925 {
1814 LLViewerParcelMgr::getInstance()->deselectLand(); 1926 LLViewerParcelMgr::getInstance()->deselectLand();
1815 1927
1928// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f
1929 if (rlv_handler_t::isEnabled())
1930 {
1931 if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT))
1932 {
1933 return true; // Can't edit any object under @edit=n
1934 }
1935 else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) &&
1936 (SELECT_TYPE_WORLD == LLSelectMgr::getInstance()->getSelection()->getSelectType()) &&
1937 (dist_vec_squared(gAgent.getPositionAgent(), LLToolPie::getInstance()->getPick().mIntersection) > 1.5f * 1.5f) )
1938 {
1939 // TODO-RLVa: this code is rather redundant since we'll never get an active selection to show a pie menu for
1940 return true; // Can't edit in-world objects farther than 1.5m away under @fartouch=n
1941 }
1942 }
1943// [/RLVa:KB]
1944
1816 if (gAgent.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit()) 1945 if (gAgent.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit())
1817 { 1946 {
1818 LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); 1947 LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
@@ -1962,6 +2091,22 @@ class LLEnableEdit : public view_listener_t
1962 enable = LLViewerParcelMgr::getInstance()->agentCanBuild() 2091 enable = LLViewerParcelMgr::getInstance()->agentCanBuild()
1963 || LLSelectMgr::getInstance()->getSelection()->isAttachment(); 2092 || LLSelectMgr::getInstance()->getSelection()->isAttachment();
1964 } 2093 }
2094// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
2095 // TODO-RLV: include fartouch here?
2096 if ( (rlv_handler_t::isEnabled()) && (enable) )
2097 {
2098 // We have no way of knowing whether we're being called for "Create" or for "Edit", but we can
2099 // make an educated guess based on the currently active selection which puts us halfway there.
2100 BOOL fActiveSelection = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
2101
2102 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) )
2103 enable = false; // Edit and rez restricted, disable them both
2104 else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (fActiveSelection) )
2105 enable = false; // Edit restricted and there's an active selection => disable Edit and Create
2106 else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) && (!fActiveSelection) )
2107 enable = false; // Rez restricted and there's no active selection => disable Create
2108 }
2109// [/RLVa:KB]
1965 gMenuHolder->findControl(userdata["control"].asString())->setValue(enable); 2110 gMenuHolder->findControl(userdata["control"].asString())->setValue(enable);
1966 return true; 2111 return true;
1967 } 2112 }
@@ -1989,7 +2134,10 @@ class LLSelfEnableRemoveAllAttachments : public view_listener_t
1989 { 2134 {
1990 LLVOAvatar::attachment_map_t::iterator curiter = iter++; 2135 LLVOAvatar::attachment_map_t::iterator curiter = iter++;
1991 LLViewerJointAttachment* attachment = curiter->second; 2136 LLViewerJointAttachment* attachment = curiter->second;
1992 if (attachment->getObject()) 2137// if (attachment->getObject())
2138// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0c
2139 if ( (attachment->getObject()) && ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isDetachable(curiter->first)) ) )
2140// [/RLVa:KB]
1993 { 2141 {
1994 new_value = true; 2142 new_value = true;
1995 break; 2143 break;
@@ -2036,6 +2184,9 @@ class LLObjectEnableMute : public view_listener_t
2036 BOOL is_linden = lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden"); 2184 BOOL is_linden = lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden");
2037 BOOL is_self = avatar->isSelf(); 2185 BOOL is_self = avatar->isSelf();
2038 new_value = !is_linden && !is_self; 2186 new_value = !is_linden && !is_self;
2187// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
2188 new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES));
2189// [/RLVa:KB]
2039 } 2190 }
2040 } 2191 }
2041 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 2192 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
@@ -2056,6 +2207,12 @@ class LLObjectMute : public view_listener_t
2056 LLVOAvatar* avatar = find_avatar_from_object(object); 2207 LLVOAvatar* avatar = find_avatar_from_object(object);
2057 if (avatar) 2208 if (avatar)
2058 { 2209 {
2210// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-1.0.0e
2211 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
2212 {
2213 return true; // Fallback code [see LLObjectEnableMute::handleEvent()]
2214 }
2215// [/RLVa:KB]
2059 id = avatar->getID(); 2216 id = avatar->getID();
2060 2217
2061 LLNameValue *firstname = avatar->getNVPair("FirstName"); 2218 LLNameValue *firstname = avatar->getNVPair("FirstName");
@@ -2106,6 +2263,13 @@ class LLObjectMute : public view_listener_t
2106 2263
2107bool handle_go_to() 2264bool handle_go_to()
2108{ 2265{
2266// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
2267 if ( (rlv_handler_t::isEnabled()) && gAgent.forwardGrabbed() && (gRlvHandler.hasLockedAttachment()) )
2268 {
2269 return true;
2270 }
2271// [/RLVa:KB]
2272
2109 // JAMESDEBUG try simulator autopilot 2273 // JAMESDEBUG try simulator autopilot
2110 std::vector<std::string> strings; 2274 std::vector<std::string> strings;
2111 std::string val; 2275 std::string val;
@@ -2188,6 +2352,12 @@ class LLAvatarFreeze : public view_listener_t
2188 { 2352 {
2189 LLUUID* avatar_id = new LLUUID( avatar->getID() ); 2353 LLUUID* avatar_id = new LLUUID( avatar->getID() );
2190 std::string fullname = avatar->getFullname(); 2354 std::string fullname = avatar->getFullname();
2355// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e)
2356 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!fullname.empty()) )
2357 {
2358 fullname = gRlvHandler.getAnonym(fullname);
2359 }
2360// [/RLVa:KB]
2191 2361
2192 if (!fullname.empty()) 2362 if (!fullname.empty())
2193 { 2363 {
@@ -2213,7 +2383,11 @@ class LLAvatarVisibleDebug : public view_listener_t
2213{ 2383{
2214 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 2384 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2215 { 2385 {
2216 bool new_value = gAgent.isGodlike(); 2386 //bool new_value = gAgent.isGodlike();
2387// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
2388 // TODO-RLVa: can you actually use this to cheat anything?
2389 bool new_value = gAgent.isGodlike() && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES));
2390// [/RLVa:KB]
2217 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 2391 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
2218 return true; 2392 return true;
2219 } 2393 }
@@ -2325,6 +2499,12 @@ class LLAvatarEject : public view_listener_t
2325 MenuCallbackData *data = new MenuCallbackData; 2499 MenuCallbackData *data = new MenuCallbackData;
2326 (*data).avatar_id = avatar->getID(); 2500 (*data).avatar_id = avatar->getID();
2327 std::string fullname = avatar->getFullname(); 2501 std::string fullname = avatar->getFullname();
2502// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e)
2503 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!fullname.empty()) )
2504 {
2505 fullname = gRlvHandler.getAnonym(fullname);
2506 }
2507// [/RLVa:KB]
2328 2508
2329 const LLVector3d& pos = avatar->getPositionGlobal(); 2509 const LLVector3d& pos = avatar->getPositionGlobal();
2330 LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel(); 2510 LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel();
@@ -2406,6 +2586,13 @@ class LLAvatarGiveCard : public view_listener_t
2406{ 2586{
2407 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 2587 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2408 { 2588 {
2589// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
2590 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
2591 {
2592 return true;
2593 }
2594// [/RLVa:KB]
2595
2409 llinfos << "handle_give_card()" << llendl; 2596 llinfos << "handle_give_card()" << llendl;
2410 LLViewerObject* dest = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); 2597 LLViewerObject* dest = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
2411 if(dest && dest->isAvatar()) 2598 if(dest && dest->isAvatar())
@@ -2655,6 +2842,13 @@ class LLSelfStandUp : public view_listener_t
2655{ 2842{
2656 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 2843 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2657 { 2844 {
2845// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
2846 if (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT))
2847 {
2848 return true;
2849 }
2850// [/RLVa:KB]
2851
2658 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); 2852 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
2659 return true; 2853 return true;
2660 } 2854 }
@@ -2664,7 +2858,10 @@ class LLSelfEnableStandUp : public view_listener_t
2664{ 2858{
2665 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 2859 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2666 { 2860 {
2667 bool new_value = gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting; 2861// bool new_value = gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting;
2862// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
2863 bool new_value = gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting && !gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT);
2864// [/RLVa:KB]
2668 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 2865 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
2669 return true; 2866 return true;
2670 } 2867 }
@@ -2839,6 +3036,11 @@ class LLAvatarEnableAddFriend : public view_listener_t
2839 { 3036 {
2840 LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); 3037 LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
2841 bool new_value = avatar && !is_agent_friend(avatar->getID()); 3038 bool new_value = avatar && !is_agent_friend(avatar->getID());
3039
3040// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
3041 new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES));
3042// [/RLVa:KB]
3043
2842 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 3044 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
2843 return true; 3045 return true;
2844 } 3046 }
@@ -2897,6 +3099,15 @@ bool handle_sit_or_stand()
2897 return true; 3099 return true;
2898 } 3100 }
2899 3101
3102// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0c)
3103 if ( (rlv_handler_t::isEnabled()) &&
3104 ( ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->mIsSitting)) ||
3105 (gRlvHandler.hasBehaviour(RLV_BHVR_SIT)) ) )
3106 {
3107 return true;
3108 }
3109// [/RLVa:KB]
3110
2900 if (sitting_on_selection()) 3111 if (sitting_on_selection())
2901 { 3112 {
2902 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); 3113 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
@@ -2907,6 +3118,15 @@ bool handle_sit_or_stand()
2907 3118
2908 if (object && object->getPCode() == LL_PCODE_VOLUME) 3119 if (object && object->getPCode() == LL_PCODE_VOLUME)
2909 { 3120 {
3121// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0g
3122 if ( (rlv_handler_t::isEnabled()) &&
3123 ((gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) || (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH))) &&
3124 (dist_vec_squared(gAgent.getPositionGlobal(), object->getPositionGlobal() + LLVector3d(pick.mObjectOffset)) > 1.5f * 1.5f) )
3125 {
3126 return true; // Don't allow sitting farther away than 1.5m under @sittp=n or @fartouch=n
3127 }
3128// [/RLVa:KB]
3129
2910 gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit); 3130 gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit);
2911 gMessageSystem->nextBlockFast(_PREHASH_AgentData); 3131 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
2912 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); 3132 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
@@ -2944,6 +3164,13 @@ class LLLandSit : public view_listener_t
2944{ 3164{
2945 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 3165 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2946 { 3166 {
3167// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
3168 if (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT))
3169 {
3170 return true;
3171 }
3172// [/RLVa:KB]
3173
2947 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); 3174 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
2948 LLViewerParcelMgr::getInstance()->deselectLand(); 3175 LLViewerParcelMgr::getInstance()->deselectLand();
2949 3176
@@ -3254,6 +3481,14 @@ class LLEditDuplicate : public view_listener_t
3254{ 3481{
3255 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 3482 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
3256 { 3483 {
3484// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
3485 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) &&
3486 (LLEditMenuHandler::gEditMenuHandler == LLSelectMgr::getInstance()) )
3487 {
3488 return true;
3489 }
3490// [/RLVa:KB]
3491
3257 if(LLEditMenuHandler::gEditMenuHandler) 3492 if(LLEditMenuHandler::gEditMenuHandler)
3258 { 3493 {
3259 LLEditMenuHandler::gEditMenuHandler->duplicate(); 3494 LLEditMenuHandler::gEditMenuHandler->duplicate();
@@ -3267,6 +3502,13 @@ class LLEditEnableDuplicate : public view_listener_t
3267 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 3502 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
3268 { 3503 {
3269 bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDuplicate(); 3504 bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDuplicate();
3505// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
3506 if ( (new_value) && (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) &&
3507 (LLEditMenuHandler::gEditMenuHandler == LLSelectMgr::getInstance()) )
3508 {
3509 new_value = false;
3510 }
3511// [/RLVa:KB]
3270 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 3512 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
3271 return true; 3513 return true;
3272 } 3514 }
@@ -3652,6 +3894,11 @@ class LLToolsTakeCopy : public view_listener_t
3652 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 3894 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
3653 { 3895 {
3654 if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true; 3896 if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true;
3897// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | Modified: RLVa-1.0.0b
3898 // NOTE: we need to handle "Take Copy" because it will force a sim-side unsit if we're sitting on the selection,
3899 // but we do want to allow "Take Copy" under @rez=n so that's why we explicitly check for @unsit=n here
3900 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (!rlvCanDeleteOrReturn()) ) return true;
3901// [/RLVa:KB]
3655 3902
3656 const LLUUID& category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT); 3903 const LLUUID& category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT);
3657 derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id); 3904 derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
@@ -3667,6 +3914,9 @@ class LLObjectReturn : public view_listener_t
3667 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 3914 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
3668 { 3915 {
3669 if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true; 3916 if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true;
3917// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-05 (RLVa-1.0.0b)
3918 if ( (rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn()) ) return true;
3919// [/RLVa:KB]
3670 3920
3671 mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); 3921 mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
3672 3922
@@ -3736,6 +3986,14 @@ class LLObjectEnableReturn : public view_listener_t
3736 } 3986 }
3737 } 3987 }
3738#endif 3988#endif
3989
3990// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
3991 if ( (new_value) && (rlv_handler_t::isEnabled()) )
3992 {
3993 new_value = rlvCanDeleteOrReturn();
3994 }
3995// [/RLVa:KB]
3996
3739 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 3997 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
3740 return true; 3998 return true;
3741 } 3999 }
@@ -3757,6 +4015,13 @@ void handle_take()
3757 return; 4015 return;
3758 } 4016 }
3759 4017
4018// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
4019 if ( (rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn()) )
4020 {
4021 return;
4022 }
4023// [/RLVa:KB]
4024
3760 BOOL you_own_everything = TRUE; 4025 BOOL you_own_everything = TRUE;
3761 BOOL locked_but_takeable_object = FALSE; 4026 BOOL locked_but_takeable_object = FALSE;
3762 LLUUID category_id; 4027 LLUUID category_id;
@@ -3878,6 +4143,13 @@ BOOL enable_take()
3878 return FALSE; 4143 return FALSE;
3879 } 4144 }
3880 4145
4146// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
4147 if ( (rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn()) )
4148 {
4149 return FALSE;
4150 }
4151// [/RLVa:KB]
4152
3881 for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin(); 4153 for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin();
3882 iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++) 4154 iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++)
3883 { 4155 {
@@ -4199,6 +4471,21 @@ class LLToolsEnableUnlink : public view_listener_t
4199 new_value = true; 4471 new_value = true;
4200 } 4472 }
4201 } 4473 }
4474
4475// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0g
4476 // The user might not be allowed to unlink this object due to RLV settings,
4477 // because it would unsit them if they are sitting on the object.
4478 if ( (new_value) && (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) &&
4479 (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->mIsSitting) )
4480 {
4481 // Allow if the avie isn't sitting on any of the selected objects
4482 LLObjectSelectionHandle handleSel = LLSelectMgr::getInstance()->getSelection();
4483 RlvSelectIsSittingOn func(gAgent.getAvatarObject()->getRoot());
4484 if (handleSel->getFirstRootNode(&func, TRUE))
4485 new_value = false;
4486 }
4487// [/RLVa:KB]
4488
4202 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 4489 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
4203 return true; 4490 return true;
4204 } 4491 }
@@ -4208,6 +4495,19 @@ class LLToolsUnlink : public view_listener_t
4208{ 4495{
4209 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4496 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4210 { 4497 {
4498// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0g
4499 // The user might not be allowed to unlink this object due to RLV settings,
4500 // because it would unsit them if they are sitting on the object.
4501 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->mIsSitting) )
4502 {
4503 // Allow if the avie isn't sitting on any of the selected objects
4504 LLObjectSelectionHandle handleSel = LLSelectMgr::getInstance()->getSelection();
4505 RlvSelectIsSittingOn func(gAgent.getAvatarObject()->getRoot());
4506 if (handleSel->getFirstRootNode(&func, TRUE))
4507 return true;
4508 }
4509// [/RLVa:KB]
4510
4211 LLSelectMgr::getInstance()->sendDelink(); 4511 LLSelectMgr::getInstance()->sendDelink();
4212 return true; 4512 return true;
4213 } 4513 }
@@ -4227,6 +4527,13 @@ class LLToolsReleaseKeys : public view_listener_t
4227{ 4527{
4228 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4528 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4229 { 4529 {
4530// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
4531 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) )
4532 {
4533 return true;
4534 }
4535// [/RLVa:KB]
4536
4230 gAgent.forceReleaseControls(); 4537 gAgent.forceReleaseControls();
4231 4538
4232 return true; 4539 return true;
@@ -4237,7 +4544,11 @@ class LLToolsEnableReleaseKeys : public view_listener_t
4237{ 4544{
4238 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4545 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4239 { 4546 {
4240 gMenuHolder->findControl(userdata["control"].asString())->setValue( gAgent.anyControlGrabbed() ); 4547// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
4548 gMenuHolder->findControl(userdata["control"].asString())->setValue(
4549 gAgent.anyControlGrabbed() && ( (!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedAttachment() ) ) );
4550// [/RLVa:KB]
4551 //gMenuHolder->findControl(userdata["control"].asString())->setValue( gAgent.anyControlGrabbed() );
4241 return true; 4552 return true;
4242 } 4553 }
4243}; 4554};
@@ -4345,6 +4656,15 @@ class LLEditEnableDelete : public view_listener_t
4345 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4656 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4346 { 4657 {
4347 bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete(); 4658 bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete();
4659
4660// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
4661 // NOTE: we want to disable delete on objects but not disable delete on text
4662 if ( (new_value) && (rlv_handler_t::isEnabled()) && (LLEditMenuHandler::gEditMenuHandler == LLSelectMgr::getInstance()) )
4663 {
4664 new_value = rlvCanDeleteOrReturn();
4665 }
4666// [/RLVa:KB]
4667
4348 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 4668 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
4349 return true; 4669 return true;
4350 } 4670 }
@@ -4354,6 +4674,15 @@ class LLEditDelete : public view_listener_t
4354{ 4674{
4355 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4675 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4356 { 4676 {
4677// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
4678 // NOTE: we want to disable delete on objects but not disable delete on text
4679 if ( (rlv_handler_t::isEnabled()) && (LLEditMenuHandler::gEditMenuHandler == LLSelectMgr::getInstance()) &&
4680 (!rlvCanDeleteOrReturn()) )
4681 {
4682 return true;
4683 }
4684// [/RLVa:KB]
4685
4357 // If a text field can do a deletion, it gets precedence over deleting 4686 // If a text field can do a deletion, it gets precedence over deleting
4358 // an object in the world. 4687 // an object in the world.
4359 if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete()) 4688 if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete())
@@ -4385,6 +4714,12 @@ class LLObjectEnableDelete : public view_listener_t
4385# endif 4714# endif
4386 LLSelectMgr::getInstance()->canDoDelete(); 4715 LLSelectMgr::getInstance()->canDoDelete();
4387#endif 4716#endif
4717// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
4718 if ( (new_value) && (rlv_handler_t::isEnabled()) )
4719 {
4720 new_value = rlvCanDeleteOrReturn();
4721 }
4722// [/RLVa:KB]
4388 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 4723 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
4389 return true; 4724 return true;
4390 } 4725 }
@@ -4403,6 +4738,13 @@ class LLObjectDelete : public view_listener_t
4403{ 4738{
4404 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4739 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4405 { 4740 {
4741// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
4742 if ( (rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn()) )
4743 {
4744 return true;
4745 }
4746// [/RLVa:KB]
4747
4406 if (LLSelectMgr::getInstance()) 4748 if (LLSelectMgr::getInstance())
4407 { 4749 {
4408 LLSelectMgr::getInstance()->doDelete(); 4750 LLSelectMgr::getInstance()->doDelete();
@@ -4752,6 +5094,12 @@ class LLWorldCreateLandmark : public view_listener_t
4752{ 5094{
4753 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 5095 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4754 { 5096 {
5097// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
5098 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
5099 {
5100 return true;
5101 }
5102// [/RLVa:KB]
4755 LLViewerRegion* agent_region = gAgent.getRegion(); 5103 LLViewerRegion* agent_region = gAgent.getRegion();
4756 if(!agent_region) 5104 if(!agent_region)
4757 { 5105 {
@@ -4859,6 +5207,13 @@ class LLAvatarInviteToGroup : public view_listener_t
4859{ 5207{
4860 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 5208 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4861 { 5209 {
5210// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
5211 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
5212 {
5213 return true;
5214 }
5215// [/RLVa:KB]
5216
4862 LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); 5217 LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
4863 if(avatar) 5218 if(avatar)
4864 { 5219 {
@@ -4872,6 +5227,13 @@ class LLAvatarAddFriend : public view_listener_t
4872{ 5227{
4873 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 5228 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4874 { 5229 {
5230// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
5231 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
5232 {
5233 return true; // Fallback code [see LLAvatarEnableAddFriend::handleEvent()]
5234 }
5235// [/RLVa:KB]
5236
4875 LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); 5237 LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
4876 if(avatar && !is_agent_friend(avatar->getID())) 5238 if(avatar && !is_agent_friend(avatar->getID()))
4877 { 5239 {
@@ -4959,6 +5321,12 @@ class LLEnablePayObject : public view_listener_t
4959 } 5321 }
4960 } 5322 }
4961 } 5323 }
5324
5325// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
5326 // Don't enable "Pay..." on the avatar pie menu under @shownames=n
5327 new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) || (avatar == NULL);
5328// [/RLVa:KB]
5329
4962 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 5330 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
4963 return true; 5331 return true;
4964 } 5332 }
@@ -5147,6 +5515,12 @@ class LLShowFloater : public view_listener_t
5147 } 5515 }
5148 else if (floater_name == "buy land") 5516 else if (floater_name == "buy land")
5149 { 5517 {
5518// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
5519 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
5520 {
5521 return true;
5522 }
5523// [/RLVa:KB]
5150 if (LLViewerParcelMgr::getInstance()->selectionEmpty()) 5524 if (LLViewerParcelMgr::getInstance()->selectionEmpty())
5151 { 5525 {
5152 LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal()); 5526 LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal());
@@ -5324,6 +5698,13 @@ class LLShowAgentProfile : public view_listener_t
5324 } 5698 }
5325 else if (userdata.asString() == "hit object") 5699 else if (userdata.asString() == "hit object")
5326 { 5700 {
5701// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
5702 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
5703 {
5704 return true;
5705 }
5706// [/RLVa:KB]
5707
5327 LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); 5708 LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
5328 if (objectp) 5709 if (objectp)
5329 { 5710 {
@@ -5383,6 +5764,13 @@ class LLLandEdit : public view_listener_t
5383{ 5764{
5384 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 5765 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
5385 { 5766 {
5767// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b)
5768 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) )
5769 {
5770 return true;
5771 }
5772// [/RLVa:KB]
5773
5386 if (gAgent.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") ) 5774 if (gAgent.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") )
5387 { 5775 {
5388 // zoom in if we're looking at the avatar 5776 // zoom in if we're looking at the avatar
@@ -5468,6 +5856,18 @@ private:
5468 LLViewerJointAttachment* attachment_point = NULL; 5856 LLViewerJointAttachment* attachment_point = NULL;
5469 if (index > 0) 5857 if (index > 0)
5470 attachment_point = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL); 5858 attachment_point = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL);
5859
5860// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
5861 if ( (rlv_handler_t::isEnabled()) &&
5862 ( ((index == 0) && (gRlvHandler.hasLockedAttachment())) || // Can't wear on default attach point
5863 ((index > 0) && (!gRlvHandler.isDetachable(attachment_point->getObject()))) || // Can't replace locked attachment
5864 (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) ) ) // Attach on rezzed object == "Take"
5865 {
5866 setObjectSelection(NULL); // Clear the selection or it'll get stuck
5867 return true;
5868 }
5869// [/RLVa:KB]
5870
5471 confirm_replace_attachment(0, attachment_point); 5871 confirm_replace_attachment(0, attachment_point);
5472 } 5872 }
5473 return true; 5873 return true;
@@ -5575,6 +5975,24 @@ class LLAttachmentDrop : public view_listener_t
5575 return true; 5975 return true;
5576 } 5976 }
5577 5977
5978// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
5979 if (rlv_handler_t::isEnabled())
5980 {
5981 if (gRlvHandler.hasLockedAttachment())
5982 {
5983 // NOTE: copy/paste of the code in enable_detach()
5984 LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection();
5985 RlvSelectHasLockedAttach functor;
5986 if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&functor, FALSE)) )
5987 return true;
5988 }
5989 else if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ))
5990 {
5991 return true;
5992 }
5993 }
5994// [/RLVa:KB]
5995
5578 // The sendDropAttachment() method works on the list of selected 5996 // The sendDropAttachment() method works on the list of selected
5579 // objects. Thus we need to clear the list, make sure it only 5997 // objects. Thus we need to clear the list, make sure it only
5580 // contains the object the user clicked, send the message, 5998 // contains the object the user clicked, send the message,
@@ -5593,6 +6011,13 @@ void handle_detach_from_avatar(void* user_data)
5593 6011
5594 if (attached_object) 6012 if (attached_object)
5595 { 6013 {
6014// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0d
6015 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(attached_object)) )
6016 {
6017 return;
6018 }
6019// [/RLVa:KB]
6020
5596 gMessageSystem->newMessage("ObjectDetach"); 6021 gMessageSystem->newMessage("ObjectDetach");
5597 gMessageSystem->nextBlockFast(_PREHASH_AgentData); 6022 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
5598 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); 6023 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
@@ -5675,6 +6100,17 @@ class LLAttachmentDetach : public view_listener_t
5675 return true; 6100 return true;
5676 } 6101 }
5677 6102
6103// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6104 // NOTE: copy/paste of the code in enable_detach()
6105 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) )
6106 {
6107 LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection();
6108 RlvSelectHasLockedAttach functor;
6109 if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&functor, FALSE)) )
6110 return FALSE;
6111 }
6112// [/RLVa:KB]
6113
5678 // The sendDetach() method works on the list of selected 6114 // The sendDetach() method works on the list of selected
5679 // objects. Thus we need to clear the list, make sure it only 6115 // objects. Thus we need to clear the list, make sure it only
5680 // contains the object the user clicked, send the message, 6116 // contains the object the user clicked, send the message,
@@ -5758,7 +6194,10 @@ class LLAttachmentEnableDrop : public view_listener_t
5758 } 6194 }
5759 6195
5760 //now check to make sure that the item is actually in the inventory before we enable dropping it 6196 //now check to make sure that the item is actually in the inventory before we enable dropping it
5761 bool new_value = enable_detach(NULL) && can_build && item; 6197// bool new_value = enable_detach(NULL) && can_build && item;
6198// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
6199 bool new_value = enable_detach(NULL) && can_build && item && (!gRlvHandler.hasBehaviour(RLV_BHVR_REZ));
6200// [/RLVa:KB]
5762 6201
5763 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 6202 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
5764 return true; 6203 return true;
@@ -5778,6 +6217,20 @@ BOOL enable_detach(void*)
5778 // ...if it's you, good to detach 6217 // ...if it's you, good to detach
5779 if (avatar->getID() == gAgent.getID()) 6218 if (avatar->getID() == gAgent.getID())
5780 { 6219 {
6220// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6221 // NOTE: this code is reused as-is in LLAttachmentDetach::handleEvent() and LLAttachmentDrop::handleEvent()
6222 // so any changes here should be reflected there as well (I think it's in a number of other places as well by now)
6223
6224 // RELEASE-RLVa: LLSelectMgr::sendDetach() and LLSelectMgr::sendDropAttachment() call sendListToRegions with
6225 // SEND_ONLY_ROOTS so we only need to examine the roots which saves us time
6226 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) )
6227 {
6228 LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection();
6229 RlvSelectHasLockedAttach functor;
6230 if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&functor, FALSE)) )
6231 return FALSE;
6232 }
6233// [/RLVa:KB]
5781 return TRUE; 6234 return TRUE;
5782 } 6235 }
5783 6236
@@ -5800,6 +6253,25 @@ class LLAttachmentEnableDetach : public view_listener_t
5800// Used to tell if the selected object can be attached to your avatar. 6253// Used to tell if the selected object can be attached to your avatar.
5801BOOL object_selected_and_point_valid(void *user_data) 6254BOOL object_selected_and_point_valid(void *user_data)
5802{ 6255{
6256// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
6257 if (rlv_handler_t::isEnabled())
6258 {
6259 // RELEASE-RLVa: look at the caller graph for this function on every new release
6260 // -> 1.22.11 and 1.23.4
6261 // - object_is_wearable() => dead code [user_data == NULL => default attach point => OK!]
6262 // - LLObjectEnableWear::handleEvent() => Rezzed prim / right-click / "Wear" [user_data == NULL => see above]
6263 // - enabler set up in LLVOAvatar::buildCharacter() => Rezzed prim / right-click / "Attach >" [user_data == pAttachPt]
6264 // - enabler set up in LLVOAvatar::buildCharacter() => Rezzed prim / Edit menu / "Attach Object" [user_data == pAttachPt]
6265 LLViewerJointAttachment* pAttachPt = (LLViewerJointAttachment*)user_data;
6266 if ( ((!pAttachPt) && (gRlvHandler.hasLockedAttachment())) || // Don't allow attach to default attach point
6267 ((pAttachPt) && (!gRlvHandler.isDetachable(pAttachPt->getObject()))) || // Don't allow replacing of locked attachment
6268 (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) ) // Attaching a rezzed object == "Take"
6269 {
6270 return FALSE;
6271 }
6272 }
6273// [/RLVa:KB]
6274
5803 //LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; 6275 //LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
5804 LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); 6276 LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
5805 for (LLObjectSelection::root_iterator iter = selection->root_begin(); 6277 for (LLObjectSelection::root_iterator iter = selection->root_begin();
@@ -5867,7 +6339,13 @@ BOOL object_attached(void *user_data)
5867{ 6339{
5868 LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; 6340 LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
5869 6341
5870 return attachment->getObject() != NULL; 6342// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6343 return (
6344 (attachment->getObject() != NULL) &&
6345 ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isDetachable(attachment->getObject())) )
6346 );
6347// [/RLVa:KB]
6348// return attachment->getObject() != NULL;
5871} 6349}
5872 6350
5873class LLAvatarSendIM : public view_listener_t 6351class LLAvatarSendIM : public view_listener_t
@@ -5875,6 +6353,12 @@ class LLAvatarSendIM : public view_listener_t
5875 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 6353 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
5876 { 6354 {
5877 LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); 6355 LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
6356// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
6357 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
6358 {
6359 return true;
6360 }
6361// [/RLVa:KB]
5878 if(avatar) 6362 if(avatar)
5879 { 6363 {
5880 std::string name("IM"); 6364 std::string name("IM");
@@ -6010,6 +6494,16 @@ class LLToolsSelectedScriptAction : public view_listener_t
6010{ 6494{
6011 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 6495 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
6012 { 6496 {
6497// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6498 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) )
6499 {
6500 LLObjectSelectionHandle selectHandle = LLSelectMgr::getInstance()->getSelection();
6501 RlvSelectHasLockedAttach functor;
6502 if ( (selectHandle->isAttachment()) && (selectHandle->getFirstNode(&functor)) )
6503 return true;
6504 }
6505// [/RLVa:KB]
6506
6013 std::string action = userdata.asString(); 6507 std::string action = userdata.asString();
6014 if (action == "compile mono") 6508 if (action == "compile mono")
6015 { 6509 {
@@ -6091,12 +6585,30 @@ void handle_dump_image_list(void*)
6091 6585
6092void handle_test_male(void*) 6586void handle_test_male(void*)
6093{ 6587{
6588// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6589 if ( (rlv_handler_t::isEnabled()) &&
6590 ( (gRlvHandler.hasLockedAttachment()) ||
6591 (gRlvHandler.hasBehaviour(RLV_BHVR_ADDOUTFIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_REMOUTFIT)) ) )
6592 {
6593 return;
6594 }
6595// [/RLVa:KB]
6596
6094 wear_outfit_by_name("Male Shape & Outfit"); 6597 wear_outfit_by_name("Male Shape & Outfit");
6095 //gGestureList.requestResetFromServer( TRUE ); 6598 //gGestureList.requestResetFromServer( TRUE );
6096} 6599}
6097 6600
6098void handle_test_female(void*) 6601void handle_test_female(void*)
6099{ 6602{
6603// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6604 if ( (rlv_handler_t::isEnabled()) &&
6605 ( (gRlvHandler.hasLockedAttachment()) ||
6606 (gRlvHandler.hasBehaviour(RLV_BHVR_ADDOUTFIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_REMOUTFIT)) ) )
6607 {
6608 return;
6609 }
6610// [/RLVa:KB]
6611
6100 wear_outfit_by_name("Female Shape & Outfit"); 6612 wear_outfit_by_name("Female Shape & Outfit");
6101 //gGestureList.requestResetFromServer( FALSE ); 6613 //gGestureList.requestResetFromServer( FALSE );
6102} 6614}
@@ -6239,6 +6751,22 @@ BOOL enable_more_than_one_selected(void* )
6239 6751
6240static bool is_editable_selected() 6752static bool is_editable_selected()
6241{ 6753{
6754// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-1.0.0c
6755 // RELEASE-RLVa: check that this still isn't called by anything but script actions in the Tools menu
6756 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) )
6757 {
6758 LLObjectSelectionHandle selectHandle = LLSelectMgr::getInstance()->getSelection();
6759
6760 // NOTE: this is called for 5 different menu items so we'll trade accuracy for efficiency and only
6761 // examine root nodes (LLToolsSelectedScriptAction::handleEvent() will catch what we miss)
6762 RlvSelectHasLockedAttach functor;
6763 if ( (selectHandle->isAttachment()) && (selectHandle->getFirstRootNode(&functor)) )
6764 {
6765 return false;
6766 }
6767 }
6768// [/RLVa:KB]
6769
6242 return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL); 6770 return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL);
6243} 6771}
6244 6772
@@ -6285,7 +6813,12 @@ class LLToolsEnableTakeCopy : public view_listener_t
6285 { 6813 {
6286 virtual bool apply(LLViewerObject* obj) 6814 virtual bool apply(LLViewerObject* obj)
6287 { 6815 {
6288 return (!obj->permCopy() || obj->isAttachment()); 6816// return (!obj->permCopy() || obj->isAttachment());
6817// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
6818 return (!obj->permCopy() || obj->isAttachment()) ||
6819 ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) &&
6820 (gAgent.getAvatarObject()->getRoot() == obj) );
6821// [/RLVa:KB]
6289 } 6822 }
6290 } func; 6823 } func;
6291 const bool firstonly = true; 6824 const bool firstonly = true;
@@ -6488,6 +7021,9 @@ class LLWorldEnableCreateLandmark : public view_listener_t
6488 { 7021 {
6489 bool new_value = gAgent.isGodlike() || 7022 bool new_value = gAgent.isGodlike() ||
6490 (gAgent.getRegion() && gAgent.getRegion()->getAllowLandmark()); 7023 (gAgent.getRegion() && gAgent.getRegion()->getAllowLandmark());
7024// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
7025 new_value &= !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC);
7026// [/RLVa:KB]
6491 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 7027 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
6492 return true; 7028 return true;
6493 } 7029 }
@@ -6540,7 +7076,11 @@ BOOL enable_god_customer_service(void*)
6540 7076
6541BOOL enable_god_basic(void*) 7077BOOL enable_god_basic(void*)
6542{ 7078{
6543 return gAgent.getGodLevel() > GOD_NOT; 7079// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
7080 // RELEASE-RLVa: check that this function isn't used for anything other than to enable/disable showing the "God Tools..." floater
7081 return (gAgent.getGodLevel() > GOD_NOT) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC));
7082// [/RLVa:KB]
7083 //return gAgent.getGodLevel() > GOD_NOT;
6544} 7084}
6545 7085
6546#if 0 // 1.9.2 7086#if 0 // 1.9.2
@@ -7051,6 +7591,13 @@ class LLViewHighlightTransparent : public view_listener_t
7051{ 7591{
7052 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 7592 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
7053 { 7593 {
7594// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b)
7595 if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT))
7596 {
7597 return true;
7598 }
7599// [/RLVa:KB]
7600
7054 LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha; 7601 LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha;
7055 return true; 7602 return true;
7056 } 7603 }
@@ -7098,6 +7645,13 @@ class LLViewShowHUDAttachments : public view_listener_t
7098{ 7645{
7099 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 7646 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
7100 { 7647 {
7648// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
7649 if ( (LLPipeline::sShowHUDAttachments) && (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedHUD()) )
7650 {
7651 return true;
7652 }
7653// [/RLVa:KB]
7654
7101 LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments; 7655 LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments;
7102 return true; 7656 return true;
7103 } 7657 }
@@ -7156,6 +7710,15 @@ class LLEditEnableTakeOff : public view_listener_t
7156 { 7710 {
7157 new_value = LLAgent::selfHasWearable((void *)WT_SKIRT); 7711 new_value = LLAgent::selfHasWearable((void *)WT_SKIRT);
7158 } 7712 }
7713
7714// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d)
7715 // Why aren't they using LLWearable::typeNameToType()? *confuzzled*
7716 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isRemovable(LLWearable::typeNameToType(clothing))) )
7717 {
7718 new_value = false;
7719 }
7720// [/RLVa:KB]
7721
7159 gMenuHolder->findControl(control_name)->setValue(new_value); 7722 gMenuHolder->findControl(control_name)->setValue(new_value);
7160 return true; 7723 return true;
7161 } 7724 }
@@ -7253,6 +7816,13 @@ class LLWorldEnvSettings : public view_listener_t
7253{ 7816{
7254 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 7817 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
7255 { 7818 {
7819// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
7820 if (gRlvHandler.hasBehaviour(RLV_BHVR_SETENV))
7821 {
7822 return true;
7823 }
7824// [/RLVa:KB]
7825
7256 std::string tod = userdata.asString(); 7826 std::string tod = userdata.asString();
7257 LLVector3 sun_direction; 7827 LLVector3 sun_direction;
7258 7828
@@ -7330,6 +7900,13 @@ class LLWorldWaterSettings : public view_listener_t
7330{ 7900{
7331 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 7901 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
7332 { 7902 {
7903// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
7904 if (gRlvHandler.hasBehaviour(RLV_BHVR_SETENV))
7905 {
7906 return true;
7907 }
7908// [/RLVa:KB]
7909
7333 // if not there or is hidden, show it 7910 // if not there or is hidden, show it
7334 if( !LLFloaterWater::isOpen() || 7911 if( !LLFloaterWater::isOpen() ||
7335 !LLFloaterWater::instance()->getVisible()) { 7912 !LLFloaterWater::instance()->getVisible()) {
@@ -7360,6 +7937,13 @@ class LLWorldDayCycle : public view_listener_t
7360{ 7937{
7361 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 7938 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
7362 { 7939 {
7940// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
7941 if (gRlvHandler.hasBehaviour(RLV_BHVR_SETENV))
7942 {
7943 return true;
7944 }
7945// [/RLVa:KB]
7946
7363 LLFloaterDayCycle::show(); 7947 LLFloaterDayCycle::show();
7364 return true; 7948 return true;
7365 } 7949 }
diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp
index 3fb8e9a..1b2ba22 100644
--- a/linden/indra/newview/llviewermessage.cpp
+++ b/linden/indra/newview/llviewermessage.cpp
@@ -140,6 +140,11 @@
140#include "llwindebug.h" // For the invalid message handler 140#include "llwindebug.h" // For the invalid message handler
141#endif 141#endif
142 142
143// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
144#include "llfloateravatarinfo.h"
145extern LLMap< const LLUUID, LLFloaterAvatarInfo* > gAvatarInfoInstances; // Only defined in llfloateravatarinfo.cpp
146// [/RLVa:KB]
147
143// 148//
144// Constants 149// Constants
145// 150//
@@ -1007,8 +1012,17 @@ void inventory_offer_callback(S32 button, void* user_data)
1007 std::string first_name, last_name; 1012 std::string first_name, last_name;
1008 if (gCacheName->getName(info->mFromID, first_name, last_name)) 1013 if (gCacheName->getName(info->mFromID, first_name, last_name))
1009 { 1014 {
1010 from_string = std::string("An object named '") + info->mFromName + "' owned by " + first_name + " " + last_name; 1015// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e)
1011 chatHistory_string = info->mFromName + " owned by " + first_name + " " + last_name; 1016 std::string full_name = first_name + " " + last_name;
1017 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (gRlvHandler.isAgentNearby(info->mFromID)) )
1018 {
1019 full_name = gRlvHandler.getAnonym(full_name);
1020 }
1021 from_string = std::string("An object named '") + info->mFromName + "' owned by " + full_name;
1022 chatHistory_string = info->mFromName + " owned by " + full_name;
1023// [/RLVa:KB]
1024 //from_string = std::string("An object named '") + info->mFromName + "' owned by " + first_name + " " + last_name;
1025 //chatHistory_string = info->mFromName + " owned by " + first_name + " " + last_name;
1012 } 1026 }
1013 else 1027 else
1014 { 1028 {
@@ -1027,6 +1041,21 @@ void inventory_offer_callback(S32 button, void* user_data)
1027 switch(button) 1041 switch(button)
1028 { 1042 {
1029 case IOR_ACCEPT: 1043 case IOR_ACCEPT:
1044// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.2a
1045 // Only change the inventory offer's destination folder to the shared root if:
1046 // - the user has enabled the feature
1047 // - the inventory offer came from a script (and specifies a folder)
1048 // - the name starts with the prefix [mDesc format (quotes are part of the string): "[OBJECTNAME] ( http://slurl.com/... )"]
1049 if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getForbidGiveToRLV()) &&
1050 (IM_TASK_INVENTORY_OFFERED == info->mIM) && (LLAssetType::AT_CATEGORY == info->mType) && (info->mDesc.find(RLV_PUTINV_PREFIX) == 1) )
1051 {
1052 LLViewerInventoryCategory* pRlvRoot = gRlvHandler.getSharedRoot();
1053 if (pRlvRoot)
1054 {
1055 info->mFolderID = pRlvRoot->getUUID();
1056 }
1057 }
1058// [/RLVa:KB]
1030 // ACCEPT. The math for the dialog works, because the accept 1059 // ACCEPT. The math for the dialog works, because the accept
1031 // for inventory_offered, task_inventory_offer or 1060 // for inventory_offered, task_inventory_offer or
1032 // group_notice_inventory is 1 greater than the offer integer value. 1061 // group_notice_inventory is 1 greater than the offer integer value.
@@ -1189,6 +1218,13 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
1189 if(indx >= 0) 1218 if(indx >= 0)
1190 { 1219 {
1191 LLStringUtil::truncate(msg, indx); 1220 LLStringUtil::truncate(msg, indx);
1221// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-1.0.0a
1222 // TODO-RLVa: needs revisiting when LL saves open notifications to disk to accept them on the next relog
1223 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
1224 {
1225 gRlvHandler.filterLocation(info->mDesc);
1226 }
1227// [/RLVa:KB]
1192 } 1228 }
1193 1229
1194 LLStringUtil::format_map_t args; 1230 LLStringUtil::format_map_t args;
@@ -1229,6 +1265,13 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
1229 std::string first_name, last_name; 1265 std::string first_name, last_name;
1230 if (gCacheName->getName(info->mFromID, first_name, last_name)) 1266 if (gCacheName->getName(info->mFromID, first_name, last_name))
1231 { 1267 {
1268// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e)
1269 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (gRlvHandler.isAgentNearby(info->mFromID)) )
1270 {
1271 first_name = gRlvHandler.getAnonym(first_name.append(" ").append(last_name));
1272 last_name.clear();
1273 }
1274// [/RLVa:KB]
1232 args["[FIRST]"] = first_name; 1275 args["[FIRST]"] = first_name;
1233 args["[LAST]"] = last_name; 1276 args["[LAST]"] = last_name;
1234 name_found = TRUE; 1277 name_found = TRUE;
@@ -1243,7 +1286,13 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
1243 else 1286 else
1244 { 1287 {
1245 // *TODO:translate -> [FIRST] [LAST] 1288 // *TODO:translate -> [FIRST] [LAST]
1246 args["[NAME]"] = info->mFromName; 1289// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e)
1290 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (gRlvHandler.isAgentNearby(info->mFromID)) )
1291 {
1292 args["[NAME]"] = gRlvHandler.getAnonym(info->mFromName);
1293 }
1294// [/RLVa:KB]
1295 //args["[NAME]"] = info->mFromName;
1247 LLNotifyBox::showXml("UserGiveItem", args, 1296 LLNotifyBox::showXml("UserGiveItem", args,
1248 &inventory_offer_callback, (void*)info); 1297 &inventory_offer_callback, (void*)info);
1249 } 1298 }
@@ -1411,7 +1460,20 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
1411 // do nothing -- don't distract newbies in 1460 // do nothing -- don't distract newbies in
1412 // Prelude with global IMs 1461 // Prelude with global IMs
1413 } 1462 }
1414 else if (offline == IM_ONLINE && !is_linden && is_busy && name != SYSTEM_FROM) 1463// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
1464 else if ( (rlv_handler_t::isEnabled()) && (offline == IM_ONLINE) && ("@version" == message) )
1465 {
1466 rlvSendBusyMessage(from_id, gRlvHandler.getVersionString(), session_id);
1467 // We won't receive a typing stop message, so do that manually (see comment at the end of LLFloaterIMPanel::sendMsg)
1468 LLPointer<LLIMInfo> im_info = new LLIMInfo(gMessageSystem);
1469 gIMMgr->processIMTypingStop(im_info);
1470 }
1471// [/RLVa:KB]
1472// else if (offline == IM_ONLINE && !is_linden && is_busy && name != SYSTEM_FROM)
1473// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
1474 else if ( (offline == IM_ONLINE && !is_linden && is_busy && name != SYSTEM_FROM) &&
1475 ( (!gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) || (gRlvHandler.isException(RLV_BHVR_RECVIM, from_id))) )
1476// [/RLVa:KB]
1415 { 1477 {
1416 // return a standard "busy" message, but only do it to online IM 1478 // return a standard "busy" message, but only do it to online IM
1417 // (i.e. not other auto responses and not store-and-forward IM) 1479 // (i.e. not other auto responses and not store-and-forward IM)
@@ -1468,6 +1530,21 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
1468 } 1530 }
1469 else if (to_id.isNull()) 1531 else if (to_id.isNull())
1470 { 1532 {
1533// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e)
1534 // Filter region messages that weren't sent by a Linden
1535 if ( (rlv_handler_t::isEnabled()) && (LLMuteList::getInstance()) &&
1536 (!LLMuteList::getInstance()->isLinden(name)) && (from_id != gAgent.getID()) )
1537 {
1538 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
1539 gRlvHandler.filterLocation(message);
1540 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
1541 {
1542 name = gRlvHandler.getAnonym(name);
1543 gRlvHandler.filterNames(message);
1544 }
1545 }
1546// [/RLVa:KB]
1547
1471 // Message to everyone from GOD 1548 // Message to everyone from GOD
1472 args["[NAME]"] = name; 1549 args["[NAME]"] = name;
1473 args["[MESSAGE]"] = message; 1550 args["[MESSAGE]"] = message;
@@ -1483,6 +1560,15 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
1483 else 1560 else
1484 { 1561 {
1485 // standard message, not from system 1562 // standard message, not from system
1563// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
1564 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) && (!gRlvHandler.isException(RLV_BHVR_RECVIM, from_id)) )
1565 {
1566 rlvSendBusyMessage(from_id, rlv_handler_t::cstrMsgRecvIM, session_id);
1567
1568 message = message.substr(0, message_offset) + rlv_handler_t::cstrBlockedRecvIM;
1569 }
1570// [/RLVa:KB]
1571
1486 std::string saved; 1572 std::string saved;
1487 if(offline == IM_OFFLINE) 1573 if(offline == IM_OFFLINE)
1488 { 1574 {
@@ -1688,6 +1774,13 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
1688 bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0]; 1774 bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0];
1689 info->mType = (LLAssetType::EType) bucketp->asset_type; 1775 info->mType = (LLAssetType::EType) bucketp->asset_type;
1690 info->mObjectID = bucketp->object_id; 1776 info->mObjectID = bucketp->object_id;
1777
1778// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
1779 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (gRlvHandler.isAgentNearby(from_id)) )
1780 {
1781 name = gRlvHandler.getAnonym(name);
1782 }
1783// [/RLVa:KB]
1691 } 1784 }
1692 else 1785 else
1693 { 1786 {
@@ -1732,13 +1825,23 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
1732 1825
1733 case IM_INVENTORY_ACCEPTED: 1826 case IM_INVENTORY_ACCEPTED:
1734 { 1827 {
1735 args["[NAME]"] = name; 1828// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.0b
1829 bool fRlvObfuscate = (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) &&
1830 (gRlvHandler.isAgentNearby(from_id)) && (!gAvatarInfoInstances.checkData(from_id));
1831 args["[NAME]"] = (!fRlvObfuscate) ? name : gRlvHandler.getAnonym(name);
1832// [/RLVa:KB]
1833// args["[NAME]"] = name;
1736 LLNotifyBox::showXml("InventoryAccepted", args); 1834 LLNotifyBox::showXml("InventoryAccepted", args);
1737 break; 1835 break;
1738 } 1836 }
1739 case IM_INVENTORY_DECLINED: 1837 case IM_INVENTORY_DECLINED:
1740 { 1838 {
1741 args["[NAME]"] = name; 1839// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.0b
1840 bool fRlvObfuscate = (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) &&
1841 (gRlvHandler.isAgentNearby(from_id)) && (!gAvatarInfoInstances.checkData(from_id));
1842 args["[NAME]"] = (!fRlvObfuscate) ? name : gRlvHandler.getAnonym(name);
1843// [/RLVa:KB]
1844// args["[NAME]"] = name;
1742 LLNotifyBox::showXml("InventoryDeclined", args); 1845 LLNotifyBox::showXml("InventoryDeclined", args);
1743 break; 1846 break;
1744 } 1847 }
@@ -1772,6 +1875,22 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
1772 return; 1875 return;
1773 } 1876 }
1774 1877
1878// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
1879 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) )
1880 {
1881 if (gAgent.isInGroup(session_id))
1882 {
1883 if (!gRlvHandler.isException(RLV_BHVR_RECVIM, session_id))
1884 return;
1885 }
1886 else
1887 {
1888 if ( (from_id != gAgent.getID()) && (!gRlvHandler.isException(RLV_BHVR_RECVIM, from_id)) )
1889 message = message.substr(0, message_offset) + rlv_handler_t::cstrBlockedRecvIM;
1890 }
1891 }
1892// [/RLVa:KB]
1893
1775 // standard message, not from system 1894 // standard message, not from system
1776 std::string saved; 1895 std::string saved;
1777 if(offline == IM_OFFLINE) 1896 if(offline == IM_OFFLINE)
@@ -1818,6 +1937,17 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
1818 return; 1937 return;
1819 } 1938 }
1820 { 1939 {
1940// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e)
1941 // TODO-RLVa: what actually generates this?
1942 if (rlv_handler_t::isEnabled())
1943 {
1944 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
1945 gRlvHandler.filterLocation(message);
1946 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
1947 gRlvHandler.filterNames(message);
1948 }
1949// [/RLVa:KB]
1950
1821 // Construct a viewer alert for this message. 1951 // Construct a viewer alert for this message.
1822 args["[NAME]"] = name; 1952 args["[NAME]"] = name;
1823 args["[MESSAGE]"] = message; 1953 args["[MESSAGE]"] = message;
@@ -1850,12 +1980,48 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
1850 } 1980 }
1851 else 1981 else
1852 { 1982 {
1853 // *TODO:translate -> [FIRST] [LAST] (maybe) 1983// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d)
1854 LLLureInfo* info = new LLLureInfo(from_id, session_id, FALSE); 1984 if (rlv_handler_t::isEnabled())
1855 args["[NAME]"] = name; 1985 {
1856 args["[MESSAGE]"] = message; 1986 // Disallow if: 1) @tplure=n restricted (sender isn't an exception), or 2) @unsit=n restricted and currently sitting
1857 LLNotifyBox::showXml("OfferTeleport", args, 1987 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
1858 lure_callback, (void*)info); 1988 if ( ( (gRlvHandler.hasBehaviour(RLV_BHVR_TPLURE)) && (!gRlvHandler.isException(RLV_BHVR_TPLURE, from_id)) ) ||
1989 ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (pAvatar) && (pAvatar->mIsSitting) ) )
1990 {
1991 rlvSendBusyMessage(from_id, rlv_handler_t::cstrMsgTpLure);
1992 return;
1993 }
1994
1995 // Censor teleport message if: 1) @revcim=n restricted (sender isn't an exception), or 2) @showloc=n restricted
1996 if ( ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) && (!gRlvHandler.isException(RLV_BHVR_RECVIM, from_id)) ) ||
1997 (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) )
1998 {
1999 message = rlv_handler_t::cstrHidden;
2000 }
2001 }
2002// [/RLVa:KB]
2003
2004// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.0b
2005 if ( (rlv_handler_t::isEnabled()) &&
2006 ((gRlvHandler.hasBehaviour(RLV_BHVR_ACCEPTTP)) || (gRlvHandler.isException(RLV_BHVR_ACCEPTTP, from_id))) )
2007 {
2008 gRlvHandler.setCanCancelTp(false);
2009 // (see IM_GODLIKE_LURE_USER below)
2010 LLLureInfo* info = new LLLureInfo(from_id, session_id, TRUE);
2011 lure_callback(0, (void*)info);
2012 }
2013 else
2014 {
2015// [/RLVa:KB]
2016 // *TODO:translate -> [FIRST] [LAST] (maybe)
2017 LLLureInfo* info = new LLLureInfo(from_id, session_id, FALSE);
2018 args["[NAME]"] = name;
2019 args["[MESSAGE]"] = message;
2020 LLNotifyBox::showXml("OfferTeleport", args,
2021 lure_callback, (void*)info);
2022// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.0b
2023 }
2024// [/RLVa:KB]
1859 } 2025 }
1860 } 2026 }
1861 break; 2027 break;
@@ -2200,8 +2366,13 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
2200 chat.mPosAgent = chatter->getPositionAgent(); 2366 chat.mPosAgent = chatter->getPositionAgent();
2201 2367
2202 // Make swirly things only for talking objects. (not script debug messages, though) 2368 // Make swirly things only for talking objects. (not script debug messages, though)
2203 if (chat.mSourceType == CHAT_SOURCE_OBJECT 2369// if (chat.mSourceType == CHAT_SOURCE_OBJECT
2204 && chat.mChatType != CHAT_TYPE_DEBUG_MSG) 2370// && chat.mChatType != CHAT_TYPE_DEBUG_MSG)
2371// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
2372 // Don't show swirly things for llOwnerSay() chat here because we handle those further down
2373 if ( (chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mChatType != CHAT_TYPE_DEBUG_MSG) &&
2374 ((!rlv_handler_t::isEnabled()) || (CHAT_TYPE_OWNER != chat.mChatType)) )
2375// [/RLVa:KB]
2205 { 2376 {
2206 LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent()); 2377 LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent());
2207 psc->setSourceObject(chatter); 2378 psc->setSourceObject(chatter);
@@ -2234,6 +2405,50 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
2234 color.setVec(1.f,1.f,1.f,1.f); 2405 color.setVec(1.f,1.f,1.f,1.f);
2235 msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, mesg); 2406 msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, mesg);
2236 2407
2408// [RLVa:KB] - Checked: 2009-08-04 (RLVa-1.0.1d) | Modified: RLVa-1.0.1d
2409 if ( (rlv_handler_t::isEnabled()) &&
2410 (CHAT_TYPE_START != chat.mChatType) && (CHAT_TYPE_STOP != chat.mChatType) && (CHAT_TYPE_OWNER != chat.mChatType) )
2411 {
2412 // NOTE: chatter can be NULL (may not have rezzed yet, or could be another avie's HUD attachment)
2413 BOOL is_attachment = (chatter) ? chatter->isAttachment() : FALSE;
2414
2415 // Filtering "rules":
2416 // avatar => filter all avie text (unless it's this avie or they're an exemption)
2417 // objects => filter everything except attachments this avie owns
2418 if ( ((CHAT_SOURCE_AGENT == chat.mSourceType) && (from_id != gAgent.getID())) || (!is_owned_by_me) || (!is_attachment) )
2419 {
2420 if (!rlvIsEmote(mesg))
2421 {
2422 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVCHAT)) && (!gRlvHandler.isException(RLV_BHVR_RECVCHAT, from_id)) )
2423 gRlvHandler.filterChat(mesg, false);
2424 }
2425 else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVEMOTE)) && (!gRlvHandler.isException(RLV_BHVR_RECVEMOTE, from_id)) )
2426 {
2427 mesg = "/me ...";
2428 }
2429 }
2430
2431 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
2432 {
2433 // Filtering "rules":
2434 // avatar => filter only their name (unless it's this avie)
2435 // other => filter everything except attachments this avie owns but then we still do filter their text
2436 if (CHAT_SOURCE_AGENT == chat.mSourceType)
2437 {
2438 if (chat.mFromID != gAgent.getID())
2439 from_name = gRlvHandler.getAnonym(from_name);
2440 }
2441 else
2442 {
2443 if ( (!is_owned_by_me) || (!is_attachment) )
2444 gRlvHandler.filterNames(from_name);
2445 gRlvHandler.filterNames(mesg);
2446 }
2447 chat.mRlvNamesFiltered = true;
2448 }
2449 }
2450// [/RLVa:KB]
2451
2237 BOOL ircstyle = FALSE; 2452 BOOL ircstyle = FALSE;
2238 2453
2239 // Look for IRC-style emotes here so chatbubbles work 2454 // Look for IRC-style emotes here so chatbubbles work
@@ -2298,8 +2513,76 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
2298 case CHAT_TYPE_WHISPER: 2513 case CHAT_TYPE_WHISPER:
2299 verb = " " + LLTrans::getString("whisper") + " "; 2514 verb = " " + LLTrans::getString("whisper") + " ";
2300 break; 2515 break;
2301 case CHAT_TYPE_DEBUG_MSG:
2302 case CHAT_TYPE_OWNER: 2516 case CHAT_TYPE_OWNER:
2517// [RLVa:KB] - Checked: 2009-08-05 (RLVa-1.0.1e) | Modified: RLVa-1.0.1e
2518 if ( (rlv_handler_t::isEnabled()) && (mesg.length() > 3) && (RLV_CMD_PREFIX == mesg[0]) )
2519 {
2520 mesg.erase(0, 1);
2521 LLStringUtil::toLower(mesg);
2522
2523 std::string strExecuted, strFailed, strRetained, *pstr;
2524
2525 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
2526 boost::char_separator<char> sep(",", "", boost::drop_empty_tokens);
2527 tokenizer tokens(mesg, sep);
2528 for (tokenizer::iterator itToken = tokens.begin(); itToken != tokens.end(); ++itToken)
2529 {
2530 if (LLStartUp::getStartupState() == STATE_STARTED)
2531 {
2532 if (gRlvHandler.processCommand(from_id, *itToken, true))
2533 pstr = &strExecuted;
2534 else
2535 pstr = &strFailed;
2536 }
2537 else
2538 {
2539 gRlvHandler.retainCommand(from_name, from_id, *itToken);
2540 pstr = &strRetained;
2541 }
2542
2543 if (!pstr->empty())
2544 pstr->push_back(',');
2545 pstr->append(*itToken);
2546 }
2547
2548 if (!RlvSettings::getDebug())
2549 return;
2550
2551 // Silly people want comprehensive debug messages, blah :p
2552 if ( (!strExecuted.empty()) && (strFailed.empty()) && (strRetained.empty()) )
2553 verb = " executes: @";
2554 else if ( (strExecuted.empty()) && (!strFailed.empty()) && (strRetained.empty()) )
2555 verb = " failed: @";
2556 else if ( (strExecuted.empty()) && (strFailed.empty()) && (!strRetained.empty()) )
2557 verb = " retained: @";
2558 else
2559 {
2560 verb = ": @";
2561 if (!strExecuted.empty())
2562 mesg += "\n - executed: @" + strExecuted;
2563 if (!strFailed.empty())
2564 mesg += "\n - failed: @" + strFailed;
2565 if (!strRetained.empty())
2566 mesg += "\n - retained: @" + strRetained;
2567 }
2568
2569 break;
2570 }
2571// [/RLVa:KB]
2572// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
2573 // Copy/paste from above
2574 if ( (chatter) && (chat.mChatType != CHAT_TYPE_DEBUG_MSG) )
2575 {
2576 LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent());
2577 psc->setSourceObject(chatter);
2578 psc->setColor(color);
2579 //We set the particles to be owned by the object's owner,
2580 //just in case they should be muted by the mute list
2581 psc->setOwnerUUID(owner_id);
2582 LLViewerPartSim::getInstance()->addPartSource(psc);
2583 }
2584// [/RLVa:KB]
2585 case CHAT_TYPE_DEBUG_MSG:
2303 case CHAT_TYPE_NORMAL: 2586 case CHAT_TYPE_NORMAL:
2304 verb = ": "; 2587 verb = ": ";
2305 break; 2588 break;
@@ -2368,7 +2651,10 @@ void process_teleport_start(LLMessageSystem *msg, void**)
2368 U32 teleport_flags = 0x0; 2651 U32 teleport_flags = 0x0;
2369 msg->getU32("Info", "TeleportFlags", teleport_flags); 2652 msg->getU32("Info", "TeleportFlags", teleport_flags);
2370 2653
2371 if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) 2654 //if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL)
2655// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.0b
2656 if ( (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) || (!gRlvHandler.getCanCancelTp()) )
2657// [/RLVa:KB]
2372 { 2658 {
2373 gViewerWindow->setProgressCancelButtonVisible(FALSE); 2659 gViewerWindow->setProgressCancelButtonVisible(FALSE);
2374 } 2660 }
@@ -2403,7 +2689,10 @@ void process_teleport_progress(LLMessageSystem* msg, void**)
2403 } 2689 }
2404 U32 teleport_flags = 0x0; 2690 U32 teleport_flags = 0x0;
2405 msg->getU32("Info", "TeleportFlags", teleport_flags); 2691 msg->getU32("Info", "TeleportFlags", teleport_flags);
2406 if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) 2692 //if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL)
2693// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.0b
2694 if ( (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) || (!gRlvHandler.getCanCancelTp()) )
2695// [/RLVa:KB]
2407 { 2696 {
2408 gViewerWindow->setProgressCancelButtonVisible(FALSE); 2697 gViewerWindow->setProgressCancelButtonVisible(FALSE);
2409 } 2698 }
@@ -2740,7 +3029,10 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
2740 // know what you look like. 3029 // know what you look like.
2741 gAgent.sendAgentSetAppearance(); 3030 gAgent.sendAgentSetAppearance();
2742 3031
2743 if (avatarp) 3032// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
3033 if ( (avatarp) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) )
3034// [/RLVa:KB]
3035// if (avatarp)
2744 { 3036 {
2745 // Chat the "back" SLURL. (DEV-4907) 3037 // Chat the "back" SLURL. (DEV-4907)
2746 LLChat chat("Teleport completed from " + gAgent.getTeleportSourceSLURL()); 3038 LLChat chat("Teleport completed from " + gAgent.getTeleportSourceSLURL());
@@ -4320,7 +4612,13 @@ void notify_cautioned_script_question(LLScriptQuestionCBData* cbdata, S32 orig_q
4320 if (viewregion) 4612 if (viewregion)
4321 { 4613 {
4322 // got the region, so include the region and 3d coordinates of the object 4614 // got the region, so include the region and 3d coordinates of the object
4323 notice.setArg("[REGIONNAME]", viewregion->getName()); 4615 notice.setArg("[REGIONNAME]", viewregion->getName());
4616// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
4617 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) )
4618 {
4619 notice.setArg("[REGIONNAME]", rlv_handler_t::cstrHiddenRegion);
4620 }
4621// [/RLVa:KB]
4324 std::string formatpos = llformat("%.1f, %.1f,%.1f", objpos[VX], objpos[VY], objpos[VZ]); 4622 std::string formatpos = llformat("%.1f, %.1f,%.1f", objpos[VX], objpos[VY], objpos[VZ]);
4325 notice.setArg("[REGIONPOS]", formatpos); 4623 notice.setArg("[REGIONPOS]", formatpos);
4326 4624
@@ -4525,8 +4823,31 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
4525 4823
4526 LLScriptQuestionCBData *cbdata = new LLScriptQuestionCBData(taskid, itemid, sender, questions, object_name, owner_name); 4824 LLScriptQuestionCBData *cbdata = new LLScriptQuestionCBData(taskid, itemid, sender, questions, object_name, owner_name);
4527 4825
4826// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0e
4827 S32 rlvQuestionsOther = questions;
4828
4829 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour("acceptpermission")) )
4830 {
4831 LLViewerObject* pObj = gObjectList.findObject(taskid);
4832 if (pObj)
4833 {
4834 if (pObj->permYouOwner())
4835 {
4836 // PERMISSION_TAKE_CONTROLS and PERMISSION_ATTACH are only auto-granted to objects this avie owns
4837 rlvQuestionsOther &= ~(LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TAKE_CONTROLS] |
4838 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_ATTACH]);
4839 }
4840 }
4841 }
4842
4843 if ( (!caution) && (!rlvQuestionsOther) )
4844 {
4845 script_question_cb(0, cbdata);
4846 }
4847 else if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
4848// [/RLVa:KB]
4528 // check whether cautions are even enabled or not 4849 // check whether cautions are even enabled or not
4529 if (gSavedSettings.getBOOL("PermissionsCautionEnabled")) 4850 //if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
4530 { 4851 {
4531 if (caution) 4852 if (caution)
4532 { 4853 {
@@ -4818,6 +5139,21 @@ void handle_lure_callback(S32 option, const std::string& text, void* userdata)
4818 5139
4819 if(0 == option) 5140 if(0 == option)
4820 { 5141 {
5142// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0b
5143 bool fRlvCensorMessage = false;
5144 if (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIM))
5145 {
5146 for (LLDynamicArray<LLUUID>::iterator it = invitees->begin(); it != invitees->end(); ++it)
5147 {
5148 if (!gRlvHandler.isException(RLV_BHVR_SENDIM, *it))
5149 {
5150 fRlvCensorMessage = true;
5151 break;
5152 }
5153 }
5154 }
5155// [/RLVa:KB]
5156
4821 LLMessageSystem* msg = gMessageSystem; 5157 LLMessageSystem* msg = gMessageSystem;
4822 msg->newMessageFast(_PREHASH_StartLure); 5158 msg->newMessageFast(_PREHASH_StartLure);
4823 msg->nextBlockFast(_PREHASH_AgentData); 5159 msg->nextBlockFast(_PREHASH_AgentData);
@@ -4825,7 +5161,10 @@ void handle_lure_callback(S32 option, const std::string& text, void* userdata)
4825 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); 5161 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
4826 msg->nextBlockFast(_PREHASH_Info); 5162 msg->nextBlockFast(_PREHASH_Info);
4827 msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in. 5163 msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in.
4828 msg->addStringFast(_PREHASH_Message, text); 5164// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0b
5165 msg->addStringFast(_PREHASH_Message, (!fRlvCensorMessage) ? text : rlv_handler_t::cstrHidden);
5166// [/RLVa:KB]
5167 //msg->addStringFast(_PREHASH_Message, text);
4829 for(LLDynamicArray<LLUUID>::iterator itr = invitees->begin(); itr != invitees->end(); ++itr) 5168 for(LLDynamicArray<LLUUID>::iterator itr = invitees->begin(); itr != invitees->end(); ++itr)
4830 { 5169 {
4831 msg->nextBlockFast(_PREHASH_TargetData); 5170 msg->nextBlockFast(_PREHASH_TargetData);
@@ -4855,8 +5194,28 @@ void handle_lure(LLDynamicArray<LLUUID>& ids)
4855{ 5194{
4856 LLDynamicArray<LLUUID>* userdata = new LLDynamicArray<LLUUID>(ids); 5195 LLDynamicArray<LLUUID>* userdata = new LLDynamicArray<LLUUID>(ids);
4857 5196
5197// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-1.0.0a
5198 // Only allow offering teleports if everyone is a @tplure exception or able to map this avie under @showloc=n
5199 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
5200 {
5201 for (LLDynamicArray<LLUUID>::iterator it = ids.begin(); it != ids.end(); ++it)
5202 {
5203 const LLRelationship* pBuddyInfo = LLAvatarTracker::instance().getBuddyInfo(*it);
5204 if ( (!gRlvHandler.isException(RLV_BHVR_TPLURE, *it)) &&
5205 ((!pBuddyInfo) || (!pBuddyInfo->isOnline()) || (!pBuddyInfo->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION))) )
5206 {
5207 delete userdata;
5208 return;
5209 }
5210 }
5211 }
5212// [/RLVa:KB]
5213
4858 LLStringUtil::format_map_t edit_args; 5214 LLStringUtil::format_map_t edit_args;
4859 edit_args["[REGION]"] = gAgent.getRegion()->getName(); 5215// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-1.0.0a
5216 edit_args["[REGION]"] = (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? gAgent.getRegion()->getName() : rlv_handler_t::cstrHidden;
5217// [/RLVa:KB]
5218 //edit_args["[REGION]"] = gAgent.getRegion()->getName();
4860 if (gAgent.isGodlike()) 5219 if (gAgent.isGodlike())
4861 { 5220 {
4862 gViewerWindow->alertXmlEditText("OfferTeleportFromGod", edit_args, 5221 gViewerWindow->alertXmlEditText("OfferTeleportFromGod", edit_args,
diff --git a/linden/indra/newview/llviewerobject.cpp b/linden/indra/newview/llviewerobject.cpp
index ca7055a..102b135 100644
--- a/linden/indra/newview/llviewerobject.cpp
+++ b/linden/indra/newview/llviewerobject.cpp
@@ -1006,6 +1006,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
1006 coloru.mV[3] = 255 - coloru.mV[3]; 1006 coloru.mV[3] = 255 - coloru.mV[3];
1007 mText->setColor(LLColor4(coloru)); 1007 mText->setColor(LLColor4(coloru));
1008 mText->setStringUTF8(temp_string); 1008 mText->setStringUTF8(temp_string);
1009// [RLVa:KB] - Checked: 2009-07-09 (RLVa-1.0.0f) | Added: RLVa-1.0.0f
1010 if (rlv_handler_t::isEnabled())
1011 {
1012 mText->setObjectText(temp_string);
1013 }
1014// [/RLVa:KB]
1009 1015
1010 if (mDrawable.notNull()) 1016 if (mDrawable.notNull())
1011 { 1017 {
@@ -1423,6 +1429,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
1423 coloru.mV[3] = 255 - coloru.mV[3]; 1429 coloru.mV[3] = 255 - coloru.mV[3];
1424 mText->setColor(LLColor4(coloru)); 1430 mText->setColor(LLColor4(coloru));
1425 mText->setStringUTF8(temp_string); 1431 mText->setStringUTF8(temp_string);
1432// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-09 (RLVa-1.0.0f) | Added: RLVa-1.0.0f
1433 if (rlv_handler_t::isEnabled())
1434 {
1435 mText->setObjectText(temp_string);
1436 }
1437// [/RLVa:KB]
1426 1438
1427 setChanged(TEXTURE); 1439 setChanged(TEXTURE);
1428 } 1440 }
@@ -4795,7 +4807,10 @@ BOOL LLViewerObject::permTransfer() const
4795// given you modify rights to. JC 4807// given you modify rights to. JC
4796BOOL LLViewerObject::allowOpen() const 4808BOOL LLViewerObject::allowOpen() const
4797{ 4809{
4798 return !flagInventoryEmpty() && (permYouOwner() || permModify()); 4810// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b)
4811 return !flagInventoryEmpty() && (permYouOwner() || permModify()) && (!gRlvHandler.hasBehaviour(RLV_BHVR_EDIT));
4812// [/RLVa:KB]
4813// return !flagInventoryEmpty() && (permYouOwner() || permModify());
4799} 4814}
4800 4815
4801LLViewerObject::LLInventoryCallbackInfo::~LLInventoryCallbackInfo() 4816LLViewerObject::LLInventoryCallbackInfo::~LLInventoryCallbackInfo()
diff --git a/linden/indra/newview/llviewertexteditor.cpp b/linden/indra/newview/llviewertexteditor.cpp
index 3e2cc19..cef6926 100644
--- a/linden/indra/newview/llviewertexteditor.cpp
+++ b/linden/indra/newview/llviewertexteditor.cpp
@@ -95,6 +95,13 @@ public:
95 } 95 }
96 else 96 else
97 { 97 {
98// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
99 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour("viewnote")) )
100 {
101 return;
102 }
103// [/RLVa:KB]
104
98 // See if we can bring an existing preview to the front 105 // See if we can bring an existing preview to the front
99 if(!LLPreview::show(item->getUUID(), true)) 106 if(!LLPreview::show(item->getUUID(), true))
100 { 107 {
diff --git a/linden/indra/newview/llviewerwindow.cpp b/linden/indra/newview/llviewerwindow.cpp
index 7e6c24f..0ab4ab6 100644
--- a/linden/indra/newview/llviewerwindow.cpp
+++ b/linden/indra/newview/llviewerwindow.cpp
@@ -3248,6 +3248,16 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls,
3248 { 3248 {
3249 moveable_object_selected = TRUE; 3249 moveable_object_selected = TRUE;
3250 this_object_movable = TRUE; 3250 this_object_movable = TRUE;
3251
3252// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0g
3253 if ( (rlv_handler_t::isEnabled()) &&
3254 ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP))) )
3255 {
3256 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
3257 if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == object->getRootEdit()) )
3258 moveable_object_selected = this_object_movable = FALSE;
3259 }
3260// [/RLVa:KB]
3251 } 3261 }
3252 all_selected_objects_move = all_selected_objects_move && this_object_movable; 3262 all_selected_objects_move = all_selected_objects_move && this_object_movable;
3253 all_selected_objects_modify = all_selected_objects_modify && object->permModify(); 3263 all_selected_objects_modify = all_selected_objects_modify && object->permModify();
diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp
index 3d2523e..158977e 100644
--- a/linden/indra/newview/llvoavatar.cpp
+++ b/linden/indra/newview/llvoavatar.cpp
@@ -125,6 +125,10 @@
125#include "llvoicevisualizer.h" 125#include "llvoicevisualizer.h"
126#include "llvoiceclient.h" 126#include "llvoiceclient.h"
127 127
128// [RLVa:KB]
129#include "llstartup.h"
130// [/RLVa:KB]
131
128LLXmlTree LLVOAvatar::sXMLTree; 132LLXmlTree LLVOAvatar::sXMLTree;
129LLXmlTree LLVOAvatar::sSkeletonXMLTree; 133LLXmlTree LLVOAvatar::sSkeletonXMLTree;
130LLVOAvatarSkeletonInfo* LLVOAvatar::sSkeletonInfo = NULL; 134LLVOAvatarSkeletonInfo* LLVOAvatar::sSkeletonInfo = NULL;
@@ -2093,9 +2097,15 @@ void LLVOAvatar::buildCharacter()
2093 if (attachment->getGroup() == i) 2097 if (attachment->getGroup() == i)
2094 { 2098 {
2095 LLMenuItemCallGL* item; 2099 LLMenuItemCallGL* item;
2100// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
2101 // We need the userdata param to disable options in this pie menu later on (Left Hand / Right Hand option)
2096 item = new LLMenuItemCallGL(attachment->getName(), 2102 item = new LLMenuItemCallGL(attachment->getName(),
2097 NULL, 2103 NULL,
2098 object_selected_and_point_valid); 2104 object_selected_and_point_valid, attachment);
2105// [/RLVa:KB]
2106// item = new LLMenuItemCallGL(attachment->getName(),
2107// NULL,
2108// object_selected_and_point_valid);
2099 item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", curiter->first); 2109 item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", curiter->first);
2100 2110
2101 gAttachPieMenu->append(item); 2111 gAttachPieMenu->append(item);
@@ -2150,9 +2160,15 @@ void LLVOAvatar::buildCharacter()
2150 if (attachment->getGroup() == 8) 2160 if (attachment->getGroup() == 8)
2151 { 2161 {
2152 LLMenuItemCallGL* item; 2162 LLMenuItemCallGL* item;
2163// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
2164 // We need the userdata param to disable options in this pie menu later on
2153 item = new LLMenuItemCallGL(attachment->getName(), 2165 item = new LLMenuItemCallGL(attachment->getName(),
2154 NULL, 2166 NULL,
2155 object_selected_and_point_valid); 2167 object_selected_and_point_valid, attachment);
2168// [/RLVa:KB]
2169// item = new LLMenuItemCallGL(attachment->getName(),
2170// NULL,
2171// object_selected_and_point_valid);
2156 item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", curiter->first); 2172 item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", curiter->first);
2157 gAttachScreenPieMenu->append(item); 2173 gAttachScreenPieMenu->append(item);
2158 gDetachScreenPieMenu->append(new LLMenuItemCallGL(attachment->getName(), 2174 gDetachScreenPieMenu->append(new LLMenuItemCallGL(attachment->getName(),
@@ -2171,6 +2187,7 @@ void LLVOAvatar::buildCharacter()
2171 { 2187 {
2172 continue; 2188 continue;
2173 } 2189 }
2190 // RELEASE-RLVa: random comment because we want know if LL ever changes this to not include "attachment" as userdata
2174 LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(), 2191 LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(),
2175 NULL, &object_selected_and_point_valid, 2192 NULL, &object_selected_and_point_valid,
2176 &attach_label, attachment); 2193 &attach_label, attachment);
@@ -2230,8 +2247,13 @@ void LLVOAvatar::buildCharacter()
2230 LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attach_index, (LLViewerJointAttachment*)NULL); 2247 LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attach_index, (LLViewerJointAttachment*)NULL);
2231 if (attachment) 2248 if (attachment)
2232 { 2249 {
2250// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
2251 // We need the userdata param to disable options in this pie menu later on
2233 LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(), 2252 LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(),
2234 NULL, object_selected_and_point_valid); 2253 NULL, object_selected_and_point_valid, attachment);
2254// [/RLVa:KB]
2255// LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(),
2256// NULL, object_selected_and_point_valid);
2235 gAttachBodyPartPieMenus[group]->append(item); 2257 gAttachBodyPartPieMenus[group]->append(item);
2236 item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", attach_index); 2258 item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", attach_index);
2237 gDetachBodyPartPieMenus[group]->append(new LLMenuItemCallGL(attachment->getName(), 2259 gDetachBodyPartPieMenus[group]->append(new LLMenuItemCallGL(attachment->getName(),
@@ -3089,10 +3111,16 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
3089 const F32 time_visible = mTimeVisible.getElapsedTimeF32(); 3111 const F32 time_visible = mTimeVisible.getElapsedTimeF32();
3090 const F32 NAME_SHOW_TIME = gSavedSettings.getF32("RenderNameShowTime"); // seconds 3112 const F32 NAME_SHOW_TIME = gSavedSettings.getF32("RenderNameShowTime"); // seconds
3091 const F32 FADE_DURATION = gSavedSettings.getF32("RenderNameFadeDuration"); // seconds 3113 const F32 FADE_DURATION = gSavedSettings.getF32("RenderNameFadeDuration"); // seconds
3114// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b
3115 bool fRlvShowNames = gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES);
3116// [/RLVa:KB]
3092 BOOL visible_avatar = isVisible() || mNeedsAnimUpdate; 3117 BOOL visible_avatar = isVisible() || mNeedsAnimUpdate;
3093 BOOL visible_chat = gSavedSettings.getBOOL("UseChatBubbles") && (mChats.size() || mTyping); 3118 BOOL visible_chat = gSavedSettings.getBOOL("UseChatBubbles") && (mChats.size() || mTyping);
3094 BOOL render_name = visible_chat || 3119 BOOL render_name = visible_chat ||
3095 (visible_avatar && 3120 (visible_avatar &&
3121// [RLVa:KB] - Checked: 2009-08-11 (RLVa-1.0.1h) | Added: RLVa-1.0.0h
3122 ( (!fRlvShowNames) || (RlvSettings::fShowNameTags) ) &&
3123// [/RLVa:KB]
3096 ((sRenderName == RENDER_NAME_ALWAYS) || 3124 ((sRenderName == RENDER_NAME_ALWAYS) ||
3097 (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME))); 3125 (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME)));
3098 // If it's your own avatar, don't draw in mouselook, and don't 3126 // If it's your own avatar, don't draw in mouselook, and don't
@@ -3113,7 +3141,18 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
3113 new_name = TRUE; 3141 new_name = TRUE;
3114 } 3142 }
3115 3143
3116 if (sRenderGroupTitles != mRenderGroupTitles) 3144// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b
3145 if (fRlvShowNames)
3146 {
3147 if (mRenderGroupTitles)
3148 {
3149 mRenderGroupTitles = FALSE;
3150 new_name = TRUE;
3151 }
3152 }
3153 else if (sRenderGroupTitles != mRenderGroupTitles)
3154// [/RLVa]
3155 //if (sRenderGroupTitles != mRenderGroupTitles)
3117 { 3156 {
3118 mRenderGroupTitles = sRenderGroupTitles; 3157 mRenderGroupTitles = sRenderGroupTitles;
3119 new_name = TRUE; 3158 new_name = TRUE;
@@ -3218,6 +3257,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
3218 || is_appearance != mNameAppearance) 3257 || is_appearance != mNameAppearance)
3219 { 3258 {
3220 std::string line; 3259 std::string line;
3260
3221 if (title && title->getString() && title->getString()[0] != '\0') 3261 if (title && title->getString() && title->getString()[0] != '\0')
3222 { 3262 {
3223 line += title->getString(); 3263 line += title->getString();
@@ -3232,6 +3272,15 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
3232 3272
3233 line += " "; 3273 line += " ";
3234 line += lastname->getString(); 3274 line += lastname->getString();
3275
3276// [RLVa:KB]
3277 if (fRlvShowNames)
3278 {
3279 // User is not allowed to see who it is, due to RLV settings.
3280 line = gRlvHandler.getAnonym(line);
3281 }
3282// [/RLVa:KB]
3283
3235 BOOL need_comma = FALSE; 3284 BOOL need_comma = FALSE;
3236 3285
3237 if (is_away || is_muted || is_busy) 3286 if (is_away || is_muted || is_busy)
@@ -6328,6 +6377,40 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object)
6328 { 6377 {
6329 updateAttachmentVisibility(gAgent.getCameraMode()); 6378 updateAttachmentVisibility(gAgent.getCameraMode());
6330 6379
6380// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
6381 if (rlv_handler_t::isEnabled())
6382 {
6383 static bool fRlvFullyLoaded = false;
6384 static LLFrameTimer* pRlvFullyLoadedTimer = NULL;
6385
6386 // 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
6387 if (!fRlvFullyLoaded)
6388 {
6389 if (pRlvFullyLoadedTimer)
6390 {
6391 if (pRlvFullyLoadedTimer->getElapsedTimeF32() > 30.0f)
6392 {
6393 fRlvFullyLoaded = true;
6394 delete pRlvFullyLoadedTimer;
6395 pRlvFullyLoadedTimer = NULL;
6396 }
6397 else
6398 {
6399 pRlvFullyLoadedTimer->reset();
6400 }
6401 }
6402 else if ( (!pRlvFullyLoadedTimer) &&
6403 ( (0 == mPendingAttachment.size()) ||
6404 ((1 == mPendingAttachment.size()) && (mPendingAttachment[0] == viewer_object)) ) )
6405 {
6406 pRlvFullyLoadedTimer = new LLFrameTimer();
6407 }
6408 }
6409
6410 gRlvHandler.onAttach(attachment, fRlvFullyLoaded);
6411 }
6412// [/RLVa:KB]
6413
6331 // Then make sure the inventory is in sync with the avatar. 6414 // Then make sure the inventory is in sync with the avatar.
6332 gInventory.addChangedMask( LLInventoryObserver::LABEL, attachment->getItemID() ); 6415 gInventory.addChangedMask( LLInventoryObserver::LABEL, attachment->getItemID() );
6333 gInventory.notifyObservers(); 6416 gInventory.notifyObservers();
@@ -6383,6 +6466,14 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
6383 // only one object per attachment point for now 6466 // only one object per attachment point for now
6384 if (attachment->getObject() == viewer_object) 6467 if (attachment->getObject() == viewer_object)
6385 { 6468 {
6469// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
6470 // URGENT-RLV: it looks like LLApp::isExiting() isn't always accurate so find something better (if it exists)
6471 if ( (rlv_handler_t::isEnabled()) && (!LLApp::isExiting()) && (mIsSelf) )
6472 {
6473 gRlvHandler.onDetach(attachment);
6474 }
6475// [/RLVa:KB]
6476
6386 LLUUID item_id = attachment->getItemID(); 6477 LLUUID item_id = attachment->getItemID();
6387 attachment->removeObject(viewer_object); 6478 attachment->removeObject(viewer_object);
6388 if (mIsSelf) 6479 if (mIsSelf)
@@ -6441,6 +6532,14 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)
6441 6532
6442 gPipeline.markMoved(mDrawable, TRUE); 6533 gPipeline.markMoved(mDrawable, TRUE);
6443 mIsSitting = TRUE; 6534 mIsSitting = TRUE;
6535// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.1d
6536 #ifdef RLV_EXTENSION_STARTLOCATION
6537 if (rlv_handler_t::isEnabled())
6538 {
6539 RlvSettings::updateLoginLastLocation();
6540 }
6541 #endif // RLV_EXTENSION_STARTLOCATION
6542// [/RLVa:KB]
6444 mRoot.getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject 6543 mRoot.getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject
6445 mRoot.setPosition(getPosition()); 6544 mRoot.setPosition(getPosition());
6446 mRoot.updateWorldMatrixChildren(); 6545 mRoot.updateWorldMatrixChildren();
@@ -6502,6 +6601,14 @@ void LLVOAvatar::getOffObject()
6502 gPipeline.markMoved(mDrawable, TRUE); 6601 gPipeline.markMoved(mDrawable, TRUE);
6503 6602
6504 mIsSitting = FALSE; 6603 mIsSitting = FALSE;
6604// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.1d
6605 #ifdef RLV_EXTENSION_STARTLOCATION
6606 if (rlv_handler_t::isEnabled())
6607 {
6608 RlvSettings::updateLoginLastLocation();
6609 }
6610 #endif // RLV_EXTENSION_STARTLOCATION
6611// [/RLVa:KB]
6505 mRoot.getXform()->setParent(NULL); // LLVOAvatar::getOffObject 6612 mRoot.getXform()->setParent(NULL); // LLVOAvatar::getOffObject
6506 mRoot.setPosition(cur_position_world); 6613 mRoot.setPosition(cur_position_world);
6507 mRoot.setRotation(cur_rotation_world); 6614 mRoot.setRotation(cur_rotation_world);
diff --git a/linden/indra/newview/llvovolume.cpp b/linden/indra/newview/llvovolume.cpp
index ad44356..adf82cd 100644
--- a/linden/indra/newview/llvovolume.cpp
+++ b/linden/indra/newview/llvovolume.cpp
@@ -1942,7 +1942,11 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
1942 1942
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)
1947 ( (gHideSelectedObjects && isSelected()) &&
1948 ((!rlv_handler_t::isEnabled()) || (!isHUDAttachment()) || (gRlvHandler.isDetachable(this))) ) ||
1949// [/RLVa:KB]
1946 mDrawable->isDead() || 1950 mDrawable->isDead() ||
1947 !gPipeline.hasRenderType(mDrawable->getRenderType())) 1951 !gPipeline.hasRenderType(mDrawable->getRenderType()))
1948 { 1952 {
@@ -2084,10 +2088,18 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
2084{ 2088{
2085 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 2089 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
2086 2090
2087 if (facep->getViewerObject()->isSelected() && gHideSelectedObjects) 2091// if (facep->getViewerObject()->isSelected() && gHideSelectedObjects)
2092// {
2093// return;
2094// }
2095// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
2096 LLViewerObject* pObj = facep->getViewerObject();
2097 if ( (pObj->isSelected() && gHideSelectedObjects) &&
2098 ((!rlv_handler_t::isEnabled()) || (!pObj->isHUDAttachment()) || (gRlvHandler.isDetachable(pObj))) )
2088 { 2099 {
2089 return; 2100 return;
2090 } 2101 }
2102// [/RVLa:KB]
2091 2103
2092 //add face to drawmap 2104 //add face to drawmap
2093 LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[type]; 2105 LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[type];
diff --git a/linden/indra/newview/llworldmapview.cpp b/linden/indra/newview/llworldmapview.cpp
index 77833c3..5e51e6f 100644
--- a/linden/indra/newview/llworldmapview.cpp
+++ b/linden/indra/newview/llworldmapview.cpp
@@ -640,7 +640,14 @@ void LLWorldMapView::draw()
640 // info->mAgents, 640 // info->mAgents,
641 // info->mName.c_str(), 641 // info->mName.c_str(),
642 // LLViewerRegion::accessToShortString(info->mAccess).c_str() ); 642 // LLViewerRegion::accessToShortString(info->mAccess).c_str() );
643 if (info->mAccess == SIM_ACCESS_DOWN) 643// [RLVa:KB] - Alternate: Snowglobe-1.0 | Checked: 2009-07-04 (RLVa-1.0.0a)
644 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
645 {
646 mesg = rlv_handler_t::cstrHidden;
647 }
648 else if (info->mAccess == SIM_ACCESS_DOWN)
649// [/RLVa:KB]
650// if (info->mAccess == SIM_ACCESS_DOWN)
644 { 651 {
645 mesg = llformat( "%s (%s)", info->mName.c_str(), sStringsMap["offline"].c_str()); 652 mesg = llformat( "%s (%s)", info->mName.c_str(), sStringsMap["offline"].c_str());
646 } 653 }
@@ -1069,7 +1076,10 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4&
1069 text_x = llclamp(text_x, half_text_width + TEXT_PADDING, getRect().getWidth() - half_text_width - TEXT_PADDING); 1076 text_x = llclamp(text_x, half_text_width + TEXT_PADDING, getRect().getWidth() - half_text_width - TEXT_PADDING);
1070 text_y = llclamp(text_y + vert_offset, TEXT_PADDING + vert_offset, getRect().getHeight() - llround(font->getLineHeight()) - TEXT_PADDING - vert_offset); 1077 text_y = llclamp(text_y + vert_offset, TEXT_PADDING + vert_offset, getRect().getHeight() - llround(font->getLineHeight()) - TEXT_PADDING - vert_offset);
1071 1078
1072 if (label != "") 1079 //if (label != "")
1080// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-1.0.0a
1081 if ( (label != "") && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) )
1082// [/RLVa:KB]
1073 { 1083 {
1074 font->renderUTF8( 1084 font->renderUTF8(
1075 label, 0, 1085 label, 0,
@@ -1129,7 +1139,10 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* stic
1129 1139
1130 std::string message = 1140 std::string message =
1131 llformat("%s (%s)", 1141 llformat("%s (%s)",
1132 info->mName.c_str(), 1142 //info->mName.c_str(),
1143// [RLVa:KB] - Alternate: Snowglobe-1.0 | Checked: 2009-07-04 (RLVa-1.0.0a)
1144 (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? info->mName.c_str() : rlv_handler_t::cstrHidden.c_str(),
1145// [/RLVa:KB]
1133 LLViewerRegion::accessToString(info->mAccess).c_str()); 1146 LLViewerRegion::accessToString(info->mAccess).c_str());
1134 1147
1135 if (info->mAccess != SIM_ACCESS_DOWN) 1148 if (info->mAccess != SIM_ACCESS_DOWN)
diff --git a/linden/indra/newview/pipeline.cpp b/linden/indra/newview/pipeline.cpp
index 87b810c..67af961 100644
--- a/linden/indra/newview/pipeline.cpp
+++ b/linden/indra/newview/pipeline.cpp
@@ -1795,8 +1795,13 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
1795 1795
1796 if (gHideSelectedObjects) 1796 if (gHideSelectedObjects)
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)
1801 LLViewerObject* pObj = drawablep->getVObj();
1802 if ( (pObj) && (pObj->isSelected()) &&
1803 ((!rlv_handler_t::isEnabled()) || (!pObj->isHUDAttachment()) || (gRlvHandler.isDetachable(pObj))) )
1804// [/RVLa:KB]
1800 { 1805 {
1801 return; 1806 return;
1802 } 1807 }
diff --git a/linden/indra/newview/rlvevent.h b/linden/indra/newview/rlvevent.h
new file mode 100644
index 0000000..c3d9c45
--- /dev/null
+++ b/linden/indra/newview/rlvevent.h
@@ -0,0 +1,224 @@
1#ifndef RLV_EVENTEMITTER_H
2#define RLV_EVENTEMITTER_H
3
4#include <algorithm>
5#include <typeinfo>
6#include <list>
7
8#include "lluuid.h"
9
10#include "rlvhelper.h"
11
12// ============================================================================
13/*
14 * RlvEvent
15 * ========
16 * Passed to observer event handlers (contains the same paramaters as RlvHandler::processXXXCommand)
17 */
18
19class RlvEvent
20{
21public:
22 RlvEvent(const LLUUID& uuid, const RlvCommand& rlvCmd) : m_UUID(uuid), m_rlvCmd(rlvCmd) {}
23 virtual ~RlvEvent() {}
24
25 const LLUUID& getSenderID() const { return m_UUID; };
26 const RlvCommand& getCommand() const { return m_rlvCmd; };
27
28protected:
29 LLUUID m_UUID;
30 RlvCommand m_rlvCmd;
31};
32
33// ============================================================================
34/*
35 * RlvObserver
36 * ===========
37 * Provides a way to extend the existing command set without changing the main RlvHandler class
38 *
39 * Steps:
40 * - derive your class from RlvObserver
41 * - override any of the event functions you need
42 * - add it as an observer: gRlvHandler.addObserver(new RlbObserverDerivedClass());
43 * - done
44 *
45 * Notes:
46 * - as long as you don't call gRlvHandler.remObserver() your class will be cleaned up from
47 * RlvEventEmitter destructor (see below)
48 * - event handlers are called only if RlvHandler didn't handle it so while you can
49 * add a new command @foobar=n, you won't get called for @detach=n
50 * - event handlers are called *after* the command is added so a call to
51 * RlvHandler::hasBehaviour("foobar") would return TRUE
52 * - return TRUE if you handled the command (won't get passed on to the next observer)
53 * return FALSE if you didn't handle the command (gets passed on to the next observer)
54 *
55 */
56
57class RlvObserver
58{
59public:
60 virtual ~RlvObserver() {}
61
62 typedef RlvEvent EventType;
63
64 virtual BOOL onAddCommand(const EventType& rlvEvent) { return FALSE; }
65 virtual BOOL onRemoveCommand(const EventType& rlvEvent) { return FALSE; }
66 virtual BOOL onReplyCommand(const EventType& rlvEvent) { return FALSE; }
67 virtual BOOL onForceCommand(const EventType& rlvEvent) { return FALSE; }
68};
69
70// ============================================================================
71/*
72 * RlvEventEmitter
73 * ===============
74 * Essentially a slightly modified eventEmitter (see lleventemitter.h)
75 *
76 * Changes:
77 * - if an event handler returns TRUE then no further observers are notified
78 * - cleans up the (remaining) observers in the destructor
79 */
80
81template < class T >
82class RlvEventEmitter
83{
84 public:
85 typedef typename T::EventType EventType;
86 typedef std::list< T* > ObserverContainer;
87 typedef BOOL ( T::*observerMethod )( const EventType& );
88
89 protected:
90 ObserverContainer observers;
91
92 public:
93 RlvEventEmitter() { };
94
95 ~RlvEventEmitter()
96 {
97 clearObservers();
98 }
99
100 BOOL addObserver ( T* observerIn )
101 {
102 if ( ! observerIn )
103 return FALSE;
104
105 // check if observer already exists
106 if ( std::find ( observers.begin (), observers.end (), observerIn ) != observers.end () )
107 return FALSE;
108
109 // save it
110 observers.push_back ( observerIn );
111
112 return true;
113 }
114
115 BOOL remObserver ( T* observerIn )
116 {
117 if ( ! observerIn )
118 return FALSE;
119
120 observers.remove ( observerIn );
121
122 return TRUE;
123 }
124
125 void clearObservers()
126 {
127 typename std::list< T* >::iterator iter = observers.begin ();
128
129 while (iter != observers.end ())
130 {
131 delete *iter;
132 ++iter;
133 };
134
135 observers.clear();
136 }
137
138 BOOL update ( observerMethod method, const EventType& msgIn )
139 {
140 typename std::list< T* >::iterator iter = observers.begin ();
141
142 BOOL fContinue = TRUE;
143 while ( (iter != observers.end ()) && (fContinue) )
144 {
145 fContinue = !( ( ( *iter )->*method ) ( msgIn ) );
146 ++iter;
147 };
148
149 return !fContinue;
150 }
151};
152
153// ============================================================================
154
155class RlvBehaviourObserver
156{
157public:
158 virtual ~RlvBehaviourObserver() {}
159 virtual void changed(const RlvCommand& rlvCmd, bool fInternal) = 0;
160};
161
162// ============================================================================
163
164class RlvBehaviourNotifyObserver : public RlvBehaviourObserver
165{
166public:
167 virtual ~RlvBehaviourNotifyObserver() { }
168
169 void changed(const RlvCommand& rlvCmd, bool fInternal)
170 {
171 if ( (fInternal) || ((RLV_TYPE_ADD != rlvCmd.getParamType()) && (RLV_TYPE_REMOVE != rlvCmd.getParamType())) )
172 return;
173
174 std::string strCmd = rlvCmd.asString();
175 std::string strNotify = llformat("/%s=%c", strCmd.c_str(), (RLV_TYPE_ADD == rlvCmd.getParamType()) ? 'n' : 'y');
176
177 for (std::multimap<LLUUID, notifyData>::const_iterator itNotify = m_Notifications.begin();
178 itNotify != m_Notifications.end(); ++itNotify)
179 {
180 if ( (itNotify->second.strFilter.empty()) || (std::string::npos != strCmd.find(itNotify->second.strFilter)) )
181 rlvSendChatReply(itNotify->second.nChannel, strNotify);
182 }
183 }
184
185 void addNotify(const LLUUID& idObj, S32 nChannel, const std::string& strFilter)
186 {
187 m_Notifications.insert(std::pair<LLUUID, notifyData>(idObj, notifyData(nChannel, strFilter)));
188 }
189
190 void clearNotify(const LLUUID& idObj)
191 {
192 m_Notifications.erase(idObj);
193 }
194
195 bool hasNotify()
196 {
197 return (m_Notifications.size() != 0);
198 }
199
200 void removeNotify(const LLUUID& idObj, S32 nChannel, const std::string& strFilter)
201 {
202 for (std::multimap<LLUUID, notifyData>::iterator itNotify = m_Notifications.lower_bound(idObj),
203 endNotify = m_Notifications.upper_bound(idObj); itNotify != endNotify; ++itNotify)
204 {
205 if ( (itNotify->second.nChannel == nChannel) && (itNotify->second.strFilter == strFilter) )
206 {
207 m_Notifications.erase(itNotify);
208 break;
209 }
210 }
211 }
212protected:
213 struct notifyData
214 {
215 S32 nChannel;
216 std::string strFilter;
217 notifyData(S32 channel, const std::string& filter) : nChannel(channel), strFilter(filter) {}
218 };
219 std::multimap<LLUUID, notifyData> m_Notifications;
220};
221
222// ============================================================================
223
224#endif // RLV_EVENTEMITTER_H
diff --git a/linden/indra/newview/rlvextensions.cpp b/linden/indra/newview/rlvextensions.cpp
new file mode 100644
index 0000000..6f79636
--- /dev/null
+++ b/linden/indra/newview/rlvextensions.cpp
@@ -0,0 +1,454 @@
1#include "llviewerprecompiledheaders.h"
2#include "llagent.h"
3#include "llviewercontrol.h"
4#include "llviewerwindow.h"
5#include "llvoavatar.h"
6#include "llwlparammanager.h"
7
8#include "rlvextensions.h"
9#include "rlvhandler.h"
10
11// ============================================================================
12
13std::map<std::string, S16> RlvExtGetSet::m_DbgAllowed;
14
15// Checked: 2009-06-03 (RLVa-0.2.0h) | Modified: RLVa-0.2.0h
16RlvExtGetSet::RlvExtGetSet()
17{
18 if (!m_DbgAllowed.size()) // m_DbgAllowed is static and should only be initialized once
19 {
20 m_DbgAllowed.insert(std::pair<std::string, S16>("AvatarSex", DBG_READ | DBG_PSEUDO));
21 m_DbgAllowed.insert(std::pair<std::string, S16>("RenderResolutionDivisor", DBG_READ | DBG_WRITE));
22 #ifdef RLV_EXTENSION_CMD_GETSETDEBUG_EX
23 m_DbgAllowed.insert(std::pair<std::string, S16>(RLV_SETTING_FORBIDGIVETORLV, DBG_READ));
24 m_DbgAllowed.insert(std::pair<std::string, S16>(RLV_SETTING_NOSETENV, DBG_READ));
25 m_DbgAllowed.insert(std::pair<std::string, S16>("WindLightUseAtmosShaders", DBG_READ));
26 #endif // RLV_EXTENSION_CMD_GETSETDEBUG_EX
27
28 // Cache persistance of every setting
29 LLControlVariable* pSetting;
30 for (std::map<std::string, S16>::iterator itDbg = m_DbgAllowed.begin(); itDbg != m_DbgAllowed.end(); ++itDbg)
31 {
32 if ( ((pSetting = gSavedSettings.getControl(itDbg->first)) != NULL) && (pSetting->isPersisted()) )
33 itDbg->second |= DBG_PERSIST;
34 }
35 }
36}
37
38// Checked: 2009-05-17 (RLVa-0.2.0a)
39BOOL RlvExtGetSet::onForceCommand(const RlvEvent& rlvEvent)
40{
41 return processCommand(rlvEvent.getSenderID(), rlvEvent.getCommand());
42}
43
44// Checked: 2009-05-17 (RLVa-0.2.0a)
45BOOL RlvExtGetSet::onReplyCommand(const EventType& rlvEvent)
46{
47 return processCommand(rlvEvent.getSenderID(), rlvEvent.getCommand());
48}
49
50// Checked: 2009-06-18 (RLVa-0.2.1d) | Modified: RLVa-0.2.1d
51BOOL RlvExtGetSet::processCommand(const LLUUID& idObj, const RlvCommand& rlvCmd)
52{
53 std::string strBehaviour = rlvCmd.getBehaviour(), strGetSet, strSetting;
54 int idxSetting = strBehaviour.find('_');
55 if ( (strBehaviour.length() >= 6) && (-1 != idxSetting) && ((int)strBehaviour.length() > idxSetting + 1) )
56 {
57 strSetting = strBehaviour.substr(idxSetting + 1);
58 strBehaviour.erase(idxSetting); // Get rid of "_<setting>"
59
60 strGetSet = strBehaviour.substr(0, 3);
61 strBehaviour.erase(0, 3); // Get rid of get/set
62
63 if ("debug" == strBehaviour)
64 {
65 if ( ("get" == strGetSet) && (RLV_TYPE_REPLY == rlvCmd.getParamType()) )
66 {
67 rlvSendChatReply(rlvCmd.getParam(), onGetDebug(strSetting));
68 return TRUE;
69 }
70 else if ( ("set" == strGetSet) && (RLV_TYPE_FORCE == rlvCmd.getParamType()) )
71 {
72 if (!gRlvHandler.hasBehaviourExcept(RLV_BHVR_SETDEBUG, idObj))
73 onSetDebug(strSetting, rlvCmd.getOption());
74 return TRUE;
75 }
76 }
77 else if ("env" == strBehaviour)
78 {
79 if ( ("get" == strGetSet) && (RLV_TYPE_REPLY == rlvCmd.getParamType()) )
80 {
81 rlvSendChatReply(rlvCmd.getParam(), onGetEnv(strSetting));
82 return TRUE;
83 }
84 else if ( ("set" == strGetSet) && (RLV_TYPE_FORCE == rlvCmd.getParamType()) )
85 {
86 if (!gRlvHandler.hasBehaviourExcept(RLV_BHVR_SETENV, idObj))
87 onSetEnv(strSetting, rlvCmd.getOption());
88 return TRUE;
89 }
90 }
91 }
92 else if ("setrot" == rlvCmd.getBehaviour())
93 {
94 // NOTE: if <option> is invalid (or missing) altogether then RLV-1.17 will rotate to 0.0 (which is actually PI / 4)
95 F32 nAngle = 0.0f;
96 if (LLStringUtil::convertToF32(rlvCmd.getOption(), nAngle))
97 {
98 nAngle += RLV_SETROT_OFFSET;
99
100 gAgent.startCameraAnimation();
101
102 LLVector3 at(LLVector3::x_axis);
103 at.rotVec(nAngle, LLVector3::z_axis);
104 at.normalize();
105 gAgent.resetAxes(at);
106
107 return TRUE;
108 }
109 }
110 return FALSE;
111}
112
113// Checked: 2009-06-03 (RLVa-0.2.0h) | Modified: RLVa-0.2.0h
114bool RlvExtGetSet::findDebugSetting(std::string& strSetting, S16& flags)
115{
116 LLStringUtil::toLower(strSetting); // Convenience for non-RLV calls
117
118 std::string strTemp;
119 for (std::map<std::string, S16>::const_iterator itSetting = m_DbgAllowed.begin(); itSetting != m_DbgAllowed.end(); ++itSetting)
120 {
121 strTemp = itSetting->first;
122 LLStringUtil::toLower(strTemp);
123
124 if (strSetting == strTemp)
125 {
126 strSetting = itSetting->first;
127 flags = itSetting->second;
128 return true;
129 }
130 }
131 return false;
132}
133
134// Checked: 2009-06-03 (RLVa-0.2.0h) | Added: RLVa-0.2.0h
135S16 RlvExtGetSet::getDebugSettingFlags(const std::string& strSetting)
136{
137 std::map<std::string, S16>::const_iterator itSetting = m_DbgAllowed.find(strSetting);
138 return (itSetting != m_DbgAllowed.end()) ? itSetting->second : 0;
139}
140
141// Checked: 2009-06-03 (RLVa-0.2.0h) | Modified: RLVa-0.2.0h
142std::string RlvExtGetSet::onGetDebug(std::string strSetting)
143{
144 S16 dbgFlags;
145 if ( (findDebugSetting(strSetting, dbgFlags)) && ((dbgFlags & DBG_READ) == DBG_READ) )
146 {
147 if ((dbgFlags & DBG_PSEUDO) == 0)
148 {
149 LLControlVariable* pSetting = gSavedSettings.getControl(strSetting);
150 if (pSetting)
151 {
152 switch (pSetting->type())
153 {
154 case TYPE_U32:
155 return llformat("%u", gSavedSettings.getU32(strSetting));
156 case TYPE_S32:
157 return llformat("%d", gSavedSettings.getS32(strSetting));
158 case TYPE_BOOLEAN:
159 return llformat("%d", gSavedSettings.getBOOL(strSetting));
160 default:
161 RLV_ERRS << "Unexpected debug setting type" << LL_ENDL;
162 break;
163 }
164 }
165 }
166 else
167 {
168 return onGetPseudoDebug(strSetting);
169 }
170 }
171 return std::string();
172}
173
174// Checked: 2009-06-03 (RLVa-0.2.0h) | Added: RLVa-0.2.0h
175std::string RlvExtGetSet::onGetPseudoDebug(const std::string& strSetting)
176{
177 // Skip sanity checking because it's all done in RlvExtGetSet::onGetDebug() already
178 if ("AvatarSex" == strSetting)
179 {
180 if (gAgent.getAvatarObject())
181 return llformat("%d", (gAgent.getAvatarObject()->getSex() == SEX_MALE)); // [See LLFloaterCustomize::LLFloaterCustomize()]
182 }
183 return std::string();
184}
185
186// Checked: 2009-06-03 (RLVa-0.2.0h) | Modified: RLVa-0.2.0h
187void RlvExtGetSet::onSetDebug(std::string strSetting, const std::string& strValue)
188{
189 S16 dbgFlags;
190 if ( (findDebugSetting(strSetting, dbgFlags)) && ((dbgFlags & DBG_WRITE) == DBG_WRITE) )
191 {
192 if ((dbgFlags & DBG_PSEUDO) == 0)
193 {
194 LLControlVariable* pSetting = gSavedSettings.getControl(strSetting);
195 if (pSetting)
196 {
197 U32 u32Value; S32 s32Value; BOOL fValue;
198 switch (pSetting->type())
199 {
200 case TYPE_U32:
201 if (LLStringUtil::convertToU32(strValue, u32Value))
202 gSavedSettings.setU32(strSetting, u32Value);
203 break;
204 case TYPE_S32:
205 if (LLStringUtil::convertToS32(strValue, s32Value))
206 gSavedSettings.setS32(strSetting, s32Value);
207 break;
208 case TYPE_BOOLEAN:
209 if (LLStringUtil::convertToBOOL(strValue, fValue))
210 gSavedSettings.setBOOL(strSetting, fValue);
211 break;
212 default:
213 RLV_ERRS << "Unexpected debug setting type" << LL_ENDL;
214 break;
215 }
216
217 // Default settings should persist if they were marked that way, but non-default settings should never persist
218 pSetting->setPersist( (pSetting->isDefault()) ? ((dbgFlags & DBG_PERSIST) == DBG_PERSIST) : false );
219 }
220 }
221 }
222}
223
224std::string RlvExtGetSet::onGetEnv(std::string strSetting)
225{
226 LLWLParamManager* pWLParams = LLWLParamManager::instance();
227
228 F32 nValue = 0.0f;
229 if ("daytime" == strSetting)
230 {
231 nValue = (pWLParams->mAnimator.mIsRunning && pWLParams->mAnimator.mUseLindenTime) ? -1.0f : pWLParams->mAnimator.getDayTime();
232 }
233 else if ("preset" == strSetting)
234 {
235 return (pWLParams->mAnimator.mIsRunning && pWLParams->mAnimator.mUseLindenTime) ? std::string() : pWLParams->mCurParams.mName;
236 }
237 else if ("cloudcoverage" == strSetting) nValue = pWLParams->mCloudCoverage;
238 else if ("cloudscale" == strSetting) nValue = pWLParams->mCloudScale;
239 else if ("cloudscrollx" == strSetting) nValue = pWLParams->mCurParams.getCloudScrollX() - 10.0f;
240 else if ("cloudscrolly" == strSetting) nValue = pWLParams->mCurParams.getCloudScrollY() - 10.0f;
241 else if ("densitymultiplier" == strSetting) nValue = pWLParams->mDensityMult * 1000;
242 else if ("distancemultiplier" == strSetting) nValue = pWLParams->mDistanceMult;
243 else if ("eastangle" == strSetting) nValue = pWLParams->mCurParams.getEastAngle() / F_TWO_PI;
244 else if ("hazedensity" == strSetting) nValue = pWLParams->mHazeDensity.r;
245 else if ("hazehorizon" == strSetting) nValue = pWLParams->mHazeHorizon.r;
246 else if ("maxaltitude" == strSetting) nValue = pWLParams->mMaxAlt;
247 else if ("scenegamma" == strSetting) nValue = pWLParams->mWLGamma;
248 else if ("starbrightness" == strSetting) nValue = pWLParams->mCurParams.getStarBrightness();
249 else if ("sunglowfocus" == strSetting) nValue = -pWLParams->mGlow.b / 5.0f;
250 else if ("sunglowsize" == strSetting) nValue = 2 - pWLParams->mGlow.r / 20.0f;
251 else if ("sunmoonposition" == strSetting) nValue = pWLParams->mCurParams.getSunAngle() / F_TWO_PI;
252 else
253 {
254 char ch = strSetting[strSetting.length() - 1];
255 // HACK-RLVa: not entirely proper (creates new synonyms)
256 if ('x' == ch) ch = 'r';
257 else if ('y' == ch) ch = 'g';
258 else if ('d' == ch) ch = 'b';
259
260 if ( ('r' == ch) || ('g' == ch) || ('b' == ch) || ('i' == ch) )
261 {
262 WLColorControl* pColour = NULL;
263 strSetting.erase(strSetting.length() - 2, 1);
264
265 if ("ambient" == strSetting) pColour = &pWLParams->mAmbient;
266 else if ("bluedensity" == strSetting) pColour = &pWLParams->mBlueDensity;
267 else if ("bluehorizon" == strSetting) pColour = &pWLParams->mBlueHorizon;
268 else if ("sunmooncolor" == strSetting) pColour = &pWLParams->mSunlight;
269 else if ("cloudcolor" == strSetting) pColour = &pWLParams->mCloudColor;
270 else if ("cloud" == strSetting) pColour = &pWLParams->mCloudMain;
271 else if ("clouddetail" == strSetting) pColour = &pWLParams->mCloudDetail;
272
273 if (pColour)
274 {
275 if ('r' == ch) nValue = pColour->b;
276 else if ('g' == ch) nValue = pColour->b;
277 else if ('b' == ch) nValue = pColour->b;
278 else if (('i' == ch) && (pColour->hasSliderName)) nValue = pColour->i;
279
280 if (pColour->isBlueHorizonOrDensity) nValue /= 2.0f;
281 else if (pColour->isSunOrAmbientColor) nValue /= 3.0f;
282 }
283 }
284 }
285
286 return llformat("%f", nValue);
287}
288
289void RlvExtGetSet::onSetEnv(std::string strSetting, const std::string& strValue)
290{
291 LLWLParamManager* pWLParams = LLWLParamManager::instance();
292 WLFloatControl* pFloat = NULL;
293 WLColorControl* pColour = NULL;
294
295 F32 nValue = 0.0f;
296 // Sanity check - make sure strValue specifies a number for all settings except "preset"
297 if ( (rlv_handler_t::fNoSetEnv) || ( (!LLStringUtil::convertToF32(strValue, nValue)) && ("preset" != strSetting) ))
298 return;
299
300 // Not quite correct, but RLV-1.16.0 will halt the default daytime cycle on invalid commands so we need to as well
301 pWLParams->mAnimator.mIsRunning = false;
302 pWLParams->mAnimator.mUseLindenTime = false;
303
304 // See LLWorldEnvSettings::handleEvent()
305 if ("daytime" == strSetting)
306 {
307 if (0.0f <= nValue)
308 {
309 pWLParams->mAnimator.setDayTime(llmin(nValue, 1.0f));
310 pWLParams->mAnimator.update(pWLParams->mCurParams);
311 }
312 else
313 {
314 pWLParams->mAnimator.mIsRunning = true;
315 pWLParams->mAnimator.mUseLindenTime = true;
316 }
317 return;
318 }
319 // See LLFloaterWindLight::onChangePresetName()
320 else if ("preset" == strSetting)
321 {
322 pWLParams->loadPreset(strValue, true);
323 return;
324 }
325 // See LLFloaterWindLight::onStarAlphaMoved
326 else if ("starbrightness" == strSetting)
327 {
328 pWLParams->mCurParams.setStarBrightness(nValue);
329 return;
330 }
331 // See LLFloaterWindLight::onGlowRMoved() / LLFloaterWindLight::onGlowBMoved()
332 else if ( ("sunglowfocus" == strSetting) || ("sunglowsize" == strSetting) )
333 {
334 WLColorControl *pColour = &pWLParams->mGlow;
335 if ("sunglowfocus" == strSetting)
336 pColour->b = -nValue * 5;
337 else
338 pColour->r = (2 - nValue) * 20;
339
340 pColour->update(pWLParams->mCurParams);
341 pWLParams->propagateParameters();
342 return;
343 }
344 // See LLFloaterWindLight::onSunMoved()
345 else if ( ("eastangle" == strSetting) || ("sunmoonposition" == strSetting) )
346 {
347 if ("eastangle" == strSetting)
348 pWLParams->mCurParams.setEastAngle(F_TWO_PI * nValue);
349 else
350 pWLParams->mCurParams.setSunAngle(F_TWO_PI * nValue);
351
352 // TODO-RLVa: it looks like propagateParameters() will actually take care of this for us, making this redundant?
353 WLColorControl* pColour = &pWLParams->mLightnorm;
354 pColour->r = -sin(pWLParams->mCurParams.getEastAngle()) * cos(pWLParams->mCurParams.getSunAngle());
355 pColour->g = sin(pWLParams->mCurParams.getSunAngle());
356 pColour->b = cos(pWLParams->mCurParams.getEastAngle()) * cos(pWLParams->mCurParams.getSunAngle());
357 pColour->i = 1.f;
358
359 pColour->update(pWLParams->mCurParams);
360 pWLParams->propagateParameters();
361 return;
362 }
363 // See LLFloaterWindLight::onCloudScrollXMoved() / LLFloaterWindLight::onCloudScrollYMoved()
364 else if ("cloudscrollx" == strSetting)
365 {
366 pWLParams->mCurParams.setCloudScrollX(nValue + 10.0f);
367 return;
368 }
369 else if ("cloudscrolly" == strSetting)
370 {
371 pWLParams->mCurParams.setCloudScrollY(nValue + 10.0f);
372 return;
373 }
374 // See LLFloaterWindLight::onFloatControlMoved()
375 else if ("cloudcoverage" == strSetting) pFloat = &pWLParams->mCloudCoverage;
376 else if ("cloudscale" == strSetting) pFloat = &pWLParams->mCloudScale;
377 else if ("densitymultiplier" == strSetting) pFloat = &pWLParams->mDensityMult;
378 else if ("distancemultiplier" == strSetting) pFloat = &pWLParams->mDistanceMult;
379 else if ("maxaltitude" == strSetting) pFloat = &pWLParams->mMaxAlt;
380 else if ("scenegamma" == strSetting) pFloat = &pWLParams->mWLGamma;
381 // See LLFloaterWindLight::onColorControlRMoved()
382 else if ("hazedensity" == strSetting) pColour = &pWLParams->mHazeDensity;
383 else if ("hazehorizon" == strSetting) pColour = &pWLParams->mHazeHorizon;
384
385 if (pFloat)
386 {
387 pFloat->x = nValue / pFloat->mult;
388 pFloat->update(pWLParams->mCurParams);
389 pWLParams->propagateParameters();
390 return;
391 }
392 else if (pColour)
393 {
394 pColour->r = nValue;
395 pColour->update(pWLParams->mCurParams);
396 pWLParams->propagateParameters();
397 return;
398 }
399
400 // RGBI settings
401 char ch = strSetting[strSetting.length() - 1];
402 if ('x' == ch) ch = 'r';
403 else if ('y' == ch) ch = 'g';
404 else if ('d' == ch) ch = 'b';
405
406 if ( ('r' == ch) || ('g' == ch) || ('b' == ch) || ('i' == ch) )
407 {
408 strSetting.erase(strSetting.length() - 2, 1);
409
410 if ("ambient" == strSetting) pColour = &pWLParams->mAmbient;
411 else if ("bluedensity" == strSetting) pColour = &pWLParams->mBlueDensity;
412 else if ("bluehorizon" == strSetting) pColour = &pWLParams->mBlueHorizon;
413 else if ("sunmooncolor" == strSetting) pColour = &pWLParams->mSunlight;
414 else if ("cloudcolor" == strSetting) pColour = &pWLParams->mCloudColor;
415 else if ("cloud" == strSetting) pColour = &pWLParams->mCloudMain;
416 else if ("clouddetail" == strSetting) pColour = &pWLParams->mCloudDetail;
417
418 if (pColour)
419 {
420 if (pColour->isBlueHorizonOrDensity) nValue *= 2.0f;
421 else if (pColour->isSunOrAmbientColor) nValue *= 3.0f;
422
423 if ('i' == ch) // (See: LLFloaterWindLight::onColorControlIMoved)
424 {
425 if (!pColour->hasSliderName)
426 return;
427
428 F32 curMax = llmax(pColour->r, pColour->g, pColour->b);
429 if ( (0.0f == nValue) || (0.0f == curMax) )
430 pColour->r = pColour->g = pColour->b = pColour->i = nValue;
431 else
432 {
433 F32 nDelta = (nValue - curMax) / curMax;
434 pColour->r *= (1.0f + nDelta);
435 pColour->g *= (1.0f + nDelta);
436 pColour->b *= (1.0f + nDelta);
437 pColour->i = nValue;
438 }
439 }
440 else // (See: LLFloaterWindLight::onColorControlRMoved)
441 {
442 F32* pnValue = ('r' == ch) ? &pColour->r : ('g' == ch) ? &pColour->g : ('b' == ch) ? &pColour->b : NULL;
443 if (pnValue)
444 *pnValue = nValue;
445 pColour->i = llmax(pColour->r, pColour->g, pColour->b);
446 }
447
448 pColour->update(pWLParams->mCurParams);
449 pWLParams->propagateParameters();
450 }
451 }
452}
453
454// ============================================================================
diff --git a/linden/indra/newview/rlvextensions.h b/linden/indra/newview/rlvextensions.h
new file mode 100644
index 0000000..5c10c58
--- /dev/null
+++ b/linden/indra/newview/rlvextensions.h
@@ -0,0 +1,43 @@
1#ifndef RLV_EXTENSIONS_H
2#define RLV_EXTENSIONS_H
3
4#include "rlvhelper.h"
5#include "rlvevent.h"
6
7// ============================================================================
8/*
9 * RlvExtGetSet
10 * ============
11 * Implements @get_XXX:<option>=<channel> and @set_XXX:<option>=force
12 *
13 */
14
15class RlvExtGetSet : public RlvObserver
16{
17public:
18 RlvExtGetSet();
19 virtual ~RlvExtGetSet() {}
20
21 virtual BOOL onForceCommand(const RlvEvent& rlvEvent);
22 virtual BOOL onReplyCommand(const RlvEvent& rlvEvent);
23protected:
24 std::string onGetDebug(std::string strSetting);
25 std::string onGetPseudoDebug(const std::string& strSetting);
26 void onSetDebug(std::string strSetting, const std::string& strValue);
27
28 std::string onGetEnv(std::string strSetting);
29 void onSetEnv(std::string strSetting, const std::string& strValue);
30
31 BOOL processCommand(const LLUUID& idObj, const RlvCommand& rlvCmd);
32
33public:
34 enum { DBG_READ = 0x01, DBG_WRITE = 0x02, DBG_PERSIST = 0x04, DBG_PSEUDO = 0x08 };
35 static std::map<std::string, S16> m_DbgAllowed;
36
37 static bool findDebugSetting(/*[in,out]*/ std::string& strSetting, /*[out]*/ S16& flags);
38 static S16 getDebugSettingFlags(const std::string& strSetting);
39};
40
41// ============================================================================
42
43#endif // RLV_EXTENSIONS_H
diff --git a/linden/indra/newview/rlvfloaterbehaviour.cpp b/linden/indra/newview/rlvfloaterbehaviour.cpp
new file mode 100644
index 0000000..39fcf12
--- /dev/null
+++ b/linden/indra/newview/rlvfloaterbehaviour.cpp
@@ -0,0 +1,152 @@
1#include "llviewerprecompiledheaders.h"
2
3#include "llagent.h"
4#include "llcachename.h"
5#include "llscrolllistctrl.h"
6#include "lluictrlfactory.h"
7#include "llviewerinventory.h"
8#include "llviewerobjectlist.h"
9#include "llvoavatar.h"
10
11#include "rlvfloaterbehaviour.h"
12
13// ============================================================================
14
15RlvFloaterBehaviour::RlvFloaterBehaviour(const LLSD& key)
16 : LLFloater(std::string("rlvBehaviours"))
17{
18 LLUICtrlFactory::getInstance()->buildFloater(this, "floater_rlv_behaviour.xml");
19}
20
21
22void RlvFloaterBehaviour::show(void*)
23{
24 RlvFloaterBehaviour::showInstance();
25}
26
27void RlvFloaterBehaviour::refreshAll()
28{
29 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
30 LLCtrlListInterface* pList = childGetListInterface("behaviour_list");
31 const rlv_object_map_t* pRlvObjects = gRlvHandler.getObjectMap();
32 if ( (!pAvatar) || (!pList) || (!pRlvObjects) )
33 return;
34
35 pList->operateOnAll(LLCtrlListInterface::OP_DELETE);
36
37 for (rlv_object_map_t::const_iterator itObj = pRlvObjects->begin(), endObj = pRlvObjects->end(); itObj != endObj; ++itObj)
38 {
39 std::string strName = itObj->first.asString();
40
41 LLViewerInventoryItem* pItem = NULL;
42 LLViewerObject* pObj = gObjectList.findObject(itObj->first);
43 if (pObj)
44 {
45 LLViewerJointAttachment* pAttachPt =
46 get_if_there(pAvatar->mAttachmentPoints, gRlvHandler.getAttachPointIndex(pObj), (LLViewerJointAttachment*)NULL);
47 if (pAttachPt)
48 {
49 pItem = gInventory.getItem(pAttachPt->getItemID());
50 }
51 }
52
53 if (pItem)
54 strName = pItem->getName();
55
56 const rlv_command_list_t* pCommands = itObj->second.getCommandList();
57 for (rlv_command_list_t::const_iterator itCmd = pCommands->begin(), endCmd = pCommands->end(); itCmd != endCmd; ++itCmd)
58 {
59 std::string strBhvr = itCmd->asString(); LLUUID uuid(itCmd->getOption());
60 if (uuid.notNull())
61 {
62 std::string strLookup;
63 if ( (gCacheName->getFullName(uuid, strLookup)) || (gCacheName->getGroupName(uuid, strLookup)) )
64 {
65 if (strLookup.find("???") == std::string::npos)
66 strBhvr.assign(itCmd->getBehaviour()).append(":").append(strLookup);
67 }
68 else if (m_PendingLookup.end() == std::find(m_PendingLookup.begin(), m_PendingLookup.end(), uuid))
69 {
70 gCacheName->get(uuid, FALSE, onAvatarNameLookup, this);
71 m_PendingLookup.push_back(uuid);
72 }
73 }
74
75 LLSD element;
76
77 // Restriction column
78 element["columns"][0]["column"] = "behaviour";
79 element["columns"][0]["value"] = strBhvr;
80 element["columns"][0]["font"] = "SANSSERIF";
81 element["columns"][0]["font-style"] = "NORMAL";
82
83 // Object Name column
84 element["columns"][1]["column"] = "name";
85 element["columns"][1]["value"] = strName;
86 element["columns"][1]["font"] = "SANSSERIF";
87 element["columns"][1]["font-style"] = "NORMAL";
88
89 pList->addElement(element, ADD_BOTTOM);
90 }
91 }
92}
93
94// ============================================================================
95/*
96 * LLFloater overrides
97 */
98
99BOOL RlvFloaterBehaviour::canClose()
100{
101 return !LLApp::isExiting();
102}
103
104void RlvFloaterBehaviour::onOpen()
105{
106 gRlvHandler.addBehaviourObserver(this);
107
108 refreshAll();
109}
110
111void RlvFloaterBehaviour::onClose(bool fQuitting)
112{
113 LLFloater::setVisible(FALSE);
114
115 gRlvHandler.removeBehaviourObserver(this);
116
117 for (std::list<LLUUID>::const_iterator itLookup = m_PendingLookup.begin(); itLookup != m_PendingLookup.end(); ++itLookup)
118 {
119 gCacheName->cancelCallback(*itLookup, onAvatarNameLookup, this);
120 }
121 m_PendingLookup.clear();
122}
123
124BOOL RlvFloaterBehaviour::postBuild()
125{
126 return TRUE;
127}
128
129// ============================================================================
130/*
131 * RlvBehaviourObserver overrides
132 */
133
134void RlvFloaterBehaviour::changed(const RlvCommand& /*rlvCmd*/, bool /*fInternal*/)
135{
136 refreshAll();
137}
138
139// ============================================================================
140
141void RlvFloaterBehaviour::onAvatarNameLookup(const LLUUID& uuid, const std::string& strFirst, const std::string& strLast, BOOL fGroup, void* pParam)
142{
143 RlvFloaterBehaviour* pSelf = (RlvFloaterBehaviour*)pParam;
144
145 std::list<LLUUID>::iterator itLookup = std::find(pSelf->m_PendingLookup.begin(), pSelf->m_PendingLookup.end(), uuid);
146 if (itLookup != pSelf->m_PendingLookup.end())
147 pSelf->m_PendingLookup.erase(itLookup);
148
149 pSelf->refreshAll();
150}
151
152// ============================================================================
diff --git a/linden/indra/newview/rlvfloaterbehaviour.h b/linden/indra/newview/rlvfloaterbehaviour.h
new file mode 100644
index 0000000..1410dd5
--- /dev/null
+++ b/linden/indra/newview/rlvfloaterbehaviour.h
@@ -0,0 +1,49 @@
1#ifndef RLV_FLOATER_BEHAVIOUR
2#define RLV_FLOATER_BEHAVIOUR
3
4#include "llfloater.h"
5#include "rlvevent.h"
6
7// ============================================================================
8
9class RlvFloaterBehaviour :
10 public LLFloater,
11 public LLFloaterSingleton<RlvFloaterBehaviour>,
12 public RlvBehaviourObserver
13{
14 friend class LLUISingleton<RlvFloaterBehaviour, VisibilityPolicy<LLFloater> >;
15public:
16 virtual ~RlvFloaterBehaviour() {}
17
18 /*
19 * LLFloater overrides
20 */
21public:
22 /*virtual*/ BOOL canClose();
23 /*virtual*/ void onOpen();
24 /*virtual*/ void onClose(bool app_quitting);
25 /*virtual*/ BOOL postBuild();
26
27 /*
28 * RlvBehaviourObserver overrides
29 */
30public:
31 /*virtual*/ void changed(const RlvCommand& rlvCmd, bool fInternal);
32
33 /*
34 * Member functions
35 */
36public:
37 static void show(void*);
38 static void onAvatarNameLookup(const LLUUID& uuid, const std::string& strFirst, const std::string& strLast, BOOL fGroup, void* pParam);
39protected:
40 void refreshAll();
41private:
42 RlvFloaterBehaviour(const LLSD& key = LLSD());
43
44 std::list<LLUUID> m_PendingLookup;
45};
46
47// ============================================================================
48
49#endif // RLV_FLOATER_BEHAVIOUR
diff --git a/linden/indra/newview/rlvhandler.cpp b/linden/indra/newview/rlvhandler.cpp
new file mode 100644
index 0000000..2915002
--- /dev/null
+++ b/linden/indra/newview/rlvhandler.cpp
@@ -0,0 +1,2549 @@
1#include "llviewerprecompiledheaders.h"
2#include "llagent.h"
3#include "lldrawpoolalpha.h"
4#include "llfloaterbeacons.h"
5#include "llfloaterchat.h"
6#include "llfloaterdaycycle.h"
7#include "llfloaterenvsettings.h"
8#include "llfloatergodtools.h"
9#include "llfloaterland.h"
10#include "llfloatermap.h"
11#include "llfloaterregioninfo.h"
12#include "llfloatertools.h"
13#include "llfloaterwater.h"
14#include "llfloaterwindlight.h"
15#include "llfloaterworldmap.h"
16#include "llgesturemgr.h"
17#include "llinventoryview.h"
18#include "llstartup.h"
19#include "llviewermenu.h"
20#include "llviewermessage.h"
21#include "llviewerparcelmgr.h"
22#include "llviewerregion.h"
23#include "llviewerwindow.h"
24#include "llvoavatar.h"
25#include "llworld.h"
26#include "pipeline.h"
27
28#include "rlvhelper.h"
29#include "rlvevent.h"
30#include "rlvextensions.h"
31#include "rlvhandler.h"
32
33// Only defined in llinventorybridge.cpp
34#if RLV_TARGET < RLV_MAKE_TARGET(1, 23, 0) // Version: 1.22.11
35 #include "llinventorybridge.h"
36 void confirm_replace_attachment_rez(S32 option, void* user_data);
37#endif
38// Only defined in llinventorymodel.cpp
39extern const char* NEW_CATEGORY_NAME;
40
41// ============================================================================
42// Static variable initialization
43//
44
45BOOL RlvHandler::m_fEnabled = FALSE;
46BOOL RlvHandler::fNoSetEnv = FALSE;
47BOOL RlvHandler::fLegacyNaming = FALSE;
48BOOL RlvHandler::m_fFetchStarted = FALSE;
49BOOL RlvHandler::m_fFetchComplete = FALSE;
50RlvMultiStringSearch RlvHandler::m_AttachLookup;
51
52const std::string RlvHandler::cstrSharedRoot = RLV_ROOT_FOLDER;
53
54// Keep these consistent with regular RLV
55const std::string RlvHandler::cstrBlockedRecvIM = "*** IM blocked by your viewer";
56const std::string RlvHandler::cstrBlockedSendIM = "*** IM blocked by sender's viewer";
57const std::string RlvHandler::cstrHidden = "(Hidden)";
58const std::string RlvHandler::cstrHiddenParcel = "(Hidden parcel)";
59const std::string RlvHandler::cstrHiddenRegion = "(Hidden region)";
60const std::string RlvHandler::cstrMsgRecvIM =
61 "The Resident you messaged is prevented from reading your instant messages at the moment, please try again later.";
62const std::string RlvHandler::cstrMsgTpLure =
63 "The Resident you invited is prevented from accepting teleport offers. Please try again later.";
64
65const std::string RlvHandler::cstrAnonyms[] =
66{
67 "A resident", "This resident", "That resident", "An individual", "This individual", "That individual", "A person",
68 "This person", "That person", "A stranger", "This stranger", "That stranger", "A human being", "This human being",
69 "That human being", "An agent", "This agent", "That agent", "A soul", "This soul", "That soul", "Somebody",
70 "Some people", "Someone", "Mysterious one", "An unknown being", "Unidentified one", "An unknown person"
71};
72
73rlv_handler_t gRlvHandler;
74
75// ============================================================================
76// Helper functions
77//
78
79// Checked: 2009-07-12 (RLVa-1.0.0h) | Added: RLVa-0.2.0e
80inline bool rlvIsWearingItem(const LLInventoryItem* pItem)
81{
82 return
83 ((LLAssetType::AT_OBJECT == pItem->getType()) && (gAgent.getAvatarObject()->isWearingAttachment(pItem->getUUID()))) ||
84 ((LLAssetType::AT_GESTURE == pItem->getType()) && (gGestureManager.isGestureActive(pItem->getUUID()))) ||
85 (gAgent.isWearingItem(pItem->getUUID()));
86}
87
88// ============================================================================
89// Command specific helper functions
90//
91
92// Checked: 2009-08-04 (RLVa-1.0.1d) | Added: RLVa-1.0.1d
93static bool rlvParseNotifyOption(const std::string& strOption, S32& nChannel, std::string& strFilter)
94{
95 boost_tokenizer tokens(strOption, boost::char_separator<char>(";", "", boost::keep_empty_tokens));
96 boost_tokenizer::iterator itTok = tokens.begin();
97
98 // Extract and sanity check the first token (required) which is the channel
99 if ( (itTok == tokens.end()) || (!LLStringUtil::convertToS32(*itTok, nChannel)) || (!rlvIsValidChannel(nChannel)) )
100 return false;
101
102 // Second token (optional) is the filter
103 strFilter.clear();
104 if (++itTok != tokens.end())
105 {
106 strFilter = *itTok;
107 ++itTok;
108 }
109
110 return (itTok == tokens.end());
111}
112
113// ============================================================================
114// Constructor/destructor
115//
116
117// Checked: 2009-08-04 (RLVa-1.0.1d) | Modified: RLVa-1.0.1d
118RlvHandler::RlvHandler()
119 : m_fCanCancelTp(false), m_idCurObject(LLUUID::null), m_pCurCommand(NULL), m_pGCTimer(NULL), m_pWLSnapshot(NULL), m_pBhvrNotify(NULL)
120{
121 // Array auto-initialization to 0 is non-standard? (Compiler warning in VC-8.0)
122 memset(m_LayersAdd, 0, sizeof(S16) * WT_COUNT);
123 memset(m_LayersRem, 0, sizeof(S16) * WT_COUNT);
124 memset(m_Behaviours, 0, sizeof(S16) * RLV_BHVR_COUNT);
125}
126
127// Checked: 2009-08-04 (RLVa-1.0.1d) | Modified: RLVa-1.0.1d
128RlvHandler::~RlvHandler()
129{
130 //delete m_pGCTimer; // <- deletes itself
131 delete m_pWLSnapshot; // <- delete on NULL is harmless
132 delete m_pBhvrNotify;
133}
134
135// ============================================================================
136// Attachment related functions
137//
138
139// Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-0.2.0d
140inline LLViewerJointAttachment* RlvHandler::getAttachPoint(const std::string& strText, bool fExact) const
141{
142 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
143 return (pAvatar) ? get_if_there(pAvatar->mAttachmentPoints, getAttachPointIndex(strText, fExact), (LLViewerJointAttachment*)NULL)
144 : NULL;
145}
146
147// Checked: 2009-07-29 (RLVa-1.0.1b) | Modified: RLVa-1.0.1b
148LLViewerJointAttachment* RlvHandler::getAttachPoint(const LLInventoryCategory* pFolder, bool /*fStrict*/) const
149{
150 if (!pFolder)
151 return NULL;
152
153 // RLVa-1.0.1 added support for legacy matching (See http://rlva.catznip.com/blog/2009/07/attachment-point-naming-convention/)
154 if (fLegacyNaming)
155 return getAttachPointLegacy(pFolder);
156
157 // Otherwise the only valid way to specify an attachment point in a folder name is: ^\.\(\s+attachpt\s+\)
158 std::string::size_type idxMatch;
159 std::string strAttachPt = rlvGetFirstParenthesisedText(pFolder->getName(), &idxMatch);
160 LLStringUtil::trim(strAttachPt);
161
162 return ( (1 == idxMatch) && (RLV_FOLDER_PREFIX_HIDDEN == pFolder->getName().at(0)) ) ? getAttachPoint(strAttachPt, true) : NULL;
163}
164
165// Checked: 2009-07-29 (RLVa-1.0.1b) | Modified: RLVa-1.0.1b
166LLViewerJointAttachment* RlvHandler::getAttachPoint(const LLInventoryItem* pItem, bool fStrict) const
167{
168 // Sanity check - if it's not an object then it can't have an attachment point
169 if ( (!pItem) || (LLAssetType::AT_OBJECT != pItem->getType()) )
170 return NULL;
171
172 // The attachment point should be placed at the end of the item's name, surrounded by parenthesis
173 // (if there is no such text then strAttachPt will be an empty string which is fine since it means we'll look at the item's parent)
174 std::string strAttachPt = rlvGetLastParenthesisedText(pItem->getName());
175 LLStringUtil::trim(strAttachPt);
176
177 // If the item is modify : we look at the item's name first and only then at the containing folder
178 // If the item is no modify: we look at the containing folder's name first and only then at the item itself
179 LLViewerJointAttachment* pAttachPt;
180 if (pItem->getPermissions().allowModifyBy(gAgent.getID()))
181 {
182 pAttachPt = (!strAttachPt.empty()) ? getAttachPoint(strAttachPt, true) : NULL;
183 if (!pAttachPt)
184 pAttachPt = getAttachPoint(gInventory.getCategory(pItem->getParentUUID()), fStrict);
185 }
186 else
187 {
188 pAttachPt = getAttachPoint(gInventory.getCategory(pItem->getParentUUID()), fStrict);
189 if ( (!pAttachPt) && (!strAttachPt.empty()) )
190 pAttachPt = getAttachPoint(strAttachPt, true);
191 }
192 return pAttachPt;
193}
194
195// Checked: 2009-07-12 (RLVa-1.0.0h) | Added: RLVa-0.2.2a
196S32 RlvHandler::getAttachPointIndex(const LLViewerJointAttachment* pAttachPt) const
197{
198 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
199 if (pAvatar)
200 {
201 for (LLVOAvatar::attachment_map_t::const_iterator itAttach = pAvatar->mAttachmentPoints.begin();
202 itAttach != pAvatar->mAttachmentPoints.end(); ++itAttach)
203 {
204 if (itAttach->second == pAttachPt)
205 return itAttach->first;
206 }
207 }
208 return 0;
209}
210
211// Checked: 2009-07-29 (RLVa-1.0.1b) | Added: RLVa-1.0.1b
212LLViewerJointAttachment* RlvHandler::getAttachPointLegacy(const LLInventoryCategory* pFolder) const
213{
214 // Hopefully some day this can just be deprecated (see http://rlva.catznip.com/blog/2009/07/attachment-point-naming-convention/)
215 if ( (!pFolder) || (pFolder->getName().empty()) )
216 return NULL;
217
218 // Check for a (...) block *somewhere* in the name
219 std::string::size_type idxMatch;
220 std::string strAttachPt = rlvGetFirstParenthesisedText(pFolder->getName(), &idxMatch);
221 if (!strAttachPt.empty())
222 {
223 // Could be "(attachpt)", ".(attachpt)" or "Folder name (attachpt)"
224 if ( (0 != idxMatch) && ((1 != idxMatch) || (RLV_FOLDER_PREFIX_HIDDEN == pFolder->getName().at(0)) ) && // No '(' or '.(' start
225 (idxMatch + strAttachPt.length() + 1 != pFolder->getName().length()) ) // or there's extra text
226 {
227 // It's definitely not one of the first two so assume it's the last form (in which case we need the last paranthesised block)
228 strAttachPt = rlvGetLastParenthesisedText(pFolder->getName());
229 }
230 }
231 else
232 {
233 // There's no paranthesised block, but it could still be "attachpt" or ".attachpt" (just strip away the '.' from the last one)
234 strAttachPt = pFolder->getName();
235 if (RLV_FOLDER_PREFIX_HIDDEN == strAttachPt[0])
236 strAttachPt.erase(0, 1);
237 }
238 return getAttachPoint(strAttachPt, true);
239}
240
241bool RlvHandler::hasLockedHUD() const
242{
243 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
244 if (!pAvatar)
245 return false;
246
247 LLViewerJointAttachment* pAttachPt;
248 for (rlv_detach_map_t::const_iterator itAttachPt = m_Attachments.begin(); itAttachPt != m_Attachments.end(); ++itAttachPt)
249 {
250 pAttachPt = get_if_there(pAvatar->mAttachmentPoints, (S32)itAttachPt->first, (LLViewerJointAttachment*)NULL);
251 if ( (pAttachPt) && (pAttachPt->getIsHUDAttachment()) )
252 return true; // At least one of our locked attachments is a HUD
253 }
254 return false; // None of our locked attachments is a HUD
255}
256
257bool RlvHandler::isDetachable(const LLInventoryItem* pItem) const
258{
259 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
260 return ( (pItem) && (pAvatar) ) ? isDetachable(pAvatar->getWornAttachment(pItem->getUUID())) : true;
261}
262
263// Checked: 2009-08-11 (RLVa-1.0.1h) | Added: RLVa-1.0.1h
264bool RlvHandler::isDetachableExcept(S32 idxAttachPt, LLViewerObject *pObj) const
265{
266 // Loop over every object that marked the specific attachment point undetachable (but ignore pObj and any of its children)
267 for (rlv_detach_map_t::const_iterator itAttach = m_Attachments.lower_bound(idxAttachPt),
268 endAttach = m_Attachments.upper_bound(idxAttachPt); itAttach != endAttach; ++itAttach)
269 {
270 LLViewerObject* pTempObj = gObjectList.findObject(itAttach->second);
271 if ( (!pTempObj) || (pTempObj->getRootEdit()->getID() != pObj->getID()) )
272 return false;
273 }
274 return true;
275}
276
277// Checked: 2009-05-31 (RLVa-0.2.0e) | Modified: RLVa-0.2.0e
278bool RlvHandler::setDetachable(S32 idxAttachPt, const LLUUID& idRlvObj, bool fDetachable)
279{
280 // Sanity check - make sure it's an object we know about
281 rlv_object_map_t::const_iterator itObj = m_Objects.find(idRlvObj);
282 if ( (itObj == m_Objects.end()) || (!idxAttachPt) )
283 return false; // If (idxAttachPt) == 0 then: (pObj == NULL) || (pObj->isAttachment() == FALSE)
284
285 if (!fDetachable)
286 {
287 // Sanity check - make sure it's not already marked undetachable by this object (NOTE: m_Attachments is a *multimap*, not a map)
288 for (rlv_detach_map_t::const_iterator itAttach = m_Attachments.lower_bound(idxAttachPt),
289 endAttach = m_Attachments.upper_bound(idxAttachPt); itAttach != endAttach; ++itAttach)
290 {
291 if (itObj->second.m_UUID == itAttach->second)
292 return false;
293 }
294
295 m_Attachments.insert(std::pair<S32, LLUUID>(idxAttachPt, itObj->second.m_UUID));
296 return true;
297 }
298 else
299 {
300 // NOTE: m_Attachments is a *multimap*, not a map
301 for (rlv_detach_map_t::iterator itAttach = m_Attachments.lower_bound(idxAttachPt),
302 endAttach = m_Attachments.upper_bound(idxAttachPt); itAttach != endAttach; ++itAttach)
303 {
304 if (itObj->second.m_UUID == itAttach->second)
305 {
306 m_Attachments.erase(itAttach);
307 return true;
308 }
309 }
310 }
311 return false; // Fall-through for (fDetachable == TRUE) - if the object wasn't undetachable then we consider it a failure
312}
313
314
315
316#ifdef RLV_EXTENSION_FLAG_NOSTRIP
317 // Checked: 2009-05-26 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d
318 bool RlvHandler::isStrippable(const LLUUID& idItem) const
319 {
320 // An item is exempt from @detach or @remoutfit if:
321 // - its name contains "nostrip" (anywhere in the name)
322 // - its parent folder contains "nostrip" (anywhere in the name)
323 if (idItem.notNull())
324 {
325 LLViewerInventoryItem* pItem = gInventory.getItem(idItem);
326 if (pItem)
327 {
328 if (-1 != pItem->getName().find(RLV_FOLDER_FLAG_NOSTRIP))
329 return false;
330
331 LLViewerInventoryCategory* pFolder = gInventory.getCategory(pItem->getParentUUID());
332 if ( (pFolder) && (-1 != pFolder->getName().find(RLV_FOLDER_FLAG_NOSTRIP)) )
333 return false;
334 }
335 }
336 return true;
337 }
338#endif // RLV_EXTENSION_FLAG_NOSTRIP
339
340// ============================================================================
341// Behaviour related functions
342//
343
344bool RlvHandler::hasBehaviourExcept(const std::string& strBehaviour, const LLUUID& idObj) const
345{
346 for (rlv_object_map_t::const_iterator itObj = m_Objects.begin(); itObj != m_Objects.end(); ++itObj)
347 if ( (idObj != itObj->second.m_UUID) && (itObj->second.hasBehaviour(strBehaviour)) )
348 return true;
349 return false;
350}
351
352bool RlvHandler::hasBehaviourExcept(ERlvBehaviour eBehaviour, const std::string& strOption, const LLUUID& idObj) const
353{
354 for (rlv_object_map_t::const_iterator itObj = m_Objects.begin(); itObj != m_Objects.end(); ++itObj)
355 if ( (idObj != itObj->second.m_UUID) && (itObj->second.hasBehaviour(eBehaviour, strOption)) )
356 return true;
357 return false;
358}
359
360bool RlvHandler::hasBehaviourExcept(const std::string& strBehaviour, const std::string& strOption, const LLUUID& idObj) const
361{
362 for (rlv_object_map_t::const_iterator itObj = m_Objects.begin(); itObj != m_Objects.end(); ++itObj)
363 if ( (idObj != itObj->second.m_UUID) && (itObj->second.hasBehaviour(strBehaviour, strOption)) )
364 return true;
365 return false;
366}
367
368// ============================================================================
369// Command processing functions
370//
371
372// Checked: 2009-06-03 (RLVa-0.2.0h)
373void RlvHandler::addBehaviourObserver(RlvBehaviourObserver* pBhvrObserver)
374{
375 std::list<RlvBehaviourObserver*>::iterator itBhvrObserver = std::find(m_BhvrObservers.begin(), m_BhvrObservers.end(), pBhvrObserver);
376 if (itBhvrObserver == m_BhvrObservers.end())
377 m_BhvrObservers.push_back(pBhvrObserver);
378}
379
380// Checked: 2009-06-03 (RLVa-0.2.0h)
381void RlvHandler::removeBehaviourObserver(RlvBehaviourObserver* pBhvrObserver)
382{
383 std::list<RlvBehaviourObserver*>::iterator itBhvrObserver = std::find(m_BhvrObservers.begin(), m_BhvrObservers.end(), pBhvrObserver);
384 if (itBhvrObserver != m_BhvrObservers.end())
385 m_BhvrObservers.erase(itBhvrObserver);
386}
387
388// Checked: 2009-06-03 (RLVa-0.2.0h)
389void RlvHandler::notifyBehaviourObservers(const RlvCommand& rlvCmd, bool fInternal)
390{
391 for (std::list<RlvBehaviourObserver*>::const_iterator itBhvrObserver = m_BhvrObservers.begin();
392 itBhvrObserver != m_BhvrObservers.end(); ++itBhvrObserver)
393 {
394 (*itBhvrObserver)->changed(rlvCmd, fInternal);
395 }
396}
397
398// Checked:
399BOOL RlvHandler::processCommand(const LLUUID& uuid, const std::string& strCmd, bool fFromObj)
400{
401 #ifdef RLV_DEBUG
402 RLV_INFOS << "[" << uuid << "]: " << strCmd << LL_ENDL;
403 #endif // RLV_DEBUG
404
405 RlvCommand rlvCmd(strCmd);
406 if (!rlvCmd.isValid())
407 {
408 #ifdef RLV_DEBUG
409 RLV_INFOS << "\t-> invalid command: " << strCmd << LL_ENDL;
410 #endif // RLV_DEBUG
411 return FALSE;
412 }
413 m_pCurCommand = &rlvCmd; m_idCurObject = uuid;
414
415 BOOL fRet = FALSE;
416 switch (rlvCmd.getParamType())
417 {
418 case RLV_TYPE_ADD: // Checked: 2009-06-03 (RLVa-0.2.0h) | Modified: RLVa-0.2.0h
419 {
420 if ( (m_Behaviours[rlvCmd.getBehaviourType()]) &&
421 ( (RLV_BHVR_SETDEBUG == rlvCmd.getBehaviourType()) || (RLV_BHVR_SETENV == rlvCmd.getBehaviourType()) ) )
422 {
423 // Some restrictions can only be held by one single object to avoid deadlocks
424 #ifdef RLV_DEBUG
425 RLV_INFOS << "\t- " << rlvCmd.getBehaviour() << " is already set by another object => discarding" << LL_ENDL;
426 #endif // RLV_DEBUG
427 break;
428 }
429
430 rlv_object_map_t::iterator itObj = m_Objects.find(uuid);
431 if (itObj != m_Objects.end())
432 {
433 RlvObject& rlvObj = itObj->second;
434 fRet = rlvObj.addCommand(rlvCmd);
435 }
436 else
437 {
438 RlvObject rlvObj(uuid);
439 fRet = rlvObj.addCommand(rlvCmd);
440 m_Objects.insert(std::pair<LLUUID, RlvObject>(uuid, rlvObj));
441 }
442
443 #ifdef RLV_DEBUG
444 RLV_INFOS << "\t- " << ( (fRet) ? "adding behaviour" : "skipping duplicate") << LL_ENDL;
445 #endif // RLV_DEBUG
446
447 if (fRet) { // If FALSE then this was a duplicate, there's no need to handle those
448 if (!m_pGCTimer)
449 m_pGCTimer = new RlvGCTimer();
450 processAddCommand(uuid, rlvCmd);
451 notifyBehaviourObservers(rlvCmd, !fFromObj);
452 }
453 }
454 break;
455 case RLV_TYPE_REMOVE: // Checked:
456 {
457 rlv_object_map_t::iterator itObj = m_Objects.find(uuid);
458 if (itObj != m_Objects.end())
459 fRet = itObj->second.removeCommand(rlvCmd);
460
461 #ifdef RLV_DEBUG
462 RLV_INFOS << "\t- " << ( (fRet) ? "removing behaviour"
463 : "skipping remove (unset behaviour or unknown object)") << LL_ENDL;
464 #endif // RLV_DEBUG
465
466 if (fRet) { // Don't handle non-sensical removes
467 processRemoveCommand(uuid, rlvCmd);
468 notifyBehaviourObservers(rlvCmd, !fFromObj);
469
470 if (0 == itObj->second.m_Commands.size())
471 {
472 #ifdef RLV_DEBUG
473 RLV_INFOS << "\t- command list empty => removing " << uuid << LL_ENDL;
474 #endif // RLV_DEBUG
475 m_Objects.erase(itObj);
476 }
477 }
478 }
479 break;
480 case RLV_TYPE_FORCE: // Checked:
481 fRet = processForceCommand(uuid, rlvCmd);
482 break;
483 case RLV_TYPE_REPLY: // Checked:
484 fRet = processReplyCommand(uuid, rlvCmd);
485 break;
486 case RLV_TYPE_UNKNOWN: // Checked:
487 {
488 if ("clear" == rlvCmd.getBehaviour())
489 {
490 const std::string& strFilter = rlvCmd.getParam(); std::string strCmdRem;
491
492 rlv_object_map_t::const_iterator itObj = m_Objects.find(uuid);
493 if (itObj != m_Objects.end()) // No sense in @clear'ing if we don't have any commands for this object
494 {
495 const RlvObject& rlvObj = itObj->second; bool fContinue = true;
496 for (rlv_command_list_t::const_iterator itCmd = rlvObj.m_Commands.begin(), itCurCmd;
497 ((fContinue) && (itCmd != rlvObj.m_Commands.end())); )
498 {
499 itCurCmd = itCmd++; // Point itCmd ahead so it won't get invalidated if/when we erase a command
500
501 const RlvCommand& rlvCmdRem = *itCurCmd;
502 if ( (strFilter.empty()) || (-1 != rlvCmdRem.asString().find(strFilter)) )
503 {
504 fContinue = (rlvObj.m_Commands.size() > 1); // rlvObj will become invalid once we remove the last command
505 strCmdRem = rlvCmdRem.getBehaviour() + ":" + rlvCmdRem.getOption() + "=y";
506 processCommand(uuid, strCmdRem, false);
507 }
508 }
509 fRet = TRUE;
510 }
511 }
512 }
513 break;
514 #ifdef LL_GNUC
515 default:
516 break;
517 #endif // LL_GNUC
518 }
519
520 #ifdef RLV_DEBUG
521 RLV_INFOS << "\t--> command " << ((fRet) ? "succeeded" : "failed") << LL_ENDL;
522 #endif // RLV_DEBUG
523
524 m_pCurCommand = NULL; m_idCurObject.setNull();
525 return fRet;
526}
527
528BOOL RlvHandler::processAddCommand(const LLUUID& uuid, const RlvCommand& rlvCmd)
529{
530 // NOTE: - at this point the command has already been added to the corresponding RlvObject instance
531 // - the object's UUID may or may not exist in gObjectList (see handling of @detach=n)
532
533 ERlvBehaviour eBehaviour = rlvCmd.getBehaviourType();
534 const std::string& strOption = rlvCmd.getOption();
535
536 if ( (RLV_BHVR_UNKNOWN != eBehaviour) && (strOption.empty()) )
537 m_Behaviours[eBehaviour]++;
538
539 switch (eBehaviour)
540 {
541 case RLV_BHVR_DETACH: // @detach[:<option>]=n - Checked: 2009-08-04 (RLVa-1.0.1d) | Modified: RLVa-1.0.1d
542 {
543 LLViewerObject* pObj = NULL; S32 idxAttachPt = 0;
544 if (strOption.empty()) // @detach=n
545 {
546 // If the object rezzed before we received @detach=n from it then we can just do our thing here
547 // If the object hasn't rezzed yet then we need to wait until RlvHandler::onAttach()
548 // If @detach=n were possible for non-attachments another copy/paste would be needed in RlvHandler::onGC()
549 if ((pObj = gObjectList.findObject(uuid)) != NULL)
550 setDetachable(pObj, uuid, false);
551 }
552 else if ((idxAttachPt = getAttachPointIndex(strOption, true)) != 0) // @detach:<attachpt>=n
553 {
554 setDetachable(idxAttachPt, uuid, false);
555
556 // (See below)
557 LLViewerJointAttachment* pAttachPt = getAttachPoint(strOption, true);
558 if (pAttachPt)
559 pObj = pAttachPt->getObject();
560 }
561
562 // When at least one HUD attachment is locked we want to make sure they're all visible (ie prevent hiding a blindfold HUD)
563 // However, since @detach:<attachpt>=n might lock a HUD attachment point that doesn't currently have an object we
564 // have to do this here *and* in RlvHandler::onAttach()
565 if ( (pObj) && (pObj->isHUDAttachment()) )
566 LLPipeline::sShowHUDAttachments = TRUE;
567 }
568 break;
569 case RLV_BHVR_REDIRCHAT: // @redirchat:<option>=n - Checked: 2009-07-07 (RLVa-1.0.0d)
570 case RLV_BHVR_REDIREMOTE: // @rediremote:<option>=n - Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.2a
571 {
572 if (!strOption.empty())
573 m_Behaviours[eBehaviour]++; // @redirchat and @rediremote don't have an optionless version so keep track of it here
574 else
575 m_Behaviours[eBehaviour]--; // @redirchat=n and @rediremote=n are undefined, don't keep track of them
576 }
577 break;
578 case RLV_BHVR_SHOWWORLDMAP: // @showworldmap=n - Checked: 2009-07-05 (RLVa-1.0.0c)
579 {
580 // Simulate clicking the Map button [see LLToolBar::onClickMap()]
581 if (gFloaterWorldMap->getVisible())
582 LLFloaterWorldMap::toggle(NULL);
583 }
584 break;
585 case RLV_BHVR_SHOWMINIMAP: // @showminimap=n - Checked: 2009-07-05 (RLVa-1.0.0c)
586 {
587 // Simulate clicking the Minimap button [see LLToolBar::onClickRadar()]
588 if (LLFloaterMap::instanceVisible())
589 LLFloaterMap::hideInstance();
590 }
591 break;
592 #ifdef RLV_EXTENSION_STARTLOCATION
593 case RLV_BHVR_TPLOC: // @tploc=n - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.1d
594 case RLV_BHVR_UNSIT: // @unsit=n - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.1d
595 {
596 if (strOption.empty())
597 RlvSettings::updateLoginLastLocation();
598 }
599 break;
600 #endif // RLV_EXTENSION_STARTLOCATION
601 case RLV_BHVR_EDIT: // @edit=n - Checked: 2009-07-04 (RLVa-1.0.0b)
602 {
603 // Turn off "View / Highlight Transparent"
604 LLDrawPoolAlpha::sShowDebugAlpha = FALSE;
605
606 // Close the Beacons floater if it's open
607 if (LLFloaterBeacons::instanceVisible())
608 LLFloaterBeacons::toggleInstance();
609
610 // Get rid of the build floater if it's open [copy/paste from toggle_build_mode()]
611 if (gFloaterTools->getVisible())
612 {
613 gAgent.resetView(FALSE);
614 gFloaterTools->close();
615 gViewerWindow->showCursor();
616 }
617 }
618 break;
619 case RLV_BHVR_ADDOUTFIT: // @addoutfit[:<layer>]=n - Checked: 2009-07-07 (RLVa-1.0.0d)
620 case RLV_BHVR_REMOUTFIT: // @remoutfit[:<layer>]=n - Checked: 2009-07-07 (RLVa-1.0.0d)
621 {
622 S16* pLayers = (eBehaviour == RLV_BHVR_ADDOUTFIT) ? m_LayersAdd : m_LayersRem;
623
624 if (strOption.empty())
625 {
626 for (int idx = 0; idx < WT_COUNT; idx++)
627 pLayers[idx]++;
628 }
629 else
630 {
631 EWearableType type = LLWearable::typeNameToType(strOption);
632 if (WT_INVALID != type)
633 {
634 pLayers[type]++;
635 m_Behaviours[eBehaviour]++;
636 }
637 }
638 }
639 break;
640 case RLV_BHVR_SHOWINV: // @showinv=n - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-1.0.0g
641 {
642 // Close all open inventory windows
643 LLInventoryView::closeAll();
644 }
645 break;
646 case RLV_BHVR_SHOWLOC: // @showloc=n - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
647 {
648 // If we're the first @showloc=n restriction refresh all object text so we can filter it if necessary
649 if (1 == m_Behaviours[RLV_BHVR_SHOWLOC])
650 LLHUDText::refreshAllObjectText();
651
652 // Close the "About Land" floater if it's currently visible
653 if (LLFloaterLand::instanceVisible())
654 LLFloaterLand::hideInstance();
655
656 // Close the "Estate Tools" floater is it's currently visible
657 if (LLFloaterRegionInfo::instanceVisible())
658 LLFloaterRegionInfo::hideInstance();
659
660 // NOTE: we should close the "God Tools" floater as well, but since calling LLFloaterGodTools::instance() always
661 // creates a new instance of the floater and since it's very unlikely to be open it's just better not to
662 }
663 break;
664 case RLV_BHVR_SHOWNAMES: // @shownames=n - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
665 {
666 // If we're the first @shownames=n restriction refresh all object text so we can filter it if necessary
667 if (1 == m_Behaviours[RLV_BHVR_SHOWNAMES])
668 LLHUDText::refreshAllObjectText();
669
670 // Close the "Active Speakers" panel if it's currently visible
671 LLFloaterChat::getInstance()->childSetVisible("active_speakers_panel", false);
672 }
673 break;
674 case RLV_BHVR_FLY: // @fly=n - Checked: 2009-07-05 (RLVa-1.0.0c)
675 {
676 // If currently flying, simulate clicking the Fly button [see LLToolBar::onClickFly()]
677 if (gAgent.getFlying())
678 gAgent.toggleFlying();
679 }
680 break;
681 case RLV_BHVR_SETENV: // @setenv=n - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0a
682 {
683 if (!fNoSetEnv)
684 {
685 // Only close the floaters if their instance exists and they're actually visible
686 if ( (LLFloaterEnvSettings::isOpen()) && (LLFloaterEnvSettings::instance()->getVisible()) )
687 LLFloaterEnvSettings::instance()->close();
688 if ( (LLFloaterWindLight::isOpen()) && (LLFloaterWindLight::instance()->getVisible()) )
689 LLFloaterWindLight::instance()->close();
690 if ( (LLFloaterWater::isOpen()) && (LLFloaterWater::instance()->getVisible()) )
691 LLFloaterWater::instance()->close();
692 if ( (LLFloaterDayCycle::isOpen()) && (LLFloaterDayCycle::instance()->getVisible()) )
693 LLFloaterDayCycle::instance()->close();
694
695 // Save the current WindLight params so we can restore them on @setenv=y
696 if (m_pWLSnapshot)
697 {
698 RLV_ERRS << "m_pWLSnapshot != NULL" << LL_ENDL; // Safety net in case we set @setenv=n for more than 1 object
699 delete m_pWLSnapshot;
700 }
701 m_pWLSnapshot = RlvWLSnapshot::takeSnapshot();
702 }
703 }
704 break;
705 case RLV_BHVR_SHOWHOVERTEXTALL: // @showhovertextal=n - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
706 case RLV_BHVR_SHOWHOVERTEXTWORLD: // @showhovertextworld=n - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
707 case RLV_BHVR_SHOWHOVERTEXTHUD: // @showhovertexthud=n - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
708 {
709 // Refresh all hover text (LLHUDText::setStringUTF8() will decide what needs clearing and what doesn't)
710 LLHUDText::refreshAllObjectText();
711 }
712 break;
713 case RLV_BHVR_SHOWHOVERTEXT: // @showhovertext:<uuid>=n - Checked: 2009-07-09 (RLVa-0.2.2a) | Modified: RLVa-1.0.0f
714 {
715 LLUUID idException(strOption);
716 if (!idException.isNull()) // If there's an option it should be a valid UUID
717 {
718 addException(eBehaviour, LLUUID(strOption));
719
720 // Clear the object's hover text
721 LLViewerObject* pObj = gObjectList.findObject(idException);
722 if ( (pObj) && (pObj->mText.notNull()) && (!pObj->mText->getObjectText().empty()) )
723 pObj->mText->setStringUTF8("");
724 }
725 }
726 break;
727 case RLV_BHVR_NOTIFY: // @notify:<option>=add - Checked: 2009-08-04 (RLVa-1.0.1d) | Modified: RLVa-1.0.1d
728 {
729 S32 nChannel; std::string strFilter;
730 if ( (!strOption.empty()) && (rlvParseNotifyOption(strOption, nChannel, strFilter)) )
731 {
732 if (!m_pBhvrNotify)
733 addBehaviourObserver(m_pBhvrNotify = new RlvBehaviourNotifyObserver());
734 m_pBhvrNotify->addNotify(uuid, nChannel, strFilter);
735 }
736 }
737 break;
738 case RLV_BHVR_RECVCHAT: // @recvchat:<uuid>=add - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
739 case RLV_BHVR_RECVEMOTE: // @recvemote:<uuid>=add - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
740 case RLV_BHVR_RECVIM: // @recvim:<uuid>=add - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
741 case RLV_BHVR_SENDIM: // @sendim:<uuid>=add - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
742 case RLV_BHVR_TPLURE: // @tplure:<uuid>=add - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
743 case RLV_BHVR_ACCEPTTP: // @accepttp:<uuid>=add - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
744 {
745 addException(eBehaviour, LLUUID(strOption));
746 }
747 break;
748 default:
749 {
750 // Give our observers a chance to handle any command we don't
751 RlvEvent rlvEvent(uuid, rlvCmd);
752 m_Emitter.update(&RlvObserver::onAddCommand, rlvEvent);
753 }
754 break;
755 }
756 return TRUE; // Add command success/failure is decided by RlvObject::addCommand()
757}
758
759// Checked: 2009-08-05 (RLVa-1.0.1e) | Added: RLVa-1.0.1e
760void RlvHandler::processRetainedCommands()
761{
762 for (rlv_retained_list_t::const_iterator itCmd = m_Retained.begin(); itCmd != m_Retained.end(); ++itCmd)
763 {
764 const RlvRetainedCommand& cmd = *itCmd;
765 processCommand(cmd.idObject, cmd.strCmd, true);
766 }
767 m_Retained.clear();
768}
769
770BOOL RlvHandler::processRemoveCommand(const LLUUID& uuid, const RlvCommand& rlvCmd)
771{
772 // NOTE: - the RlvObject instance still exists at this point, but the viewer might already have removed it from its object list
773 ERlvBehaviour eBehaviour = rlvCmd.getBehaviourType();
774 const std::string& strOption = rlvCmd.getOption();
775
776 if ( (RLV_BHVR_UNKNOWN != eBehaviour) && (strOption.empty()) )
777 m_Behaviours[eBehaviour]--;
778
779 switch (eBehaviour)
780 {
781 case RLV_BHVR_DETACH: // @detach[:<option>]=y - Checked: 2009-08-04 (RLVa-1.0.1d) | Modified: RLVa-1.0.1d
782 {
783 S32 idxAttachPt;
784 if (strOption.empty()) // @detach=y
785 {
786 // The object may or may not (if it got detached) still exist so clean up the hard way
787 if (m_Objects.find(uuid) != m_Objects.end())
788 {
789 for (rlv_detach_map_t::const_iterator itAttach = m_Attachments.begin(), endAttach = m_Attachments.end();
790 itAttach != endAttach; ++itAttach)
791 {
792 if (itAttach->second == uuid)
793 {
794 setDetachable(itAttach->first, uuid, true); // <- invalidates our iterators on return
795 break;
796 }
797 }
798 }
799 }
800 else if ((idxAttachPt = getAttachPointIndex(strOption, true))) // @detach:<attachpt>=y
801 {
802 setDetachable(idxAttachPt, uuid, true);
803 }
804 }
805 break;
806 case RLV_BHVR_REDIRCHAT: // @redirchat:<option>=y - Checked: 2009-07-07 (RLVa-1.0.0d)
807 case RLV_BHVR_REDIREMOTE: // @rediremote:<option>=y - Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.2a
808 {
809 if (!strOption.empty())
810 m_Behaviours[eBehaviour]--; // @redirchat and @rediremote don't have an optionless version so keep track of it here
811 else
812 m_Behaviours[eBehaviour]++; // @redirchat=n and @rediremote=n are undefined, don't keep track of them
813 }
814 break;
815 #ifdef RLV_EXTENSION_STARTLOCATION
816 case RLV_BHVR_TPLOC: // @tploc=y - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.1d
817 case RLV_BHVR_UNSIT: // @unsit=y - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.1d
818 {
819 if (strOption.empty())
820 RlvSettings::updateLoginLastLocation();
821 }
822 break;
823 #endif // RLV_EXTENSION_STARTLOCATION
824 case RLV_BHVR_ADDOUTFIT: // @addoutfit[:<layer>]=y - Checked: 2009-07-07 (RLVa-1.0.0d)
825 case RLV_BHVR_REMOUTFIT: // @remoutfit[:<layer>]=y - Checked: 2009-07-07 (RLVa-1.0.0d)
826 {
827 S16* pLayers = (eBehaviour == RLV_BHVR_ADDOUTFIT) ? m_LayersAdd : m_LayersRem;
828
829 if (strOption.empty())
830 {
831 for (int idx = 0; idx < WT_COUNT; idx++)
832 pLayers[idx]--;
833 }
834 else
835 {
836 EWearableType type = LLWearable::typeNameToType(strOption);
837 if (WT_INVALID != type)
838 {
839 pLayers[type]--;
840 m_Behaviours[eBehaviour]--;
841 }
842 }
843 }
844 break;
845 case RLV_BHVR_SETENV: // @setenv=y - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0h
846 {
847 if (!fNoSetEnv)
848 {
849 // Restore WindLight parameters to what they were before @setenv=n was issued
850 RlvWLSnapshot::restoreSnapshot(m_pWLSnapshot);
851 delete m_pWLSnapshot;
852 m_pWLSnapshot = NULL;
853 }
854 }
855 break;
856 case RLV_BHVR_SHOWLOC: // @showloc=y - Checked: 2009-07-09 (RLVa-1.0.0f) | Added: RLVa-1.0.0f
857 case RLV_BHVR_SHOWNAMES: // @shownames=y - Checked: 2009-07-09 (RLVa-1.0.0f) | Added: RLVa-1.0.0f
858 case RLV_BHVR_SHOWHOVERTEXTALL: // @showhovertextal=y - Checked: 2009-07-09 (RLVa-1.0.0f) | Added: RLVa-1.0.0f
859 case RLV_BHVR_SHOWHOVERTEXTWORLD: // @showhovertextworld=y - Checked: 2009-07-09 (RLVa-1.0.0f) | Added: RLVa-1.0.0f
860 case RLV_BHVR_SHOWHOVERTEXTHUD: // @showhovertexthud=y - Checked: 2009-07-09 (RLVa-1.0.0f) | Added: RLVa-1.0.0f
861 {
862 // If this was the last of any of the five restrictions we should refresh all hover text in case anything needs restoring
863 if (!m_Behaviours[eBehaviour])
864 LLHUDText::refreshAllObjectText();
865 }
866 break;
867 case RLV_BHVR_SHOWHOVERTEXT: // @showhovertext:<uuid>=y - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
868 {
869 LLUUID idException(strOption);
870 if (!idException.isNull()) // If there's an option it should be a valid UUID
871 {
872 removeException(eBehaviour, LLUUID(strOption));
873
874 // Restore the object's hover text
875 LLViewerObject* pObj = gObjectList.findObject(idException);
876 if ( (pObj) && (pObj->mText.notNull()) && (!pObj->mText->getObjectText().empty()) )
877 pObj->mText->setStringUTF8(pObj->mText->getObjectText());
878 }
879 }
880 break;
881 case RLV_BHVR_NOTIFY: // @notify:<option>=rem - Checked: 2009-08-04 (RLVa-1.0.1d) | Modified: RLVa-1.0.1d
882 {
883 S32 nChannel; std::string strFilter;
884 if ( (m_pBhvrNotify) && (!strOption.empty()) && (rlvParseNotifyOption(strOption, nChannel, strFilter)) )
885 {
886 m_pBhvrNotify->removeNotify(uuid, nChannel, strFilter);
887
888 if (!m_pBhvrNotify->hasNotify())
889 {
890 removeBehaviourObserver(m_pBhvrNotify);
891 delete m_pBhvrNotify;
892 m_pBhvrNotify = NULL;
893 }
894 }
895 }
896 break;
897 case RLV_BHVR_RECVCHAT: // @recvchat:<uuid>=rem - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
898 case RLV_BHVR_RECVEMOTE: // @recvemote:<uui>=red - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
899 case RLV_BHVR_RECVIM: // @recvim:<uuid>=rem - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
900 case RLV_BHVR_SENDIM: // @sendim:<uuid>=rem - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
901 case RLV_BHVR_TPLURE: // @recvim:<uuid>=rem - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
902 case RLV_BHVR_ACCEPTTP: // @accepttp:<uuid>=rem - Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
903 {
904 removeException(eBehaviour, LLUUID(strOption));
905 }
906 break;
907 default:
908 {
909 // Give our observers a chance to handle any command we don't
910 RlvEvent rlvEvent(uuid, rlvCmd);
911 m_Emitter.update(&RlvObserver::onRemoveCommand, rlvEvent);
912 }
913 break;
914 }
915 return TRUE; // Remove commands don't fail, doesn't matter what we return here
916}
917
918BOOL RlvHandler::processForceCommand(const LLUUID& idObj, const RlvCommand& rlvCmd) const
919{
920 const std::string& strOption = rlvCmd.getOption();
921 BOOL fHandled = TRUE;
922
923 switch (rlvCmd.getBehaviourType())
924 {
925 case RLV_BHVR_DETACH: // @detach[:<option>]=force - Checked:
926 onForceDetach(idObj, strOption);
927 break;
928 case RLV_BHVR_REMOUTFIT: // @remoutfit:<option>=force - Checked:
929 onForceRemOutfit(idObj, strOption);
930 break;
931 case RLV_BHVR_UNSIT: // @unsit=force - Checked: 2009-06-02 (RLVa-0.2.0g)
932 {
933 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
934 if ( (pAvatar) && (pAvatar->mIsSitting) && (!hasBehaviourExcept(RLV_BHVR_UNSIT, idObj)) )
935 {
936 // See behaviour notes on why we have to force an agent update here
937 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
938 send_agent_update(TRUE, TRUE);
939 }
940 }
941 break;
942 case RLV_BHVR_TPTO: // @tpto:<option>=force - Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-1.0.0h
943 {
944 fHandled = FALSE;
945 if ( (!strOption.empty()) && (-1 == strOption.find_first_not_of("0123456789/.")) )
946 {
947 LLVector3d posGlobal;
948
949 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
950 boost::char_separator<char> sep("/", "", boost::keep_empty_tokens);
951 tokenizer tokens(strOption, sep); int idx = 0;
952 for (tokenizer::iterator itToken = tokens.begin(); itToken != tokens.end(); ++itToken)
953 {
954 if (idx < 3)
955 LLStringUtil::convertToF64(*itToken, posGlobal[idx++]);
956 }
957
958 if (idx == 3)
959 {
960 gAgent.teleportViaLocation(posGlobal);
961 fHandled = TRUE;
962 }
963 }
964 }
965 break;
966 case RLV_BHVR_SIT: // @sit:<option>=force - Checked: 2009-06-02 (RLVa-0.2.0g)
967 fHandled = onForceSit(idObj, rlvCmd.getOption());
968 break;
969 case RLV_BHVR_ADDOUTFIT: // @addoutfit:<option>=force <- synonym of @attach:<option>=force
970 case RLV_BHVR_ATTACH: // @attach:<option>=force - Checked:
971 onForceWear(rlvCmd.getOption(), true, false); // Force attach single folder
972 break;
973 case RLV_BHVR_ATTACHALL: // @attachall:<option>=force - Checked:
974 onForceWear(rlvCmd.getOption(), true, true); // Force attach nested folders
975 break;
976 case RLV_BHVR_DETACHALL: // @detachall:<option>=force - Checked:
977 onForceWear(rlvCmd.getOption(), false, true); // Force detach nested folders
978 break;
979 case RLV_BHVR_ATTACHTHIS:
980 case RLV_BHVR_ATTACHALLTHIS:
981 case RLV_BHVR_DETACHTHIS:
982 case RLV_BHVR_DETACHALLTHIS:
983 {
984 ERlvBehaviour eBehaviour = rlvCmd.getBehaviourType();
985 std::string strReply;
986 if (onGetPath(idObj, strOption, strReply))
987 {
988 LLStringUtil::toLower(strReply);
989 onForceWear(strReply,
990 (RLV_BHVR_ATTACHTHIS == eBehaviour) || (RLV_BHVR_ATTACHALLTHIS == eBehaviour),
991 (RLV_BHVR_ATTACHALLTHIS == eBehaviour) || (RLV_BHVR_DETACHALLTHIS == eBehaviour));
992 }
993 }
994 break;
995 case RLV_BHVR_DETACHME: // @detachme=force - Checked: 2009-06-07 (RLVa-0.2.1c)
996 {
997 // NOTE: @detachme=force could be seen as a @detach:<attachpt>=force but RLV implements it as a "detach by UUID"
998 LLViewerObject* pObj; LLVOAvatar* pAvatar; LLViewerJointAttachment* pAttachPt;
999 if ( ((pObj = gObjectList.findObject(idObj)) != NULL) && (pObj->isAttachment()) &&
1000 ((pAvatar = gAgent.getAvatarObject()) != NULL) &&
1001 ((pAttachPt = pAvatar->getTargetAttachmentPoint(pObj->getRootEdit())) != NULL) )
1002 {
1003 handle_detach_from_avatar(pAttachPt);
1004 }
1005 }
1006 break;
1007 default:
1008 {
1009 // Give our observers a chance to handle any command we don't
1010 RlvEvent rlvEvent(idObj, rlvCmd);
1011 fHandled = m_Emitter.update(&RlvObserver::onForceCommand, rlvEvent);
1012 }
1013 break;
1014 }
1015 return fHandled; // If we handled it then it'll still be TRUE; if an observer doesn't handle it'll be FALSE
1016}
1017
1018// Checked: 2009-07-12 (RLVa-1.0.0h)
1019BOOL RlvHandler::processReplyCommand(const LLUUID& uuid, const RlvCommand& rlvCmd) const
1020{
1021 const std::string& strOption = rlvCmd.getOption();
1022 const std::string& strChannel = rlvCmd.getParam();
1023 std::string strReply;
1024
1025 BOOL fHandled = TRUE;
1026 switch (rlvCmd.getBehaviourType())
1027 {
1028 case RLV_BHVR_VERSION: // @version=<channel> - Checked: 2009-07-12 (RLVa-1.0.0h)
1029 strReply = getVersionString();
1030 break;
1031 case RLV_BHVR_GETOUTFIT: // @getoufit[:<layer>]=<channel> - Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-0.2.0d
1032 {
1033 // (Quirk: RLV 1.16.1 will execute @getoutfit=<channel> if <layer> is invalid, so we need to as well)
1034 EWearableType layerType = LLWearable::typeNameToType(strOption);
1035
1036 const EWearableType layerTypes[] =
1037 {
1038 WT_GLOVES, WT_JACKET, WT_PANTS, WT_SHIRT, WT_SHOES, WT_SKIRT, WT_SOCKS,
1039 WT_UNDERPANTS, WT_UNDERSHIRT, WT_SKIN, WT_EYES, WT_HAIR, WT_SHAPE
1040 };
1041
1042 #ifdef RLV_EXPERIMENTAL_COMPOSITE_FOLDING
1043 for (int idx = 0, cnt = sizeof(layerTypes) / sizeof(EWearableType); idx < cnt; idx++)
1044 {
1045 if ( (WT_INVALID == layerType) || (layerTypes[idx] == layerType) )
1046 {
1047 // TODO-RLVa: add support for 'fHideLockedLayers'
1048 bool fWorn = (gAgent.getWearable(layerTypes[idx])) &&
1049 (!isHiddenCompositeItem(gAgent.getWearableItem(layerTypes[idx]),
1050 LLWearable::typeToTypeName(layerTypes[idx])));
1051 strReply.push_back( (fWorn) ? '1' : '0' );
1052 }
1053 }
1054 #else
1055 for (int idx = 0, cnt = sizeof(layerTypes) / sizeof(EWearableType); idx < cnt; idx++)
1056 if ( (WT_INVALID == layerType) || (layerTypes[idx] == layerType) )
1057 {
1058 // We never hide body parts, even if they're "locked" and we're hiding locked layers
1059 // (nor do we hide a layer if the issuing object is the only one that has this layer locked)
1060 bool fWorn = (gAgent.getWearable(layerTypes[idx])) &&
1061 ( (!RlvSettings::getHideLockedLayers()) ||
1062 (LLAssetType::AT_BODYPART == LLWearable::typeToAssetType(layerTypes[idx])) ||
1063 ( (isRemovableExcept(layerTypes[idx], uuid)) &&
1064 (isStrippable(gAgent.getWearableItem(layerTypes[idx]))) ) );
1065 strReply.push_back( (fWorn) ? '1' : '0' );
1066 //strReply.push_back( (gAgent.getWearable(layerTypes[idx])) ? '1' : '0' );
1067 }
1068 #endif // RLV_EXPERIMENTAL_COMPOSITE_FOLDING
1069 }
1070 break;
1071 case RLV_BHVR_GETATTACH: // @getattach[:<layer>]=<channel> - Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-0.2.0d
1072 {
1073 // If we're fetching all worn attachments then the reply should start with 0
1074 if (strOption.empty())
1075 strReply.push_back('0');
1076
1077 LLVOAvatar* pAvatar = gAgent.getAvatarObject(); std::string strAttachName;
1078 for (LLVOAvatar::attachment_map_t::const_iterator itAttach = pAvatar->mAttachmentPoints.begin();
1079 itAttach != pAvatar->mAttachmentPoints.end(); ++itAttach)
1080 {
1081 LLViewerJointAttachment* pAttachment = itAttach->second;
1082 if (!pAttachment)
1083 continue;
1084
1085 strAttachName = pAttachment->getName(); // Capitalized (see avatar_lad.xml)
1086 LLStringUtil::toLower(strAttachName);
1087
1088 #ifdef RLV_EXPERIMENTAL_COMPOSITE_FOLDING
1089 if ( (strOption.empty()) || (strOption == strAttachName) )
1090 {
1091 // TODO-RLVa: add support for 'fHideLockedAttach'
1092 bool fWorn = (pAttachment->getItemID().notNull()) &&
1093 (!isHiddenCompositeItem(pAttachment->getItemID(), strAttachName));
1094 strReply.push_back( (fWorn) ? '1' : '0' );
1095 }
1096 #else
1097 if ( (strOption.empty()) || (strOption == strAttachName) )
1098 {
1099 bool fWorn = (pAttachment->getItemID().notNull()) &&
1100 ( (!RlvSettings::getHideLockedAttach()) ||
1101 ( (isDetachable(itAttach->first)) && (isStrippable(pAttachment->getItemID())) ) );
1102 strReply.push_back( (fWorn) ? '1' : '0' );
1103 //strReply.push_back( (pAttachment->getItemID().notNull()) ? '1' : '0' );
1104 }
1105 #endif // RLV_EXPERIMENTAL_COMPOSITE_FOLDING
1106 }
1107 }
1108 break;
1109 case RLV_BHVR_GETSTATUS: // @getstatus[:<option>]=<channel> - Checked: 2009-07-12 (RLVa-1.0.0h)
1110 {
1111 // NOTE: specification says response should start with '/' but RLV-1.16.1 returns an empty string when no rules are set
1112 rlv_object_map_t::const_iterator itObj = m_Objects.find(uuid);
1113 if (itObj != m_Objects.end())
1114 {
1115 std::string strObjStatus = itObj->second.getStatusString(strOption);
1116 if (!strObjStatus.empty())
1117 {
1118 strReply.push_back('/');
1119 strReply += strObjStatus;
1120 }
1121 }
1122 }
1123 break;
1124 case RLV_BHVR_GETSTATUSALL: // @getstatusall[:<option>]=<channel> - Checked: 2009-07-12 (RLVa-1.0.0h)
1125 {
1126 // NOTE: specification says response should start with '/' but RLV-1.16.1 returns an empty string when no rules are set
1127 std::string strObjStatus;
1128 for (rlv_object_map_t::const_iterator itObj = m_Objects.begin(); itObj != m_Objects.end(); ++itObj)
1129 {
1130 strObjStatus = itObj->second.getStatusString(strOption);
1131 if (!strObjStatus.empty())
1132 {
1133 strReply.push_back('/');
1134 strReply += strObjStatus;
1135 }
1136 }
1137 }
1138 break;
1139 case RLV_BHVR_GETINV: // @getinv[:<path>]=<channel> - Checked: 2009-07-28 (RLVa-1.0.1b) | Modified: RLVa-1.0.1b
1140 {
1141 LLViewerInventoryCategory* pFolder = getSharedFolder(strOption);
1142 if (pFolder)
1143 {
1144 LLInventoryModel::cat_array_t* pFolders;
1145 LLInventoryModel::item_array_t* pItems;
1146 gInventory.getDirectDescendentsOf(pFolder->getUUID(), pFolders, pItems);
1147
1148 if (pFolders)
1149 {
1150 for (S32 idxFolder = 0, cntFolder = pFolders->count(); idxFolder < cntFolder; idxFolder++)
1151 {
1152 const std::string& strFolder = pFolders->get(idxFolder)->getName();
1153 if ( (!strFolder.empty()) && (RLV_FOLDER_PREFIX_HIDDEN != strFolder[0]) &&
1154 (!isFoldedFolder(pFolders->get(idxFolder).get(), true)) )
1155 {
1156 if (!strReply.empty())
1157 strReply.push_back(',');
1158 strReply += strFolder;
1159 }
1160 }
1161 }
1162 }
1163 }
1164 break;
1165 case RLV_BHVR_GETINVWORN: // @getinvworn[:path]=<channel> - Checked:
1166 onGetInvWorn(rlvCmd.getOption(), strReply);
1167 break;
1168 case RLV_BHVR_FINDFOLDER: // @findfolder:<criteria>=<channel> - Checked: 2009-07-12 (RLVa-1.0.0h)
1169 {
1170 // COMPAT-RLV: RLV 1.16.1 returns the first random folder it finds (probably tries to match "" to a folder name?)
1171 // (just going to stick with what's there for now... no option => no folder)
1172 LLInventoryModel::cat_array_t folders;
1173 if ( (!strOption.empty()) && (findSharedFolders(strOption, folders)) )
1174 {
1175 // We need to return an "in depth" result so whoever has the most '/' is our lucky winner
1176 int maxSlashes = 0, curSlashes; std::string strFolderName;
1177 for (S32 idxFolder = 0, cntFolder = folders.count(); idxFolder < cntFolder; idxFolder++)
1178 {
1179 strFolderName = getSharedPath(folders.get(idxFolder));
1180
1181 curSlashes = std::count(strFolderName.begin(), strFolderName.end(), '/');
1182 if (curSlashes > maxSlashes)
1183 {
1184 maxSlashes = curSlashes;
1185 strReply = strFolderName;
1186 }
1187 }
1188 }
1189 }
1190 break;
1191 #ifdef RLV_EXTENSION_CMD_FINDFOLDERS
1192 case RLV_BHVR_FINDFOLDERS: // @findfolders:<criteria>=<channel> - Checked: 2009-07-12 (RLVa-1.0.0h) | Added: RLVa-0.2.0b
1193 {
1194 LLInventoryModel::cat_array_t folders;
1195 if ( (!strOption.empty()) && (findSharedFolders(strOption, folders)) )
1196 {
1197 for (S32 idxFolder = 0, cntFolder = folders.count(); idxFolder < cntFolder; idxFolder++)
1198 {
1199 if (!strReply.empty())
1200 strReply.push_back(',');
1201 strReply += getSharedPath(folders.get(idxFolder));
1202 }
1203 }
1204 }
1205 break;
1206 #endif // RLV_EXTENSION_CMD_FINDFOLDERS
1207 case RLV_BHVR_GETPATH: // @getpath[:<option>]=<channel> - Checked: 2009-07-12 (RLVa-1.0.0h)
1208 onGetPath(uuid, rlvCmd.getOption(), strReply);
1209 break;
1210 case RLV_BHVR_GETSITID: // @getsitid=<channel> - Checked: 2009-07-12 (RLVa-1.0.0h)
1211 {
1212 // (Quirk: RLV 1.16.1 returns a NULL uuid if we're not sitting)
1213 LLVOAvatar* pAvatarObj = gAgent.getAvatarObject(); LLUUID uuid;
1214 if ( (pAvatarObj) && (pAvatarObj->mIsSitting) )
1215 {
1216 // LLVOAvatar inherits from 2 classes so make sure we get the right vfptr
1217 LLViewerObject* pAvatar = dynamic_cast<LLViewerObject*>(pAvatarObj), *pParent;
1218 // (If there is a parent, we need to upcast it from LLXform to LLViewerObject to get its UUID)
1219 if ( (pAvatar) && ((pParent = static_cast<LLViewerObject*>(pAvatar->getRoot())) != pAvatar) )
1220 uuid = pParent->getID();
1221 }
1222 strReply = uuid.asString();
1223 }
1224 break;
1225 default:
1226 {
1227 // Give our observers a chance to handle any command we don't
1228 RlvEvent rlvEvent(uuid, rlvCmd);
1229 return m_Emitter.update(&RlvObserver::onReplyCommand, rlvEvent);
1230 }
1231 break;
1232 }
1233
1234 if (fHandled)
1235 rlvSendChatReply(strChannel, strReply);
1236 return fHandled;
1237}
1238
1239// ============================================================================
1240// House keeping (see debug notes for test methodology, test script and last run)
1241//
1242
1243void RlvHandler::initLookupTables()
1244{
1245 static bool fInitialized = false;
1246 if (!fInitialized)
1247 {
1248 // Initialize the attachment name lookup table
1249 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
1250 if (pAvatar)
1251 {
1252 std::string strAttachPtName;
1253 for (LLVOAvatar::attachment_map_t::const_iterator itAttach = pAvatar->mAttachmentPoints.begin();
1254 itAttach != pAvatar->mAttachmentPoints.end(); ++itAttach)
1255 {
1256 LLViewerJointAttachment* pAttachPt = itAttach->second;
1257 if (pAttachPt)
1258 {
1259 strAttachPtName = pAttachPt->getName();
1260 LLStringUtil::toLower(strAttachPtName);
1261 m_AttachLookup.addKeyword(strAttachPtName, itAttach->first);
1262 }
1263 }
1264 fInitialized = true;
1265 }
1266 }
1267}
1268
1269// Checked: 2009-08-11 (RLVa-1.0.1h) | Modified: RLVa-1.0.1h
1270void RlvHandler::onAttach(LLViewerJointAttachment* pAttachPt, bool fFullyLoaded)
1271{
1272 // Sanity check - LLVOAvatar::attachObject() should call us *after* calling LLViewerJointAttachment::addObject()
1273 LLViewerObject* pObj = pAttachPt->getObject();
1274 S32 idxAttachPt = getAttachPointIndex(pObj); // getAttachPointIndex() has a NULL pointer check so this is safe
1275 if ( (!pObj) || (!idxAttachPt) )
1276 {
1277 RLV_ERRS << "pAttachPt->getObject() == NULL" << LL_ENDL;
1278 return;
1279 }
1280
1281 // Check if this attachment point has a pending "reattach-on-detach"
1282 rlv_reattach_map_t::iterator itReattach = m_AttachPending.find(idxAttachPt);
1283 if (itReattach != m_AttachPending.end())
1284 {
1285 if (itReattach->second == pAttachPt->getItemID())
1286 {
1287 RLV_INFOS << "Reattached " << pAttachPt->getItemID().asString() << " to " << idxAttachPt << LL_ENDL;
1288 m_AttachPending.erase(itReattach);
1289 }
1290 }
1291 else if ( (fFullyLoaded) && (!isDetachableExcept(idxAttachPt, pObj)) )
1292 {
1293 // We're fully loaded with no pending reattach on this attach point but it's "undetachable" -> force detach the new attachment
1294
1295 // Assertion: the only way the attachment point could be locked at this point is if some object locked it with @detach:attachpt=n
1296 // - previous attachments on this attachment point might have issued @detach=n but those were all cleaned up at detach
1297 // - the new attachment might have issued @detach=n but that won't actually lock down the attachment point until further down
1298 // NOTE 1: "some object" may no longer exist if it was not an attachment and the GC hasn't cleaned it up yet (informative)
1299 // NOTE 2: "some object" may refer to the new attachment - ie @detach:spine=n from object on spine (problematic, causes reattach)
1300 // -> solved by using isDetachableExcept(idxAttachPt, pObj) instead of isDetachable(idxAttachPt)
1301
1302 m_DetachPending.insert(std::pair<S32, LLUUID>(idxAttachPt, pObj->getID()));
1303 rlvForceDetach(pAttachPt);
1304 }
1305
1306 // Check if we already have an RlvObject instance for this object (rezzed prim attached from in-world, or an attachment that rezzed in)
1307 rlv_object_map_t::iterator itObj = m_Objects.find(pObj->getID());
1308 if (itObj != m_Objects.end())
1309 {
1310 // If it's an attachment we processed commands for but that only just rezzed in we need to mark it as existing in gObjectList
1311 if (!itObj->second.m_fLookup)
1312 itObj->second.m_fLookup = true;
1313
1314 // In both cases we should check for "@detach=n" and actually lock down the attachment point it got attached to
1315 if (itObj->second.hasBehaviour(RLV_BHVR_DETACH))
1316 {
1317 // (Copy/paste from processAddCommand)
1318 setDetachable(pObj, pObj->getID(), false);
1319
1320 if (pObj->isHUDAttachment())
1321 LLPipeline::sShowHUDAttachments = TRUE; // Prevents hiding of locked HUD attachments
1322 }
1323 }
1324
1325 // Fetch the inventory item if we don't currently have it since we might need it for reattach-on-detach
1326 const LLUUID& idItem = pAttachPt->getItemID();
1327 LLViewerInventoryItem* pItem = ( (idItem.notNull()) && (gInventory.isInventoryUsable()) ) ? gInventory.getItem(idItem) : NULL;
1328 if ( (STATE_STARTED == LLStartUp::getStartupState()) && (pItem != NULL) )
1329 {
1330 RlvCurrentlyWorn f;
1331 f.fetchItem(idItem);
1332 }
1333
1334 // If what we're wearing is located under the shared root then append the attachment point name (if needed)
1335 LLViewerInventoryCategory* pRlvRoot = getSharedRoot();
1336 if ( (STATE_STARTED == LLStartUp::getStartupState()) && (pRlvRoot) && (pItem) && (pItem->isComplete()) &&
1337 (gInventory.isObjectDescendentOf(idItem, pRlvRoot->getUUID())) )
1338 {
1339 std::string strAttachPt = pAttachPt->getName();
1340 LLStringUtil::toLower(strAttachPt);
1341
1342 // If we can modify the item then it should contain the attach point name itself, otherwise its parent should
1343 if (pItem->getPermissions().allowModifyBy(gAgent.getID()))
1344 {
1345 if (!getAttachPoint(pItem, true))
1346 {
1347 // It doesn't specify an attach point and we can rename it [see LLItemBridge::renameItem()]
1348 std::string strName = pItem->getName();
1349 LLStringUtil::truncate(strName, DB_INV_ITEM_NAME_STR_LEN - strAttachPt.length() - 3);
1350
1351 strName += " (" + strAttachPt + ")";
1352
1353 pItem->rename(strName);
1354 pItem->updateServer(FALSE);
1355 gInventory.updateItem(pItem);
1356 //gInventory.notifyObservers(); <- done further down in LLVOAvatar::attachObject()
1357 }
1358 }
1359 else
1360 {
1361 // Folder can't be the shared root, or be its direct descendant (= nested at least 2 levels deep)
1362 LLViewerInventoryCategory* pFolder = gInventory.getCategory(pItem->getParentUUID());
1363 if ( (pFolder) &&
1364 (pFolder->getUUID() != pRlvRoot->getUUID()) && (pFolder->getParentUUID() != pRlvRoot->getUUID()) &&
1365 (!getAttachPoint(pFolder, true)) )
1366 {
1367 // It's no mod and its parent folder doesn't contain an attach point
1368 LLInventoryModel::cat_array_t* pFolders;
1369 LLInventoryModel::item_array_t* pItems;
1370 gInventory.getDirectDescendentsOf(pFolder->getUUID(), pFolders, pItems);
1371
1372 if (pItems)
1373 {
1374 int cntObjects = 0;
1375 for (S32 idxItem = 0, cntItem = pItems->size(); idxItem < cntItem; idxItem++)
1376 {
1377 if (LLAssetType::AT_OBJECT == pItems->get(idxItem)->getType())
1378 cntObjects++;
1379 }
1380
1381 // Only rename if there's exactly 1 object/attachment inside of it [see LLFolderBridge::renameItem()]
1382 if ( (1 == cntObjects) && (NEW_CATEGORY_NAME == pFolder->getName()) )
1383 {
1384 std::string strName = ".(" + strAttachPt + ")";
1385
1386 pFolder->rename(strName);
1387 pFolder->updateServer(FALSE);
1388 gInventory.updateCategory(pFolder);
1389 //gInventory.notifyObservers(); <- done further down in LLVOAvatar::attachObject()
1390 }
1391 }
1392 }
1393 }
1394 }
1395}
1396
1397// Checked: 2009-05-31 (RLVa-0.2.0e) | Modified: RLVa-0.2.0e
1398void RlvHandler::onDetach(LLViewerJointAttachment* pAttachPt)
1399{
1400 LLViewerObject* pObj = pAttachPt->getObject();
1401 if (!pObj)
1402 {
1403 // LLVOAvatar::detachObject() should call us *before* calling LLViewerJointAttachment::removeObject()
1404 RLV_ERRS << "pAttachPt->getObject() == NULL" << LL_ENDL;
1405 return;
1406 }
1407 S32 idxAttachPt = getAttachPointIndex(pObj);
1408 if (0 == idxAttachPt)
1409 {
1410 // If we ended up here then the user "Drop"'ed this attachment (which we can't recover from)
1411 return;
1412 }
1413
1414 #ifdef RLV_DEBUG
1415 // TODO-RLV: when we're exiting (for whatever reason) app state won't always reflect it but
1416 // gAgent.getAvatarObject()->mAttachmentPoints will be NULL so anywhere we use
1417 // "get_if_there" will call through a NULL pointer. One case is "idling out" -> test the rest
1418 //LLViewerJointAttachment* pDbgAttachmentPt =
1419 // get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, (S32)idxAttachPt, (LLViewerJointAttachment*)NULL);
1420 //RLV_INFOS << "Clean up for '" << pDbgAttachmentPt->getName() << "'" << LL_ENDL;
1421 #endif // RLV_DEBUG
1422
1423 // If the attachment was locked then we should reattach it (unless we're already trying to reattach to this attachment point)
1424 // (unless we forcefully detached it else in which case we do not want to reattach it)
1425 rlv_reattach_map_t::iterator itDetach = m_DetachPending.find(idxAttachPt);
1426 if (itDetach != m_DetachPending.end())
1427 {
1428 // RLVa-TODO: we should really be comparing item UUIDs but is it even possible to end up here and not have them match?
1429 m_DetachPending.erase(itDetach);
1430 }
1431 else if ( (!isDetachable(idxAttachPt)) && (m_AttachPending.find(idxAttachPt) == m_AttachPending.end()) )
1432 {
1433 // In an ideal world we would simply set up an LLInventoryObserver but there's no specific "asset updated" changed flag *sighs*
1434 // NOTE: attachments *always* know their "inventory item UUID" so we don't have to worry about fetched vs unfetched inventory
1435 m_AttachPending.insert(std::pair<S32, LLUUID>(idxAttachPt, pAttachPt->getItemID()));
1436 }
1437
1438 // We can't - easily - clean up child prims that never issued @detach=n but the GC will get those eventually
1439 rlv_detach_map_t::iterator itAttach = m_Attachments.find(idxAttachPt);
1440 while ( (itAttach != m_Attachments.upper_bound(idxAttachPt)) && (itAttach != m_Attachments.end()) )
1441 {
1442 LLViewerObject* pTempObj = gObjectList.findObject(itAttach->second);
1443 if ( (pTempObj) && (pTempObj->getRootEdit()->getID() == pObj->getID()) )
1444 {
1445 // Iterator points to the object (or to a child prim) so issue a clear on behalf of the object (there's the
1446 // possibility of going into an eternal loop, but that's ok since it indicates a bug in @clear that needs fixing)
1447 processCommand(itAttach->second, "clear", true);
1448
1449 itAttach = m_Attachments.find(idxAttachPt); // @clear will invalidate all iterators so we have to start anew
1450 }
1451 else
1452 {
1453 itAttach++;
1454 }
1455 }
1456
1457 // Clean up in case there was never a @detach=n (only works for the root prim - see above)
1458 rlv_object_map_t::iterator itObj = m_Objects.find(pObj->getID());
1459 if (itObj != m_Objects.end())
1460 processCommand(itObj->second.m_UUID, "clear", true);
1461}
1462
1463// Checked: 2009-07-30 (RLVa-1.0.1c) | Modified: RLVa-1.0.1c
1464bool RlvHandler::onGC()
1465{
1466 // We can't issue @clear on an object while we're in the loop below since that would invalidate our iterator
1467 // (and starting over would mean that some objects might get their "lookup misses" counter updated more than once per GC run)
1468 std::list<LLUUID> ExpiredObjects;
1469
1470 for (rlv_object_map_t::iterator itObj = m_Objects.begin(); itObj != m_Objects.end(); ++itObj)
1471 {
1472 LLViewerObject* pObj = gObjectList.findObject(itObj->second.m_UUID);
1473 if (!pObj)
1474 {
1475 // If the RlvObject once existed in the gObjectList and now doesn't then expire it right now
1476 // If the RlvObject never existed in the gObjectList and still doesn't then increase its "lookup misses" counter
1477 // but if that reaches 20 (we run every 30 seconds so that's about 10 minutes) then we'll expire it too
1478 if ( (itObj->second.m_fLookup) || (++itObj->second.m_nLookupMisses > 20) )
1479 ExpiredObjects.push_back(itObj->first);
1480 }
1481 else
1482 {
1483 // Check if this is an RlvObject instance who's object never existed in gObjectList before (rezzed prim in-world)
1484 // (it could also be an attachment that only just rezzed in but RlvHandler::onAttach() should be handling those)
1485 if ( (!itObj->second.m_fLookup) && (!pObj->isAttachment()) )
1486 itObj->second.m_fLookup = true;
1487 }
1488 }
1489
1490 for (std::list<LLUUID>::const_iterator itExpired = ExpiredObjects.begin(); itExpired != ExpiredObjects.end(); ++itExpired)
1491 {
1492 #ifdef RLV_DEBUG
1493 RLV_INFOS << "Garbage collecting " << *itExpired << LL_ENDL;
1494 #endif // RLV_DEBUG
1495
1496 processCommand(*itExpired, "clear", true);
1497 }
1498
1499 return (0 != m_Objects.size()); // GC will kill itself if it has nothing to do
1500}
1501
1502// Checked: 2009-08-08 (RLVa-1.0.1g) | Modified: RLVa-1.0.1g
1503void RlvHandler::onSavedAssetIntoInventory(const LLUUID& idItem)
1504{
1505 for (rlv_reattach_map_t::iterator itAttach = m_AttachPending.begin(); itAttach != m_AttachPending.end(); ++itAttach)
1506 {
1507 if (idItem == itAttach->second)
1508 {
1509 RLV_INFOS << "Reattaching " << idItem.asString() << " to " << itAttach->first << LL_ENDL;
1510
1511 #if RLV_TARGET < RLV_MAKE_TARGET(1, 23, 0) // Version: 1.22.11
1512 LLAttachmentRezAction* rez_action = new LLAttachmentRezAction;
1513 rez_action->mItemID = itAttach->second;
1514 rez_action->mAttachPt = itAttach->first;
1515
1516 confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action); // (Will call delete on rez_action)
1517 #else // Version: 1.23.4
1518 LLSD payload;
1519 payload["item_id"] = itAttach->second;
1520 payload["attachment_point"] = itAttach->first;
1521
1522 LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
1523 #endif
1524 }
1525 }
1526}
1527
1528// ============================================================================
1529// String/chat censoring functions
1530//
1531
1532// LL must have included an strlen for UTF8 *somewhere* but I can't seem to find it so this one is home grown
1533size_t utf8str_strlen(const std::string& utf8)
1534{
1535 const char* pUTF8 = utf8.c_str(); size_t length = 0;
1536 for (int idx = 0, cnt = utf8.length(); idx < cnt ;idx++)
1537 {
1538 // We're looking for characters that don't start with 10 as their high bits
1539 if ((pUTF8[idx] & 0xC0) != 0x80)
1540 length++;
1541 }
1542 return length;
1543}
1544
1545// TODO-RLV: works, but more testing won't hurt
1546std::string utf8str_chtruncate(const std::string& utf8, size_t length)
1547{
1548 if (0 == length)
1549 return std::string();
1550 if (utf8.length() <= length)
1551 return utf8;
1552
1553 const char* pUTF8 = utf8.c_str(); int idx = 0;
1554 while ( (pUTF8[idx]) && (length > 0) )
1555 {
1556 // We're looking for characters that don't start with 10 as their high bits
1557 if ((pUTF8[idx] & 0xC0) != 0x80)
1558 length--;
1559 idx++;
1560 }
1561
1562 return utf8.substr(0, idx);
1563}
1564
1565// Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
1566void RlvHandler::filterChat(std::string& strUTF8Text, bool fFilterEmote) const
1567{
1568 if (strUTF8Text.empty())
1569 return;
1570
1571 if (rlvIsEmote(strUTF8Text)) // Check if it's an emote
1572 {
1573 if (fFilterEmote) // Emote filtering depends on fFilterEmote
1574 {
1575 if ( (strUTF8Text.find_first_of("\"()*=^_?~") != -1) ||
1576 (strUTF8Text.find(" -") != -1) || (strUTF8Text.find("- ") != -1) || (strUTF8Text.find("''") != -1) )
1577 {
1578 strUTF8Text = "..."; // Emote contains illegal character (or character sequence)
1579 }
1580 else if (!hasBehaviour("emote"))
1581 {
1582 int idx = strUTF8Text.find('.'); // Truncate at 20 characters or at the dot (whichever is shorter)
1583 strUTF8Text = utf8str_chtruncate(strUTF8Text, ( (idx > 0) && (idx < 20) ) ? idx + 1 : 20);
1584 }
1585 }
1586 }
1587 else if (strUTF8Text[0] == '/') // Not an emote, but starts with a '/'
1588 {
1589 if (utf8str_strlen(strUTF8Text) > 7) // Allow as long if it's 6 characters or less
1590 strUTF8Text = "...";
1591 }
1592 else if ((strUTF8Text.length() < 4) || (strUTF8Text.compare(0, 2, "((")) || (strUTF8Text.compare(strUTF8Text.length() - 2, 2, "))")))
1593 {
1594 strUTF8Text = "..."; // Regular chat (not OOC)
1595 }
1596}
1597
1598// Checked: 2009-07-04 (RLVa-1.0.0a) | Modified: RLVa-1.0.0a
1599void RlvHandler::filterLocation(std::string& strUTF8Text) const
1600{
1601 // TODO-RLVa: if either the region or parcel name is a simple word such as "a" or "the" then confusion will ensue?
1602 // -> not sure how you would go about preventing this though :|...
1603
1604 // Filter any mention of the surrounding region names
1605 LLWorld::region_list_t regions = LLWorld::getInstance()->getRegionList();
1606 for (LLWorld::region_list_t::const_iterator itRegion = regions.begin(); itRegion != regions.end(); ++itRegion)
1607 rlvStringReplace(strUTF8Text, (*itRegion)->getName(), rlv_handler_t::cstrHiddenRegion);
1608
1609 // Filter any mention of the parcel name
1610 LLViewerParcelMgr* pParcelMgr = LLViewerParcelMgr::getInstance();
1611 if (pParcelMgr)
1612 rlvStringReplace(strUTF8Text, pParcelMgr->getAgentParcelName(), rlv_handler_t::cstrHiddenParcel);
1613}
1614
1615void RlvHandler::filterNames(std::string& strUTF8Text) const
1616{
1617 std::string strFirstName, strLastName, strName;
1618
1619 // TODO-RLV: make this a bit more efficient (ie people with a large draw distance will have a load of active regions)
1620 // -> the cost of multi string matching them all at once seems to be about the same as calling rlvStringReplace
1621 // twice so that would be a tremendous gain (and we'd get first name and word matching for free)
1622 #if RLV_TARGET < RLV_MAKE_TARGET(1, 23, 0) // Version: 1.22.11
1623 for (LLWorld::region_list_t::const_iterator itRegion = LLWorld::getInstance()->getRegionList().begin();
1624 itRegion != LLWorld::getInstance()->getRegionList().end(); ++itRegion)
1625 {
1626 LLViewerRegion* pRegion = *itRegion;
1627
1628 for (S32 idxAgent = 0, cntAgent = pRegion->mMapAvatars.count(); idxAgent < cntAgent; idxAgent++)
1629 {
1630 // LLCacheName::getName() will add the UUID to the lookup queue if we don't know it yet
1631 if (gCacheName->getName(pRegion->mMapAvatarIDs.get(idxAgent), strFirstName, strLastName))
1632 {
1633 strName = strFirstName + " " + strLastName;
1634
1635 rlvStringReplace(strUTF8Text, strName, getAnonym(strName));
1636 }
1637 }
1638 }
1639 #else // Version: trunk
1640 // TODO-RLV: should restrict this to a certain radius (probably 1-2 sim range?)
1641 std::vector<LLUUID> idAgents;
1642 LLWorld::getInstance()->getAvatars(&idAgents, NULL);
1643
1644 for (int idxAgent = 0, cntAgent = idAgents.size(); idxAgent < cntAgent; idxAgent++)
1645 {
1646 // LLCacheName::getName() will add the UUID to the lookup queue if we don't know it yet
1647 if (gCacheName->getName(idAgents[idxAgent], strFirstName, strLastName))
1648 {
1649 strName = strFirstName + " " + strLastName;
1650
1651 rlvStringReplace(strUTF8Text, strName, getAnonym(strName));
1652 }
1653 }
1654 #endif
1655}
1656
1657const std::string& RlvHandler::getAnonym(const std::string& strName) const
1658{
1659 const char* pszName = strName.c_str();
1660 U32 nHash = 0;
1661
1662 // Test with 11,264 SL names showed a 3.33% - 3.82% occurance for each so we *should* get a very even spread
1663 for (int idx = 0, cnt = strName.length(); idx < cnt; idx++)
1664 nHash += pszName[idx];
1665
1666 return cstrAnonyms[nHash % 28];
1667}
1668
1669// Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.2a
1670bool RlvHandler::redirectChatOrEmote(const std::string& strUTF8Text) const
1671{
1672 // Sanity check - @redirchat only for chat and @rediremote only for emotes
1673 bool fIsEmote = rlvIsEmote(strUTF8Text);
1674 if ( ((!fIsEmote) && (!hasBehaviour(RLV_BHVR_REDIRCHAT))) || ((fIsEmote) && (!hasBehaviour(RLV_BHVR_REDIREMOTE))) )
1675 return false;
1676
1677 if (!fIsEmote)
1678 {
1679 std::string strText = strUTF8Text;
1680 filterChat(strText, true);
1681 if (strText != "...")
1682 return false; // @sendchat wouldn't filter it so @redirchat won't redirect it either
1683 }
1684
1685 bool fSendChannel = hasBehaviour("sendchannel");
1686 for (rlv_object_map_t::const_iterator itObj = m_Objects.begin(); itObj != m_Objects.end(); ++itObj)
1687 {
1688 for (rlv_command_list_t::const_iterator itCmd = itObj->second.m_Commands.begin(),
1689 endCmd = itObj->second.m_Commands.end(); itCmd != endCmd; ++itCmd)
1690 {
1691 if ( ( ((!fIsEmote) && (RLV_BHVR_REDIRCHAT == itCmd->getBehaviourType())) ||
1692 ((fIsEmote) && (RLV_BHVR_REDIREMOTE == itCmd->getBehaviourType())) ) &&
1693 ( (!fSendChannel) || (hasBehaviour("sendchannel", itCmd->getOption())) ) )
1694 {
1695 rlvSendChatReply(itCmd->getOption(), strUTF8Text);
1696 }
1697 }
1698 }
1699 return true;
1700}
1701
1702// ============================================================================
1703// Public service functions (called by the outside world or by extension handlers)
1704//
1705
1706BOOL RlvHandler::isAgentNearby(const LLUUID& uuid) const
1707{
1708 #if RLV_TARGET < RLV_MAKE_TARGET(1, 23, 0) // Version: 1.22.11
1709 for (LLWorld::region_list_t::const_iterator itRegion = LLWorld::getInstance()->getRegionList().begin();
1710 itRegion != LLWorld::getInstance()->getRegionList().end(); ++itRegion)
1711 {
1712 LLViewerRegion* pRegion = *itRegion;
1713
1714 for (S32 idxAgent = 0, cntAgent = pRegion->mMapAvatars.count(); idxAgent < cntAgent; idxAgent++)
1715 if (pRegion->mMapAvatarIDs.get(idxAgent) == uuid)
1716 return TRUE;
1717 }
1718 #else // Version: trunk
1719 // TODO-RLV: rewrite this to fit trunk, but still need the radius limited to a sane range
1720 std::vector<LLUUID> idAgents;
1721 LLWorld::getInstance()->getAvatars(&idAgents, NULL);
1722
1723 for (int idxAgent = 0, cntAgent = idAgents.size(); idxAgent < cntAgent; idxAgent++)
1724 {
1725 if (idAgents[idxAgent] == uuid)
1726 return TRUE;
1727 }
1728 #endif
1729 return FALSE;
1730}
1731
1732// ============================================================================
1733// General purpose inventory functions
1734//
1735
1736// Checked: 2009-07-12 (RLVa-1.0.0h)
1737class RlvSharedRootFetcher : public LLInventoryFetchDescendentsObserver
1738{
1739public:
1740 RlvSharedRootFetcher() {}
1741
1742 virtual void done()
1743 {
1744 RLV_INFOS << "Shared folders fetch completed" << LL_ENDL;
1745 RlvHandler::m_fFetchComplete = TRUE;
1746
1747 gInventory.removeObserver(this);
1748 delete this;
1749 }
1750};
1751
1752// Checked: 2009-07-12 (RLVa-1.0.0h)
1753void RlvHandler::fetchSharedInventory()
1754{
1755 // Sanity check - don't fetch if we're already fetching, or if we don't have a shared root
1756 LLViewerInventoryCategory* pRlvRoot = getSharedRoot();
1757 if ( (m_fFetchStarted) || (!pRlvRoot) )
1758 return;
1759
1760 // Grab all the folders under the shared root
1761 LLInventoryModel::cat_array_t folders;
1762 LLInventoryModel::item_array_t items;
1763 gInventory.collectDescendents(pRlvRoot->getUUID(), folders, items, FALSE);
1764
1765 /*
1766 * Add them to the "to fetch" list
1767 */
1768 LLInventoryFetchDescendentsObserver::folder_ref_t fetchFolders;
1769
1770 fetchFolders.push_back(pRlvRoot->getUUID());
1771 for (S32 idxFolder = 0, cntFolder = folders.count(); idxFolder < cntFolder; idxFolder++)
1772 fetchFolders.push_back(folders.get(idxFolder)->getUUID());
1773
1774 /*
1775 * Now fetch them all in one go
1776 */
1777 RlvSharedRootFetcher* fetcher = new RlvSharedRootFetcher;
1778
1779 RLV_INFOS << "Starting fetch of " << fetchFolders.size() << " shared folders" << LL_ENDL;
1780 fetcher->fetchDescendents(fetchFolders);
1781
1782 if (fetcher->isEverythingComplete())
1783 fetcher->done();
1784 else
1785 gInventory.addObserver(fetcher);
1786}
1787
1788bool RlvHandler::findSharedFolders(const std::string& strCriteria, LLInventoryModel::cat_array_t& folders) const
1789{
1790 // Sanity check - can't do anything without a shared root
1791 LLViewerInventoryCategory* pRlvRoot = getSharedRoot();
1792 if (!pRlvRoot)
1793 return false;
1794
1795 folders.clear();
1796 LLInventoryModel::item_array_t items;
1797 RlvCriteriaCategoryCollector functor(strCriteria);
1798 gInventory.collectDescendentsIf(pRlvRoot->getUUID(), folders, items, FALSE, functor);
1799
1800 return (folders.count() != 0);
1801}
1802
1803// Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-0.2.0e
1804LLViewerInventoryCategory* RlvHandler::getSharedRoot()
1805{
1806 if (gInventory.isInventoryUsable())
1807 {
1808 LLInventoryModel::cat_array_t* pFolders;
1809 LLInventoryModel::item_array_t* pItems;
1810 gInventory.getDirectDescendentsOf(gAgent.getInventoryRootID(), pFolders, pItems);
1811 if (pFolders)
1812 {
1813 // NOTE: we might have multiple #RLV folders so we'll just go with the first one we come across
1814 LLViewerInventoryCategory* pFolder;
1815 for (S32 idxFolder = 0, cntFolder = pFolders->count(); idxFolder < cntFolder; idxFolder++)
1816 {
1817 if ( ((pFolder = pFolders->get(idxFolder)) != NULL) && (RlvHandler::cstrSharedRoot == pFolder->getName()) )
1818 return pFolder;
1819 }
1820 }
1821 }
1822 return NULL;
1823}
1824
1825// Checked: 2009-07-28 (RLVa-1.0.1a) | Modified: RLVa-1.0.1a
1826LLViewerInventoryCategory* RlvHandler::getSharedFolder(const LLUUID& idParent, const std::string& strFolderName) const
1827{
1828 LLInventoryModel::cat_array_t* pFolders;
1829 LLInventoryModel::item_array_t* pItems;
1830 gInventory.getDirectDescendentsOf(idParent, pFolders, pItems);
1831 if ( (!pFolders) || (strFolderName.empty()) )
1832 return NULL;
1833
1834 // If we can't find an exact match then we'll settle for a "contains" match
1835 LLViewerInventoryCategory* pPartial = NULL;
1836
1837 //LLStringUtil::toLower(strFolderName); <- everything was already converted to lower case before
1838
1839 std::string strName;
1840 for (S32 idxFolder = 0, cntFolder = pFolders->count(); idxFolder < cntFolder; idxFolder++)
1841 {
1842 LLViewerInventoryCategory* pFolder = pFolders->get(idxFolder);
1843
1844 strName = pFolder->getName();
1845 if (strName.empty())
1846 continue;
1847 LLStringUtil::toLower(strName);
1848
1849 if (strFolderName == strName)
1850 return pFolder; // Found an exact match, no need to keep on going
1851 else if ( (!pPartial) && (RLV_FOLDER_PREFIX_HIDDEN != strName[0]) && (strName.find(strFolderName) != std::string::npos) )
1852 pPartial = pFolder; // Found a partial (non-hidden) match, but we might still find an exact one (first partial match wins)
1853 }
1854
1855 return pPartial;
1856}
1857
1858// Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-0.2.0e
1859LLViewerInventoryCategory* RlvHandler::getSharedFolder(const std::string& strPath) const
1860{
1861 // Sanity check - no shared root => no shared folder
1862 LLViewerInventoryCategory* pRlvRoot = getSharedRoot(), *pFolder = pRlvRoot;
1863 if (!pRlvRoot)
1864 return NULL;
1865
1866 // Walk the path (starting at the root)
1867 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
1868 boost::char_separator<char> sep("/", "", boost::drop_empty_tokens);
1869 tokenizer tokens(strPath, sep);
1870 for (tokenizer::iterator itToken = tokens.begin(); itToken != tokens.end(); ++itToken)
1871 {
1872 pFolder = getSharedFolder(pFolder->getUUID(), *itToken);
1873 if (!pFolder)
1874 return NULL; // No such folder
1875 }
1876
1877 return pFolder; // If strPath was empty or just a bunch of //// then: pFolder == pRlvRoot
1878}
1879
1880// Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-0.2.0g
1881std::string RlvHandler::getSharedPath(const LLViewerInventoryCategory* pFolder) const
1882{
1883 LLViewerInventoryCategory* pRlvRoot = getSharedRoot();
1884 // Sanity check - no shared root or no folder => no path
1885 if ( (!pRlvRoot) || (!pFolder) || (pRlvRoot->getUUID() == pFolder->getUUID()) )
1886 return std::string();
1887
1888 const LLUUID& idRLV = pRlvRoot->getUUID();
1889 const LLUUID& idRoot = gAgent.getInventoryRootID();
1890 std::string strPath;
1891
1892 // Walk up the tree until we reach the top
1893 while (pFolder)
1894 {
1895 strPath = "/" + pFolder->getName() + strPath;
1896
1897 const LLUUID& idParent = pFolder->getParentUUID();
1898 if (idRLV == idParent) // Reached the shared root, we're done
1899 break;
1900 else if (idRoot == idParent) // We reached the agent's inventory root (indicative of a logic error elsewhere)
1901 {
1902 RLV_ERRS << "Reached agent's inventory root while building path for shared folder" << LL_ENDL;
1903 return std::string();
1904 }
1905 else
1906 pFolder = gInventory.getCategory(idParent);
1907 }
1908
1909 return strPath.erase(0, 1);
1910}
1911
1912// ============================================================================
1913// Composite folders
1914//
1915
1916#ifdef RLV_EXPERIMENTAL_COMPOSITES
1917 // Checked:
1918 bool RlvHandler::getCompositeInfo(const LLInventoryCategory* pFolder, std::string* pstrName) const
1919 {
1920 if (pFolder)
1921 {
1922 // Composite folder naming: ^\.?[Folder]
1923 const std::string& cstrFolder = pFolder->getName();
1924 int idxStart = cstrFolder.find('['), idxEnd = cstrFolder.find(']', idxStart);
1925 if ( ((0 == idxStart) || (1 == idxStart)) && (idxEnd - idxStart > 1) )
1926 {
1927 if (pstrName)
1928 pstrName->assign(cstrFolder.substr(idxStart + 1, idxEnd - idxStart - 1));
1929 return true;
1930 }
1931 }
1932 return false;
1933 }
1934
1935 // Checked:
1936 bool RlvHandler::getCompositeInfo(const LLUUID& idItem, std::string* pstrName, LLViewerInventoryCategory** ppFolder) const
1937 {
1938 LLViewerInventoryCategory* pRlvRoot; LLViewerInventoryItem* pItem;
1939
1940 if ( (idItem.notNull()) && ((pRlvRoot = getSharedRoot()) != NULL) &&
1941 (gInventory.isObjectDescendentOf(idItem, pRlvRoot->getUUID())) && ((pItem = gInventory.getItem(idItem)) != NULL) )
1942 {
1943 // We know it's an item in a folder under the shared root...
1944 LLViewerInventoryCategory* pFolder = gInventory.getCategory(pItem->getParentUUID());
1945 if (getAttachPoint(pFolder, true))
1946 {
1947 // ... but it could be named ".(attachpt)" in which case we need its parent
1948 pFolder = gInventory.getCategory(pFolder->getParentUUID());
1949 }
1950
1951 if ( (pFolder) && (getCompositeInfo(pFolder, pstrName)) )
1952 {
1953 if (ppFolder)
1954 *ppFolder = pFolder;
1955 return true;
1956 }
1957 }
1958 return false;
1959 }
1960#endif // RLV_EXPERIMENTAL_COMPOSITES
1961
1962#ifdef RLV_EXPERIMENTAL_COMPOSITE_FOLDING
1963 // Checked:
1964 inline bool RlvHandler::isHiddenCompositeItem(const LLUUID& idItem, const std::string& cstrItemType) const
1965 {
1966 // An item that's part of a composite folder will be hidden from @getoutfit and @getattach if:
1967 // (1) the composite name specifies either a wearable layer or an attachment point
1968 // (2) the specified wearable layer or attachment point is worn and resides in the folder
1969 // (3) cstrItemType isn't the specified wearable layer or attach point
1970 //
1971 // Example: #RLV/Separates/Shoes/ChiChi Pumps/.[shoes] with items: "Shoe Base", "Shoe (left foot)" and "Shoe (right foot)"
1972 // -> as long as "Shoe Base" is worn, @getattach should not reflect "left foot", nor "right foot"
1973 std::string strComposite; LLViewerInventoryCategory* pFolder;
1974 EWearableType type; S32 idxAttachPt;
1975 if ( (getCompositeInfo(idItem, &strComposite, &pFolder)) && (cstrItemType != strComposite) )
1976 {
1977 LLUUID idCompositeItem;
1978 if ((type = LLWearable::typeNameToType(strComposite)) != WT_INVALID)
1979 {
1980 idCompositeItem = gAgent.getWearableItem(type);
1981 }
1982 else if ((idxAttachPt = getAttachPointIndex(strComposite, true)) != 0)
1983 {
1984 LLVOAvatar* pAvatar; LLViewerJointAttachment* pAttachmentPt;
1985 if ( ((pAvatar = gAgent.getAvatarObject()) != NULL) &&
1986 ((pAttachmentPt = get_if_there(pAvatar->mAttachmentPoints, idxAttachPt, (LLViewerJointAttachment*)NULL)) != NULL) )
1987 {
1988 idCompositeItem = pAttachmentPt->getItemID();
1989 }
1990 }
1991
1992 if ( (idCompositeItem.notNull()) && (gInventory.isObjectDescendentOf(idCompositeItem, pFolder->getUUID())) )
1993 return true;
1994 }
1995 return false;
1996 }
1997#endif // RLV_EXPERIMENTAL_COMPOSITEFOLDING
1998
1999#ifdef RLV_EXPERIMENTAL_COMPOSITE_LOCKING
2000 // Checked:
2001 bool RlvHandler::canTakeOffComposite(const LLInventoryCategory* pFolder) const
2002 {
2003 if (!pFolder) // If there's no folder then there is nothing to take off
2004 return false;
2005
2006 LLInventoryModel::cat_array_t folders;
2007 LLInventoryModel::item_array_t items;
2008 RlvWearableItemCollector functor(pFolder->getUUID(), true, false);
2009
2010 // Grab a list of all the items @detachthis would be detaching/unwearing
2011 gInventory.collectDescendentsIf(pFolder->getUUID(), folders, items, FALSE, functor);
2012 if (!items.count())
2013 return false; // There are no wearable items in the folder so there is nothing to take off
2014
2015 LLViewerInventoryItem* pItem;
2016 for (S32 idxItem = 0, cntItem = items.count(); idxItem < cntItem; idxItem++)
2017 {
2018 pItem = items.get(idxItem);
2019
2020 switch (pItem->getType())
2021 {
2022 case LLAssetType::AT_CLOTHING:
2023 {
2024 LLWearable* pWearable = gAgent.getWearableFromWearableItem(pItem->getUUID());
2025 if ( (pWearable) && (!isRemovable(pWearable->getType())) )
2026 return false; // If one clothing layer in the composite folder is unremoveable then the entire folder is
2027 }
2028 break;
2029 case LLAssetType::AT_OBJECT:
2030 {
2031 LLVOAvatar* pAvatar; LLViewerObject* pObj;
2032 if ( ((pAvatar = gAgent.getAvatarObject()) != NULL) &&
2033 ((pObj = pAvatar->getWornAttachment(pItem->getUUID())) != NULL) && (!isDetachable(pObj)) )
2034 {
2035 return false; // If one attachment in the composite folder is undetachable then the entire folder is
2036 }
2037 }
2038 break;
2039 #ifdef LL_GNUC
2040 default:
2041 break;
2042 #endif // LL_GNUC
2043 }
2044 }
2045 return true;
2046 }
2047#endif // RLV_EXPERIMENTAL_COMPOSITE_LOCKING
2048
2049// ============================================================================
2050// Event handlers
2051//
2052
2053// Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-0.2.0d
2054void RlvHandler::onForceDetach(const LLUUID& idObj, const std::string& strOption) const
2055{
2056 U16 nParam;
2057 if (strOption.empty())
2058 {
2059 // Simulate right-click / Take Off > Detach All
2060 LLAgent::userRemoveAllAttachments(NULL);
2061 }
2062 else if (m_AttachLookup.getExactMatchParam(strOption, nParam))
2063 {
2064 // Simulate right-click / Take Off > Detach > ...
2065 LLVOAvatar* pAvatar; LLViewerJointAttachment* pAttachmentPt;
2066 if ( ((pAvatar = gAgent.getAvatarObject()) != NULL) && // Make sure we're actually wearing something on the attachment point
2067 ((pAttachmentPt = get_if_there(pAvatar->mAttachmentPoints, (S32)nParam, (LLViewerJointAttachment*)NULL)) != NULL) &&
2068 (isStrippable(pAttachmentPt->getItemID())) ) // ... and that it's not marked as "nostrip"
2069 {
2070 #ifdef RLV_EXPERIMENTAL_COMPOSITES
2071 // If we're stripping something that's part of a composite folder then we should @detachthis instead
2072 if (isCompositeDescendent(pAttachmentPt->getItemID()))
2073 {
2074 std::string strCmd = "detachthis:" + strOption + "=force";
2075 #ifdef RLV_DEBUG
2076 RLV_INFOS << "\t- '" << strOption << "' belongs to composite folder: @" << strCmd << LL_ENDL;
2077 #endif // RLV_DEBUG
2078 processForceCommand(idObj, RlvCommand(strCmd));
2079 }
2080 else
2081 #endif // RLV_EXPERIMENTAL_COMPOSITES
2082 {
2083 handle_detach_from_avatar(pAttachmentPt);
2084 }
2085 }
2086 }
2087 else
2088 {
2089 // Force detach single folder
2090 onForceWear(strOption, false, false);
2091 }
2092}
2093
2094// Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-0.2.0d
2095void RlvHandler::onForceRemOutfit(const LLUUID& idObj, const std::string& strOption) const
2096{
2097 EWearableType typeOption = LLWearable::typeNameToType(strOption), type;
2098 if ( (WT_INVALID == typeOption) && (!strOption.empty()) )
2099 return;
2100
2101 // Before we had an option and optionless branch, but with the addition of composites and nostrip there's less duplication this way
2102 for (int idxType = 0; idxType < WT_COUNT; idxType++)
2103 {
2104 type = (EWearableType)idxType;
2105
2106 // Only strip clothing (that's currently worn and not marked "nostrip")
2107 if ( (LLAssetType::AT_CLOTHING != LLWearable::typeToAssetType(type)) ||
2108 (!gAgent.getWearable(type)) || (!isStrippable(gAgent.getWearableItem(type))) )
2109 {
2110 continue;
2111 }
2112
2113 if ( (typeOption == type) || (strOption.empty()) )
2114 {
2115 #ifdef RLV_EXPERIMENTAL_COMPOSITES
2116 // If we're stripping something that's part of a composite folder then we should @detachthis instead
2117 if (isCompositeDescendent(gAgent.getWearableItem(type)))
2118 {
2119 std::string strCmd = "detachthis:" + LLWearable::typeToTypeName(type) + "=force";
2120 #ifdef RLV_DEBUG
2121 RLV_INFOS << "\t- '" << LLWearable::typeToTypeName(type) << "' is composite descendent: @" << strCmd << LL_ENDL;
2122 #endif // RLV_DEBUG
2123 processForceCommand(idObj, RlvCommand(strCmd));
2124 }
2125 else
2126 #endif // RLV_EXPERIMENTAL_COMPOSITES
2127 {
2128 gAgent.removeWearable(type);
2129 }
2130 }
2131 }
2132}
2133
2134// Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-0.2.0g
2135bool RlvHandler::onForceSit(const LLUUID& idObj, const std::string& strOption) const
2136{
2137 LLViewerObject* pObject = NULL; LLUUID idTarget(strOption);
2138 // Sanity checking - we need to know about the object and it should identify a prim/linkset
2139 if ( (idTarget.isNull()) || ((pObject = gObjectList.findObject(idTarget)) == NULL) || (LL_PCODE_VOLUME != pObject->getPCode()) )
2140 return false;
2141
2142 // Don't force sit if:
2143 // 1) currently sitting and prevented from standing up
2144 // 2) prevented from sitting
2145 // 3) @sittp=n restricted (except if @sittp=n was issued by the same prim that's currently force sitting the avie)
2146 if ( ( (hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->mIsSitting) ) ||
2147 ( (hasBehaviour(RLV_BHVR_SIT)) ) ||
2148 ( (hasBehaviourExcept(RLV_BHVR_SITTP, idObj)) &&
2149 (dist_vec_squared(gAgent.getPositionGlobal(), pObject->getPositionGlobal()) > 1.5f * 1.5f) ))
2150 {
2151 return false;
2152 }
2153
2154 // Copy/paste from handle_sit_or_stand() [see http://wiki.secondlife.com/wiki/AgentRequestSit]
2155 gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit);
2156 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
2157 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
2158 gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
2159 gMessageSystem->nextBlockFast(_PREHASH_TargetObject);
2160 gMessageSystem->addUUIDFast(_PREHASH_TargetID, pObject->mID);
2161 // Offset: "a rough position in local coordinates for the edge to sit on"
2162 // (we might not even be looking at the object so I don't think we can supply the offset to an edge)
2163 gMessageSystem->addVector3Fast(_PREHASH_Offset, LLVector3::zero);
2164 pObject->getRegion()->sendReliableMessage();
2165
2166 return true;
2167}
2168
2169void RlvHandler::onForceWear(const std::string& strPath, bool fAttach, bool fMatchAll) const
2170{
2171 // See LLWearableBridge::wearOnAvatar(): don't wear anything until initial wearables are loaded, can destroy clothing items
2172 if (!gAgent.areWearablesLoaded())
2173 return;
2174
2175 LLViewerInventoryCategory* pFolder = getSharedFolder(strPath);
2176 if (!pFolder) // Folder not found = nothing to attach
2177 return;
2178
2179 LLInventoryModel::cat_array_t folders;
2180 LLInventoryModel::item_array_t items;
2181 RlvWearableItemCollector functor(pFolder->getUUID(), fAttach, fMatchAll);
2182
2183 // Grab a list of all the items we'll be wearing/attaching
2184 gInventory.collectDescendentsIf(pFolder->getUUID(), folders, items, FALSE, functor);
2185
2186 LLViewerInventoryItem* pItem;
2187 for (S32 idxItem = 0, cntItem = items.count(); idxItem < cntItem; idxItem++)
2188 {
2189 pItem = items.get(idxItem);
2190
2191 switch (pItem->getType())
2192 {
2193 case LLAssetType::AT_CLOTHING:
2194 case LLAssetType::AT_BODYPART:
2195 {
2196 LLWearable* pWearable = gAgent.getWearableFromWearableItem(pItem->getUUID());
2197
2198 #ifdef RLV_EXPERIMENTAL_COMPOSITE_LOCKING
2199 // If we're already wearing something on this layer then we have to check if it isn't part of a composite
2200 // folder that has at least one unremovable item (in which case we can't wear or remove this item)
2201 LLViewerInventoryCategory* pCompositeFolder;
2202 if ( (!pWearable) || (!getCompositeInfo(pItem->getUUID(), NULL, &pCompositeFolder)) ||
2203 (canTakeOffComposite(pFolder)))
2204 {
2205 #endif // RLV_EXPERIMENTAL_COMPOSITE_LOCKING
2206 if (fAttach)
2207 {
2208 // Simulate wearing a clothing item from inventory (right click / "Wear")
2209 // LLWearableBridge::performAction() => LLWearableBridge::wearOnAvatar() => wear_inventory_item_on_avatar()
2210 wear_inventory_item_on_avatar(pItem);
2211 }
2212 else
2213 {
2214 if ( (pWearable) && (LLAssetType::AT_CLOTHING == pItem->getType()) )
2215 gAgent.removeWearable(pWearable->getType());
2216 }
2217 #ifdef RLV_EXPERIMENTAL_COMPOSITE_LOCKING
2218 }
2219 #endif // RLV_EXPERIMENTAL_COMPOSITE_LOCKING
2220 }
2221 break;
2222 case LLAssetType::AT_OBJECT:
2223 {
2224 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
2225 LLViewerObject* pObj;
2226
2227 #ifdef RLV_EXPERIMENTAL_COMPOSITE_LOCKING
2228 // If we're already wearing something on this attach point then we have to check if it isn't part of a composite
2229 // folder that has at least one unremovable item (in which case we can't attach or detach this item)
2230 LLViewerInventoryCategory* pCompositeFolder;
2231 if ( (pAvatar) &&
2232 ( ((pObj = pAvatar->getWornAttachment(pItem->getUUID())) == NULL) ||
2233 (!getCompositeInfo(pItem->getUUID(), NULL, &pCompositeFolder)) || (canTakeOffComposite(pFolder)) ) )
2234 {
2235 #endif // RLV_EXPERIMENTAL_COMPOSITE_LOCKING
2236 if (fAttach)
2237 {
2238 // Simulate wearing an object to a specific attachment point (copy/paste to suppress replacement dialog)
2239 // LLAttachObject::handleEvent() => rez_attachment()
2240 LLViewerJointAttachment* pAttachPt = getAttachPoint(pItem, true);
2241 if ( (pAttachPt) && (isDetachable(pAttachPt->getObject())) )
2242 {
2243 #if RLV_TARGET < RLV_MAKE_TARGET(1, 23, 0) // Version: 1.22.11
2244 LLAttachmentRezAction* rez_action = new LLAttachmentRezAction;
2245 rez_action->mItemID = pItem->getUUID();
2246 rez_action->mAttachPt = getAttachPointIndex(pAttachPt->getName(), true);
2247
2248 confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action); // (Will call delete on rez_action)
2249 #else // Version: 1.23.4
2250 LLSD payload;
2251 payload["item_id"] = pItem->getUUID();
2252 payload["attachment_point"] = getAttachPointIndex(pAttachPt->getName(), true);
2253
2254 LLNotifications::instance().forceResponse(
2255 LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
2256 #endif
2257 }
2258 }
2259 else
2260 {
2261 if ( (pAvatar) && ((pObj = pAvatar->getWornAttachment(pItem->getUUID())) != NULL) )
2262 {
2263 LLViewerJointAttachment* pAttachment = pAvatar->getTargetAttachmentPoint(pObj);
2264 if (pAttachment)
2265 handle_detach_from_avatar(pAttachment);
2266 }
2267 }
2268 #ifdef RLV_EXPERIMENTAL_COMPOSITE_LOCKING
2269 }
2270 #endif // RLV_EXPERIMENTAL_COMPOSITE_LOCKING
2271 }
2272 break;
2273 #ifdef LL_GNUC
2274 default:
2275 break;
2276 #endif // LL_GNUC
2277 }
2278 }
2279}
2280
2281// Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-0.2.0g
2282bool RlvHandler::onGetPath(const LLUUID &uuid, const std::string& strOption, std::string& strReply) const
2283{
2284 // Sanity check - no need to go through all this trouble if we don't have a shared root
2285 LLViewerInventoryCategory* pRlvRoot = getSharedRoot();
2286 if (!pRlvRoot)
2287 return false;
2288
2289 LLUUID idItem;
2290
2291 // <option> can be a clothing layer
2292 EWearableType layerType = LLWearable::typeNameToType(strOption);
2293 if (WT_INVALID != layerType)
2294 {
2295 idItem = gAgent.getWearableItem(layerType);
2296 }
2297 else
2298 {
2299 LLViewerJointAttachment* pAttachPt = NULL;
2300
2301 // ... or it can be empty
2302 if (strOption.empty())
2303 {
2304 // (in which case we act on the object that issued the command)
2305 LLViewerObject* pObj = gObjectList.findObject(uuid);
2306 if ( (pObj) && (pObj->isAttachment()) && (gAgent.getAvatarObject()) )
2307 pAttachPt = gAgent.getAvatarObject()->getTargetAttachmentPoint(pObj);
2308 }
2309 else
2310 {
2311 // ... or it can specify an attach point
2312 pAttachPt = getAttachPoint(strOption, true);
2313 }
2314
2315 // If we found something, get its inventory item UUID
2316 if (pAttachPt)
2317 idItem = pAttachPt->getItemID();
2318 }
2319
2320 // If we found something and it's under the shared root, then get its path
2321 if ( (!idItem.isNull()) && (gInventory.isObjectDescendentOf(idItem, pRlvRoot->getUUID())) )
2322 {
2323 LLInventoryItem* pItem = gInventory.getItem(idItem);
2324 if (pItem)
2325 {
2326 // ... unless the containing folder's name specifies an attach point (or nostrip) in which case we need its parent
2327 LLViewerInventoryCategory* pFolder = gInventory.getCategory(pItem->getParentUUID());
2328 #ifdef RLV_EXTENSION_FLAG_NOSTRIP
2329 if ( (getAttachPoint(pFolder, true)) || (pFolder->getName() == ".("RLV_FOLDER_FLAG_NOSTRIP")") )
2330 #else
2331 if (getAttachPoint(pFolder, true))
2332 #endif // RLV_EXTENSION_FLAG_NOSTRIP
2333 strReply = getSharedPath(pFolder->getParentUUID());
2334 else
2335 strReply = getSharedPath(pFolder);
2336 }
2337 }
2338 return !strReply.empty();
2339}
2340
2341struct rlv_wear_info { U32 cntWorn, cntTotal, cntChildWorn, cntChildTotal; };
2342
2343// Checked: 2009-05-30 (RLVa-0.2.0e) | Modified: RLVa-0.2.0e
2344void RlvHandler::onGetInvWorn(const std::string& strPath, std::string& strReply) const
2345{
2346 // Sanity check - getAvatarObject() can't be NULL [see rlvIsWearingItem()] and the folder should exist and not be hidden
2347 LLViewerInventoryCategory* pFolder = getSharedFolder(strPath);
2348 if ((!gAgent.getAvatarObject()) || (!pFolder) || (pFolder->getName().empty()) || (RLV_FOLDER_PREFIX_HIDDEN == pFolder->getName()[0]))
2349 return;
2350
2351 // Collect everything @attachall would be attaching
2352 LLInventoryModel::cat_array_t folders;
2353 LLInventoryModel::item_array_t items;
2354 RlvWearableItemCollector functor(pFolder->getUUID(), true, true);
2355 gInventory.collectDescendentsIf(pFolder->getUUID(), folders, items, FALSE, functor);
2356
2357 rlv_wear_info wi = {0};
2358
2359 // Add all the folders to a lookup map
2360 std::map<LLUUID, rlv_wear_info> mapFolders;
2361 mapFolders.insert(std::pair<LLUUID, rlv_wear_info>(pFolder->getUUID(), wi));
2362 for (S32 idxFolder = 0, cntFolder = folders.count(); idxFolder < cntFolder; idxFolder++)
2363 mapFolders.insert(std::pair<LLUUID, rlv_wear_info>(folders.get(idxFolder)->getUUID(), wi));
2364
2365 // Iterate over all the found items
2366 LLViewerInventoryItem* pItem; std::map<LLUUID, rlv_wear_info>::iterator itFolder;
2367 for (S32 idxItem = 0, cntItem = items.count(); idxItem < cntItem; idxItem++)
2368 {
2369 pItem = items.get(idxItem);
2370
2371 // The "folded parent" is the folder this item should be considered a direct descendent of (may or may not match actual parent)
2372 const LLUUID& idParent = functor.getFoldedParent(pItem->getParentUUID());
2373
2374 // Walk up the tree: sooner or later one of the parents will be a folder in the map
2375 LLViewerInventoryCategory* pParent = gInventory.getCategory(idParent);
2376 while ( (itFolder = mapFolders.find(pParent->getUUID())) == mapFolders.end() )
2377 pParent = gInventory.getCategory(pParent->getParentUUID());
2378
2379 U32 &cntWorn = (idParent == pParent->getUUID()) ? itFolder->second.cntWorn : itFolder->second.cntChildWorn,
2380 &cntTotal = (idParent == pParent->getUUID()) ? itFolder->second.cntTotal : itFolder->second.cntChildTotal;
2381
2382 if (rlvIsWearingItem(pItem))
2383 cntWorn++;
2384 cntTotal++;
2385 }
2386
2387 // Extract the result for the main folder
2388 itFolder = mapFolders.find(pFolder->getUUID());
2389 wi.cntWorn = itFolder->second.cntWorn;
2390 wi.cntTotal = itFolder->second.cntTotal;
2391 mapFolders.erase(itFolder);
2392
2393 // Build the result for each child folder
2394 for (itFolder = mapFolders.begin(); itFolder != mapFolders.end(); ++itFolder)
2395 {
2396 rlv_wear_info& wiFolder = itFolder->second;
2397
2398 wi.cntChildWorn += wiFolder.cntWorn + wiFolder.cntChildWorn;
2399 wi.cntChildTotal += wiFolder.cntTotal + wiFolder.cntChildTotal;
2400
2401 strReply += llformat(",%s|%d%d", gInventory.getCategory(itFolder->first)->getName().c_str(),
2402 (0 == wiFolder.cntTotal) ? 0 : (0 == wiFolder.cntWorn) ? 1 : (wiFolder.cntWorn != wiFolder.cntTotal) ? 2 : 3,
2403 (0 == wiFolder.cntChildTotal) ? 0 : (0 == wiFolder.cntChildWorn) ? 1 : (wiFolder.cntChildWorn != wiFolder.cntChildTotal) ? 2 : 3
2404 );
2405 }
2406
2407 // Now just prepend the root and done
2408 strReply = llformat("|%d%d", (0 == wi.cntTotal) ? 0 : (0 == wi.cntWorn) ? 1 : (wi.cntWorn != wi.cntTotal) ? 2 : 3,
2409 (0 == wi.cntChildTotal) ? 0 : (0 == wi.cntChildWorn) ? 1 : (wi.cntChildWorn != wi.cntChildTotal) ? 2: 3) + strReply;
2410}
2411
2412// (In case anyone cares: this isn't used in public builds)
2413bool RlvHandler::getWornInfo(const LLInventoryCategory* pFolder, U8& wiFolder, U8& wiChildren) const
2414{
2415 // Sanity check - getAvatarObject() can't be NULL [see rlvIsWearingItem()] and the folder should exist and not be hidden
2416 if ((!gAgent.getAvatarObject()) || (!pFolder) || (pFolder->getName().empty()) || (RLV_FOLDER_PREFIX_HIDDEN == pFolder->getName()[0]))
2417 return false;
2418
2419 LLInventoryModel::cat_array_t folders;
2420 LLInventoryModel::item_array_t items;
2421 RlvWearableItemCollector functor(pFolder->getUUID(), true, true);
2422 gInventory.collectDescendentsIf(pFolder->getUUID(), folders, items, FALSE, functor);
2423
2424 LLViewerInventoryItem* pItem;
2425 U32 cntWorn = 0, cntTotal = 0, cntChildWorn = 0, cntChildTotal = 0;
2426 for (S32 idxItem = 0, cntItem = items.count(); idxItem < cntItem; idxItem++)
2427 {
2428 pItem = items.get(idxItem);
2429
2430 bool fDirectDescendent = (pFolder->getUUID() == functor.getFoldedParent(pItem->getParentUUID()));
2431 U32 &refWorn = (fDirectDescendent) ? cntWorn : cntChildWorn, &refTotal = (fDirectDescendent) ? cntTotal : cntChildTotal;
2432
2433 if (rlvIsWearingItem(pItem))
2434 refWorn++;
2435 refTotal++;
2436 }
2437
2438 wiFolder = (0 == cntTotal + cntChildTotal) ? 0 : (0 == cntWorn + cntChildWorn) ? 1 :
2439 (cntWorn + cntChildWorn != cntTotal + cntChildTotal) ? 2 : 3;
2440 wiChildren = (0 == cntChildTotal) ? 0 : (0 == cntChildWorn) ? 1 : (cntChildWorn != cntChildTotal) ? 2 : 3;
2441
2442 return true;
2443}
2444
2445// ============================================================================
2446// Initialization helper functions
2447//
2448
2449BOOL RlvHandler::setEnabled(BOOL fEnable)
2450{
2451 if (m_fEnabled == fEnable)
2452 return fEnable;
2453
2454 if (fEnable)
2455 {
2456 if (gSavedSettings.controlExists(RLV_SETTING_NOSETENV))
2457 fNoSetEnv = gSavedSettings.getBOOL(RLV_SETTING_NOSETENV);
2458 if (gSavedSettings.controlExists(RLV_SETTING_ENABLELEGACYNAMING))
2459 fLegacyNaming = gSavedSettings.getBOOL(RLV_SETTING_ENABLELEGACYNAMING);
2460 if (gSavedSettings.controlExists(RLV_SETTING_SHOWNAMETAGS))
2461 RlvSettings::fShowNameTags = gSavedSettings.getBOOL(RLV_SETTING_SHOWNAMETAGS);
2462
2463 RlvCommand::initLookupTable();
2464 gRlvHandler.addObserver(new RlvExtGetSet());
2465
2466 if (LLStartUp::getStartupState() >= STATE_CLEANUP)
2467 fetchSharedInventory();
2468
2469 m_fEnabled = TRUE;
2470 }
2471 else if (canDisable())
2472 {
2473 #ifdef RLV_DEBUG
2474 RLV_INFOS << "Disabling RLV:" << LL_ENDL;
2475 #endif // RLV_DEBUG
2476
2477 gRlvHandler.clearState();
2478
2479 #ifdef RLV_DEBUG
2480 RLV_INFOS << "\t--> RLV disabled" << LL_ENDL;
2481 #endif // RLV_DEBUG
2482
2483 m_fEnabled = FALSE;
2484 }
2485
2486 #ifdef RLV_ADVANCED_MENU
2487 // RELEASE-RLVa: LL defines CLIENT_MENU_NAME but we can't get to it from here so we need to keep those two in sync manually
2488 LLMenuGL* pClientMenu = NULL;
2489 if ( (gMenuBarView) && ((pClientMenu = gMenuBarView->getChildMenuByName("Advanced", FALSE)) != NULL) )
2490 {
2491 pClientMenu->setItemVisible("RLVa", m_fEnabled);
2492 pClientMenu->setItemEnabled("RLVa", m_fEnabled);
2493 }
2494 #endif // RLV_ADVANCED_MENU
2495
2496 return m_fEnabled; // Return enabled/disabled state
2497}
2498
2499BOOL RlvHandler::canDisable()
2500{
2501 return TRUE;
2502}
2503
2504void RlvHandler::clearState()
2505{
2506 // TODO-RLVa: should restore all RLV controlled debug variables to their defaults
2507
2508 // Issue @clear on behalf of every object that has a currently active RLV restriction (even if it's just an exception)
2509 LLUUID idObj; LLViewerObject* pObj; bool fDetachable;
2510 while (m_Objects.size())
2511 {
2512 idObj = m_Objects.begin()->first; // Need a copy since after @clear the data it points to will no longer exist
2513 fDetachable = ((pObj = gObjectList.findObject(idObj)) != NULL) ? isDetachable(pObj) : true;
2514
2515 processCommand(idObj, "clear", false);
2516 if (!fDetachable)
2517 processCommand(idObj, "detachme=force", false);
2518 }
2519
2520 // Sanity check - these should all be empty after we issue @clear on the last object
2521 if ( (!m_Objects.empty()) || !(m_Exceptions.empty()) || (!m_Attachments.empty()) )
2522 {
2523 RLV_ERRS << "Object, exception or attachment map not empty after clearing state!" << LL_ENDL;
2524 m_Objects.clear();
2525 m_Exceptions.clear();
2526 m_Attachments.clear();
2527 }
2528
2529 // These all need manual clearing
2530 memset(m_LayersAdd, 0, sizeof(S16) * WT_COUNT);
2531 memset(m_LayersRem, 0, sizeof(S16) * WT_COUNT);
2532 memset(m_Behaviours, 0, sizeof(S16) * RLV_BHVR_COUNT);
2533 m_AttachPending.clear();
2534 m_Emitter.clearObservers(); // <- calls delete on all active observers
2535
2536 // Clear dynamically allocated memory
2537 if (m_pGCTimer)
2538 {
2539 delete m_pGCTimer;
2540 m_pGCTimer = NULL;
2541 }
2542 if (m_pWLSnapshot)
2543 {
2544 delete m_pWLSnapshot;
2545 m_pWLSnapshot = NULL;
2546 }
2547}
2548
2549// ============================================================================
diff --git a/linden/indra/newview/rlvhandler.h b/linden/indra/newview/rlvhandler.h
new file mode 100644
index 0000000..df3ff9b
--- /dev/null
+++ b/linden/indra/newview/rlvhandler.h
@@ -0,0 +1,462 @@
1#ifndef RLV_HANDLER_H
2#define RLV_HANDLER_H
3
4#include "llagentconstants.h"
5#include "llappviewer.h"
6#include "llformat.h"
7#include "llversionviewer.h"
8#include "llviewerjointattachment.h"
9#include "llviewerobject.h"
10#include "llwearable.h"
11
12#include "rlvhelper.h"
13#include "rlvevent.h"
14#include "rlvmultistringsearch.h"
15
16// ============================================================================
17/*
18 * RlvHandler
19 * ==========
20 *
21 */
22
23typedef std::map<LLUUID, RlvObject> rlv_object_map_t;
24typedef std::multimap<S32, LLUUID> rlv_detach_map_t;
25typedef std::map<S32, LLUUID> rlv_reattach_map_t;
26typedef std::multimap<LLUUID, ERlvBehaviour> rlv_exception_map_t;
27typedef std::map<S32, RlvRedirInfo> rlv_redir_map_t;
28
29class RlvHandler
30{
31public:
32 RlvHandler();
33 ~RlvHandler();
34
35 // --------------------------------
36
37 /*
38 * Rule checking functions
39 */
40public:
41 // Returns a pointer to the attachment point for a supplied parameter
42 LLViewerJointAttachment* getAttachPoint(const std::string& strText, bool fExact) const;
43 LLViewerJointAttachment* getAttachPoint(const LLInventoryItem* pItem, bool fStrict) const;
44 LLViewerJointAttachment* getAttachPoint(const LLInventoryCategory* pFolder, bool fStrict) const;
45 LLViewerJointAttachment* getAttachPointLegacy(const LLInventoryCategory* pFolder) const;
46 S32 getAttachPointIndex(std::string strText, bool fExact) const;
47 S32 getAttachPointIndex(LLViewerObject* pObj) const;
48 S32 getAttachPointIndex(const LLViewerJointAttachment* pObj) const;
49 bool hasAttachPointName(const LLInventoryItem* pItem, bool fStrict) const;
50
51 // Returns TRUE is at least one object contains the specified behaviour (and optional parameter)
52 // NOTE: - to check @detach=n -> hasLockedAttachment() / hasLockedHUD() / isDetachable()
53 // - to check @addoutfit=n -> isWearable()
54 // - to check @remoutfit=n -> isRemovable()
55 // - to check exceptions -> isException()
56 // (You *can* use hasBehaviour(); the specialized ones just don't have to iterate over all the objects)
57 bool hasBehaviour(ERlvBehaviour eBehaviour) const { return (eBehaviour < RLV_BHVR_COUNT) ? (0 != m_Behaviours[eBehaviour]) : false; }
58 bool hasBehaviour(const std::string& strBehaviour) const;
59 bool hasBehaviour(ERlvBehaviour eBehaviour, const std::string& strOption) const;
60 bool hasBehaviour(const std::string& strBehaviour, const std::string& strOption) const;
61
62 // Returns TRUE if at least one object (except the specified one) contains the specified behaviour
63 bool hasBehaviourExcept(ERlvBehaviour eBehaviour, const LLUUID& idObj) const;
64 bool hasBehaviourExcept(const std::string& strBehaviour, const LLUUID& uuid) const;
65 bool hasBehaviourExcept(ERlvBehaviour eBehaviour, const std::string& strOption, const LLUUID& idObj) const;
66 bool hasBehaviourExcept(const std::string& strBehaviour, const std::string& strOption, const LLUUID& idObj) const;
67
68 // Returns TRUE if there is at least 1 undetachable attachment
69 bool hasLockedAttachment() const { return (0 != m_Attachments.size()); }
70 // Returns TRUE if there is at least 1 undetachable HUD attachment
71 bool hasLockedHUD() const;
72
73 // Returns TRUE if the specified attachment point is detachable
74 bool isDetachable(S32 idxAttachPt) const { return (idxAttachPt) && (m_Attachments.find(idxAttachPt) == m_Attachments.end()); }
75 bool isDetachable(const LLInventoryItem* pItem) const;
76 bool isDetachable(LLViewerObject* pObj) const;
77 // Returns TRUE if the specified attachment point is set undetachable by anything other than pObj (or one of its children)
78 bool isDetachableExcept(S32 idxAttachPt, LLViewerObject* pObj) const;
79 // Marks the specified attachment point as (un)detachable (return value indicates success ; used by unit tests)
80 bool setDetachable(S32 idxAttachPt, const LLUUID& idRlvObj, bool fDetachable);
81 bool setDetachable(LLViewerObject* pObj, const LLUUID& idRlvObj, bool fDetachable);
82
83 // Adds or removes an exception for the specified restriction
84 void addException(ERlvBehaviour eBehaviour, const LLUUID& uuid);
85 void removeException(ERlvBehaviour eBehaviour, const LLUUID& uuid);
86 // Returns TRUE is the specified UUID is exempt from a restriction (tplure/sendim/recvim/etc)
87 bool isException(ERlvBehaviour eBehaviour, const LLUUID& uuid) const;
88 bool isException(const std::string& strBehaviour, const LLUUID& uuid) const;
89
90 // Returns TRUE if the specified layer is removable (use hasBehaviour(RLV_BHVR_REMOUTFIT) for the general case)
91 bool isRemovable(EWearableType type) const { return (type < WT_COUNT) ? (0 == m_LayersRem[type]) : true; }
92 // Returns TRUE if the specified layer is not remoutfit blocked by any object (except the one specified by UUID)
93 bool isRemovableExcept(EWearableType type, const LLUUID& idObj) const;
94 // Returns TRUE if the inventory item is strippable by @detach or @remoutfit
95 bool isStrippable(const LLUUID& idItem) const;
96 // Returns TRUE if the specified layer is wearable (use hasBehaviour(RLV_BHVR_ADDOUTFIT) for the general case)
97 bool isWearable(EWearableType type) const { return (type < WT_COUNT) ? (0 == m_LayersAdd[type]) : true; }
98
99 // Returns TRUE if the composite folder doesn't contain any "locked" items
100 bool canTakeOffComposite(const LLInventoryCategory* pFolder) const;
101 // Returns TRUE if the folder is a composite folder and optionally returns the name
102 bool getCompositeInfo(const LLInventoryCategory* pFolder, std::string* pstrName) const;
103 // Returns TRUE if the inventory item belongs to a composite folder and optionally returns the name and composite folder
104 bool getCompositeInfo(const LLUUID& idItem, std::string* pstrName, LLViewerInventoryCategory** ppFolder) const;
105 // Returns TRUE if the folder is a composite folder
106 bool isCompositeFolder(const LLInventoryCategory* pFolder) const;
107 // Returns TRUE if the inventory item belongs to a composite folder
108 bool isCompositeDescendent(const LLUUID& idItem) const;
109 // Returns TRUE if the inventory item is part of a folded composite folder and should be hidden from @getoufit or @getattach
110 bool isHiddenCompositeItem(const LLUUID& idItem, const std::string& strItemType) const;
111
112 // --------------------------------
113
114 /*
115 * Helper functions
116 */
117public:
118 // Accessors
119 bool getCanCancelTp() const { return m_fCanCancelTp; } // @accepttp and @tpto
120 void setCanCancelTp(bool fAllow) { m_fCanCancelTp = fAllow; } // @accepttp and @tpto
121
122 // Command specific helper functions
123 bool canShowHoverText(LLViewerObject* pObj) const; // @showhovertext* command family
124 void filterChat(std::string& strUTF8Text, bool fFilterEmote) const; // @sendchat, @recvchat and @redirchat
125 void filterLocation(std::string& strUTF8Text) const; // @showloc
126 void filterNames(std::string& strUTF8Text) const; // @shownames
127 const std::string& getAnonym(const std::string& strName) const; // @shownames
128 std::string getVersionString() const; // @version
129 BOOL isAgentNearby(const LLUUID& uuid) const; // @shownames
130 bool redirectChatOrEmote(const std::string& strUTF8Test) const; // @redirchat and @rediremote
131
132 // Command processing helper functions
133 BOOL processCommand(const LLUUID& idObj, const std::string& strCommand, bool fFromObj);
134 void processRetainedCommands();
135 void retainCommand(const std::string& strObj, const LLUUID& idObj, const std::string& strCmd);
136
137 // Returns a pointer to the currently executing command (do *not* save this pointer)
138 const RlvCommand* getCurrentCommand() const { return m_pCurCommand; }
139 // Returns the UUID of the object we're currently executing a command for
140 const LLUUID& getCurrentObject() const { return m_idCurObject; }
141
142 // Initialization
143 static BOOL canDisable();
144 static BOOL isEnabled() { return m_fEnabled; }
145 static void initLookupTables();
146 static BOOL setEnabled(BOOL fEnable);
147protected:
148 void clearState();
149
150 // --------------------------------
151
152 /*
153 * Inventory related functions
154 */
155public:
156 // Starts a fetch of everything under the shared root (if there is one)
157 static void fetchSharedInventory();
158 // Returns the path of the supplied folder (relative to the shared root)
159 std::string getSharedPath(const LLViewerInventoryCategory* pFolder) const;
160 std::string getSharedPath(const LLUUID& idFolder) const;
161 // Returns a pointer to the shared root folder (if there is one)
162 static LLViewerInventoryCategory* getSharedRoot();
163 // A "folded folder" is a folder whose items logically belong to the grandparent rather than the parent
164 bool isFoldedFolder(const LLInventoryCategory* pFolder, bool fAttach) const;
165 bool isFoldedFolderLegacy(const LLInventoryCategory* pFolder, bool fAttach) const;
166protected:
167 // Find all folders that match a supplied criteria (clears the supplied array)
168 bool findSharedFolders(const std::string& strCriteria, LLInventoryModel::cat_array_t& folders) const;
169
170 // Returns a subfolder of idParent that starts with name (exact match > partial match)
171 LLViewerInventoryCategory* getSharedFolder(const LLUUID& idParent, const std::string& strName) const;
172 // Looks up a folder from a path (relative to the shared root)
173 LLViewerInventoryCategory* getSharedFolder(const std::string& strPath) const;
174
175 bool getWornInfo(const LLInventoryCategory* pFolder, U8& wiFolder, U8& wiChildren) const;
176
177 // --------------------------------
178
179 /*
180 * Event handling (forwards to registered observers if we don't handle the command)
181 */
182public:
183 BOOL addObserver(RlvObserver* pObserver) { return m_Emitter.addObserver(pObserver); }
184 BOOL removeObserver(RlvObserver* pObserver) { return m_Emitter.remObserver(pObserver); }
185 void addBehaviourObserver(RlvBehaviourObserver* pBhvrObserver);
186 void removeBehaviourObserver(RlvBehaviourObserver* pBhvrObserver);
187 void notifyBehaviourObservers(const RlvCommand& rlvCmd, bool fInternal);
188
189 // Externally invoked event handlers
190 void onAttach(LLViewerJointAttachment* pAttachPt, bool fFullyLoaded); // LLVOAvatar::attachObject()
191 void onDetach(LLViewerJointAttachment* pAttachPt); // LLVOAvatar::detachObject()
192 bool onGC(); // RlvGCTimer::tick()
193 void onSavedAssetIntoInventory(const LLUUID& idItem); // LLInventoryModel::processSaveAssetIntoInventory()
194protected:
195 BOOL processAddCommand(const LLUUID& uuid, const RlvCommand& rlvCmd);
196 BOOL processRemoveCommand(const LLUUID& uuid, const RlvCommand& rlvCmd);
197 BOOL processReplyCommand(const LLUUID& uuid, const RlvCommand& rlvCmd) const;
198 BOOL processForceCommand(const LLUUID& uuid, const RlvCommand& rlvCmd) const;
199
200 // Command handlers (exist for no other reason than to keep the length of the processXXX functions down)
201 void onForceDetach(const LLUUID& idObj, const std::string& strOption) const;
202 void onForceRemOutfit(const LLUUID& idObj, const std::string& strOption) const;
203 bool onForceSit(const LLUUID& uuid, const std::string& strOption) const;
204 void onForceWear(const std::string& strPath, bool fAttach, bool fMatchAll) const;
205 bool onGetPath(const LLUUID& uuid, const std::string& strOption, std::string& strReply) const;
206 void onGetInvWorn(const std::string& strPath, std::string &strReply) const;
207
208 // --------------------------------
209
210 /*
211 * Member variables
212 */
213public:
214 static BOOL fNoSetEnv;
215 static BOOL fLegacyNaming;
216
217 static const std::string cstrSharedRoot; // Name of the shared root folder
218 static const std::string cstrBlockedRecvIM; // Stand-in text for incoming IM when recvim restricted
219 static const std::string cstrBlockedSendIM; // Stand-in text for outgoing IM when sendim restricted
220 static const std::string cstrHidden; // General purpose "this was censored" text
221 static const std::string cstrHiddenParcel;
222 static const std::string cstrHiddenRegion;
223 static const std::string cstrMsgRecvIM; // Message sent to IM sender when sendim restricted
224 static const std::string cstrMsgTpLure; // Message sent to tplure sender when tplure restricted
225 static const std::string cstrAnonyms[28];
226protected:
227 rlv_object_map_t m_Objects; // Map of objects that have active restrictions (by UUID)
228 rlv_exception_map_t m_Exceptions; // Map of UUIDs that are exempt from the associated ERlvBehaviour
229 rlv_detach_map_t m_Attachments; // Map of locked attachments (attachment point index -> object that issued @detach=n)
230 S16 m_LayersAdd[WT_COUNT]; // Array of locked layers (reference counted)
231 S16 m_LayersRem[WT_COUNT]; // Array of locked layers (reference counted)
232 S16 m_Behaviours[RLV_BHVR_COUNT];
233
234 rlv_retained_list_t m_Retained;
235 rlv_reattach_map_t m_AttachPending;
236 rlv_reattach_map_t m_DetachPending;
237 rlv_redir_map_t m_Redirections;
238 RlvGCTimer* m_pGCTimer;
239 RlvWLSnapshot* m_pWLSnapshot;
240
241 RlvCommand* m_pCurCommand; // Convenience (see @tpto)
242 LLUUID m_idCurObject; // Convenience (see @tpto)
243
244 mutable RlvEventEmitter<RlvObserver> m_Emitter;
245 mutable std::list<RlvBehaviourObserver*> m_BhvrObservers;
246 RlvBehaviourNotifyObserver* m_pBhvrNotify;
247
248 static BOOL m_fEnabled; // Use setEnabled() to toggle this
249 static BOOL m_fFetchStarted; // TRUE if we fired off an inventory fetch
250 static BOOL m_fFetchComplete; // TRUE if everything was fetched
251 static RlvMultiStringSearch m_AttachLookup; // Lookup table for attachment names (lower case)
252
253 bool m_fCanCancelTp;
254
255 friend class RlvSharedRootFetcher; // Fetcher needs access to m_fFetchComplete
256 friend class RlvGCTimer; // Timer clear its own point at destruction
257
258 // --------------------------------
259
260 /*
261 * Internal access functions used by unit tests
262 */
263public:
264 const rlv_object_map_t* getObjectMap() const { return &m_Objects; }
265 const rlv_exception_map_t* getExceptionMap() const { return &m_Exceptions; }
266 const rlv_detach_map_t* getDetachMap() const { return &m_Attachments; }
267 #ifdef RLV_DEBUG_TESTS
268 const S16* getAddLayers() const { return m_LayersAdd; }
269 const S16* getRemLayers() const { return m_LayersRem; }
270 const S16* getBehaviours() const { return m_Behaviours; }
271 const rlv_retained_list_t* getRetainedList() const { return &m_Retained; }
272 #endif // RLV_DEBUG_TESTS
273};
274
275typedef RlvHandler rlv_handler_t;
276extern rlv_handler_t gRlvHandler;
277
278// ============================================================================
279// Inlined member functions
280//
281
282// Checked: 2009-07-09 (RLVa-1.0.0f)
283inline void RlvHandler::addException(ERlvBehaviour eBehaviour, const LLUUID& uuid)
284{
285 if (!uuid.isNull())
286 m_Exceptions.insert(std::pair<LLUUID, ERlvBehaviour>(uuid, eBehaviour));
287}
288
289// Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f
290inline bool RlvHandler::canShowHoverText(LLViewerObject *pObj) const
291{
292 return ( (!pObj) || (LL_PCODE_VOLUME != pObj->getPCode()) ||
293 !( (hasBehaviour(RLV_BHVR_SHOWHOVERTEXTALL)) ||
294 ( (hasBehaviour(RLV_BHVR_SHOWHOVERTEXTWORLD)) && (!pObj->isHUDAttachment()) ) ||
295 ( (hasBehaviour(RLV_BHVR_SHOWHOVERTEXTHUD)) && (pObj->isHUDAttachment()) ) ||
296 (isException(RLV_BHVR_SHOWHOVERTEXT, pObj->getID())) ) );
297}
298
299// Checked: 2009-05-23 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d
300inline S32 RlvHandler::getAttachPointIndex(std::string strText, bool fExact) const
301{
302 U16 nParam; RlvMultiStringSearchMatch match;
303 LLStringUtil::toLower(strText);
304 return (fExact) ? ((m_AttachLookup.getExactMatchParam(strText, nParam)) ? nParam : 0)
305 : ((m_AttachLookup.findLast(strText, match)) ? match.nParam : 0);
306}
307
308// Checked: 2009-05-23 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d
309inline S32 RlvHandler::getAttachPointIndex(LLViewerObject* pObj) const
310{
311 return (pObj) ? ATTACHMENT_ID_FROM_STATE(pObj->getState()) : 0;
312}
313
314// Checked: 2009-06-02 (RLVa-0.2.0g)
315inline std::string RlvHandler::getSharedPath(const LLUUID& idFolder) const
316{
317 return getSharedPath(gInventory.getCategory(idFolder)); // getSharedPath() has a NULL pointer check so this is safe
318}
319
320// Checked: 2009-06-07 (RLVa-0.2.1c)
321inline std::string RlvHandler::getVersionString() const
322{
323 return llformat("RestrainedLife viewer v%d.%d.%d (%s %d.%d.%d.%d - RLVa %d.%d.%d)",
324 RLV_VERSION_MAJOR, RLV_VERSION_MINOR, RLV_VERSION_PATCH,
325 LLAppViewer::instance()->getSecondLifeTitle().c_str(), LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VERSION_BUILD,
326 RLVa_VERSION_MAJOR, RLVa_VERSION_MINOR, RLVa_VERSION_PATCH);
327}
328
329// Checked: 2009-05-23 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d
330inline bool RlvHandler::hasAttachPointName(const LLInventoryItem *pItem, bool fStrict) const
331{
332 return (getAttachPoint(pItem, fStrict) != NULL); // getAttachPoint() has a NULL pointer check so this is safe
333}
334
335// Checked:
336inline bool RlvHandler::hasBehaviour(ERlvBehaviour eBehaviour, const std::string& strOption) const
337{
338 return hasBehaviourExcept(eBehaviour, strOption, LLUUID::null);
339}
340
341// Checked:
342inline bool RlvHandler::hasBehaviour(const std::string& strBehaviour) const
343{
344 return hasBehaviourExcept(strBehaviour, LLUUID::null);
345}
346
347// Checked:
348inline bool RlvHandler::hasBehaviour(const std::string& strBehaviour, const std::string& strOption) const
349{
350 return hasBehaviourExcept(strBehaviour, strOption, LLUUID::null);
351}
352
353// Checked:
354inline bool RlvHandler::hasBehaviourExcept(ERlvBehaviour eBehaviour, const LLUUID& idObj) const
355{
356 return hasBehaviourExcept(eBehaviour, std::string(), idObj);
357}
358
359#ifdef RLV_EXPERIMENTAL_COMPOSITES
360 // Checked:
361 inline bool RlvHandler::isCompositeFolder(const LLInventoryCategory* pFolder) const
362 {
363 return getCompositeInfo(pFolder, NULL);
364 }
365
366 // Checked:
367 inline bool RlvHandler::isCompositeDescendent(const LLUUID& idItem) const
368 {
369 return getCompositeInfo(idItem, NULL, NULL);
370 }
371#endif // RLV_EXPERIMENTAL_COMPOSITES
372
373// Checked: 2009-05-23 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d
374inline bool RlvHandler::isDetachable(LLViewerObject* pObj) const
375{
376 return (pObj == NULL) || (!pObj->isAttachment()) || (isDetachable(getAttachPointIndex(pObj)));
377}
378
379// Checked:
380inline bool RlvHandler::isException(ERlvBehaviour eBehaviour, const LLUUID& uuid) const
381{
382 for (rlv_exception_map_t::const_iterator itException = m_Exceptions.lower_bound(uuid),
383 endException = m_Exceptions.upper_bound(uuid); itException != endException; ++itException)
384 {
385 if (itException->second == eBehaviour)
386 return true;
387 }
388 return false;
389}
390
391// Checked:
392inline bool RlvHandler::isException(const std::string& strBehaviour, const LLUUID& uuid) const
393{
394 return hasBehaviour(strBehaviour, uuid.asString());
395}
396
397// Checked: 2009-07-29 (RLVa-1.0.1b) | Added: RLVa-1.0.1b
398inline bool RlvHandler::isFoldedFolder(const LLInventoryCategory* pFolder, bool fAttach) const
399{
400 return
401 (
402 // .(<attachpt>) type folder (on detach we don't care about its children, but on attach there can only be 1 attachment)
403 ( (gRlvHandler.getAttachPoint(pFolder, true)) &&
404 ( (!fAttach) || (1 == rlvGetDirectDescendentsCount(pFolder, LLAssetType::AT_OBJECT))) )
405 #ifdef RLV_EXTENSION_FLAG_NOSTRIP
406 // .(nostrip) folder
407 || ( (pFolder) && (".("RLV_FOLDER_FLAG_NOSTRIP")" == pFolder->getName()) )
408 #endif // RLV_EXTENSION_FLAG_NOSTRIP
409 );
410}
411
412// Checked: 2009-05-23 (RLVa-0.2.0d) | Added: RLVa-0.2.0d
413inline bool RlvHandler::isRemovableExcept(EWearableType type, const LLUUID& idObj) const
414{
415 // NOTE: mind the bitwise OR rather than the logical OR!!
416 return (isRemovable(type)) || !( (hasBehaviourExcept(RLV_BHVR_REMOUTFIT, idObj)) |
417 (hasBehaviourExcept(RLV_BHVR_REMOUTFIT, LLWearable::typeToTypeName(type), idObj)) );
418}
419
420#ifndef RLV_EXTENSION_FLAG_NOSTRIP
421 // Checked: 2009-05-23 (RLVa-0.2.0d) | Added: RLVa-0.2.0d
422 bool RlvHandler::isStrippable(const LLUUID& idItem) const
423 {
424 return true;
425 }
426#endif // RLV_EXTENSION_FLAG_NOSTRIP
427
428// Checked: 2009-07-09 (RLVa-1.0.0f)
429inline void RlvHandler::removeException(ERlvBehaviour eBehaviour, const LLUUID &uuid)
430{
431 if (!uuid.isNull())
432 {
433 for (rlv_exception_map_t::iterator itException = m_Exceptions.lower_bound(uuid),
434 endException = m_Exceptions.upper_bound(uuid); itException != endException; ++itException)
435 {
436 if (itException->second == eBehaviour)
437 {
438 m_Exceptions.erase(itException);
439 break;
440 }
441 }
442 }
443}
444
445// Checked: 2009-08-05 (RLVa-1.0.1e) | Modified: RLVa-1.0.1e
446inline void RlvHandler::retainCommand(const std::string& strObj, const LLUUID& idObj, const std::string& strCmd)
447{
448 #ifdef RLV_DEBUG
449 RLV_INFOS << "[" << idObj << "]: " << strCmd << " (retaining)" << LL_ENDL;
450 #endif // RLV_DEBUG
451 m_Retained.push_back(RlvRetainedCommand(strObj, idObj, strCmd));
452}
453
454// Checked: 2009-05-23 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d
455inline bool RlvHandler::setDetachable(LLViewerObject* pObj, const LLUUID& idRlvObj, bool fDetachable)
456{
457 return setDetachable(getAttachPointIndex(pObj), idRlvObj, fDetachable); // getAttachPointIndex() has a NULL pointer check
458}
459
460// ============================================================================
461
462#endif // RLV_HANDLER_H
diff --git a/linden/indra/newview/rlvhelper.cpp b/linden/indra/newview/rlvhelper.cpp
new file mode 100644
index 0000000..6b2a1a0
--- /dev/null
+++ b/linden/indra/newview/rlvhelper.cpp
@@ -0,0 +1,674 @@
1#include "llviewerprecompiledheaders.h"
2#include "llagent.h"
3#include "llviewerobject.h"
4#include "llviewerstats.h"
5#include "llviewerwindow.h"
6#include "llvoavatar.h"
7#include "llwlparammanager.h"
8
9#include "rlvhelper.h"
10#include "rlvevent.h"
11#include "rlvhandler.h"
12
13// ============================================================================
14// Static variable initialization
15//
16
17RlvMultiStringSearch RlvCommand::m_BhvrLookup;
18
19// ============================================================================
20
21// Checked:
22RlvCommand::RlvCommand(const std::string& strCommand)
23 : m_eBehaviour(RLV_BHVR_UNKNOWN), m_eParamType(RLV_TYPE_UNKNOWN)
24{
25 if ((m_fValid = parseCommand(strCommand, m_strBehaviour, m_strOption, m_strParam)))
26 {
27 if ( ("n" == m_strParam) || ("add" == m_strParam) )
28 m_eParamType = RLV_TYPE_ADD;
29 else if ( ("y" == m_strParam) || ("rem" == m_strParam) )
30 m_eParamType = RLV_TYPE_REMOVE;
31 else if ("force" == m_strParam)
32 m_eParamType = RLV_TYPE_FORCE;
33 else
34 {
35 m_eParamType = RLV_TYPE_REPLY; // Assume it's a reply command until we encounter a non-digit
36
37 if ( (m_strParam.empty()) || (-1 != m_strParam.find_first_not_of("0123456789")) )
38 {
39 m_eParamType = RLV_TYPE_UNKNOWN;
40 m_fValid = ("clear" == m_strBehaviour);
41 }
42 }
43 }
44
45 if (!m_fValid)
46 {
47 m_strBehaviour = m_strOption = m_strParam = "";
48 return;
49 }
50
51 U16 nBehaviour;
52 if (m_BhvrLookup.getExactMatchParam(m_strBehaviour, nBehaviour))
53 {
54 m_eBehaviour = (ERlvBehaviour)nBehaviour;
55 }
56}
57
58RlvCommand::RlvCommand(const RlvCommand& rlvCmd)
59 : m_fValid(rlvCmd.m_fValid),
60 m_strBehaviour(rlvCmd.m_strBehaviour), m_eBehaviour(rlvCmd.m_eBehaviour),
61 m_strOption(rlvCmd.m_strOption),
62 m_strParam(rlvCmd.m_strParam), m_eParamType(rlvCmd.m_eParamType)
63{
64}
65
66// ============================================================================
67
68/*
69 * ------------------------------
70 * Command | RLV | RLVa
71 * ------------------------------
72 * : | F | F (missing behaviour)
73 * :option | F | F (missing behaviour)
74 * := | T | F (missing behaviour)
75 * :option= | T | F (missing behaviour)
76 * :option=param | T | F (missing behaviour)
77 * = | T | F (missing behaviour)
78 * =param | T | F (missing behaviour)
79 * cmd | F | F (missing param) [T if <behaviour> == "clear"]
80 * cmd: | F | F (missing param)
81 * cmd:option | F | F (missing param)
82 * cmd:= | T | F (missing param) [1]
83 * cmd:option= | T | F (missing param) [1]
84 * cmd= | T | F (missing param) [1]
85 * cmd:option=param | T | T
86 * cmd=param | T | T
87 * cmd:=param | T | T
88 *
89 * [1] 'clear:=', 'clear:option=' and 'clear=' are "valid" variations of 'clear'
90 */
91
92BOOL RlvCommand::parseCommand(/*[in]*/ const std::string& strCommand,
93 /*[out]*/ std::string& strBehaviour, /*[out]*/ std::string& strOption, /*[out]*/ std::string& strParam)
94{
95 // Format: <behaviour>[:<option>]=<param>
96 int idxParam = strCommand.find('=');
97 int idxOption = (idxParam > 0) ? strCommand.find(':') : -1;
98 if (idxOption > idxParam - 1)
99 idxOption = -1;
100
101 // If <behaviour> is missing it's always an improperly formatted command
102 if ( (0 == idxOption) || (0 == idxParam) )
103 return FALSE;
104
105 strBehaviour = strCommand.substr(0, (-1 != idxOption) ? idxOption : idxParam);
106 strOption = strParam = "";
107
108 // If <param> is missing it's an improperly formatted command
109 if ( (-1 == idxParam) || ((int)strCommand.length() - 1 == idxParam) )
110 {
111 // Unless "<behaviour> == "clear" AND (idxOption == 0)"
112 // OR <behaviour> == "clear" AND (idxParam != 0) [see table above]
113 if ( ("clear" == strBehaviour) && ( (!idxOption) || (idxParam) ) )
114 return TRUE;
115 return FALSE;
116 }
117
118 if ( (-1 != idxOption) && (idxOption + 1 != idxParam) )
119 strOption = strCommand.substr(idxOption + 1, idxParam - idxOption - 1);
120 strParam = strCommand.substr(idxParam + 1);
121
122 return TRUE;
123}
124
125void RlvCommand::initLookupTable()
126{
127 static bool fInitialized = false;
128 if (!fInitialized)
129 {
130 // NOTE: keep this match with the enumeration at all times
131 std::string arBehaviours[RLV_BHVR_COUNT] =
132 {
133 "version", "detach", "redirchat", "rediremote", "sendim", "recvchat", "recvemote", "recvim", "tploc", "tplure",
134 "sittp", "edit", "rez", "addoutfit", "remoutfit", "getoutfit", "getattach", "showinv", "unsit", "sit",
135 "getstatus", "getstatusall", "getinv", "getinvworn", "findfolder", "findfolders", "attach", "attachall", "detachall",
136 "getpath", "attachthis", "attachallthis", "detachthis", "detachallthis", "fartouch", "showworldmap", "showminimap",
137 "showloc", "tpto", "accepttp", "shownames", "fly", "getsitid", "setdebug", "setenv", "detachme",
138 "showhovertextall", "showhovertextworld", "showhovertexthud", "showhovertext", "notify"
139 };
140
141 for (int idxBvhr = 0; idxBvhr < RLV_BHVR_COUNT; idxBvhr++)
142 m_BhvrLookup.addKeyword(arBehaviours[idxBvhr], idxBvhr);
143
144 fInitialized = true;
145 }
146}
147
148// Checked: 2009-06-07 (RLVa-0.2.1c)
149std::string RlvCommand::asString() const
150{
151 return (!m_strOption.empty()) ? (std::string(m_strBehaviour)).append(":").append(m_strOption) : (std::string(m_strBehaviour));
152}
153
154// =========================================================================
155
156BOOL RlvObject::addCommand(const RlvCommand& rlvCmd)
157{
158 // Sanity checking
159 if (RLV_TYPE_ADD != rlvCmd.getParamType())
160 return FALSE;
161
162 // Don't add duplicate commands for this object (ie @detach=n followed by another @detach=n later on)
163 BOOL fDuplicate =
164 (RLV_BHVR_UNKNOWN != rlvCmd.getBehaviourType())
165 ? hasBehaviour(rlvCmd.getBehaviourType(), rlvCmd.getOption())
166 : hasBehaviour(rlvCmd.getBehaviour(), rlvCmd.getOption());
167 if (fDuplicate)
168 return FALSE;
169
170 // Now that we know it's not a duplicate, add it to the end of the list
171 m_Commands.push_back(rlvCmd);
172
173 return TRUE;
174}
175
176BOOL RlvObject::removeCommand(const RlvCommand& rlvCmd)
177{
178 // Sanity checking
179 if (RLV_TYPE_REMOVE != rlvCmd.getParamType())
180 return FALSE;
181
182 for (rlv_command_list_t::iterator itCmd = m_Commands.begin(); itCmd != m_Commands.end(); ++itCmd)
183 {
184 //if (*itCmd == rlvCmd) <- commands will never be equal since one is an add and the other is a remove *rolls eyes*
185 if ( (itCmd->getBehaviour() == rlvCmd.getBehaviour()) && (itCmd->getOption() == rlvCmd.getOption()) )
186 {
187 m_Commands.erase(itCmd);
188 return TRUE;
189 }
190 }
191 return FALSE; // Command was never added so nothing to remove now
192}
193
194BOOL RlvObject::hasBehaviour(ERlvBehaviour eBehaviour) const
195{
196 for (rlv_command_list_t::const_iterator itCmd = m_Commands.begin(); itCmd != m_Commands.end(); ++itCmd)
197 if ( (itCmd->getBehaviourType() == eBehaviour) && (itCmd->getOption().empty()) )
198 return TRUE;
199 return FALSE;
200}
201
202BOOL RlvObject::hasBehaviour(const std::string& strBehaviour) const
203{
204 for (rlv_command_list_t::const_iterator itCmd = m_Commands.begin(); itCmd != m_Commands.end(); ++itCmd)
205 if ( (itCmd->getBehaviour() == strBehaviour) && (itCmd->getOption().empty()) )
206 return TRUE;
207 return FALSE;
208}
209
210BOOL RlvObject::hasBehaviour(ERlvBehaviour eBehaviour, const std::string& strOption) const
211{
212 for (rlv_command_list_t::const_iterator itCmd = m_Commands.begin(); itCmd != m_Commands.end(); ++itCmd)
213 if ( (itCmd->getBehaviourType() == eBehaviour) && (itCmd->getOption() == strOption) )
214 return TRUE;
215 return FALSE;
216}
217
218BOOL RlvObject::hasBehaviour(const std::string& strBehaviour, const std::string& strOption) const
219{
220 for (rlv_command_list_t::const_iterator itCmd = m_Commands.begin(); itCmd != m_Commands.end(); ++itCmd)
221 if ( (itCmd->getBehaviour() == strBehaviour) && (itCmd->getOption() == strOption) )
222 return TRUE;
223 return FALSE;
224}
225
226// Checked: 2009-06-07 (RLVa-0.2.1c)
227std::string RlvObject::getStatusString(const std::string& strMatch) const
228{
229 std::string strStatus, strCmd;
230
231 for (rlv_command_list_t::const_iterator itCmd = m_Commands.begin(); itCmd != m_Commands.end(); ++itCmd)
232 {
233 strCmd = itCmd->asString();
234 if ( (strMatch.empty()) || (std::string::npos != strCmd.find(strMatch)) )
235 {
236 if (!strStatus.empty())
237 strStatus.push_back('/');
238 strStatus += strCmd;
239 }
240 }
241
242 return strStatus;
243}
244
245// =========================================================================
246/*
247 * Various helper classes/timers/functors
248 *
249 */
250
251// Checked: 2009-05-26 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d
252S32 rlvGetDirectDescendentsCount(const LLInventoryCategory* pFolder, LLAssetType::EType type)
253{
254 S32 cntType = 0;
255 if (pFolder)
256 {
257 LLInventoryModel::cat_array_t* pFolders;
258 LLInventoryModel::item_array_t* pItems;
259 gInventory.getDirectDescendentsOf(pFolder->getUUID(), pFolders, pItems);
260
261 if (pItems)
262 {
263 for (S32 idxItem = 0, cntItem = pItems->count(); idxItem < cntItem; idxItem++)
264 if (pItems->get(idxItem)->getType() == type)
265 cntType++;
266 }
267 }
268 return cntType;
269}
270
271// Checked: 2009-05-30 (RLVa-0.2.0e) | Added: RLVa-0.2.0e
272const LLUUID& RlvWearableItemCollector::getFoldedParent(const LLUUID& idFolder) const
273{
274 std::map<LLUUID, LLUUID>::const_iterator itFolder = m_Folding.end(), itCur = m_Folding.find(idFolder);
275 while (itCur != m_Folding.end())
276 {
277 itFolder = itCur;
278 itCur = m_Folding.find(itFolder->second);
279 }
280 return (m_Folding.end() == itFolder) ? idFolder : itFolder->second;
281}
282
283// Checked: 2009-07-29 (RLVa-1.0.1b) | Modified: RLVa-1.0.1b
284bool RlvWearableItemCollector::onCollectFolder(const LLInventoryCategory* pFolder)
285{
286 const LLUUID& idParent = pFolder->getParentUUID();
287 if (m_Wearable.end() == std::find(m_Wearable.begin(), m_Wearable.end(), idParent))
288 return false; // Not the child of a wearable folder == skip
289
290 const std::string& strFolder = pFolder->getName();
291 if (strFolder.empty()) // Shouldn't happen but does... naughty Lindens
292 return false;
293
294 #ifdef RLV_EXTENSION_FLAG_NOSTRIP
295 if ( (!m_fAttach) && (-1 != strFolder.find(RLV_FOLDER_FLAG_NOSTRIP)) ) // Don't process "nostrip" folders on detach
296 return false;
297 #endif // RLV_EXTENSION_FLAG_NOSTRIP
298
299 if (gRlvHandler.isFoldedFolder(pFolder, m_fAttach)) // Check for folder that should get folded under its parent
300 {
301 m_Tentative.push_front(pFolder->getUUID());
302 m_Folding.insert(std::pair<LLUUID, LLUUID>(pFolder->getUUID(), idParent));
303 }
304 else if ( (RLV_FOLDER_PREFIX_HIDDEN != strFolder[0]) && (m_fMatchAll) ) // Collect from any non-hidden child folder for *all
305 {
306 m_Wearable.push_front(pFolder->getUUID());
307 return (idParent == m_idFolder); // (Convenience for @getinvworn)
308 }
309 #ifdef RLV_EXPERIMENTAL_COMPOSITES
310 else if ( (RLV_FOLDER_PREFIX_HIDDEN == strFolder[0]) && // Hidden folder that's a...
311 (gRlvHandler.isCompositeFolder(pFolder)) && // ... composite folder which we...
312 ((m_fAttach) || (gRlvHandler.canTakeOffComposite(pFolder))) ) // ... attach or can detach (see composite locking)
313 {
314 m_Wearable.push_front(pFolder->getUUID());
315 m_Folding.insert(std::pair<LLUUID, LLUUID>(pFolder->getUUID(), idParent));
316 }
317 #endif // RLV_EXPERIMENTAL_COMPOSITES
318
319 return false;
320}
321
322// Checked: 2009-05-26 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d
323bool RlvWearableItemCollector::onCollectItem(const LLInventoryItem* pItem)
324{
325 #ifdef RLV_EXTENSION_FLAG_NOSTRIP
326 if ( (!m_fAttach) && (-1 != pItem->getName().find(RLV_FOLDER_FLAG_NOSTRIP)) ) // Don't process "nostrip" items on detach
327 return false;
328 #endif // RLV_EXTENSION_FLAG_NOSTRIP
329
330 const LLUUID& idParent = pItem->getParentUUID(); bool fRet = false;
331 switch (pItem->getType())
332 {
333 case LLAssetType::AT_BODYPART:
334 if (!m_fAttach)
335 break; // Don't process body parts on detach
336 case LLAssetType::AT_CLOTHING:
337 #ifdef RLV_EXTENSION_FLAG_NOSTRIP
338 fRet = ( (m_Wearable.end() != std::find(m_Wearable.begin(), m_Wearable.end(), idParent)) ||
339 ( (m_fAttach) && (m_Tentative.end() != std::find(m_Tentative.begin(), m_Tentative.end(), idParent)) &&
340 (gInventory.getCategory(pItem->getParentUUID())->getName() == ".("RLV_FOLDER_FLAG_NOSTRIP")") ) );
341 #else
342 fRet = (m_Wearable.end() != std::find(m_Wearable.begin(), m_Wearable.end(), idParent));
343 #endif // RLV_EXTENSION_FLAG_NOSTRIP
344 break;
345 case LLAssetType::AT_OBJECT:
346 fRet = ( (m_Wearable.end() != std::find(m_Wearable.begin(), m_Wearable.end(), idParent)) ||
347 (m_Tentative.end() != std::find(m_Tentative.begin(), m_Tentative.end(), idParent)) ) &&
348 ( (!m_fAttach) || (gRlvHandler.hasAttachPointName(pItem, true)) ); // Only care about attach point on attach*
349 break;
350 #ifdef RLV_EXPERIMENTAL_FORCEWEAR_GESTURES
351 case LLAssetType::AT_GESTURE:
352 fRet = (m_Wearable.end() != std::find(m_Wearable.begin(), m_Wearable.end(), idParent));
353 break;
354 #endif // RLV_EXPERIMENTAL_FORCEWEAR_GESTURES
355 default:
356 break;
357 }
358 return fRet;
359}
360
361// Checked: 2009-05-26 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d
362bool RlvWearableItemCollector::operator()(LLInventoryCategory* pFolder, LLInventoryItem* pItem)
363{
364 // NOTE: this is used for more than was originally intended so only modify if you're sure it won't break something obscure
365 return (pFolder) ? onCollectFolder(pFolder) : ( (pItem) ? onCollectItem(pItem) : false );
366}
367
368// Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0f
369bool RlvSelectHasLockedAttach::apply(LLSelectNode* pNode)
370{
371 return (pNode->getObject()) ? !gRlvHandler.isDetachable(pNode->getObject()) : false;
372}
373
374// Checked: 2009-07-05 (RLVa-1.0.0b) | Modified: RLVa-0.2.0f
375bool RlvSelectIsOwnedByOrGroupOwned::apply(LLSelectNode* pNode)
376{
377 return (pNode->mPermissions->isGroupOwned()) || (pNode->mPermissions->getOwner() == m_idAgent);
378}
379
380// Checked: 2009-05-31 (RLVa-0.2.0f) | Modified: RLVa-0.2.0f
381bool RlvSelectIsSittingOn::apply(LLSelectNode* pNode)
382{
383 return (pNode->getObject()) && (pNode->getObject()->getRootEdit() == m_pObject);
384}
385
386// Checked: 2009-07-05 (RLVa-1.0.0b) | Modified: RLVa-0.2.0g
387bool rlvCanDeleteOrReturn()
388{
389 bool fIsAllowed = true;
390
391 if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ))
392 {
393 // We'll allow if none of the prims are owned by the avie or group owned
394 LLObjectSelectionHandle handleSel = LLSelectMgr::getInstance()->getSelection();
395 RlvSelectIsOwnedByOrGroupOwned func(gAgent.getID());
396 if ( (handleSel.notNull()) && ((0 == handleSel->getRootObjectCount()) || (NULL != handleSel->getFirstRootNode(&func, FALSE))) )
397 fIsAllowed = false;
398 }
399
400 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) )
401 {
402 // We'll allow if the avie isn't sitting on any of the selected objects
403 LLObjectSelectionHandle handleSel = LLSelectMgr::getInstance()->getSelection();
404 RlvSelectIsSittingOn func(gAgent.getAvatarObject()->getRoot());
405 if ( (handleSel.notNull()) && (handleSel->getFirstRootNode(&func, TRUE)) )
406 fIsAllowed = false;
407 }
408
409 return fIsAllowed;
410}
411
412// Checked: 2009-07-05 (RLVa-1.0.0c)
413BOOL rlvAttachToEnabler(void* pParam)
414{
415 // Enables/disables an option on the "Attach to (HUD)" submenu depending on whether it is (un)detachable
416 LLViewerJointAttachment* pAttachment = (LLViewerJointAttachment*)pParam;
417 return (!pAttachment) || (gRlvHandler.isDetachable(pAttachment->getObject()));
418}
419
420BOOL RlvGCTimer::tick()
421{
422 bool fContinue = gRlvHandler.onGC();
423 if (!fContinue)
424 gRlvHandler.m_pGCTimer = NULL;
425 return !fContinue;
426}
427
428void RlvCurrentlyWorn::fetchWorn()
429{
430 LLInventoryFetchObserver::item_ref_t idItems;
431
432 // Fetch all currently worn clothing layers and body parts
433 for (int type = 0; type < (int)WT_COUNT; type++)
434 {
435 const LLUUID& idItem = gAgent.getWearableItem((EWearableType)type);
436 if (idItem.notNull())
437 idItems.push_back(idItem);
438 }
439
440 // Fetch all currently worn attachments
441 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
442 if (pAvatar)
443 {
444 for (LLVOAvatar::attachment_map_t::const_iterator itAttach = pAvatar->mAttachmentPoints.begin();
445 itAttach != pAvatar->mAttachmentPoints.end(); ++itAttach)
446 {
447 const LLUUID& idItem = itAttach->second->getItemID();
448 if (idItem.notNull())
449 idItems.push_back(idItem);
450 }
451 }
452
453 RlvCurrentlyWorn f;
454 f.fetchItems(idItems);
455}
456
457// =========================================================================
458
459// Checked: 2009-06-03 (RLVa-0.2.0h) | Added: RLVa-0.2.0h
460void RlvWLSnapshot::restoreSnapshot(const RlvWLSnapshot* pWLSnapshot)
461{
462 LLWLParamManager* pWLParams = LLWLParamManager::instance();
463 if ( (pWLSnapshot) && (pWLParams) )
464 {
465 pWLParams->mAnimator.mIsRunning = pWLSnapshot->fIsRunning;
466 pWLParams->mAnimator.mUseLindenTime = pWLSnapshot->fUseLindenTime;
467 pWLParams->mCurParams = pWLSnapshot->WLParams;
468 pWLParams->propagateParameters();
469 }
470}
471
472// Checked: 2009-06-03 (RLVa-0.2.0h) | Added: RLVa-0.2.0h
473RlvWLSnapshot* RlvWLSnapshot::takeSnapshot()
474{
475 RlvWLSnapshot* pWLSnapshot = NULL;
476 LLWLParamManager* pWLParams = LLWLParamManager::instance();
477 if (pWLParams)
478 {
479 pWLSnapshot = new RlvWLSnapshot();
480 pWLSnapshot->fIsRunning = pWLParams->mAnimator.mIsRunning;
481 pWLSnapshot->fUseLindenTime = pWLParams->mAnimator.mUseLindenTime;
482 pWLSnapshot->WLParams = pWLParams->mCurParams;
483 }
484 return pWLSnapshot;
485}
486
487// =========================================================================
488
489BOOL RlvSettings::fShowNameTags = FALSE;
490
491#ifdef RLV_EXTENSION_STARTLOCATION
492 // Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.1d
493 void RlvSettings::updateLoginLastLocation()
494 {
495 if (gSavedPerAccountSettings.controlExists(RLV_SETTING_LOGINLASTLOCATION))
496 {
497 BOOL fValue = (gRlvHandler.hasBehaviour(RLV_BHVR_TPLOC)) ||
498 ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) &&
499 (gAgent.getAvatarObject()) && (!gAgent.getAvatarObject()->mIsSitting) );
500 if (gSavedPerAccountSettings.getBOOL(RLV_SETTING_LOGINLASTLOCATION) != fValue)
501 {
502 gSavedPerAccountSettings.setBOOL(RLV_SETTING_LOGINLASTLOCATION, fValue);
503 gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
504 }
505 }
506 }
507#endif // RLV_EXTENSION_STARTLOCATION
508
509// =========================================================================
510
511#ifdef RLV_ADVANCED_TOGGLE_RLVA
512 // Checked: 2009-07-12 (RLVa-1.0.0h) | Modified: RLVa-1.0.0h
513 void rlvDbgToggleEnabled(void*)
514 {
515 gSavedSettings.setBOOL(RLV_SETTING_MAIN, !rlv_handler_t::isEnabled());
516
517 #if RLV_TARGET < RLV_MAKE_TARGET(1, 23, 0) // Version: 1.22.11
518 LLStringUtil::format_map_t args;
519 args["[MESSAGE]"] = llformat("Restrained Life Support will be %s after you restart",
520 (rlv_handler_t::isEnabled()) ? "disabled" : "enabled" );
521 gViewerWindow->alertXml("GenericAlert", args);
522 #else // Version: 1.23.4
523 LLSD args;
524 args["MESSAGE"] = llformat("Restrained Life Support will be %s after you restart",
525 (rlv_handler_t::isEnabled()) ? "disabled" : "enabled" );
526 LLNotifications::instance().add("GenericAlert", args);
527 #endif
528 }
529 // Checked: 2009-07-08 (RLVa-1.0.0e)
530 BOOL rlvDbgGetEnabled(void*)
531 {
532 return rlv_handler_t::isEnabled();
533 }
534#endif // RLV_ADVANCED_TOGGLE_RLVA
535
536// =========================================================================
537// Message sending functions
538//
539
540// Checked: 2009-08-11 (RLVa-1.0.1h) | Added: RLVa-1.0.1h
541void rlvForceDetach(LLViewerJointAttachment* pAttachPt)
542{
543 // Copy/paste from handle_detach_from_avatar()
544 LLViewerObject* attached_object = pAttachPt->getObject();
545 if (attached_object)
546 {
547 gMessageSystem->newMessage("ObjectDetach");
548 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
549 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
550 gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
551
552 gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
553 gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID());
554 gMessageSystem->sendReliable( gAgent.getRegionHost() );
555 }
556}
557
558void rlvSendBusyMessage(const LLUUID& idTo, const std::string& strMsg, const LLUUID& idSession)
559{
560 // (See process_improved_im)
561 std::string strFullName;
562 gAgent.buildFullname(strFullName);
563
564 pack_instant_message(gMessageSystem, gAgent.getID(), FALSE, gAgent.getSessionID(), idTo, strFullName,
565 strMsg, IM_ONLINE, IM_BUSY_AUTO_RESPONSE, idSession);
566 gAgent.sendReliableMessage();
567}
568
569// Checked: 2009-08-05 (RLVa-1.0.1e) | Modified: RLVa-1.0.1e
570bool rlvSendChatReply(S32 nChannel, const std::string& strReply)
571{
572 if (!rlvIsValidChannel(nChannel))
573 return false;
574
575 // Copy/paste from send_chat_from_viewer()
576 LLMessageSystem* msg = gMessageSystem;
577 msg->newMessageFast(_PREHASH_ChatFromViewer);
578 msg->nextBlockFast(_PREHASH_AgentData);
579 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
580 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
581 msg->nextBlockFast(_PREHASH_ChatData);
582 msg->addStringFast(_PREHASH_Message, strReply);
583 msg->addU8Fast(_PREHASH_Type, CHAT_TYPE_SHOUT);
584 msg->addS32("Channel", nChannel);
585 gAgent.sendReliableMessage();
586 LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT);
587
588 return true;
589}
590
591// =========================================================================
592// String helper functions
593//
594
595// Checked: 2009-07-04 (RLVa-1.0.0a)
596void rlvStringReplace(std::string& strText, std::string strFrom, const std::string& strTo)
597{
598 if (strFrom.empty())
599 return;
600
601 size_t lenFrom = strFrom.length();
602 size_t lenTo = strTo.length();
603
604 std::string strTemp(strText);
605 LLStringUtil::toLower(strTemp);
606 LLStringUtil::toLower(strFrom);
607
608 std::string::size_type idxCur, idxStart = 0, idxOffset = 0;
609 while ( (idxCur = strTemp.find(strFrom, idxStart)) != std::string::npos)
610 {
611 strText.replace(idxCur + idxOffset, lenFrom, strTo);
612 idxStart = idxCur + lenFrom;
613 idxOffset += lenTo - lenFrom;
614 }
615}
616
617// Checked: 2009-07-29 (RLVa-1.0.1b) | Added: RLVa-1.0.1b
618std::string rlvGetFirstParenthesisedText(const std::string& strText, std::string::size_type* pidxMatch /*=NULL*/)
619{
620 if (pidxMatch)
621 *pidxMatch = std::string::npos; // Assume we won't find anything
622
623 std::string::size_type idxIt, idxStart; int cntLevel = 1;
624 if ((idxStart = strText.find_first_of('(')) == std::string::npos)
625 return std::string();
626
627 const char* pstrText = strText.c_str(); idxIt = idxStart;
628 while ( (cntLevel > 0) && (idxIt < strText.length()) )
629 {
630 if ('(' == pstrText[++idxIt])
631 cntLevel++;
632 else if (')' == pstrText[idxIt])
633 cntLevel--;
634 }
635
636 if (idxIt < strText.length())
637 {
638 if (pidxMatch)
639 *pidxMatch = idxStart; // Return the character index of the starting '('
640 return strText.substr(idxStart + 1, idxIt - idxStart - 1);
641 }
642 return std::string();
643}
644
645// Checked: 2009-07-29 (RLVa-1.0.1b) | Added: RLVa-1.0.1b
646std::string rlvGetLastParenthesisedText(const std::string& strText, std::string::size_type* pidxStart /*=NULL*/)
647{
648 if (pidxStart)
649 *pidxStart = std::string::npos; // Assume we won't find anything
650
651 // Extracts the last - matched - parenthesised text from the input string
652 std::string::size_type idxIt, idxEnd; int cntLevel = 1;
653 if ((idxEnd = strText.find_last_of(')')) == std::string::npos)
654 return std::string();
655
656 const char* pstrText = strText.c_str(); idxIt = idxEnd;
657 while ( (cntLevel > 0) && (idxIt >= 0) )
658 {
659 if (')' == pstrText[--idxIt])
660 cntLevel++;
661 else if ('(' == pstrText[idxIt])
662 cntLevel--;
663 }
664
665 if ( (idxIt >= 0) && (idxIt < strText.length()) ) // NOTE: allow for std::string::size_type to be signed or unsigned
666 {
667 if (pidxStart)
668 *pidxStart = idxIt; // Return the character index of the starting '('
669 return strText.substr(idxIt + 1, idxEnd - idxIt - 1);
670 }
671 return std::string();
672}
673
674// =========================================================================
diff --git a/linden/indra/newview/rlvhelper.h b/linden/indra/newview/rlvhelper.h
new file mode 100644
index 0000000..a0e040e
--- /dev/null
+++ b/linden/indra/newview/rlvhelper.h
@@ -0,0 +1,579 @@
1#ifndef RLV_HELPER_H
2#define RLV_HELPER_H
3
4#include "llboost.h"
5#include "llinventorymodel.h"
6#include "llselectmgr.h"
7#include "llviewercontrol.h"
8#include "llviewerobjectlist.h"
9#include "llwlparamset.h"
10
11#include "rlvmultistringsearch.h"
12
13// ============================================================================
14// Extensions
15//
16
17// Comment out if you don't want the Advanced / RLVa menu (may prevent enabling some extensions or experimental features - see below)
18#define RLV_ADVANCED_MENU
19// Comment out if you provide your own way to enable/disable RLVa
20#define RLV_ADVANCED_TOGGLE_RLVA
21
22// Provides access to "advanced" feature through the RLVa debug menu
23#define RLV_EXTENSION_ENABLE_WEAR // "Enable Wear"
24#define RLV_EXTENSION_HIDELOCKED // "Hide locked layers", "Hide locked attachments" and "Hide locked inventory"
25#define RLV_EXTENSION_FLOATER_RESTRICTIONS // Enables the Advanced / RLVa / Restrictions... floater
26
27// Extensions
28#define RLV_EXTENSION_CMD_GETSETDEBUG_EX // Extends the debug variables accessible through @getdebug_xxx/@setdebug_xxx
29#define RLV_EXTENSION_CMD_FINDFOLDERS // @findfolders:<option>=<channel> - @findfolder with multiple results
30#define RLV_EXTENSION_FLAG_NOSTRIP // Layers and attachments marked as "nostrip" are exempt from @detach/@remoutfit
31#define RLV_EXTENSION_STARTLOCATION // Reenables "Start Location" at login if not @tploc=n or @unsit=n restricted at last logoff
32#define RLV_EXPERIMENTAL // Enables/disables experimental features en masse
33
34// Experimental features
35#ifdef RLV_EXPERIMENTAL
36 // Stable (will mature to RLV_EXTENSION_XXX in next release if no bugs are found)
37 #define RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK // Enables "cleaner" UI responses when fartouch blocks something
38
39 // Under testing (stable, but requires further testing - safe for public release but may be quirky)
40
41 // Under development (don't include in public release)
42 #if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
43 #endif // LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
44#endif // RLV_EXPERIMENTAL
45
46// ============================================================================
47// Defines
48//
49
50// Version of the specifcation we support
51const S32 RLV_VERSION_MAJOR = 1;
52const S32 RLV_VERSION_MINOR = 20;
53const S32 RLV_VERSION_PATCH = 0;
54
55// Implementation version
56const S32 RLVa_VERSION_MAJOR = 1;
57const S32 RLVa_VERSION_MINOR = 0;
58const S32 RLVa_VERSION_PATCH = 1;
59const S32 RLVa_VERSION_BUILD = 7;
60
61// The official viewer version we're patching against
62#define RLV_MAKE_TARGET(x, y, z) ((x << 16) | (y << 8) | z)
63#define RLV_TARGET RLV_MAKE_TARGET(1, 22, 11)
64
65// Defining these makes it easier if we ever need to change our tag
66#define RLV_WARNS LL_WARNS("RLV")
67#define RLV_INFOS LL_INFOS("RLV")
68#define RLV_DEBUGS LL_DEBUGS("RLV")
69
70#if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
71 // Turn on extended debugging information
72 #define RLV_DEBUG
73 // Make sure we halt execution on errors
74 #define RLV_ERRS LL_ERRS("RLV")
75 // Uncomment to enable the Advanced / RLVa / Unit Tests menu (non-public)
76 //#define RLV_DEBUG_TESTS
77#else
78 // Uncomment if you want extended debugging information on release builds
79 //#define RLV_DEBUG
80 // Don't halt execution on errors in release
81 #define RLV_ERRS LL_WARNS("RLV")
82#endif // LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
83
84#define RLV_ROOT_FOLDER "#RLV"
85#define RLV_CMD_PREFIX '@'
86#define RLV_PUTINV_PREFIX "#RLV/~"
87#define RLV_SETROT_OFFSET F_PI_BY_TWO // @setrot is off by 90° with the rest of SL
88
89#define RLV_FOLDER_FLAG_NOSTRIP "nostrip"
90#define RLV_FOLDER_PREFIX_HIDDEN '.'
91#define RLV_FOLDER_PREFIX_PUTINV '~'
92
93// ============================================================================
94// Enumeration declarations
95//
96
97// NOTE: * any changes to this enumeration should be reflected in initLookupTable()
98// * only uncomment the ones we actually use in a switch() to keep the size of the lookup table down
99enum ERlvBehaviour {
100 RLV_BHVR_VERSION = 0, // "version"
101 RLV_BHVR_DETACH, // "detach"
102// RLV_BHVR_SENDCHAT, // "sendchat"
103// RLV_BHVR_EMOTE, // "emote"
104// RLV_BHVR_CHATSHOUT, // "chatshout"
105// RLV_BHVR_CHATNORMAL, // "chatnormal"
106// RLV_BHVR_CHATWHISPER, // "chatwhisper"
107 RLV_BHVR_REDIRCHAT, // "redirchat"
108 RLV_BHVR_REDIREMOTE, // "rediremote"
109 RLV_BHVR_SENDIM, // "sendim"
110 RLV_BHVR_RECVCHAT, // "recvchat"
111 RLV_BHVR_RECVEMOTE, // "recvemote"
112 RLV_BHVR_RECVIM, // "recvim"
113// RLV_BHVR_TPLM, // "tplm"
114 RLV_BHVR_TPLOC, // "tploc"
115 RLV_BHVR_TPLURE, // "tplure"
116 RLV_BHVR_SITTP, // "sittp"
117// RLV_BHVR_CLEAR, // "clear"
118 RLV_BHVR_EDIT, // "edit"
119 RLV_BHVR_REZ, // "rez"
120 RLV_BHVR_ADDOUTFIT, // "addoutfit"
121 RLV_BHVR_REMOUTFIT, // "remoutfit"
122 RLV_BHVR_GETOUTFIT, // "getoutfit"
123 RLV_BHVR_GETATTACH, // "getattach"
124 RLV_BHVR_SHOWINV, // "showinv"
125// RLV_BHVR_VIEWNOTE, // "viewnote"
126 RLV_BHVR_UNSIT, // "unsit"
127 RLV_BHVR_SIT, // "sit"
128// RLV_BHVR_SENDCHANNEL, // "sendchannel"
129 RLV_BHVR_GETSTATUS, // "getstatus"
130 RLV_BHVR_GETSTATUSALL, // "getstatusall"
131 RLV_BHVR_GETINV, // "getinv"
132 RLV_BHVR_GETINVWORN, // "getinvworn"
133 RLV_BHVR_FINDFOLDER, // "findfolder"
134 RLV_BHVR_FINDFOLDERS, // "findfolders"
135 RLV_BHVR_ATTACH, // "attach"
136 RLV_BHVR_ATTACHALL, // "attachall"
137 RLV_BHVR_DETACHALL, // "detachall"
138 RLV_BHVR_GETPATH, // "getpath"
139 RLV_BHVR_ATTACHTHIS, // "attachthis"
140 RLV_BHVR_ATTACHALLTHIS, // "attachallthis"
141 RLV_BHVR_DETACHTHIS, // "detachthis"
142 RLV_BHVR_DETACHALLTHIS, // "detachallthis"
143 RLV_BHVR_FARTOUCH, // "fartouch"
144 RLV_BHVR_SHOWWORLDMAP, // "showworldmap"
145 RLV_BHVR_SHOWMINIMAP, // "showminimap"
146 RLV_BHVR_SHOWLOC, // "showloc"
147 RLV_BHVR_TPTO, // "tpto"
148 RLV_BHVR_ACCEPTTP, // "accepttp"
149 RLV_BHVR_SHOWNAMES, // "shownames"
150 RLV_BHVR_FLY, // "fly"
151 RLV_BHVR_GETSITID, // "getsitid"
152 RLV_BHVR_SETDEBUG, // "setdebug"
153 RLV_BHVR_SETENV, // "setenv"
154 RLV_BHVR_DETACHME, // "detachme"
155 RLV_BHVR_SHOWHOVERTEXTALL, // "showhovertextall"
156 RLV_BHVR_SHOWHOVERTEXTWORLD, // "showhovertextworld"
157 RLV_BHVR_SHOWHOVERTEXTHUD, // "showhovertexthud"
158 RLV_BHVR_SHOWHOVERTEXT, // "showhovertext"
159 RLV_BHVR_NOTIFY, // "notify"
160
161 RLV_BHVR_COUNT,
162 RLV_BHVR_UNKNOWN
163};
164
165enum ERlvParamType {
166 RLV_TYPE_UNKNOWN,
167 RLV_TYPE_ADD, // <param> == "n"|"add"
168 RLV_TYPE_REMOVE, // <param> == "y"|"rem"
169 RLV_TYPE_FORCE, // <param> == "force"
170 RLV_TYPE_REPLY // <param> == <number>
171};
172
173enum ERlvCmdRet {
174 RLV_RET_NOERROR, // Command executed succesfully
175 RLV_RET_RETAINED, // Command was retained
176 RLV_RET_FAILED, // Command failed (general failure)
177 RLV_RET_FAILED_SYNTAX, // Command failed (syntax error)
178 RLV_RET_FAILED_UNSET, // Command failed (unset restriction)
179 RLV_RET_FAILED_DUPLICATE, // Command failed (duplicate)
180 RLV_RET_FAILED_OPTION, // Command failed (invalid option)
181 RLV_RET_UNKNOWN // Command unkown
182};
183
184// ============================================================================
185/*
186 * RlvCommand
187 * ==========
188 * Encapsulates an "RLV command" (duh :p)
189 *
190 */
191
192class RlvCommand
193{
194public:
195 /*
196 * Constructors
197 */
198 explicit RlvCommand(const std::string& strCommand);
199 RlvCommand(const RlvCommand& rlvCmd);
200
201 /*
202 * Accessors
203 */
204 BOOL isValid() const { return m_fValid; }
205
206 const std::string& getBehaviour() const { return m_strBehaviour; }
207 ERlvBehaviour getBehaviourType() const { return m_eBehaviour; }
208 const std::string& getOption() const { return m_strOption; }
209 const std::string& getParam() const { return m_strParam; }
210 ERlvParamType getParamType() const { return m_eParamType; }
211
212 std::string asString() const;
213
214 /*
215 * Operators
216 */
217 bool operator ==(const RlvCommand&) const;
218
219 // Parses an RLV command into its "tokens"
220 static BOOL parseCommand(/*[in]*/ const std::string& strCommand,
221 /*[out]*/ std::string& strBehaviour, /*[out]*/ std::string& strOption, /*[out]*/ std::string& strParam);
222 static void initLookupTable();
223
224 /*
225 * Member variables
226 */
227protected:
228 BOOL m_fValid;
229 std::string m_strBehaviour;
230 ERlvBehaviour m_eBehaviour;
231 std::string m_strOption;
232 std::string m_strParam;
233 ERlvParamType m_eParamType;
234
235 static RlvMultiStringSearch m_BhvrLookup;
236 friend class RlvHandler;
237};
238
239// ============================================================================
240/*
241 * RlvObject
242 * =========
243 * Encapsulates an "RLV Object" (= an object that has issued an RLV command)
244 *
245 */
246
247typedef std::list<RlvCommand> rlv_command_list_t;
248
249class RlvObject
250{
251public:
252 RlvObject(const LLUUID& uuid) : m_UUID(uuid), m_nLookupMisses(0) { m_fLookup = (NULL != gObjectList.findObject(uuid)); }
253
254 BOOL addCommand(const RlvCommand& rlvCmd);
255 BOOL removeCommand(const RlvCommand& rlvCmd);
256
257 BOOL hasBehaviour(ERlvBehaviour eBehaviour) const;
258 BOOL hasBehaviour(const std::string& strBehaviour) const;
259 BOOL hasBehaviour(ERlvBehaviour eBehaviour, const std::string& strOption) const;
260 BOOL hasBehaviour(const std::string& strBehaviour, const std::string& strOption) const;
261
262 std::string getStatusString(const std::string& strMatch) const;
263
264 const rlv_command_list_t* getCommandList() const { return &m_Commands; }
265protected:
266 LLUUID m_UUID; // The object's UUID
267 bool m_fLookup; // TRUE if the object existed in gObjectList at one point in time
268 S16 m_nLookupMisses; // Count of unsuccessful lookups in gObjectList by the GC
269 rlv_command_list_t m_Commands; // List of behaviours held by this object (in the order they were received)
270
271 friend class RlvHandler;
272};
273
274// ============================================================================
275/*
276 * RlvCriteriaCategoryCollector
277 * ============================
278 * Criteria based folder matching filter used by @findfolder and @findfolders
279 *
280 */
281
282class RlvCriteriaCategoryCollector : public LLInventoryCollectFunctor
283{
284public:
285 RlvCriteriaCategoryCollector(const std::string& strCriteria)
286 {
287 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
288 boost::char_separator<char> sep("&&", "", boost::drop_empty_tokens);
289 tokenizer tokens(strCriteria, sep);
290 for (tokenizer::iterator itToken = tokens.begin(); itToken != tokens.end(); ++itToken)
291 m_Criteria.push_back(*itToken);
292 }
293 virtual ~RlvCriteriaCategoryCollector() {}
294
295 virtual bool operator()(LLInventoryCategory* pFolder, LLInventoryItem* pItem)
296 {
297 if ( (!pFolder) || (m_Criteria.empty()) ) // We're only interested in matching folders, we don't care about items
298 return false; // (if there are no criteria then we don't want to return a match)
299
300 std::string strFolderName = pFolder->getName();
301 LLStringUtil::toLower(strFolderName);
302
303 if ( (strFolderName.empty()) || (RLV_FOLDER_PREFIX_HIDDEN == strFolderName[0]) )
304 return false;
305
306 for (std::list<std::string>::const_iterator itCrit = m_Criteria.begin(); itCrit != m_Criteria.end(); ++itCrit)
307 if (-1 == strFolderName.find(*itCrit)) // Return false on the first mismatch
308 return false;
309 return true;
310 }
311
312protected:
313 std::list<std::string> m_Criteria;
314};
315
316// ============================================================================
317/*
318 * RlvWearableItemCollector
319 * ========================
320 * Inventory item filter used by attach/detach/attachall/detachall/getinvworn (also used by "Add/Replace Outfit" and "Take Off Items")
321 *
322 */
323
324class RlvWearableItemCollector : public LLInventoryCollectFunctor
325{
326public:
327 RlvWearableItemCollector(const LLUUID& idFolder, bool fAttach, bool fMatchAll)
328 : m_idFolder(idFolder), m_fAttach(fAttach), m_fMatchAll(fMatchAll)
329 {
330 m_Wearable.push_back(idFolder);
331 }
332 virtual ~RlvWearableItemCollector() {}
333
334 virtual bool operator()(LLInventoryCategory* pFolder, LLInventoryItem* pItem);
335
336 const LLUUID& getFoldedParent(const LLUUID& idFolder) const;
337protected:
338 bool m_fAttach;
339 bool m_fMatchAll;
340 const LLUUID m_idFolder;
341
342 bool onCollectFolder(const LLInventoryCategory* pFolder);
343 bool onCollectItem(const LLInventoryItem* pItem);
344
345 std::list<LLUUID> m_Tentative;
346 std::list<LLUUID> m_Wearable;
347
348 std::map<LLUUID, LLUUID> m_Folding;
349};
350
351// ============================================================================
352/*
353 * RlvRetainedCommand
354 * ==================
355 *
356 */
357
358struct RlvRetainedCommand
359{
360public:
361 std::string strObject;
362 LLUUID idObject;
363 std::string strCmd;
364
365 RlvRetainedCommand(const std::string obj, const LLUUID& uuid, const std::string& cmd) : strObject(obj), idObject(uuid), strCmd(cmd) {}
366private:
367 RlvRetainedCommand();
368};
369typedef std::list<RlvRetainedCommand> rlv_retained_list_t;
370
371// ============================================================================
372/*
373 * RlvWLSnapshot
374 * =============
375 *
376 */
377
378struct RlvWLSnapshot
379{
380public:
381 static void restoreSnapshot(const RlvWLSnapshot* pWLSnapshot);
382 static RlvWLSnapshot* takeSnapshot();
383private:
384 RlvWLSnapshot() {}
385
386 bool fIsRunning;
387 bool fUseLindenTime;
388 LLWLParamSet WLParams;
389};
390
391// ============================================================================
392/*
393 * RlvSettings
394 * ===========
395 *
396 */
397
398#define RLV_SETTING_MAIN "RestrainedLife"
399#define RLV_SETTING_DEBUG "RestrainedLifeDebug"
400#define RLV_SETTING_NOSETENV "RestrainedLifeNoSetEnv"
401#define RLV_SETTING_FORBIDGIVETORLV "RestrainedLifeForbidGiveToRLV"
402
403#define RLV_SETTING_ENABLEWEAR "RLVaEnableWear"
404#define RLV_SETTING_ENABLELEGACYNAMING "RLVaEnableLegacyNaming"
405#define RLV_SETTING_HIDELOCKEDLAYER "RLVaHideLockedLayers"
406#define RLV_SETTING_HIDELOCKEDATTACH "RLVaHideLockedAttachments"
407#define RLV_SETTING_HIDELOCKEDINVENTORY "RLVaHideLockedInventory"
408#define RLV_SETTING_LOGINLASTLOCATION "RLVaLoginLastLocation"
409#define RLV_SETTING_SHOWNAMETAGS "RLVaShowNameTags"
410
411inline BOOL rlvGetSettingBOOL(const std::string& strSetting, BOOL fDefault)
412{
413 return (gSavedSettings.controlExists(strSetting)) ? gSavedSettings.getBOOL(strSetting) : fDefault;
414}
415inline BOOL rlvGetPerUserSettingsBOOL(const std::string& strSetting, BOOL fDefault)
416{
417 return (gSavedPerAccountSettings.controlExists(strSetting)) ? gSavedPerAccountSettings.getBOOL(strSetting) : fDefault;
418}
419
420class RlvSettings
421{
422public:
423 static BOOL getDebug() { return rlvGetSettingBOOL(RLV_SETTING_DEBUG, FALSE); }
424 static BOOL getForbidGiveToRLV() { return rlvGetSettingBOOL(RLV_SETTING_FORBIDGIVETORLV, TRUE); }
425
426 static BOOL getEnableWear() { return rlvGetSettingBOOL(RLV_SETTING_ENABLEWEAR, FALSE); }
427 static BOOL getHideLockedLayers() { return rlvGetSettingBOOL(RLV_SETTING_HIDELOCKEDLAYER, FALSE); }
428 static BOOL getHideLockedAttach() { return rlvGetSettingBOOL(RLV_SETTING_HIDELOCKEDATTACH, FALSE); }
429 static BOOL getHideLockedInventory() { return rlvGetSettingBOOL(RLV_SETTING_HIDELOCKEDINVENTORY, FALSE); }
430
431 #ifdef RLV_EXTENSION_STARTLOCATION
432 static BOOL getLoginLastLocation() { return rlvGetPerUserSettingsBOOL(RLV_SETTING_LOGINLASTLOCATION, TRUE); }
433 static void updateLoginLastLocation();
434 #endif // RLV_EXTENSION_STARTLOCATION
435
436 static BOOL fShowNameTags;
437};
438
439// ============================================================================
440/*
441 * State keeping classes/structure
442 *
443 */
444
445struct RlvRedirInfo
446{
447 S16 nRedirChat;
448 S16 nRedirEmote;
449
450 RlvRedirInfo() : nRedirChat(0), nRedirEmote(0) {}
451 bool isActive() { return (nRedirChat + nRedirEmote) != 0; }
452};
453
454struct RlvReattachInfo
455{
456 LLUUID idItem;
457 bool fInInventory;
458 bool fAssetSaved;
459
460 RlvReattachInfo() : idItem(), fInInventory(false), fAssetSaved(false) {}
461};
462
463// ============================================================================
464/*
465 * Various helper classes/timers/functors
466 *
467 */
468
469class RlvGCTimer : public LLEventTimer
470{
471public:
472 RlvGCTimer() : LLEventTimer(30.0) {}
473 virtual BOOL tick();
474};
475
476class RlvCurrentlyWorn : public LLInventoryFetchObserver
477{
478public:
479 RlvCurrentlyWorn() {}
480 ~RlvCurrentlyWorn() {}
481 virtual void done() {}
482
483 static void fetchWorn();
484 void fetchItem(const LLUUID& idItem);
485};
486
487struct RlvSelectHasLockedAttach : public LLSelectedNodeFunctor
488{
489 virtual bool apply(LLSelectNode* pNode);
490};
491
492struct RlvSelectIsOwnedByOrGroupOwned : public LLSelectedNodeFunctor
493{
494 RlvSelectIsOwnedByOrGroupOwned(const LLUUID& uuid) : m_idAgent(uuid) {}
495 virtual bool apply(LLSelectNode* pNode);
496 LLUUID m_idAgent;
497};
498
499struct RlvSelectIsSittingOn : public LLSelectedNodeFunctor
500{
501 RlvSelectIsSittingOn(LLXform* pObject) : m_pObject(pObject) {}
502 virtual bool apply(LLSelectNode* pNode);
503 LLXform* m_pObject;
504};
505
506// ============================================================================
507/*
508 * Various helper functions
509 *
510 */
511
512BOOL rlvAttachToEnabler(void* pParam);
513bool rlvCanDeleteOrReturn();
514S32 rlvGetDirectDescendentsCount(const LLInventoryCategory* pFolder, LLAssetType::EType type);
515bool rlvIsEmote(const std::string& strUTF8Text);
516bool rlvIsValidChannel(S32 nChannel);
517bool rlvIsWearingItem(const LLInventoryItem* pItem);
518
519void rlvForceDetach(LLViewerJointAttachment* pAttachPt);
520void rlvSendBusyMessage(const LLUUID& idTo, const std::string& strMsg, const LLUUID& idSession = LLUUID::null);
521bool rlvSendChatReply(const std::string& strChannel, const std::string& strReply);
522bool rlvSendChatReply(S32 nChannel, const std::string& strReply);
523
524void rlvStringReplace(std::string& strText, std::string strFrom, const std::string& strTo);
525std::string rlvGetFirstParenthesisedText(const std::string& strText, std::string::size_type* pidxMatch = NULL);
526std::string rlvGetLastParenthesisedText(const std::string& strText, std::string::size_type* pidxStart = NULL);
527
528#ifdef RLV_ADVANCED_TOGGLE_RLVA
529 // "Advanced / RLVa / Enable RLV" menu option
530 void rlvDbgToggleEnabled(void*);
531 BOOL rlvDbgGetEnabled(void*);
532#endif // RLV_ADVANCED_TOGGLE_RLVA
533
534// ============================================================================
535// Inlined class member functions
536//
537
538inline bool RlvCommand::operator ==(const RlvCommand& rhs) const
539{
540 // The specification notes that "@detach=n" is semantically identical to "@detach=add" (same for "y" and "rem"
541 return (m_strBehaviour == rhs.m_strBehaviour) && (m_strOption == rhs.m_strOption) &&
542 ( (RLV_TYPE_UNKNOWN != m_eParamType) ? (m_eParamType == rhs.m_eParamType) : (m_strParam == rhs.m_strParam) );
543}
544
545inline void RlvCurrentlyWorn::fetchItem(const LLUUID& idItem)
546{
547 if (idItem.notNull())
548 {
549 LLInventoryFetchObserver::item_ref_t idItems;
550 idItems.push_back(idItem);
551 fetchItems(idItems);
552 }
553}
554
555// ============================================================================
556// Inlined helper functions
557//
558
559inline bool rlvIsEmote(const std::string& strUTF8Text)
560{
561 return (strUTF8Text.length() > 4) && ( (strUTF8Text.compare(0, 4, "/me ") == 0) || (strUTF8Text.compare(0, 4, "/me'") == 0) );
562}
563
564// Checked: 2009-08-05 (RLVa-1.0.1e) | Added: RLVa-1.0.0e
565inline bool rlvIsValidChannel(S32 nChannel)
566{
567 return (nChannel >= 0) && (CHAT_CHANNEL_DEBUG != nChannel);
568}
569
570// Checked: 2009-08-05 (RLVa-1.0.1e) | Added: RLVa-1.0.0e
571inline bool rlvSendChatReply(const std::string& strChannel, const std::string& strReply)
572{
573 S32 nChannel;
574 return (LLStringUtil::convertToS32(strChannel, nChannel)) ? rlvSendChatReply(nChannel, strReply) : false;
575}
576
577// ============================================================================
578
579#endif // RLV_HELPER_H
diff --git a/linden/indra/newview/rlvmultistringsearch.cpp b/linden/indra/newview/rlvmultistringsearch.cpp
new file mode 100644
index 0000000..0aa9889
--- /dev/null
+++ b/linden/indra/newview/rlvmultistringsearch.cpp
@@ -0,0 +1,196 @@
1#include "llviewerprecompiledheaders.h"
2
3#include "rlvmultistringsearch.h"
4
5// ====================================================================================
6
7#ifndef RLV_LOWORD
8 #define RLV_LOWORD(x) ( (U16)( ((U32)x) & 0xFFFF) )
9#endif // RLV_LOWORD
10
11#ifndef RLV_HIWORD
12 #define RLV_HIWORD(x) ( (U16)( (((U32)x) >> 16) & 0xFFFF) )
13#endif // RLV_HIWORD
14
15// ====================================================================================
16
17// (TODO-RLV: oops, forgot I was experimenting with word matching, get rid of that again?)
18#define isLetter(ch) \
19 ( ( (ch >= 'a') && (ch <= 'z') ) || ( (ch >= 'A') && (ch <= 'Z') ) )
20
21RlvMultiStringSearch::RlvMultiStringSearch()
22 : m_FSM(256), // Start our FSM with room for 256 states (enough for all attachment point names)
23 m_cntState(0)
24{
25}
26
27void RlvMultiStringSearch::addKeyword(const std::string& strKeyword, U16 nParam) {
28 U16 nCurState = 0; // Always start the loop at state 0
29
30 //
31 // Make sure there are enough unused rows to accomodate the worst case (== strKeyword.length() new states)
32 //
33 size_t nMaxState = m_FSM.getSize();
34 if (m_cntState + strKeyword.length() > nMaxState)
35 // Allocate enough new rows (in batches of 256 rows)
36 m_FSM.resize(nMaxState + ((strKeyword.length() / 256) + 1) * 256);
37
38 //
39 // Walk the string character by character
40 //
41 for (int idxCh = 0, cntCh = strKeyword.length(); idxCh < cntCh; idxCh++) {
42 // Look up the next state for current character
43 unsigned char ch = strKeyword[idxCh];
44 U16 nState = RLV_LOWORD(m_FSM[nCurState][ch]);
45
46 // If we're at the last character in the keyword then set the termination bit
47 if (cntCh - 1 == idxCh)
48 {
49 // (Only set the termination bit for the state because this keyword might be a substring of another keyword)
50 m_FSM[nCurState][ch] = (nParam << 16) | (nState | 0x8000);
51 }
52 else if ( (nState & 0x7FFF) == 0 ) // If the new state is 0 then we're creating a new path
53 {
54 // (Preserve the termination bit because another keyword might be a substring of this one)
55 nState = ++m_cntState | (nState & 0x8000);
56
57 // Store the new path in the FSM
58 //m_FSM[nCurState][ch] = (nParam << 16) | nState;
59 m_FSM[nCurState][ch] |= nState;
60 }
61
62 nCurState = nState & 0x7FFF; // Mask out the termination bit since we never need it for the current state
63 }
64}
65
66// (Iterating over a "const char*" is *significantly* faster than "std::string")
67bool RlvMultiStringSearch::findNext(const char* pstrText, int idxCh, int cntCh, RlvMultiStringSearchMatch& match, bool fWordMatch) const
68{
69 U16 nCurState = 0; // Always start the loop at state 0
70 U32 nLastMatch = 0; // Holds the state of the last (possibly partial) keyword match
71
72 //
73 // Walk the string character by character
74 //
75 for (; idxCh < cntCh; idxCh++)
76 {
77 // Keep track of the current state in case we need to backtrack
78 U16 nPrevState = nCurState;
79
80 // If we're currently in state 0, save the current character index (for backtracking or as keyword index match)
81 if (nCurState == 0)
82 match.idxMatch = idxCh;
83
84 // Look up the current character in the FSM
85 unsigned char ch = (unsigned char)pstrText[idxCh];
86 U32 nCell = m_FSM[nCurState & 0x7FFF][ch];
87
88 // If the termination bit is set then we found a keyword substring match
89 // If the next state is non-zero then we can't stop yet because the matched keyword might be a substring of another keyword
90 if (nCell & 0x8000)
91 {
92 if ( 0 == (nCell & 0x7FFF) )
93 {
94 // Termination bit with 'next state' equal to 0: matched keyword which isn't also a substring of any other keyword
95 match.lenMatch = idxCh - match.idxMatch + 1;
96 match.nParam = RLV_HIWORD(nCell);
97
98 // Rudimentary word matching: check if the match is a 'word'
99 if
100 (
101 (!fWordMatch) ||
102 (
103 ( (0 == match.idxMatch) || (!isLetter(pstrText[match.idxMatch - 1])) ) && // Start of string OR non-letter
104 ( (!isLetter(pstrText[match.idxMatch + match.lenMatch])) )
105 )
106 )
107 {
108 return true;
109 }
110
111 // Not a word, but there's no need to backtrack: we can move on from the character after the current one
112 nCell = 0; // Will set nCurState == 0 further down
113 match.idxMatch = idxCh; // Makes sure we move on to the next character instead of backtracking
114 }
115 else
116 {
117 nLastMatch = nCell;
118
119 // In case it turns out that we need to backtrack and return this match, save the length of this match
120 match.lenMatch = idxCh - match.idxMatch + 1;
121 }
122 }
123
124 nCurState = RLV_LOWORD(nCell);
125
126 // If our new state is 0, but our previous state wasn't, then we followed a false lead and need to backtrack
127 if ( (nPrevState != 0) && (nCurState == 0) )
128 {
129 // * if nLastMatch == 0 then we need to backtrack and keep going
130 // * if nLastMatch != 0 then we previously encountered a keyword match so return that one
131 if (nLastMatch) {
132 // Rudimentary word matching: check if the match is a 'word'
133 if
134 (
135 (!fWordMatch) ||
136 (
137 ( (0 == match.idxMatch) || (!isLetter(pstrText[match.idxMatch - 1])) ) && // Start of string OR non-letter
138 ( (!isLetter(pstrText[match.idxMatch + match.lenMatch])) )
139 )
140 )
141 {
142 match.nParam = RLV_HIWORD(nLastMatch);
143 return true;
144 } else
145 // Not a word match, so throw away this partial match and backtrack
146 nLastMatch = 0;
147 }
148
149 idxCh = match.idxMatch;
150 }
151 }
152
153 // We encountered a match, but while investigating whether it was a substring of another keyword we ran out of characters
154 if (nLastMatch)
155 {
156 // Rudimentary word matching: check if we started at the beginning of a word (we know the one behind us is '\0')
157 if ( (!fWordMatch) || ( (0 == match.idxMatch) || (!isLetter(pstrText[match.idxMatch - 1])) ) )
158 {
159 match.nParam = RLV_HIWORD(nLastMatch);
160 return true;
161 }
162 }
163
164 // None of the keywords is contained in the string: return failure
165 match.idxMatch = -1;
166 return false;
167}
168
169bool RlvMultiStringSearch::findLast(const std::string& strText, RlvMultiStringSearchMatch& match) const {
170 RlvMultiStringSearchMatch matchTemp;
171 match.idxMatch = -1; // (Needed to make the return work in case we don't find anything)
172 matchTemp.lenMatch = 0; // (Needed to make the first loop iteration start at 0)
173
174 // Iterating over a "const char*" is *significantly* faster than "std::string"
175 const char* pstrText = strText.c_str();
176 int lenText = strText.length();
177
178 while (findNext(pstrText, matchTemp.idxMatch + matchTemp.lenMatch + 1, lenText, matchTemp))
179 match = matchTemp;
180
181 return (match.idxMatch != -1);
182}
183
184std::vector<RlvMultiStringSearchMatch> RlvMultiStringSearch::findAll(const std::string& strText) {
185 std::vector<RlvMultiStringSearchMatch> arMatch;
186
187 RlvMultiStringSearchMatch match;
188 match.lenMatch = 0; // (Needed to make the first loop iteration start at 0)
189
190 while (findNext(strText, match.idxMatch + match.lenMatch + 1, match))
191 arMatch.push_back(match);
192
193 return arMatch;
194}
195
196// ====================================================================================
diff --git a/linden/indra/newview/rlvmultistringsearch.h b/linden/indra/newview/rlvmultistringsearch.h
new file mode 100644
index 0000000..43b0172
--- /dev/null
+++ b/linden/indra/newview/rlvmultistringsearch.h
@@ -0,0 +1,191 @@
1#ifndef RLV_MULTISTRINGSEARCH_H
2#define RLV_MULTISTRINGSEARCH_H
3
4// ============================================================================
5// Template classes for our state machine (2 dimensional array of type T)
6
7// STL vector
8template<typename T> class RlvMultiStringSearchFSM_STL
9{
10public:
11 /*
12 * Constructor/destructor
13 */
14
15 // Initialize the FSM with an initial capacity of 'nCapacity' states
16 RlvMultiStringSearchFSM_STL(size_t nCapacity)
17 {
18 m_arFSM.reserve(nCapacity);
19
20 T* pT;
21 for (size_t idx = 0; idx < nCapacity; idx++)
22 {
23 // The width of each row is determined by the alphabet we're using (in this case UTF-8
24 // so while every character might consist of multiple bytes there are
25 // still only 256 'columns' in the state machine)
26 pT = new T[256]();
27
28 // The above *should* initialize to 0 but since we can't account for every compiler doing it :(
29 memset(pT, 0, sizeof(T) * 256);
30
31 m_arFSM.push_back(pT);
32 }
33 };
34
35 ~RlvMultiStringSearchFSM_STL()
36 {
37 // Free any memory we previously allocated
38 for (int idx = 0, cnt = m_arFSM.size(); idx < cnt; idx++)
39 delete[] m_arFSM[idx];
40 }
41
42 /*
43 * Operators
44 */
45 // ASSERTION: nState < m_arFSM.size() at all times
46 // In other words: do *NOT* go out of bounds on the array (no memory will have allocated for that non-existing state)
47 // (There probably should be a check for that even in release but it seems wasteful, just don't do it :p)
48 inline T* operator[](size_t nState)
49 {
50 //#ifdef _DEBUG
51 // assert( nState < m_arFSM.size() );
52 //#endif // _DEBUG
53
54 return m_arFSM[nState];
55 }
56 inline const T* operator[](size_t nState) const
57 {
58 //#ifdef _DEBUG
59 // assert( nState < m_arFSM.size() );
60 //#endif // _DEBUG
61
62 return m_arFSM[nState];
63 }
64
65 /*
66 * Public member functions
67 */
68
69 size_t getSize() const { return m_arFSM.size(); }
70
71 void resize(size_t nNewCapacity)
72 {
73 // Get our current capacity (only rows > capacity need memory allocated)
74 size_t nCurCapacity = m_arFSM.capacity();
75
76 // Only expand, never shrink
77 if (nNewCapacity <= nCurCapacity)
78 {
79 //#ifdef _DEBUG
80 // assert(false);
81 //#endif //_DEBUG
82
83 return;
84 }
85 m_arFSM.resize(nNewCapacity);
86
87 // For each new state we added, allocate memory for the columns
88 for(size_t idx = nCurCapacity; idx < nNewCapacity; idx++)
89 // The memset is redundant (or rather *should* be) but since we can't account for every compiler doing it :(
90 m_arFSM[idx] = (T*)memset(new T[256](), 0, sizeof(T) * 256);
91 }
92
93protected:
94 /*
95 * Member variables
96 */
97 std::vector<T*> m_arFSM;
98};
99
100// ============================================================================
101
102struct RlvMultiStringSearchMatch
103{
104 int idxMatch; // Starting character index into the string of the matched keyword (-1 if no match)
105 int lenMatch; // Length of the matched keyword (undefined if no match)
106 U16 nParam; // User supplied parameter for the matched keyword (undefined if no match)
107
108 RlvMultiStringSearchMatch() : idxMatch(-1) {}
109};
110
111// ============================================================================
112// The actual search class
113
114class RlvMultiStringSearch
115{
116public:
117 /*
118 * Constructor/destructor
119 */
120 RlvMultiStringSearch();
121 //~RlvMultiStringSearch();
122
123 /*
124 * Public member functions
125 */
126
127 // Add a keyword to the state machine (if it already exists then it will simply overwrite the existing parameter)
128 void addKeyword(const std::string& strKeyword, U16 nParam);
129
130 BOOL getExactMatchParam(const std::string& strText, U16& nParam) const
131 {
132 RlvMultiStringSearchMatch match;
133 if (findFirst(strText, match))
134 {
135 // We have an exact match if the starting index is 0
136 // and the length of the match matches the length of the string
137 if ( (0 == match.idxMatch) && (match.lenMatch == (int)strText.length()) )
138 {
139 nParam = match.nParam;
140 return TRUE;
141 }
142 }
143
144 return FALSE; // Fall-through: no (exact) match
145 }
146
147 // Finds the first occurance of any keyword in the supplied string
148 bool findFirst(const std::string& strText, RlvMultiStringSearchMatch& match) const;
149 // Finds the next occurance of any keyword in the supplied string
150 bool findNext(const std::string& strText, int idxCh, RlvMultiStringSearchMatch& match) const;
151 // Finds all occurances of any keyword in the supplied string
152 std::vector<RlvMultiStringSearchMatch> findAll(const std::string& strText);
153 // Finds the last occurance of any keyword in the supplied string (non-optimized)
154 bool findLast(const std::string& strText, RlvMultiStringSearchMatch& match) const;
155
156protected:
157 // Finds the next occurance of any keyword in the supplied string
158 bool findNext(const char* pstrText, int idxCh, int cntCh, RlvMultiStringSearchMatch& match, bool fWordMatch = true) const;
159
160 /*
161 * Member variables
162 */
163 RlvMultiStringSearchFSM_STL<U32> m_FSM; // Our finite state machine (4 bytes * 256 = 1Kb of memory/state)
164 // HIWORD(U32) = 16-bits of user data
165 // LOWORD(U32) = ABBBBBBBBBBBBBBB
166 // A = termination bit
167 // If (set) and (B == 0): match
168 // If (set) and (B != 0): match, but might only be a substring of another keyword
169 // B = next state (0..32767)
170 // If (B == 0): false lead -> backtrack
171 // If (B != 0): partial keyword match, next state
172 size_t m_cntState; // The number of states in the FSM (= the number of *used* rows in the array)
173};
174
175// ============================================================================
176// Inlined member functions
177//
178
179inline bool RlvMultiStringSearch::findFirst(const std::string& strText, RlvMultiStringSearchMatch& match) const
180{
181 return findNext(strText.c_str(), 0, strText.length(), match);
182}
183
184inline bool RlvMultiStringSearch::findNext(const std::string& strText, int idxCh, RlvMultiStringSearchMatch& match) const
185{
186 return findNext(strText.c_str(), idxCh, strText.length(), match);
187}
188
189// ============================================================================
190
191#endif // RLV_MULTISTRINGSEARCH_H
diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_rlv_behaviour.xml b/linden/indra/newview/skins/default/xui/en-us/floater_rlv_behaviour.xml
new file mode 100644
index 0000000..d9e70e6
--- /dev/null
+++ b/linden/indra/newview/skins/default/xui/en-us/floater_rlv_behaviour.xml
@@ -0,0 +1,11 @@
1<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
2<floater can_close="true" can_drag_on_left="false" can_minimize="true" can_resize="true"
3 height="425" min_height="200" min_width="375" name="rlvBehaviours"
4 title="Active RLV Restrictions" width="350">
5 <scroll_list bottom="-400" draw_border="true" draw_heading="true"
6 follows="top|left|bottom|right" height="365" left="15" multi_select="false"
7 name="behaviour_list" right="-15">
8 <column label="Restriction" name="behaviour" width="170" />
9 <column label="Object Name" name="name" width="170" />
10 </scroll_list>
11</floater> \ No newline at end of file