aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden
diff options
context:
space:
mode:
Diffstat (limited to 'linden')
-rw-r--r--linden/indra/llcommon/llchat.h8
-rw-r--r--linden/indra/newview/CMakeLists.txt13
-rw-r--r--linden/indra/newview/app_settings/settings.xml117
-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.cpp59
-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.cpp2
-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.cpp139
-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.cpp800
-rw-r--r--linden/indra/newview/llviewermessage.cpp403
-rw-r--r--linden/indra/newview/llviewerobject.cpp17
-rw-r--r--linden/indra/newview/llviewerobjectlist.cpp26
-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/primbackup.cpp1105
-rw-r--r--linden/indra/newview/primbackup.h132
-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_prim_import.xml5
-rw-r--r--linden/indra/newview/skins/default/xui/en-us/floater_rlv_behaviour.xml11
-rw-r--r--linden/indra/newview/skins/default/xui/en-us/menu_pie_object.xml6
-rw-r--r--linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml51
91 files changed, 10021 insertions, 144 deletions
diff --git a/linden/indra/llcommon/llchat.h b/linden/indra/llcommon/llchat.h
index ec86450..6c75a25 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),
@@ -84,6 +88,10 @@ public:
84 std::string mText; // UTF-8 line of text 88 std::string mText; // UTF-8 line of text
85 std::string mFromName; // agent or object name 89 std::string mFromName; // agent or object name
86 LLUUID mFromID; // agent id or object id 90 LLUUID mFromID; // agent id or object id
91// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
92 BOOL mRlvLocFiltered;
93 BOOL mRlvNamesFiltered;
94// [/RLVa:KB]
87 EChatSourceType mSourceType; 95 EChatSourceType mSourceType;
88 EChatType mChatType; 96 EChatType mChatType;
89 EChatAudible mAudible; 97 EChatAudible mAudible;
diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt
index 6f54a41..bb07922 100644
--- a/linden/indra/newview/CMakeLists.txt
+++ b/linden/indra/newview/CMakeLists.txt
@@ -435,6 +435,12 @@ set(viewer_SOURCE_FILES
435 llxmlrpctransaction.cpp 435 llxmlrpctransaction.cpp
436 noise.cpp 436 noise.cpp
437 pipeline.cpp 437 pipeline.cpp
438 primbackup.cpp
439 rlvhandler.cpp
440 rlvhelper.cpp
441 rlvmultistringsearch.cpp
442 rlvextensions.cpp
443 rlvfloaterbehaviour.cpp
438 ) 444 )
439 445
440set(VIEWER_BINARY_NAME "imprudence-bin" CACHE STRING 446set(VIEWER_BINARY_NAME "imprudence-bin" CACHE STRING
@@ -839,9 +845,16 @@ set(viewer_HEADER_FILES
839 macmain.h 845 macmain.h
840 noise.h 846 noise.h
841 pipeline.h 847 pipeline.h
848 primbackup.h
842 randgauss.h 849 randgauss.h
843 VertexCache.h 850 VertexCache.h
844 VorbisFramework.h 851 VorbisFramework.h
852 rlvevent.h
853 rlvhandler.h
854 rlvhelper.h
855 rlvmultistringsearch.h
856 rlvextensions.h
857 rlvfloaterbehaviour.h
845 ) 858 )
846 859
847source_group("CMake Rules" FILES ViewerInstall.cmake) 860source_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 149eefa..6d2f0c5 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>
@@ -3177,6 +3276,22 @@
3177 <integer>0</integer> 3276 <integer>0</integer>
3178 </array> 3277 </array>
3179 </map> 3278 </map>
3279 <key>FloaterPrimImport</key>
3280 <map>
3281 <key>Comment</key>
3282 <string>Rectangle for import/export</string>
3283 <key>Persist</key>
3284 <integer>1</integer>
3285 <key>Type</key>
3286 <string>Rect</string>
3287 <key>Value</key>
3288 <array>
3289 <integer>0</integer>
3290 <integer>25</integer>
3291 <integer>400</integer>
3292 <integer>0</integer>
3293 </array>
3294 </map>
3180 <key>FloaterRegionInfo</key> 3295 <key>FloaterRegionInfo</key>
3181 <map> 3296 <map>
3182 <key>Comment</key> 3297 <key>Comment</key>
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 7a70316..d73ddb6 100644
--- a/linden/indra/newview/llagent.cpp
+++ b/linden/indra/newview/llagent.cpp
@@ -758,6 +758,9 @@ void LLAgent::movePitch(S32 direction)
758// Does this parcel allow you to fly? 758// Does this parcel allow you to fly?
759BOOL LLAgent::canFly() 759BOOL LLAgent::canFly()
760{ 760{
761// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0c)
762 if (gRlvHandler.hasBehaviour(RLV_BHVR_FLY)) return FALSE;
763// [/RLVa:KB]
761 if (isGodlike()) return TRUE; 764 if (isGodlike()) return TRUE;
762 765
763 LLViewerRegion* regionp = getRegion(); 766 LLViewerRegion* regionp = getRegion();
@@ -797,6 +800,13 @@ void LLAgent::setFlying(BOOL fly)
797 800
798 if (fly) 801 if (fly)
799 { 802 {
803// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0c)
804 if (gRlvHandler.hasBehaviour(RLV_BHVR_FLY))
805 {
806 return;
807 }
808// [/RLVa:KB]
809
800 BOOL was_flying = getFlying(); 810 BOOL was_flying = getFlying();
801 if (!canFly() && !was_flying) 811 if (!canFly() && !was_flying)
802 { 812 {
@@ -4243,6 +4253,13 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_ani
4243 return; 4253 return;
4244 } 4254 }
4245 4255
4256// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
4257 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (mAvatarObject.notNull()) && (mAvatarObject->mIsSitting) )
4258 {
4259 return;
4260 }
4261// [/RLVa:KB]
4262
4246 setControlFlags(AGENT_CONTROL_STAND_UP); // force stand up 4263 setControlFlags(AGENT_CONTROL_STAND_UP); // force stand up
4247 gViewerWindow->getWindow()->resetBusyCount(); 4264 gViewerWindow->getWindow()->resetBusyCount();
4248 4265
@@ -5037,6 +5054,14 @@ BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOO
5037// utility to build a location string 5054// utility to build a location string
5038void LLAgent::buildLocationString(std::string& str) 5055void LLAgent::buildLocationString(std::string& str)
5039{ 5056{
5057// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
5058 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
5059 {
5060 str = rlv_handler_t::cstrHidden;
5061 return;
5062 }
5063// [/RLVa:KB]
5064
5040 const LLVector3& agent_pos_region = getPositionAgent(); 5065 const LLVector3& agent_pos_region = getPositionAgent();
5041 S32 pos_x = S32(agent_pos_region.mV[VX]); 5066 S32 pos_x = S32(agent_pos_region.mV[VX]);
5042 S32 pos_y = S32(agent_pos_region.mV[VY]); 5067 S32 pos_y = S32(agent_pos_region.mV[VY]);
@@ -5919,6 +5944,15 @@ void LLAgent::teleportRequest(
5919// Landmark ID = LLUUID::null means teleport home 5944// Landmark ID = LLUUID::null means teleport home
5920void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) 5945void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id)
5921{ 5946{
5947// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d)
5948 if ( (rlv_handler_t::isEnabled()) &&
5949 ( (gRlvHandler.hasBehaviour("tplm")) ||
5950 ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (mAvatarObject.notNull()) && (mAvatarObject->mIsSitting)) ))
5951 {
5952 return;
5953 }
5954// [/RLVa:KB]
5955
5922 LLViewerRegion *regionp = getRegion(); 5956 LLViewerRegion *regionp = getRegion();
5923 if(regionp && teleportCore()) 5957 if(regionp && teleportCore())
5924 { 5958 {
@@ -5983,6 +6017,17 @@ void LLAgent::teleportCancel()
5983 6017
5984void LLAgent::teleportViaLocation(const LLVector3d& pos_global) 6018void LLAgent::teleportViaLocation(const LLVector3d& pos_global)
5985{ 6019{
6020// [RLVa:KB] - Alternate: Snowglobe-1.0 | Checked: 2009-07-07 (RLVa-1.0.0d)
6021 // If we're getting teleported due to @tpto we should disregard any @tploc=n or @unsit=n restrictions from the same object
6022 if ( (rlv_handler_t::isEnabled()) &&
6023 ( (gRlvHandler.hasBehaviourExcept("tploc", gRlvHandler.getCurrentObject())) ||
6024 ( (mAvatarObject.notNull()) && (mAvatarObject->mIsSitting) &&
6025 (gRlvHandler.hasBehaviourExcept(RLV_BHVR_UNSIT, gRlvHandler.getCurrentObject()))) ) )
6026 {
6027 return;
6028 }
6029// [/RLVa:KB]
6030
5986 LLViewerRegion* regionp = getRegion(); 6031 LLViewerRegion* regionp = getRegion();
5987 LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); 6032 LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global);
5988 if(regionp && info) 6033 if(regionp && info)
@@ -6057,6 +6102,13 @@ void LLAgent::setTeleportState(ETeleportState state)
6057 // We're outa here. Save "back" slurl. 6102 // We're outa here. Save "back" slurl.
6058 mTeleportSourceSLURL = getSLURL(); 6103 mTeleportSourceSLURL = getSLURL();
6059 } 6104 }
6105
6106// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.0b
6107 if ( (rlv_handler_t::isEnabled()) && (TELEPORT_NONE == mTeleportState) )
6108 {
6109 gRlvHandler.setCanCancelTp(true);
6110 }
6111// [/RLVa:KB]
6060} 6112}
6061 6113
6062void LLAgent::stopCurrentAnimations() 6114void LLAgent::stopCurrentAnimations()
@@ -6684,10 +6736,17 @@ void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void
6684 } 6736 }
6685 6737
6686 // now that we have the asset ids...request the wearable assets 6738 // now that we have the asset ids...request the wearable assets
6739// [RLVa:KB] - Checked: 2009-08-08 (RLVa-1.0.1g) | Added: RLVa-1.0.1g
6740 LLInventoryFetchObserver::item_ref_t rlvItems;
6741// [/RLVa:KB]
6687 for( i = 0; i < WT_COUNT; i++ ) 6742 for( i = 0; i < WT_COUNT; i++ )
6688 { 6743 {
6689 if( !gAgent.mWearableEntry[i].mItemID.isNull() ) 6744 if( !gAgent.mWearableEntry[i].mItemID.isNull() )
6690 { 6745 {
6746// [RLVa:KB] - Checked: 2009-08-08 (RLVa-1.0.1g) | Added: RLVa-1.0.1g
6747 if (rlv_handler_t::isEnabled())
6748 rlvItems.push_back(gAgent.mWearableEntry[i].mItemID);
6749// [/RLVa:KB]
6691 gWearableList.getAsset( 6750 gWearableList.getAsset(
6692 asset_id_array[i], 6751 asset_id_array[i],
6693 LLStringUtil::null, 6752 LLStringUtil::null,
@@ -6695,6 +6754,15 @@ void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void
6695 LLAgent::onInitialWearableAssetArrived, (void*)(intptr_t)i ); 6754 LLAgent::onInitialWearableAssetArrived, (void*)(intptr_t)i );
6696 } 6755 }
6697 } 6756 }
6757
6758// [RLVa:KB] - Checked: 2009-08-08 (RLVa-1.0.1g) | Added: RLVa-1.0.1g
6759 // TODO-RLVa: checking that we're in STATE_STARTED is probably not needed, but leave it until we can be absolutely sure
6760 if ( (rlv_handler_t::isEnabled()) && (LLStartUp::getStartupState() == STATE_STARTED) )
6761 {
6762 RlvCurrentlyWorn f;
6763 f.fetchItems(rlvItems);
6764 }
6765// [/RLVa:KB]
6698 } 6766 }
6699} 6767}
6700 6768
@@ -7192,6 +7260,13 @@ void LLAgent::removeWearable( EWearableType type )
7192 return; 7260 return;
7193 } 7261 }
7194 7262
7263// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d)
7264 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isRemovable(type)) )
7265 {
7266 return;
7267 }
7268// [/RLVa:KB]
7269
7195 if( old_wearable ) 7270 if( old_wearable )
7196 { 7271 {
7197 if( old_wearable->isDirty() ) 7272 if( old_wearable->isDirty() )
@@ -7314,15 +7389,17 @@ void LLAgent::setWearableOutfit(
7314 wearables_to_remove[WT_SKIN] = FALSE; 7389 wearables_to_remove[WT_SKIN] = FALSE;
7315 wearables_to_remove[WT_HAIR] = FALSE; 7390 wearables_to_remove[WT_HAIR] = FALSE;
7316 wearables_to_remove[WT_EYES] = FALSE; 7391 wearables_to_remove[WT_EYES] = FALSE;
7317 wearables_to_remove[WT_SHIRT] = remove; 7392// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.2a
7318 wearables_to_remove[WT_PANTS] = remove; 7393 wearables_to_remove[WT_SHIRT] = remove && gRlvHandler.isRemovable(WT_SHIRT);
7319 wearables_to_remove[WT_SHOES] = remove; 7394 wearables_to_remove[WT_PANTS] = remove && gRlvHandler.isRemovable(WT_PANTS);
7320 wearables_to_remove[WT_SOCKS] = remove; 7395 wearables_to_remove[WT_SHOES] = remove && gRlvHandler.isRemovable(WT_SHOES);
7321 wearables_to_remove[WT_JACKET] = remove; 7396 wearables_to_remove[WT_SOCKS] = remove && gRlvHandler.isRemovable(WT_SOCKS);
7322 wearables_to_remove[WT_GLOVES] = remove; 7397 wearables_to_remove[WT_JACKET] = remove && gRlvHandler.isRemovable(WT_JACKET);
7323 wearables_to_remove[WT_UNDERSHIRT] = (!gAgent.isTeen()) & remove; 7398 wearables_to_remove[WT_GLOVES] = remove && gRlvHandler.isRemovable(WT_GLOVES);
7324 wearables_to_remove[WT_UNDERPANTS] = (!gAgent.isTeen()) & remove; 7399 wearables_to_remove[WT_UNDERSHIRT] = (!gAgent.isTeen()) && remove && gRlvHandler.isRemovable(WT_UNDERSHIRT);
7325 wearables_to_remove[WT_SKIRT] = remove; 7400 wearables_to_remove[WT_UNDERPANTS] = (!gAgent.isTeen()) && remove && gRlvHandler.isRemovable(WT_UNDERPANTS);
7401 wearables_to_remove[WT_SKIRT] = remove && gRlvHandler.isRemovable(WT_SKIRT);
7402// [/RLVa:KB]
7326 7403
7327 S32 count = wearables.count(); 7404 S32 count = wearables.count();
7328 llassert( items.count() == count ); 7405 llassert( items.count() == count );
@@ -7414,6 +7491,15 @@ void LLAgent::setWearable( LLInventoryItem* new_item, LLWearable* new_wearable )
7414 EWearableType type = new_wearable->getType(); 7491 EWearableType type = new_wearable->getType();
7415 7492
7416 LLWearable* old_wearable = mWearableEntry[ type ].mWearable; 7493 LLWearable* old_wearable = mWearableEntry[ type ].mWearable;
7494
7495// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d)
7496 // Block if: we can't wear on that layer; or we're already wearing something there we can't take off
7497 if ( (rlv_handler_t::isEnabled()) && ((!gRlvHandler.isWearable(type)) || ((old_wearable) && (!gRlvHandler.isRemovable(type)))) )
7498 {
7499 return;
7500 }
7501// [/RLVa:KB]
7502
7417 if( old_wearable ) 7503 if( old_wearable )
7418 { 7504 {
7419 const LLUUID& old_item_id = mWearableEntry[ type ].mItemID; 7505 const LLUUID& old_item_id = mWearableEntry[ type ].mItemID;
@@ -7622,10 +7708,13 @@ void LLAgent::userRemoveAllAttachments( void* userdata )
7622 return; 7708 return;
7623 } 7709 }
7624 7710
7625 gMessageSystem->newMessage("ObjectDetach"); 7711// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.0c
7626 gMessageSystem->nextBlockFast(_PREHASH_AgentData); 7712 // NOTE-RLVa: This function is called from inside RlvHandler as well, hence the rather heavy modifications
7627 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); 7713 std::list<U32> rlvAttachments;
7628 gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); 7714 // TODO-RLVa: Once we have the improved "removeWearable" logic implemented we can just get rid of the whole "rlvCompFolders" hassle
7715 #ifdef RLV_EXPERIMENTAL_COMPOSITES
7716 std::list<LLUUID> rlvCompFolders;
7717 #endif // RLV_EXPERIMENTAL_COMPOSITES
7629 7718
7630 for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); 7719 for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
7631 iter != avatarp->mAttachmentPoints.end(); ) 7720 iter != avatarp->mAttachmentPoints.end(); )
@@ -7635,11 +7724,78 @@ void LLAgent::userRemoveAllAttachments( void* userdata )
7635 LLViewerObject* objectp = attachment->getObject(); 7724 LLViewerObject* objectp = attachment->getObject();
7636 if (objectp) 7725 if (objectp)
7637 { 7726 {
7727 if (rlv_handler_t::isEnabled())
7728 {
7729 if (!gRlvHandler.isDetachable(curiter->first))
7730 continue;
7731
7732 // Check if we're being called in response to an RLV command (that would be @detach=force)
7733 if ( (gRlvHandler.getCurrentCommand()) && (attachment->getItemID().notNull()) )
7734 {
7735 if (!gRlvHandler.isStrippable(attachment->getItemID())) // "nostrip" can be taken off by the user but not @detach
7736 continue;
7737
7738 #ifdef RLV_EXPERIMENTAL_COMPOSITES
7739 LLViewerInventoryCategory* pFolder;
7740 if (gRlvHandler.getCompositeInfo(attachment->getItemID(), NULL, &pFolder))
7741 {
7742 #ifdef RLV_EXPERIMENTAL_COMPOSITE_LOCKING
7743 if (!gRlvHandler.canTakeOffComposite(pFolder))
7744 continue;
7745 #endif // RLV_EXPERIMENTAL_COMPOSITE_LOCKING
7746
7747 // The attachment belongs to a composite folder so there may be additional things we need to take off
7748 if (std::find(rlvCompFolders.begin(), rlvCompFolders.end(), pFolder->getUUID()) != rlvCompFolders.end())
7749 rlvCompFolders.push_back(pFolder->getUUID());
7750 }
7751 #endif // RLV_EXPERIMENTAL_COMPOSITES
7752 }
7753 }
7754 rlvAttachments.push_back(objectp->getLocalID());
7755 }
7756 }
7757
7758 // Only send the message if we actually have something to detach
7759 if (rlvAttachments.size() > 0)
7760 {
7761 gMessageSystem->newMessage("ObjectDetach");
7762 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
7763 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
7764 gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
7765
7766 for (std::list<U32>::const_iterator itAttach = rlvAttachments.begin(); itAttach != rlvAttachments.end(); ++itAttach)
7767 {
7638 gMessageSystem->nextBlockFast(_PREHASH_ObjectData); 7768 gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
7639 gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID()); 7769 gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, *itAttach);
7640 } 7770 }
7771
7772 gMessageSystem->sendReliable( gAgent.getRegionHost() );
7641 } 7773 }
7642 gMessageSystem->sendReliable( gAgent.getRegionHost() ); 7774
7775 #ifdef RLV_EXPERIMENTAL_COMPOSITES
7776 if (rlv_handler_t::isEnabled)
7777 {
7778 // If we encountered any composite folders then we need to @detach all of them
7779 for (std::list<LLUUID>::const_iterator itFolder = rlvCompFolders.begin(); itFolder != rlvCompFolders.end(); ++itFolder)
7780 {
7781 std::string strFolder = gRlvHandler.getSharedPath(*itFolder);
7782
7783 // It shouldn't happen but make absolutely sure that we don't issue @detach:=force and reenter this function
7784 if (!strFolder.empty())
7785 {
7786 std::string strCmd = "detach:" + strFolder + "=force";
7787 #ifdef RLV_DEBUG
7788 RLV_INFOS << "\t- detaching composite folder: @" << strCmd << LL_ENDL;
7789 #endif // RLV_DEBUG
7790
7791 // HACK-RLV: executing a command while another command is currently executing isn't the best thing to do, however
7792 // in this specific case it is safe (and still better than making processForceCommand public)
7793 gRlvHandler.processCommand(gRlvHandler.getCurrentObject(), strCmd);
7794 }
7795 }
7796 }
7797 #endif // RLV_EXPERIMENTAL_COMPOSITES
7798// [/RLVa:KB]
7643} 7799}
7644 7800
7645void LLAgent::observeFriends() 7801void LLAgent::observeFriends()
diff --git a/linden/indra/newview/llagent.h b/linden/indra/newview/llagent.h
index 0b8463f..d6854e4 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 0f1bfb4..ab4d8a9 100644
--- a/linden/indra/newview/llappviewer.cpp
+++ b/linden/indra/newview/llappviewer.cpp
@@ -3834,4 +3834,21 @@ void LLAppViewer::handleLoginComplete()
3834 gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState(); 3834 gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
3835 } 3835 }
3836 writeDebugInfo(); 3836 writeDebugInfo();
3837
3838// [RLVa:KB] - Alternate: Snowglobe-1.0 | Checked: 2009-08-05 (RLVa-1.0.1e) | Modified: RLVa-1.0.1e
3839 // TODO-RLVa: find some way to initialize the lookup table when we need them *and* support toggling RLVa at runtime
3840 gRlvHandler.initLookupTables();
3841
3842 if (rlv_handler_t::isEnabled())
3843 {
3844 RlvCurrentlyWorn::fetchWorn();
3845 rlv_handler_t::fetchSharedInventory();
3846
3847 #ifdef RLV_EXTENSION_STARTLOCATION
3848 RlvSettings::updateLoginLastLocation();
3849 #endif // RLV_EXTENSION_STARTLOCATION
3850
3851 gRlvHandler.processRetainedCommands();
3852 }
3853// [/RLVa:KB]
3837} 3854}
diff --git a/linden/indra/newview/llchatbar.cpp b/linden/indra/newview/llchatbar.cpp
index 1dffae3..1de3690 100644
--- a/linden/indra/newview/llchatbar.cpp
+++ b/linden/indra/newview/llchatbar.cpp
@@ -79,7 +79,10 @@ LLChatBar *gChatBar = NULL;
79 79
80// legacy calllback glue 80// legacy calllback glue
81void toggleChatHistory(void* user_data); 81void toggleChatHistory(void* user_data);
82void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); 82//void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel);
83// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.2a
84void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channel);
85// [/RLVa:KB]
83 86
84 87
85class LLChatBarGestureObserver : public LLGestureManagerObserver 88class LLChatBarGestureObserver : public LLGestureManagerObserver
@@ -516,7 +519,10 @@ void LLChatBar::onInputEditorKeystroke( LLLineEditor* caller, void* userdata )
516 519
517 S32 length = raw_text.length(); 520 S32 length = raw_text.length();
518 521
519 if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences 522 //if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences
523// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d)
524 if ( (length > 0) && (raw_text[0] != '/') && (!gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT)) )
525// [/RLVa:KB]
520 { 526 {
521 gAgent.startTyping(); 527 gAgent.startTyping();
522 } 528 }
@@ -621,6 +627,21 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL
621 utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); 627 utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1);
622 } 628 }
623 629
630// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.0b
631 if ( (0 == channel) && (rlv_handler_t::isEnabled()) )
632 {
633 // Adjust the (public) chat "volume" on chat and gestures (also takes care of playing the proper animation)
634 if ( ((CHAT_TYPE_SHOUT == type) || (CHAT_TYPE_NORMAL == type)) && (gRlvHandler.hasBehaviour("chatnormal")) )
635 type = CHAT_TYPE_WHISPER;
636 else if ( (CHAT_TYPE_SHOUT == type) && (gRlvHandler.hasBehaviour("chatshout")) )
637 type = CHAT_TYPE_NORMAL;
638 else if ( (CHAT_TYPE_WHISPER == type) && (gRlvHandler.hasBehaviour("chatwhisper")) )
639 type = CHAT_TYPE_NORMAL;
640
641 animate &= !gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT);
642 }
643// [/RLVa:KB]
644
624 // Don't animate for chats people can't hear (chat to scripts) 645 // Don't animate for chats people can't hear (chat to scripts)
625 if (animate && (channel == 0)) 646 if (animate && (channel == 0))
626 { 647 {
@@ -656,8 +677,57 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL
656 send_chat_from_viewer(utf8_out_text, type, channel); 677 send_chat_from_viewer(utf8_out_text, type, channel);
657} 678}
658 679
659void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) 680// void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel)
681// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.2a
682void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channel)
683// [/RLVa:KB]
660{ 684{
685// [RLVa:KB] - Checked: 2009-08-05 (RLVa-1.0.1e) | Modified: RLVa-1.0.1e
686 // Only process chat messages (ie not CHAT_TYPE_START, CHAT_TYPE_STOP, etc)
687 if ( (rlv_handler_t::isEnabled()) && ( (CHAT_TYPE_WHISPER == type) || (CHAT_TYPE_NORMAL == type) || (CHAT_TYPE_SHOUT == type) ) )
688 {
689 if (0 == channel)
690 {
691 // (We already did this before, but LLChatHandler::handle() calls this directly)
692 if ( ((CHAT_TYPE_SHOUT == type) || (CHAT_TYPE_NORMAL == type)) && (gRlvHandler.hasBehaviour("chatnormal")) )
693 type = CHAT_TYPE_WHISPER;
694 else if ( (CHAT_TYPE_SHOUT == type) && (gRlvHandler.hasBehaviour("chatshout")) )
695 type = CHAT_TYPE_NORMAL;
696 else if ( (CHAT_TYPE_WHISPER == type) && (gRlvHandler.hasBehaviour("chatwhisper")) )
697 type = CHAT_TYPE_NORMAL;
698
699 // Redirect chat if needed
700 if ( ( (gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT) || (gRlvHandler.hasBehaviour(RLV_BHVR_REDIREMOTE)) ) &&
701 (gRlvHandler.redirectChatOrEmote(utf8_out_text)) ) )
702 {
703 return;
704 }
705
706 // Filter public chat if sendchat restricted (and filter anything that redirchat didn't redirect)
707 if ( (gRlvHandler.hasBehaviour("sendchat")) || (gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT)) )
708 gRlvHandler.filterChat(utf8_out_text, true);
709 }
710 else
711 {
712 // Don't allow chat on a non-public channel if sendchannel restricted (unless the channel is an exception)
713 if ( (gRlvHandler.hasBehaviour("sendchannel")) && (!gRlvHandler.hasBehaviour("sendchannel", llformat("%d", channel))) )
714 return;
715
716 // Don't allow chat on debug channel if @sendchat, @redirchat or @rediremote restricted (shows as public chat on viewers)
717 if (channel >= CHAT_CHANNEL_DEBUG)
718 {
719 bool fIsEmote = rlvIsEmote(utf8_out_text);
720 if ( (gRlvHandler.hasBehaviour("sendchat")) ||
721 ((!fIsEmote) && (gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT))) ||
722 ((fIsEmote) && (gRlvHandler.hasBehaviour(RLV_BHVR_REDIREMOTE))) )
723 {
724 return;
725 }
726 }
727 }
728 }
729// [/RLVa:KB]
730
661 LLMessageSystem* msg = gMessageSystem; 731 LLMessageSystem* msg = gMessageSystem;
662 msg->newMessageFast(_PREHASH_ChatFromViewer); 732 msg->newMessageFast(_PREHASH_ChatFromViewer);
663 msg->nextBlockFast(_PREHASH_AgentData); 733 msg->nextBlockFast(_PREHASH_AgentData);
diff --git a/linden/indra/newview/llfloaterabout.cpp b/linden/indra/newview/llfloaterabout.cpp
index 0954a70..57c5339 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 d0713bc..1f51a21 100644
--- a/linden/indra/newview/llfloaterchat.cpp
+++ b/linden/indra/newview/llfloaterchat.cpp
@@ -202,7 +202,10 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4&
202 // If the msg is from an agent (not yourself though), 202 // If the msg is from an agent (not yourself though),
203 // extract out the sender name and replace it with the hotlinked name. 203 // extract out the sender name and replace it with the hotlinked name.
204 if (chat.mSourceType == CHAT_SOURCE_AGENT && 204 if (chat.mSourceType == CHAT_SOURCE_AGENT &&
205 chat.mFromID != LLUUID::null) 205 chat.mFromID != LLUUID::null &&
206// [RLVa] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e)
207 (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) )
208// [/RLVa]
206 { 209 {
207 chat.mURL = llformat("secondlife:///app/agent/%s/about",chat.mFromID.asString().c_str()); 210 chat.mURL = llformat("secondlife:///app/agent/%s/about",chat.mFromID.asString().c_str());
208 } 211 }
@@ -261,6 +264,30 @@ void LLFloaterChat::toggleHistoryChannelControl()
261// static 264// static
262void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) 265void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
263{ 266{
267// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
268 if (rlv_handler_t::isEnabled())
269 {
270 // TODO-RLVa: we might cast too broad a net by filtering here, needs testing
271 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) && (!chat.mRlvLocFiltered) && (CHAT_SOURCE_AGENT != chat.mSourceType) )
272 {
273 LLChat& rlvChat = const_cast<LLChat&>(chat);
274 gRlvHandler.filterLocation(rlvChat.mText);
275 rlvChat.mRlvLocFiltered = TRUE;
276 }
277 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!chat.mRlvNamesFiltered) )
278 {
279 // NOTE: this will also filter inventory accepted/declined text in the chat history
280 LLChat& rlvChat = const_cast<LLChat&>(chat);
281 if (CHAT_SOURCE_AGENT != chat.mSourceType)
282 {
283 // Filter object and system chat (names are filtered elsewhere to save ourselves an gObjectList lookup)
284 gRlvHandler.filterNames(rlvChat.mText);
285 }
286 rlvChat.mRlvNamesFiltered = TRUE;
287 }
288 }
289// [/RLVa:KB]
290
264 if ( gSavedPerAccountSettings.getBOOL("LogChat") && log_to_file) 291 if ( gSavedPerAccountSettings.getBOOL("LogChat") && log_to_file)
265 { 292 {
266 log_chat_text(chat); 293 log_chat_text(chat);
@@ -391,6 +418,30 @@ void LLFloaterChat::addChat(const LLChat& chat,
391 chat.mChatType == CHAT_TYPE_DEBUG_MSG 418 chat.mChatType == CHAT_TYPE_DEBUG_MSG
392 && !gSavedSettings.getBOOL("ScriptErrorsAsChat"); 419 && !gSavedSettings.getBOOL("ScriptErrorsAsChat");
393 420
421// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
422 if (rlv_handler_t::isEnabled())
423 {
424 // TODO-RLVa: we might cast too broad a net by filtering here, needs testing
425 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) && (!chat.mRlvLocFiltered) && (CHAT_SOURCE_AGENT != chat.mSourceType) )
426 {
427 LLChat& rlvChat = const_cast<LLChat&>(chat);
428 if (!from_instant_message)
429 gRlvHandler.filterLocation(rlvChat.mText);
430 rlvChat.mRlvLocFiltered = TRUE;
431 }
432 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!chat.mRlvNamesFiltered) )
433 {
434 LLChat& rlvChat = const_cast<LLChat&>(chat);
435 if ( (!from_instant_message) && (CHAT_SOURCE_AGENT != chat.mSourceType) )
436 {
437 // Filter object and system chat (names are filtered elsewhere to save ourselves an gObjectList lookup)
438 gRlvHandler.filterNames(rlvChat.mText);
439 }
440 rlvChat.mRlvNamesFiltered = TRUE;
441 }
442 }
443// [/RLVa:KB]
444
394#if LL_LCD_COMPILE 445#if LL_LCD_COMPILE
395 // add into LCD displays 446 // add into LCD displays
396 if (!invisible_script_debug_chat) 447 if (!invisible_script_debug_chat)
@@ -548,7 +599,11 @@ void LLFloaterChat::onClickToggleActiveSpeakers(void* userdata)
548{ 599{
549 LLFloaterChat* self = (LLFloaterChat*)userdata; 600 LLFloaterChat* self = (LLFloaterChat*)userdata;
550 601
551 self->childSetVisible("active_speakers_panel", !self->childIsVisible("active_speakers_panel")); 602// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
603 self->childSetVisible("active_speakers_panel",
604 (!self->childIsVisible("active_speakers_panel")) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) );
605// [/RLVa:KB]
606 //self->childSetVisible("active_speakers_panel", !self->childIsVisible("active_speakers_panel"));
552} 607}
553 608
554//static 609//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 914513b..9936f3b 100644
--- a/linden/indra/newview/llfloaterwindlight.cpp
+++ b/linden/indra/newview/llfloaterwindlight.cpp
@@ -322,12 +322,14 @@ void LLFloaterWindLight::syncMenu()
322 LLWLParamSet& currentParams = param_mgr->mCurParams; 322 LLWLParamSet& currentParams = param_mgr->mCurParams;
323 //std::map<std::string, LLVector4> & currentParams = param_mgr->mCurParams.mParamValues; 323 //std::map<std::string, LLVector4> & currentParams = param_mgr->mCurParams.mParamValues;
324 324
325// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
325 // Fixes LL "bug" (preset name isn't kept synchronized) 326 // Fixes LL "bug" (preset name isn't kept synchronized)
326 LLComboBox* comboBox = getChild<LLComboBox>("WLPresetsCombo"); 327 LLComboBox* comboBox = getChild<LLComboBox>("WLPresetsCombo");
327 if (comboBox->getSelectedItemLabel() != currentParams.mName) 328 if (comboBox->getSelectedItemLabel() != currentParams.mName)
328 { 329 {
329 comboBox->setSimple(currentParams.mName); 330 comboBox->setSimple(currentParams.mName);
330 } 331 }
332// [/RLVa:KB]
331 333
332 // blue horizon 334 // blue horizon
333 param_mgr->mBlueHorizon = currentParams.getVector(param_mgr->mBlueHorizon.mName, err); 335 param_mgr->mBlueHorizon = currentParams.getVector(param_mgr->mBlueHorizon.mName, err);
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 16b0388..014c050 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 3505bd3..19a5ade 100644
--- a/linden/indra/newview/llinventorybridge.cpp
+++ b/linden/indra/newview/llinventorybridge.cpp
@@ -1923,6 +1923,12 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
1923 LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); 1923 LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
1924 LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); 1924 LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
1925 1925
1926// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
1927 // Fixes LL bug
1928 mItems.clear();
1929 mDisabledItems.clear();
1930// [/RLVa:KB]
1931
1926 if (lost_and_found_id == mUUID) 1932 if (lost_and_found_id == mUUID)
1927 { 1933 {
1928 // This is the lost+found folder. 1934 // This is the lost+found folder.
@@ -2936,6 +2942,13 @@ void open_notecard(LLViewerInventoryItem* inv_item,
2936 const LLUUID& source_id, 2942 const LLUUID& source_id,
2937 BOOL take_focus) 2943 BOOL take_focus)
2938{ 2944{
2945// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
2946 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour("viewnote")) )
2947 {
2948 return;
2949 }
2950// [/RLVa:KB]
2951
2939 // See if we can bring an existing preview to the front 2952 // See if we can bring an existing preview to the front
2940 if(!LLPreview::show(inv_item->getUUID(), take_focus)) 2953 if(!LLPreview::show(inv_item->getUUID(), take_focus))
2941 { 2954 {
@@ -3261,7 +3274,14 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model
3261 item = (LLViewerInventoryItem*)gInventory.getItem(object_id); 3274 item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
3262 if(item && gInventory.isObjectDescendentOf(object_id, gAgent.getInventoryRootID())) 3275 if(item && gInventory.isObjectDescendentOf(object_id, gAgent.getInventoryRootID()))
3263 { 3276 {
3264 rez_attachment(item, NULL); 3277// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
3278 // User picked "Wear" so either nothing is locked, or we need to look up the specific attach point from its name
3279 // (NOTE: rez_attachment will take care of deciding whether or not we *can* attach)
3280 rez_attachment(item,
3281 ((!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedAttachment()) || (RlvSettings::getEnableWear()))
3282 ? NULL : gRlvHandler.getAttachPoint(item, true));
3283// [/RLVa:KB]
3284// rez_attachment(item, NULL);
3265 } 3285 }
3266 else if(item && item->isComplete()) 3286 else if(item && item->isComplete())
3267 { 3287 {
@@ -3280,6 +3300,15 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model
3280 else if ("detach" == action) 3300 else if ("detach" == action)
3281 { 3301 {
3282 LLInventoryItem* item = gInventory.getItem(mUUID); 3302 LLInventoryItem* item = gInventory.getItem(mUUID);
3303
3304// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
3305 // Fall-through: if there's a "Detach from yourself" code path we missed then we'll still disallow the detach here
3306 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(item)) )
3307 {
3308 return;
3309 }
3310// [/RLVa:KB]
3311
3283 if( item ) 3312 if( item )
3284 { 3313 {
3285 gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); 3314 gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
@@ -3369,11 +3398,24 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach
3369 rez_action->mAttachPt = attach_pt; 3398 rez_action->mAttachPt = attach_pt;
3370 if (attachment && attachment->getObject()) 3399 if (attachment && attachment->getObject())
3371 { 3400 {
3372 gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action); 3401// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c)
3402 if ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isDetachable(attach_pt)) )
3403 gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action);
3404 else
3405 delete rez_action;
3406// [/RLVa]
3407// gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action);
3373 } 3408 }
3374 else 3409 else
3375 { 3410 {
3376 confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action); 3411// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c)
3412 // Don't allow wear to default attach point if there are any locked attachments
3413 if ( (!rlv_handler_t::isEnabled()) || (0 != attach_pt) || (!gRlvHandler.hasLockedAttachment()) || (RlvSettings::getEnableWear()) )
3414 confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action);
3415 else
3416 delete rez_action;
3417// [/RLVa]
3418// confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action);
3377 } 3419 }
3378} 3420}
3379 3421
@@ -3442,6 +3484,11 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
3442 if( avatarp->isWearingAttachment( mUUID ) ) 3484 if( avatarp->isWearingAttachment( mUUID ) )
3443 { 3485 {
3444 items.push_back(std::string("Detach From Yourself")); 3486 items.push_back(std::string("Detach From Yourself"));
3487
3488// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
3489 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(item)) )
3490 disabled_items.push_back(std::string("Detach From Yourself"));
3491// [/RLVa:KB]
3445 } 3492 }
3446 else 3493 else
3447 if( !isInTrash() ) 3494 if( !isInTrash() )
@@ -3453,6 +3500,16 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
3453 items.push_back(std::string("RestoreToWorld Separator")); 3500 items.push_back(std::string("RestoreToWorld Separator"));
3454 items.push_back(std::string("Restore to Last Position")); 3501 items.push_back(std::string("Restore to Last Position"));
3455 3502
3503// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0c
3504 // Only enable "Wear" if there is an attach point name *and* there isn't a worn attachment there that's currently locked
3505 if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getEnableWear()) && (gRlvHandler.hasLockedAttachment()) )
3506 {
3507 LLViewerJointAttachment* pAttachPt = gRlvHandler.getAttachPoint(item, true);
3508 if ( (!pAttachPt) || (!gRlvHandler.isDetachable(pAttachPt->getObject())) )
3509 disabled_items.push_back(std::string("Object Wear"));
3510 }
3511// [/RLVa:KB]
3512
3456 LLMenuGL* attach_menu = menu.getChildMenuByName("Attach To", TRUE); 3513 LLMenuGL* attach_menu = menu.getChildMenuByName("Attach To", TRUE);
3457 LLMenuGL* attach_hud_menu = menu.getChildMenuByName("Attach To HUD", TRUE); 3514 LLMenuGL* attach_hud_menu = menu.getChildMenuByName("Attach To HUD", TRUE);
3458 LLVOAvatar *avatarp = gAgent.getAvatarObject(); 3515 LLVOAvatar *avatarp = gAgent.getAvatarObject();
@@ -3468,15 +3525,27 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
3468 LLMenuItemCallGL *new_item; 3525 LLMenuItemCallGL *new_item;
3469 if (attachment->getIsHUDAttachment()) 3526 if (attachment->getIsHUDAttachment())
3470 { 3527 {
3528// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
3471 attach_hud_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(), 3529 attach_hud_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(),
3472 NULL, //&LLObjectBridge::attachToAvatar, 3530 NULL, //&LLObjectBridge::attachToAvatar,
3473 NULL, &attach_label, (void*)attachment)); 3531 (rlv_handler_t::isEnabled()) ? &rlvAttachToEnabler : NULL,
3532 &attach_label, (void*)attachment));
3533// [/RLVa:KB]
3534 //attach_hud_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(),
3535 // NULL, //&LLObjectBridge::attachToAvatar,
3536 // NULL, &attach_label, (void*)attachment));
3474 } 3537 }
3475 else 3538 else
3476 { 3539 {
3540// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
3477 attach_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(), 3541 attach_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(),
3478 NULL, //&LLObjectBridge::attachToAvatar, 3542 NULL, //&LLObjectBridge::attachToAvatar,
3479 NULL, &attach_label, (void*)attachment)); 3543 (rlv_handler_t::isEnabled()) ? &rlvAttachToEnabler : NULL,
3544 &attach_label, (void*)attachment));
3545// [/RLVa:KB]
3546 //attach_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(),
3547 // NULL, //&LLObjectBridge::attachToAvatar,
3548 // NULL, &attach_label, (void*)attachment));
3480 } 3549 }
3481 3550
3482 LLSimpleListener* callback = mInventoryPanel->getListenerByName("Inventory.AttachObject"); 3551 LLSimpleListener* callback = mInventoryPanel->getListenerByName("Inventory.AttachObject");
@@ -3981,6 +4050,20 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata )
3981 is_gesture); 4050 is_gesture);
3982 S32 gest_count = gest_item_array.count(); 4051 S32 gest_count = gest_item_array.count();
3983 4052
4053// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-1.0.0c
4054 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) && (!RlvSettings::getEnableWear()) )
4055 {
4056 // Filter anything that doesn't specify an attachment point (or that specifies one that's currently locked)
4057 for (S32 idxObj = obj_item_array.count() - 1; idxObj >= 0; idxObj--)
4058 {
4059 LLViewerJointAttachment* pAttachPt = gRlvHandler.getAttachPoint(obj_item_array.get(idxObj).get(), true);
4060 if ( ((!pAttachPt) || (!gRlvHandler.isDetachable(pAttachPt->getObject()))) )
4061 obj_item_array.remove(idxObj);
4062 }
4063 obj_count = obj_item_array.count();
4064 }
4065// [/RLVa:KB]
4066
3984 if( !wearable_count && !obj_count && !gest_count) 4067 if( !wearable_count && !obj_count && !gest_count)
3985 { 4068 {
3986 gViewerWindow->alertXml("CouldNotPutOnOutfit"); 4069 gViewerWindow->alertXml("CouldNotPutOnOutfit");
@@ -4118,6 +4201,13 @@ void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, B
4118// item->setAssetUUID(wearable->getID()); 4201// item->setAssetUUID(wearable->getID());
4119// item->updateAssetOnServer(); 4202// item->updateAssetOnServer();
4120// } 4203// }
4204// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-1.0.0c
4205 if ( (!gRlvHandler.isWearable(wearable->getType())) ||
4206 ( (!gRlvHandler.isRemovable(wearable->getType())) && (gAgent.getWearable(wearable->getType())) ) )
4207 {
4208 continue;
4209 }
4210// [/RLVa:KB]
4121 items.put(item); 4211 items.put(item);
4122 wearables.put(wearable); 4212 wearables.put(wearable);
4123 } 4213 }
@@ -4210,14 +4300,24 @@ void wear_attachments_on_avatar(const LLInventoryModel::item_array_t& items, BOO
4210 msg->nextBlockFast(_PREHASH_HeaderData); 4300 msg->nextBlockFast(_PREHASH_HeaderData);
4211 msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id ); 4301 msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id );
4212 msg->addU8Fast(_PREHASH_TotalObjects, count ); 4302 msg->addU8Fast(_PREHASH_TotalObjects, count );
4213 msg->addBOOLFast(_PREHASH_FirstDetachAll, remove ); 4303// msg->addBOOLFast(_PREHASH_FirstDetachAll, remove );
4214 } 4304// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.2a
4305 // This really should just *always* be FALSE since TRUE can result in loss of the current asset state
4306 msg->addBOOLFast(_PREHASH_FirstDetachAll, remove && (!gRlvHandler.hasLockedAttachment()) );
4307// [/RLVa:KB]
4308 }
4215 4309
4216 LLInventoryItem* item = items.get(i); 4310 LLInventoryItem* item = items.get(i);
4217 msg->nextBlockFast(_PREHASH_ObjectData ); 4311 msg->nextBlockFast(_PREHASH_ObjectData );
4218 msg->addUUIDFast(_PREHASH_ItemID, item->getUUID() ); 4312 msg->addUUIDFast(_PREHASH_ItemID, item->getUUID() );
4219 msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); 4313 msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner());
4220 msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // Wear at the previous or default attachment point 4314// msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // Wear at the previous or default attachment point
4315// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.2a
4316 msg->addU8Fast(_PREHASH_AttachmentPt,
4317 ( (!rlv_handler_t::isEnabled()) || (RlvSettings::getEnableWear()) || (!gRlvHandler.hasLockedAttachment()) )
4318 ? 0
4319 : gRlvHandler.getAttachPointIndex(gRlvHandler.getAttachPoint(item, true)));
4320// [/RLVa:KB]
4221 pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); 4321 pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
4222 msg->addStringFast(_PREHASH_Name, item->getName()); 4322 msg->addStringFast(_PREHASH_Name, item->getName());
4223 msg->addStringFast(_PREHASH_Description, item->getDescription()); 4323 msg->addStringFast(_PREHASH_Description, item->getDescription());
@@ -4299,7 +4399,11 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata)
4299 { 4399 {
4300 for(i = 0; i < wearable_count; ++i) 4400 for(i = 0; i < wearable_count; ++i)
4301 { 4401 {
4302 if( gAgent.isWearingItem (item_array.get(i)->getUUID()) ) 4402// if( gAgent.isWearingItem (item_array.get(i)->getUUID()) )
4403// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.2a
4404 LLWearable* pWearable = gAgent.getWearableFromWearableItem(item_array.get(i)->getUUID());
4405 if ( (pWearable) && ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isRemovable(pWearable->getType()))) )
4406// [/RLVa:KB]
4303 { 4407 {
4304 gWearableList.getAsset(item_array.get(i)->getAssetUUID(), 4408 gWearableList.getAsset(item_array.get(i)->getAssetUUID(),
4305 item_array.get(i)->getName(), 4409 item_array.get(i)->getName(),
@@ -4316,6 +4420,18 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata)
4316 { 4420 {
4317 for(i = 0; i < obj_count; ++i) 4421 for(i = 0; i < obj_count; ++i)
4318 { 4422 {
4423// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.2a
4424 // TODO-RLVa: is there a reason why LL doesn't bother checking to see if you're actually wearing the object?
4425 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) )
4426 {
4427 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
4428 if ( (!pAvatar) || (!pAvatar->isWearingAttachment(obj_item_array.get(i)->getUUID())) ||
4429 (!gRlvHandler.isDetachable(obj_item_array.get(i).get())) ) // Why does LLPointer have a cast to BOOL aka S32???
4430 {
4431 continue;
4432 }
4433 }
4434// [/RVLa:KB]
4319 gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); 4435 gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
4320 gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); 4436 gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
4321 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); 4437 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
@@ -4708,8 +4824,11 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
4708 { 4824 {
4709 EWearableType type = wearable->getType(); 4825 EWearableType type = wearable->getType();
4710 4826
4711 if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR ) ) //&& 4827 //if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR ) ) //&&
4712 //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) ) 4828 //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) )
4829// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.2a | SL big fix
4830 if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES) )
4831// [/RLVa:KB]
4713 { 4832 {
4714 gAgent.removeWearable( type ); 4833 gAgent.removeWearable( type );
4715 } 4834 }
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 cc89ee1..a8d5045 100644
--- a/linden/indra/newview/llinventoryview.cpp
+++ b/linden/indra/newview/llinventoryview.cpp
@@ -774,7 +774,17 @@ void LLInventoryView::setVisible( BOOL visible )
774// Destroy all but the last floater, which is made invisible. 774// Destroy all but the last floater, which is made invisible.
775void LLInventoryView::onClose(bool app_quitting) 775void LLInventoryView::onClose(bool app_quitting)
776{ 776{
777 S32 count = sActiveViews.count(); 777// S32 count = sActiveViews.count();
778// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
779 // See LLInventoryView::closeAll() on why we're doing it this way
780 S32 count = 0;
781 for (S32 idx = 0, cnt = sActiveViews.count(); idx < cnt; idx++)
782 {
783 if (!sActiveViews.get(idx)->isDead())
784 count++;
785 }
786// [/RLVa:KB]
787
778 if (count > 1) 788 if (count > 1)
779 { 789 {
780 destroy(); 790 destroy();
@@ -852,6 +862,13 @@ LLInventoryView* LLInventoryView::showAgentInventory(BOOL take_keyboard_focus)
852 return NULL; 862 return NULL;
853 } 863 }
854 864
865// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
866 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWINV))
867 {
868 return NULL;
869 }
870// [/RLVa:KB]
871
855 LLInventoryView* iv = LLInventoryView::getActiveInventory(); 872 LLInventoryView* iv = LLInventoryView::getActiveInventory();
856#if 0 && !LL_RELEASE_FOR_DOWNLOAD 873#if 0 && !LL_RELEASE_FOR_DOWNLOAD
857 if (sActiveViews.count() == 1) 874 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 6b51b3a..12c001e 100644
--- a/linden/indra/newview/lloverlaybar.cpp
+++ b/linden/indra/newview/lloverlaybar.cpp
@@ -266,7 +266,10 @@ void LLOverlayBar::refresh()
266 BOOL sitting = FALSE; 266 BOOL sitting = FALSE;
267 if (gAgent.getAvatarObject()) 267 if (gAgent.getAvatarObject())
268 { 268 {
269 sitting = gAgent.getAvatarObject()->mIsSitting; 269// sitting = gAgent.getAvatarObject()->mIsSitting;
270// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
271 sitting = gAgent.getAvatarObject()->mIsSitting && !gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT);
272// [/RLVa:KB]
270 } 273 }
271 button = getChild<LLButton>("Stand Up"); 274 button = getChild<LLButton>("Stand Up");
272 275
@@ -349,6 +352,13 @@ void LLOverlayBar::onClickMouselook(void*)
349//static 352//static
350void LLOverlayBar::onClickStandUp(void*) 353void LLOverlayBar::onClickStandUp(void*)
351{ 354{
355// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
356 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->mIsSitting) )
357 {
358 return;
359 }
360// [/RLVa:KB]
361
352 LLSelectMgr::getInstance()->deselectAllForStandingUp(); 362 LLSelectMgr::getInstance()->deselectAllForStandingUp();
353 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); 363 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
354} 364}
diff --git a/linden/indra/newview/llpanelavatar.cpp b/linden/indra/newview/llpanelavatar.cpp
index fa1883d..e101ea2 100644
--- a/linden/indra/newview/llpanelavatar.cpp
+++ b/linden/indra/newview/llpanelavatar.cpp
@@ -792,6 +792,9 @@ void LLPanelAvatarClassified::refresh()
792 S32 tab_count = tabs ? tabs->getTabCount() : 0; 792 S32 tab_count = tabs ? tabs->getTabCount() : 0;
793 793
794 bool allow_new = tab_count < MAX_CLASSIFIEDS; 794 bool allow_new = tab_count < MAX_CLASSIFIEDS;
795// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
796 allow_new &= !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC);
797// [/RLVa:KB]
795 bool allow_delete = (tab_count > 0); 798 bool allow_delete = (tab_count > 0);
796 bool show_help = (tab_count == 0); 799 bool show_help = (tab_count == 0);
797 800
@@ -927,6 +930,12 @@ void LLPanelAvatarClassified::processAvatarClassifiedReply(LLMessageSystem* msg,
927// static 930// static
928void LLPanelAvatarClassified::onClickNew(void* data) 931void LLPanelAvatarClassified::onClickNew(void* data)
929{ 932{
933// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-04 (RLVa-1.0.0a)
934 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
935 {
936 return;
937 }
938// [/RLVa:KB]
930 LLPanelAvatarClassified* self = (LLPanelAvatarClassified*)data; 939 LLPanelAvatarClassified* self = (LLPanelAvatarClassified*)data;
931 940
932 gViewerWindow->alertXml("AddClassified",callbackNew,self); 941 gViewerWindow->alertXml("AddClassified",callbackNew,self);
@@ -1023,7 +1032,10 @@ void LLPanelAvatarPicks::refresh()
1023 BOOL self = (gAgent.getID() == getPanelAvatar()->getAvatarID()); 1032 BOOL self = (gAgent.getID() == getPanelAvatar()->getAvatarID());
1024 LLTabContainer* tabs = getChild<LLTabContainer>("picks tab"); 1033 LLTabContainer* tabs = getChild<LLTabContainer>("picks tab");
1025 S32 tab_count = tabs ? tabs->getTabCount() : 0; 1034 S32 tab_count = tabs ? tabs->getTabCount() : 0;
1026 childSetEnabled("New...", self && tab_count < MAX_AVATAR_PICKS); 1035// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
1036 childSetEnabled("New...", self && tab_count < MAX_AVATAR_PICKS && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) );
1037// [/RLVa:KB]
1038 //childSetEnabled("New...", self && tab_count < MAX_AVATAR_PICKS);
1027 childSetEnabled("Delete...", self && tab_count > 0); 1039 childSetEnabled("Delete...", self && tab_count > 0);
1028 childSetVisible("New...", self && getPanelAvatar()->isEditable()); 1040 childSetVisible("New...", self && getPanelAvatar()->isEditable());
1029 childSetVisible("Delete...", self && getPanelAvatar()->isEditable()); 1041 childSetVisible("Delete...", self && getPanelAvatar()->isEditable());
@@ -1101,6 +1113,12 @@ void LLPanelAvatarPicks::processAvatarPicksReply(LLMessageSystem* msg, void**)
1101// static 1113// static
1102void LLPanelAvatarPicks::onClickNew(void* data) 1114void LLPanelAvatarPicks::onClickNew(void* data)
1103{ 1115{
1116// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
1117 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
1118 {
1119 return;
1120 }
1121// [/RLVa:KB]
1104 LLPanelAvatarPicks* self = (LLPanelAvatarPicks*)data; 1122 LLPanelAvatarPicks* self = (LLPanelAvatarPicks*)data;
1105 LLPanelPick* panel_pick = new LLPanelPick(FALSE); 1123 LLPanelPick* panel_pick = new LLPanelPick(FALSE);
1106 LLTabContainer* tabs = self->getChild<LLTabContainer>("picks tab"); 1124 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 308f3df..e3da12a 100644
--- a/linden/indra/newview/llpaneldisplay.cpp
+++ b/linden/indra/newview/llpaneldisplay.cpp
@@ -478,7 +478,12 @@ void LLPanelDisplay::refreshEnabledState()
478 } 478 }
479 479
480 // Vertex Shaders 480 // Vertex Shaders
481 mCtrlShaderEnable->setEnabled(LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable")); 481// mCtrlShaderEnable->setEnabled(LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable"));
482// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0a
483 // "Basic Shaders" can't be disabled - but can be enabled - under @setenv=n
484 bool fCtrlShaderEnable = LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable");
485 mCtrlShaderEnable->setEnabled(fCtrlShaderEnable && (!gRlvHandler.hasBehaviour(RLV_BHVR_SETENV) || !mShaderEnable));
486// [/RLVa:KB]
482 487
483 BOOL shaders = mCtrlShaderEnable->get(); 488 BOOL shaders = mCtrlShaderEnable->get();
484 if (shaders) 489 if (shaders)
@@ -493,7 +498,12 @@ void LLPanelDisplay::refreshEnabledState()
493 498
494 // *HACK just checks to see if we can use shaders... 499 // *HACK just checks to see if we can use shaders...
495 // maybe some cards that use shaders, but don't support windlight 500 // maybe some cards that use shaders, but don't support windlight
496 mCtrlWindLight->setEnabled(mCtrlShaderEnable->getEnabled() && shaders); 501// mCtrlWindLight->setEnabled(mCtrlShaderEnable->getEnabled() && shaders);
502// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0a
503 // "Atmospheric Shaders" can't be disabled - but can be enabled - under @setenv=n
504 bool fCtrlWindLightEnable = fCtrlShaderEnable && shaders;
505 mCtrlWindLight->setEnabled(fCtrlWindLightEnable && (!gRlvHandler.hasBehaviour(RLV_BHVR_SETENV) || !mWindLight));
506// [/RLVa:KB]
497 507
498 // turn off sky detail if atmostpherics isn't on 508 // turn off sky detail if atmostpherics isn't on
499 mCtrlSkyFactor->setEnabled(gSavedSettings.getBOOL("WindLightUseAtmosShaders")); 509 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 439d8b4..24bbab6 100644
--- a/linden/indra/newview/llpanelpermissions.cpp
+++ b/linden/indra/newview/llpanelpermissions.cpp
@@ -327,9 +327,26 @@ void LLPanelPermissions::refresh()
327 } 327 }
328 } 328 }
329 329
330// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
331 bool fRlvEnableOwner = true;
332 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) )
333 {
334 // Only filter the owner name if: the selection is all owned by the same avie and not group owned
335 if ( (owners_identical) && (!LLSelectMgr::getInstance()->selectIsGroupOwned()) )
336 {
337 owner_name = gRlvHandler.getAnonym(owner_name);
338 fRlvEnableOwner = false;
339 }
340 }
341// [/RLVa:KB]
342
330 childSetText("Owner Name",owner_name); 343 childSetText("Owner Name",owner_name);
331 childSetEnabled("Owner Name",TRUE); 344 childSetEnabled("Owner Name",TRUE);
332 childSetEnabled("button owner profile",owners_identical && (mOwnerID.notNull() || LLSelectMgr::getInstance()->selectIsGroupOwned())); 345// childSetEnabled("button owner profile",owners_identical && (mOwnerID.notNull() || LLSelectMgr::getInstance()->selectIsGroupOwned()));
346// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
347 childSetEnabled("button owner profile",
348 fRlvEnableOwner && owners_identical && (mOwnerID.notNull() || LLSelectMgr::getInstance()->selectIsGroupOwned()));
349// [/RLVa:KB]
333 350
334 if (owner_name != last_owner_name) 351 if (owner_name != last_owner_name)
335 { 352 {
@@ -852,7 +869,13 @@ void LLPanelPermissions::onClickOwner(void *data)
852 } 869 }
853 else 870 else
854 { 871 {
855 LLFloaterAvatarInfo::showFromObject(self->mOwnerID); 872// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
873 if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
874 {
875 LLFloaterAvatarInfo::showFromObject(self->mOwnerID);
876 }
877// [/RLVa:KB]
878// LLFloaterAvatarInfo::showFromObject(self->mOwnerID);
856 } 879 }
857} 880}
858 881
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 6115074..5cb14fc 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 f46f104..af97e2e 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 fdc0182..8d5aa9e 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 b660b8d..b32169d 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 ddebd97..8a92963 100644
--- a/linden/indra/newview/llviewermenu.cpp
+++ b/linden/indra/newview/llviewermenu.cpp
@@ -209,6 +209,7 @@
209#include "llwaterparammanager.h" 209#include "llwaterparammanager.h"
210 210
211#include "lltexlayer.h" 211#include "lltexlayer.h"
212#include "primbackup.h"
212 213
213#include "jcfloater_animation_list.h" 214#include "jcfloater_animation_list.h"
214#include "llfloaterassetbrowser.h" 215#include "llfloaterassetbrowser.h"
@@ -222,6 +223,13 @@ void init_debug_ui_menu(LLMenuGL* menu);
222void init_debug_xui_menu(LLMenuGL* menu); 223void init_debug_xui_menu(LLMenuGL* menu);
223void init_debug_avatar_menu(LLMenuGL* menu); 224void init_debug_avatar_menu(LLMenuGL* menu);
224void init_debug_baked_texture_menu(LLMenuGL* menu); 225void init_debug_baked_texture_menu(LLMenuGL* menu);
226// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
227#ifdef RLV_DEBUG_TESTS
228 #include "rlvtest.h"
229#endif // RLV_DEBUG_TESTS
230#include "rlvfloaterbehaviour.h"
231void init_debug_rlva_menu(LLMenuGL* menu);
232// [/RLVa:KB]
225 233
226BOOL enable_land_build(void*); 234BOOL enable_land_build(void*);
227BOOL enable_object_build(void*); 235BOOL enable_object_build(void*);
@@ -828,6 +836,19 @@ void init_client_menu(LLMenuGL* menu)
828 init_debug_world_menu(sub_menu); 836 init_debug_world_menu(sub_menu);
829 menu->appendMenu(sub_menu); 837 menu->appendMenu(sub_menu);
830 838
839// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.1b
840 #ifdef RLV_ADVANCED_MENU
841 if (rlv_handler_t::isEnabled())
842 {
843 sub_menu = new LLMenuGL("RLVa");
844 init_debug_rlva_menu(sub_menu);
845 menu->appendMenu(sub_menu);
846 sub_menu->setVisible(rlv_handler_t::isEnabled());
847 sub_menu->setEnabled(rlv_handler_t::isEnabled());
848 }
849 #endif // RLV_ADVANCED_MENU
850// [/RLVa:KB]
851
831 sub_menu = new LLMenuGL("UI"); 852 sub_menu = new LLMenuGL("UI");
832 init_debug_ui_menu(sub_menu); 853 init_debug_ui_menu(sub_menu);
833 menu->appendMenu(sub_menu); 854 menu->appendMenu(sub_menu);
@@ -922,6 +943,13 @@ void init_client_menu(LLMenuGL* menu)
922 &menu_check_control, 943 &menu_check_control,
923 (void*)"ShowConsoleWindow")); 944 (void*)"ShowConsoleWindow"));
924 945
946// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-1.0.0e
947 #ifdef RLV_ADVANCED_TOGGLE_RLVA
948 if (gSavedSettings.controlExists(RLV_SETTING_MAIN))
949 menu->append(new LLMenuItemCheckGL("Restrained Life API", &rlvDbgToggleEnabled, NULL, &rlvDbgGetEnabled, NULL));
950 #endif // RLV_ADVANCED_TOGGLE_RLVA
951// [/RLVa:KB]
952
925 if(gSavedSettings.getBOOL("QAMode")) 953 if(gSavedSettings.getBOOL("QAMode"))
926 { 954 {
927 LLMenuGL* sub = NULL; 955 LLMenuGL* sub = NULL;
@@ -1369,6 +1397,53 @@ void init_debug_baked_texture_menu(LLMenuGL* menu)
1369 menu->createJumpKeys(); 1397 menu->createJumpKeys();
1370} 1398}
1371 1399
1400// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-1.0.0g
1401void init_debug_rlva_menu(LLMenuGL* menu)
1402{
1403 // Experimental feature toggles
1404 {
1405 /*
1406 #ifdef RLV_EXPERIMENTAL
1407 LLMenuGL* sub_menu = new LLMenuGL("Experimental");
1408
1409 menu->appendMenu(sub_menu);
1410 #endif // RLV_EXPERIMENTAL
1411 */
1412 }
1413
1414 // Unit tests
1415 {
1416 #ifdef RLV_DEBUG_TESTS
1417 init_debug_rlva_tests_menu(menu);
1418 #endif // RLV_DEBUG_TESTS
1419 }
1420
1421 #ifdef RLV_EXTENSION_ENABLE_WEAR
1422 if (gSavedSettings.controlExists(RLV_SETTING_ENABLEWEAR))
1423 {
1424 menu->append(new LLMenuItemCheckGL("Enable Wear", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_ENABLEWEAR));
1425 menu->appendSeparator();
1426 }
1427 #endif // RLV_EXTENSION_ENABLE_WEAR
1428
1429 #ifdef RLV_EXTENSION_HIDELOCKED
1430 if ( (gSavedSettings.controlExists(RLV_SETTING_HIDELOCKEDLAYER)) &&
1431 (gSavedSettings.controlExists(RLV_SETTING_HIDELOCKEDATTACH)) )
1432 {
1433 menu->append(new LLMenuItemCheckGL("Hide locked layers", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_HIDELOCKEDLAYER));
1434 menu->append(new LLMenuItemCheckGL("Hide locked attachments", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_HIDELOCKEDATTACH));
1435 //sub_menu->append(new LLMenuItemToggleGL("Hide locked inventory", &rlv_handler_t::fHideLockedInventory));
1436 menu->appendSeparator();
1437 }
1438 #endif // RLV_EXTENSION_HIDELOCKED
1439
1440 #ifdef RLV_EXTENSION_FLOATER_RESTRICTIONS
1441 // TODO-RLVa: figure out a way to tell if floater_rlv_behaviour.xml exists
1442 menu->append(new LLMenuItemCallGL("Restrictions...", RlvFloaterBehaviour::show, NULL, NULL));
1443 #endif // RLV_EXTENSION_FLOATER_RESTRICTIONS
1444}
1445// [/RLVa:KB]
1446
1372void init_server_menu(LLMenuGL* menu) 1447void init_server_menu(LLMenuGL* menu)
1373{ 1448{
1374 { 1449 {
@@ -1521,6 +1596,16 @@ class LLObjectTouch : public view_listener_t
1521 1596
1522 LLPickInfo pick = LLToolPie::getInstance()->getPick(); 1597 LLPickInfo pick = LLToolPie::getInstance()->getPick();
1523 1598
1599// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f
1600 // TODO-RLVa: this code is rather redundant since we'll never get an active selection to show a pie menu for
1601 // [msg->addVector3("Position", pick.mIntersection) <- see llDetectedTouchPos()]
1602 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && ((!object->isAttachment()) || (!object->permYouOwner())) &&
1603 (dist_vec_squared(gAgent.getPositionAgent(), pick.mIntersection) > 1.5f * 1.5f) )
1604 {
1605 return true; // Can't touch in-world objects (or other avie's attachments) farther than 1.5m away under @fartouch=n
1606 }
1607// [/RLVa:KB]
1608
1524 LLMessageSystem *msg = gMessageSystem; 1609 LLMessageSystem *msg = gMessageSystem;
1525 1610
1526 msg->newMessageFast(_PREHASH_ObjectGrab); 1611 msg->newMessageFast(_PREHASH_ObjectGrab);
@@ -1569,6 +1654,14 @@ class LLObjectEnableTouch : public view_listener_t
1569 { 1654 {
1570 LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); 1655 LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
1571 bool new_value = obj && obj->flagHandleTouch(); 1656 bool new_value = obj && obj->flagHandleTouch();
1657// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f
1658 // TODO-RLVa: this code is rather redundant since we'll never get an active selection to show a pie menu for
1659 if ( (new_value) && (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && ((!obj->isAttachment()) || (!obj->permYouOwner())) &&
1660 (dist_vec_squared(gAgent.getPositionAgent(), LLToolPie::getInstance()->getPick().mIntersection) > 1.5f * 1.5f) )
1661 {
1662 new_value = false; // Can't touch in-world objects (or other avie's attachments) farther than 1.5m away under @fartouch=n
1663 }
1664// [/RLVa:KB]
1572 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 1665 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
1573 1666
1574 // Update label based on the node touch name if available. 1667 // Update label based on the node touch name if available.
@@ -1637,6 +1730,14 @@ class LLObjectOpen : public view_listener_t
1637{ 1730{
1638 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 1731 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
1639 { 1732 {
1733// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b)
1734 // TODO-RLVa: shouldn't we be checking for fartouch here as well?
1735 if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT))
1736 {
1737 return true;
1738 }
1739// [/RLVa:KB]
1740
1640 return handle_object_open(); 1741 return handle_object_open();
1641 } 1742 }
1642}; 1743};
@@ -1655,6 +1756,12 @@ class LLObjectEnableOpen : public view_listener_t
1655 if (!root) new_value = false; 1756 if (!root) new_value = false;
1656 else new_value = root->allowOpen(); 1757 else new_value = root->allowOpen();
1657 } 1758 }
1759
1760// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) | Modified: RLVa-1.0.0b
1761 // TODO-RLV: shouldn't we be checking for fartouch here as well? (and LLViewerObject::allowOpen() makes this redundant?)
1762 new_value &= !gRlvHandler.hasBehaviour(RLV_BHVR_EDIT);
1763// [/RLVa:KB]
1764
1658 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 1765 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
1659 return true; 1766 return true;
1660 } 1767 }
@@ -1716,7 +1823,13 @@ bool toggle_build_mode()
1716 } 1823 }
1717 } 1824 }
1718 1825
1719 1826// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
1827 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (LLSelectMgr::getInstance()) )
1828 {
1829 LLSelectMgr::getInstance()->deselectAll();
1830 }
1831// [/RLVa:KB]
1832
1720 LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); 1833 LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
1721 LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() ); 1834 LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
1722 1835
@@ -1816,6 +1929,23 @@ class LLObjectEdit : public view_listener_t
1816 { 1929 {
1817 LLViewerParcelMgr::getInstance()->deselectLand(); 1930 LLViewerParcelMgr::getInstance()->deselectLand();
1818 1931
1932// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f
1933 if (rlv_handler_t::isEnabled())
1934 {
1935 if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT))
1936 {
1937 return true; // Can't edit any object under @edit=n
1938 }
1939 else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) &&
1940 (SELECT_TYPE_WORLD == LLSelectMgr::getInstance()->getSelection()->getSelectType()) &&
1941 (dist_vec_squared(gAgent.getPositionAgent(), LLToolPie::getInstance()->getPick().mIntersection) > 1.5f * 1.5f) )
1942 {
1943 // TODO-RLVa: this code is rather redundant since we'll never get an active selection to show a pie menu for
1944 return true; // Can't edit in-world objects farther than 1.5m away under @fartouch=n
1945 }
1946 }
1947// [/RLVa:KB]
1948
1819 if (gAgent.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit()) 1949 if (gAgent.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit())
1820 { 1950 {
1821 LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); 1951 LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
@@ -1965,6 +2095,22 @@ class LLEnableEdit : public view_listener_t
1965 enable = LLViewerParcelMgr::getInstance()->agentCanBuild() 2095 enable = LLViewerParcelMgr::getInstance()->agentCanBuild()
1966 || LLSelectMgr::getInstance()->getSelection()->isAttachment(); 2096 || LLSelectMgr::getInstance()->getSelection()->isAttachment();
1967 } 2097 }
2098// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
2099 // TODO-RLV: include fartouch here?
2100 if ( (rlv_handler_t::isEnabled()) && (enable) )
2101 {
2102 // We have no way of knowing whether we're being called for "Create" or for "Edit", but we can
2103 // make an educated guess based on the currently active selection which puts us halfway there.
2104 BOOL fActiveSelection = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
2105
2106 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) )
2107 enable = false; // Edit and rez restricted, disable them both
2108 else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (fActiveSelection) )
2109 enable = false; // Edit restricted and there's an active selection => disable Edit and Create
2110 else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) && (!fActiveSelection) )
2111 enable = false; // Rez restricted and there's no active selection => disable Create
2112 }
2113// [/RLVa:KB]
1968 gMenuHolder->findControl(userdata["control"].asString())->setValue(enable); 2114 gMenuHolder->findControl(userdata["control"].asString())->setValue(enable);
1969 return true; 2115 return true;
1970 } 2116 }
@@ -1992,7 +2138,10 @@ class LLSelfEnableRemoveAllAttachments : public view_listener_t
1992 { 2138 {
1993 LLVOAvatar::attachment_map_t::iterator curiter = iter++; 2139 LLVOAvatar::attachment_map_t::iterator curiter = iter++;
1994 LLViewerJointAttachment* attachment = curiter->second; 2140 LLViewerJointAttachment* attachment = curiter->second;
1995 if (attachment->getObject()) 2141// if (attachment->getObject())
2142// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0c
2143 if ( (attachment->getObject()) && ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isDetachable(curiter->first)) ) )
2144// [/RLVa:KB]
1996 { 2145 {
1997 new_value = true; 2146 new_value = true;
1998 break; 2147 break;
@@ -2039,6 +2188,9 @@ class LLObjectEnableMute : public view_listener_t
2039 BOOL is_linden = lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden"); 2188 BOOL is_linden = lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden");
2040 BOOL is_self = avatar->isSelf(); 2189 BOOL is_self = avatar->isSelf();
2041 new_value = !is_linden && !is_self; 2190 new_value = !is_linden && !is_self;
2191// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
2192 new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES));
2193// [/RLVa:KB]
2042 } 2194 }
2043 } 2195 }
2044 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 2196 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
@@ -2059,6 +2211,12 @@ class LLObjectMute : public view_listener_t
2059 LLVOAvatar* avatar = find_avatar_from_object(object); 2211 LLVOAvatar* avatar = find_avatar_from_object(object);
2060 if (avatar) 2212 if (avatar)
2061 { 2213 {
2214// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-1.0.0e
2215 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
2216 {
2217 return true; // Fallback code [see LLObjectEnableMute::handleEvent()]
2218 }
2219// [/RLVa:KB]
2062 id = avatar->getID(); 2220 id = avatar->getID();
2063 2221
2064 LLNameValue *firstname = avatar->getNVPair("FirstName"); 2222 LLNameValue *firstname = avatar->getNVPair("FirstName");
@@ -2107,8 +2265,155 @@ class LLObjectMute : public view_listener_t
2107 } 2265 }
2108}; 2266};
2109 2267
2268class LLObjectEnableCopyUUID : public view_listener_t
2269{
2270 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2271 {
2272 LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
2273 bool new_value = (object != NULL);
2274
2275 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
2276 return true;
2277 }
2278};
2279
2280class LLObjectCopyUUID : public view_listener_t
2281{
2282 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2283 {
2284 LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
2285 if (!object) return true;
2286
2287 LLUUID id = object->getID();
2288
2289 char buffer[UUID_STR_LENGTH];
2290 id.toString(buffer);
2291
2292
2293 gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer));
2294
2295 LLSelectMgr::getInstance()->deselectAll();
2296 return true;
2297 }
2298};
2299
2300
2301class LLObjectEnableExport : public view_listener_t
2302{
2303 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2304 {
2305 LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
2306 bool new_value = (object != NULL);
2307 if (new_value)
2308 {
2309 LLVOAvatar* avatar = find_avatar_from_object(object);
2310 new_value = (avatar == NULL);
2311 }
2312 if(new_value)
2313 {
2314
2315 struct ff : public LLSelectedNodeFunctor
2316 {
2317 ff(const LLSD& data) : LLSelectedNodeFunctor()
2318 ,userdata(data)
2319 {
2320
2321 }
2322 const LLSD& userdata;
2323 virtual bool apply(LLSelectNode* node)
2324 {
2325 if(gAgent.getID()!=node->mPermissions->getCreator())
2326 {
2327 llwarns<<"Incorrect permission to export"<<llendl;
2328 return false;
2329 }
2330 return true;
2331 }
2332 };
2333
2334#ifdef LL_GRID_PERMISSIONS
2335
2336 ff * the_ff=new ff(userdata);
2337 if(LLSelectMgr::getInstance()->getSelection()->applyToNodes(the_ff,false))
2338 {
2339 gMenuHolder->findControl(userdata["control"].asString())->setValue(true);
2340 }
2341 else
2342 {
2343 gMenuHolder->findControl(userdata["control"].asString())->setValue(false);
2344 }
2345 return true;
2346 }
2347
2348 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
2349 return true;
2350#else
2351 }
2352 gMenuHolder->findControl(userdata["control"].asString())->setValue(true);
2353 return true;
2354#endif
2355
2356 }
2357};
2358
2359class LLObjectExport : public view_listener_t
2360{
2361 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2362 {
2363 LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
2364 if (!object) return true;
2365
2366 LLVOAvatar* avatar = find_avatar_from_object(object);
2367
2368 if (!avatar)
2369 {
2370 primbackup::getInstance()->pre_export_object();
2371 }
2372
2373 return true;
2374 }
2375};
2376
2377
2378class LLObjectEnableImport : public view_listener_t
2379{
2380 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2381 {
2382 gMenuHolder->findControl(userdata["control"].asString())->setValue(TRUE);
2383 return true;
2384 }
2385};
2386
2387class LLObjectImport : public view_listener_t
2388{
2389 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2390 {
2391 primbackup::getInstance()->import_object(FALSE);
2392 return true;
2393 }
2394};
2395
2396class LLObjectImportUpload : public view_listener_t
2397{
2398 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2399 {
2400 primbackup::getInstance()->import_object(TRUE);
2401 return true;
2402 }
2403};
2404
2110bool handle_go_to() 2405bool handle_go_to()
2111{ 2406{
2407// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
2408 if ( (rlv_handler_t::isEnabled()) && gAgent.forwardGrabbed() && (gRlvHandler.hasLockedAttachment()) )
2409 {
2410 return true;
2411 }
2412// [/RLVa:KB]
2413
2414 // JAMESDEBUG try simulator autopilot
2415 std::vector<std::string> strings;
2416 std::string val;
2112 LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal; 2417 LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal;
2113 if (gSavedSettings.getBOOL("DoubleClickTeleport")) 2418 if (gSavedSettings.getBOOL("DoubleClickTeleport"))
2114 { 2419 {
@@ -2200,6 +2505,12 @@ class LLAvatarFreeze : public view_listener_t
2200 { 2505 {
2201 LLUUID* avatar_id = new LLUUID( avatar->getID() ); 2506 LLUUID* avatar_id = new LLUUID( avatar->getID() );
2202 std::string fullname = avatar->getFullname(); 2507 std::string fullname = avatar->getFullname();
2508// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e)
2509 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!fullname.empty()) )
2510 {
2511 fullname = gRlvHandler.getAnonym(fullname);
2512 }
2513// [/RLVa:KB]
2203 2514
2204 if (!fullname.empty()) 2515 if (!fullname.empty())
2205 { 2516 {
@@ -2225,7 +2536,11 @@ class LLAvatarVisibleDebug : public view_listener_t
2225{ 2536{
2226 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 2537 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2227 { 2538 {
2228 bool new_value = gAgent.isGodlike(); 2539 //bool new_value = gAgent.isGodlike();
2540// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
2541 // TODO-RLVa: can you actually use this to cheat anything?
2542 bool new_value = gAgent.isGodlike() && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES));
2543// [/RLVa:KB]
2229 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 2544 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
2230 return true; 2545 return true;
2231 } 2546 }
@@ -2337,6 +2652,12 @@ class LLAvatarEject : public view_listener_t
2337 MenuCallbackData *data = new MenuCallbackData; 2652 MenuCallbackData *data = new MenuCallbackData;
2338 (*data).avatar_id = avatar->getID(); 2653 (*data).avatar_id = avatar->getID();
2339 std::string fullname = avatar->getFullname(); 2654 std::string fullname = avatar->getFullname();
2655// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e)
2656 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!fullname.empty()) )
2657 {
2658 fullname = gRlvHandler.getAnonym(fullname);
2659 }
2660// [/RLVa:KB]
2340 2661
2341 const LLVector3d& pos = avatar->getPositionGlobal(); 2662 const LLVector3d& pos = avatar->getPositionGlobal();
2342 LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel(); 2663 LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel();
@@ -2418,6 +2739,13 @@ class LLAvatarGiveCard : public view_listener_t
2418{ 2739{
2419 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 2740 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2420 { 2741 {
2742// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
2743 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
2744 {
2745 return true;
2746 }
2747// [/RLVa:KB]
2748
2421 llinfos << "handle_give_card()" << llendl; 2749 llinfos << "handle_give_card()" << llendl;
2422 LLViewerObject* dest = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); 2750 LLViewerObject* dest = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
2423 if(dest && dest->isAvatar()) 2751 if(dest && dest->isAvatar())
@@ -2667,6 +2995,13 @@ class LLSelfStandUp : public view_listener_t
2667{ 2995{
2668 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 2996 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2669 { 2997 {
2998// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
2999 if (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT))
3000 {
3001 return true;
3002 }
3003// [/RLVa:KB]
3004
2670 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); 3005 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
2671 return true; 3006 return true;
2672 } 3007 }
@@ -2676,7 +3011,10 @@ class LLSelfEnableStandUp : public view_listener_t
2676{ 3011{
2677 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 3012 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2678 { 3013 {
2679 bool new_value = gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting; 3014// bool new_value = gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting;
3015// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
3016 bool new_value = gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting && !gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT);
3017// [/RLVa:KB]
2680 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 3018 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
2681 return true; 3019 return true;
2682 } 3020 }
@@ -2851,6 +3189,11 @@ class LLAvatarEnableAddFriend : public view_listener_t
2851 { 3189 {
2852 LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); 3190 LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
2853 bool new_value = avatar && !is_agent_friend(avatar->getID()); 3191 bool new_value = avatar && !is_agent_friend(avatar->getID());
3192
3193// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
3194 new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES));
3195// [/RLVa:KB]
3196
2854 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 3197 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
2855 return true; 3198 return true;
2856 } 3199 }
@@ -2909,6 +3252,15 @@ bool handle_sit_or_stand()
2909 return true; 3252 return true;
2910 } 3253 }
2911 3254
3255// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0c)
3256 if ( (rlv_handler_t::isEnabled()) &&
3257 ( ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->mIsSitting)) ||
3258 (gRlvHandler.hasBehaviour(RLV_BHVR_SIT)) ) )
3259 {
3260 return true;
3261 }
3262// [/RLVa:KB]
3263
2912 if (sitting_on_selection()) 3264 if (sitting_on_selection())
2913 { 3265 {
2914 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); 3266 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
@@ -2919,6 +3271,15 @@ bool handle_sit_or_stand()
2919 3271
2920 if (object && object->getPCode() == LL_PCODE_VOLUME) 3272 if (object && object->getPCode() == LL_PCODE_VOLUME)
2921 { 3273 {
3274// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0g
3275 if ( (rlv_handler_t::isEnabled()) &&
3276 ((gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) || (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH))) &&
3277 (dist_vec_squared(gAgent.getPositionGlobal(), object->getPositionGlobal() + LLVector3d(pick.mObjectOffset)) > 1.5f * 1.5f) )
3278 {
3279 return true; // Don't allow sitting farther away than 1.5m under @sittp=n or @fartouch=n
3280 }
3281// [/RLVa:KB]
3282
2922 gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit); 3283 gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit);
2923 gMessageSystem->nextBlockFast(_PREHASH_AgentData); 3284 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
2924 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); 3285 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
@@ -2956,6 +3317,13 @@ class LLLandSit : public view_listener_t
2956{ 3317{
2957 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 3318 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
2958 { 3319 {
3320// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
3321 if (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT))
3322 {
3323 return true;
3324 }
3325// [/RLVa:KB]
3326
2959 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); 3327 gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
2960 LLViewerParcelMgr::getInstance()->deselectLand(); 3328 LLViewerParcelMgr::getInstance()->deselectLand();
2961 3329
@@ -3266,6 +3634,14 @@ class LLEditDuplicate : public view_listener_t
3266{ 3634{
3267 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 3635 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
3268 { 3636 {
3637// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
3638 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) &&
3639 (LLEditMenuHandler::gEditMenuHandler == LLSelectMgr::getInstance()) )
3640 {
3641 return true;
3642 }
3643// [/RLVa:KB]
3644
3269 if(LLEditMenuHandler::gEditMenuHandler) 3645 if(LLEditMenuHandler::gEditMenuHandler)
3270 { 3646 {
3271 LLEditMenuHandler::gEditMenuHandler->duplicate(); 3647 LLEditMenuHandler::gEditMenuHandler->duplicate();
@@ -3279,6 +3655,13 @@ class LLEditEnableDuplicate : public view_listener_t
3279 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 3655 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
3280 { 3656 {
3281 bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDuplicate(); 3657 bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDuplicate();
3658// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
3659 if ( (new_value) && (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) &&
3660 (LLEditMenuHandler::gEditMenuHandler == LLSelectMgr::getInstance()) )
3661 {
3662 new_value = false;
3663 }
3664// [/RLVa:KB]
3282 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 3665 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
3283 return true; 3666 return true;
3284 } 3667 }
@@ -3664,6 +4047,11 @@ class LLToolsTakeCopy : public view_listener_t
3664 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4047 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
3665 { 4048 {
3666 if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true; 4049 if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true;
4050// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | Modified: RLVa-1.0.0b
4051 // NOTE: we need to handle "Take Copy" because it will force a sim-side unsit if we're sitting on the selection,
4052 // but we do want to allow "Take Copy" under @rez=n so that's why we explicitly check for @unsit=n here
4053 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (!rlvCanDeleteOrReturn()) ) return true;
4054// [/RLVa:KB]
3667 4055
3668 const LLUUID& category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT); 4056 const LLUUID& category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT);
3669 derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id); 4057 derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
@@ -3679,6 +4067,9 @@ class LLObjectReturn : public view_listener_t
3679 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4067 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
3680 { 4068 {
3681 if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true; 4069 if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true;
4070// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-05 (RLVa-1.0.0b)
4071 if ( (rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn()) ) return true;
4072// [/RLVa:KB]
3682 4073
3683 mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); 4074 mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
3684 4075
@@ -3748,6 +4139,14 @@ class LLObjectEnableReturn : public view_listener_t
3748 } 4139 }
3749 } 4140 }
3750#endif 4141#endif
4142
4143// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
4144 if ( (new_value) && (rlv_handler_t::isEnabled()) )
4145 {
4146 new_value = rlvCanDeleteOrReturn();
4147 }
4148// [/RLVa:KB]
4149
3751 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 4150 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
3752 return true; 4151 return true;
3753 } 4152 }
@@ -3769,6 +4168,13 @@ void handle_take()
3769 return; 4168 return;
3770 } 4169 }
3771 4170
4171// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
4172 if ( (rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn()) )
4173 {
4174 return;
4175 }
4176// [/RLVa:KB]
4177
3772 BOOL you_own_everything = TRUE; 4178 BOOL you_own_everything = TRUE;
3773 BOOL locked_but_takeable_object = FALSE; 4179 BOOL locked_but_takeable_object = FALSE;
3774 LLUUID category_id; 4180 LLUUID category_id;
@@ -3890,6 +4296,13 @@ BOOL enable_take()
3890 return FALSE; 4296 return FALSE;
3891 } 4297 }
3892 4298
4299// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
4300 if ( (rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn()) )
4301 {
4302 return FALSE;
4303 }
4304// [/RLVa:KB]
4305
3893 for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin(); 4306 for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin();
3894 iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++) 4307 iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++)
3895 { 4308 {
@@ -4212,6 +4625,21 @@ class LLToolsEnableUnlink : public view_listener_t
4212 new_value = true; 4625 new_value = true;
4213 } 4626 }
4214 } 4627 }
4628
4629// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0g
4630 // The user might not be allowed to unlink this object due to RLV settings,
4631 // because it would unsit them if they are sitting on the object.
4632 if ( (new_value) && (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) &&
4633 (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->mIsSitting) )
4634 {
4635 // Allow if the avie isn't sitting on any of the selected objects
4636 LLObjectSelectionHandle handleSel = LLSelectMgr::getInstance()->getSelection();
4637 RlvSelectIsSittingOn func(gAgent.getAvatarObject()->getRoot());
4638 if (handleSel->getFirstRootNode(&func, TRUE))
4639 new_value = false;
4640 }
4641// [/RLVa:KB]
4642
4215 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 4643 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
4216 return true; 4644 return true;
4217 } 4645 }
@@ -4221,6 +4649,19 @@ class LLToolsUnlink : public view_listener_t
4221{ 4649{
4222 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4650 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4223 { 4651 {
4652// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0g
4653 // The user might not be allowed to unlink this object due to RLV settings,
4654 // because it would unsit them if they are sitting on the object.
4655 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->mIsSitting) )
4656 {
4657 // Allow if the avie isn't sitting on any of the selected objects
4658 LLObjectSelectionHandle handleSel = LLSelectMgr::getInstance()->getSelection();
4659 RlvSelectIsSittingOn func(gAgent.getAvatarObject()->getRoot());
4660 if (handleSel->getFirstRootNode(&func, TRUE))
4661 return true;
4662 }
4663// [/RLVa:KB]
4664
4224 LLSelectMgr::getInstance()->sendDelink(); 4665 LLSelectMgr::getInstance()->sendDelink();
4225 return true; 4666 return true;
4226 } 4667 }
@@ -4240,6 +4681,13 @@ class LLToolsReleaseKeys : public view_listener_t
4240{ 4681{
4241 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4682 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4242 { 4683 {
4684// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
4685 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) )
4686 {
4687 return true;
4688 }
4689// [/RLVa:KB]
4690
4243 gAgent.forceReleaseControls(); 4691 gAgent.forceReleaseControls();
4244 4692
4245 return true; 4693 return true;
@@ -4250,7 +4698,11 @@ class LLToolsEnableReleaseKeys : public view_listener_t
4250{ 4698{
4251 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4699 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4252 { 4700 {
4253 gMenuHolder->findControl(userdata["control"].asString())->setValue( gAgent.anyControlGrabbed() ); 4701// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
4702 gMenuHolder->findControl(userdata["control"].asString())->setValue(
4703 gAgent.anyControlGrabbed() && ( (!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedAttachment() ) ) );
4704// [/RLVa:KB]
4705 //gMenuHolder->findControl(userdata["control"].asString())->setValue( gAgent.anyControlGrabbed() );
4254 return true; 4706 return true;
4255 } 4707 }
4256}; 4708};
@@ -4358,6 +4810,15 @@ class LLEditEnableDelete : public view_listener_t
4358 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4810 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4359 { 4811 {
4360 bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete(); 4812 bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete();
4813
4814// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
4815 // NOTE: we want to disable delete on objects but not disable delete on text
4816 if ( (new_value) && (rlv_handler_t::isEnabled()) && (LLEditMenuHandler::gEditMenuHandler == LLSelectMgr::getInstance()) )
4817 {
4818 new_value = rlvCanDeleteOrReturn();
4819 }
4820// [/RLVa:KB]
4821
4361 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 4822 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
4362 return true; 4823 return true;
4363 } 4824 }
@@ -4367,6 +4828,15 @@ class LLEditDelete : public view_listener_t
4367{ 4828{
4368 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4829 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4369 { 4830 {
4831// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
4832 // NOTE: we want to disable delete on objects but not disable delete on text
4833 if ( (rlv_handler_t::isEnabled()) && (LLEditMenuHandler::gEditMenuHandler == LLSelectMgr::getInstance()) &&
4834 (!rlvCanDeleteOrReturn()) )
4835 {
4836 return true;
4837 }
4838// [/RLVa:KB]
4839
4370 // If a text field can do a deletion, it gets precedence over deleting 4840 // If a text field can do a deletion, it gets precedence over deleting
4371 // an object in the world. 4841 // an object in the world.
4372 if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete()) 4842 if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete())
@@ -4398,6 +4868,12 @@ class LLObjectEnableDelete : public view_listener_t
4398# endif 4868# endif
4399 LLSelectMgr::getInstance()->canDoDelete(); 4869 LLSelectMgr::getInstance()->canDoDelete();
4400#endif 4870#endif
4871// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
4872 if ( (new_value) && (rlv_handler_t::isEnabled()) )
4873 {
4874 new_value = rlvCanDeleteOrReturn();
4875 }
4876// [/RLVa:KB]
4401 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 4877 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
4402 return true; 4878 return true;
4403 } 4879 }
@@ -4416,6 +4892,13 @@ class LLObjectDelete : public view_listener_t
4416{ 4892{
4417 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 4893 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4418 { 4894 {
4895// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
4896 if ( (rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn()) )
4897 {
4898 return true;
4899 }
4900// [/RLVa:KB]
4901
4419 if (LLSelectMgr::getInstance()) 4902 if (LLSelectMgr::getInstance())
4420 { 4903 {
4421 LLSelectMgr::getInstance()->doDelete(); 4904 LLSelectMgr::getInstance()->doDelete();
@@ -4765,6 +5248,12 @@ class LLWorldCreateLandmark : public view_listener_t
4765{ 5248{
4766 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 5249 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4767 { 5250 {
5251// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
5252 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
5253 {
5254 return true;
5255 }
5256// [/RLVa:KB]
4768 LLViewerRegion* agent_region = gAgent.getRegion(); 5257 LLViewerRegion* agent_region = gAgent.getRegion();
4769 if(!agent_region) 5258 if(!agent_region)
4770 { 5259 {
@@ -4872,6 +5361,13 @@ class LLAvatarInviteToGroup : public view_listener_t
4872{ 5361{
4873 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 5362 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4874 { 5363 {
5364// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
5365 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
5366 {
5367 return true;
5368 }
5369// [/RLVa:KB]
5370
4875 LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); 5371 LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
4876 if(avatar) 5372 if(avatar)
4877 { 5373 {
@@ -4885,6 +5381,13 @@ class LLAvatarAddFriend : public view_listener_t
4885{ 5381{
4886 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 5382 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
4887 { 5383 {
5384// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
5385 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
5386 {
5387 return true; // Fallback code [see LLAvatarEnableAddFriend::handleEvent()]
5388 }
5389// [/RLVa:KB]
5390
4888 LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); 5391 LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
4889 if(avatar && !is_agent_friend(avatar->getID())) 5392 if(avatar && !is_agent_friend(avatar->getID()))
4890 { 5393 {
@@ -4972,6 +5475,12 @@ class LLEnablePayObject : public view_listener_t
4972 } 5475 }
4973 } 5476 }
4974 } 5477 }
5478
5479// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
5480 // Don't enable "Pay..." on the avatar pie menu under @shownames=n
5481 new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) || (avatar == NULL);
5482// [/RLVa:KB]
5483
4975 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 5484 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
4976 return true; 5485 return true;
4977 } 5486 }
@@ -5160,6 +5669,12 @@ class LLShowFloater : public view_listener_t
5160 } 5669 }
5161 else if (floater_name == "buy land") 5670 else if (floater_name == "buy land")
5162 { 5671 {
5672// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
5673 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
5674 {
5675 return true;
5676 }
5677// [/RLVa:KB]
5163 if (LLViewerParcelMgr::getInstance()->selectionEmpty()) 5678 if (LLViewerParcelMgr::getInstance()->selectionEmpty())
5164 { 5679 {
5165 LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal()); 5680 LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal());
@@ -5341,6 +5856,13 @@ class LLShowAgentProfile : public view_listener_t
5341 } 5856 }
5342 else if (userdata.asString() == "hit object") 5857 else if (userdata.asString() == "hit object")
5343 { 5858 {
5859// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
5860 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
5861 {
5862 return true;
5863 }
5864// [/RLVa:KB]
5865
5344 LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); 5866 LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
5345 if (objectp) 5867 if (objectp)
5346 { 5868 {
@@ -5400,6 +5922,13 @@ class LLLandEdit : public view_listener_t
5400{ 5922{
5401 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 5923 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
5402 { 5924 {
5925// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b)
5926 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) )
5927 {
5928 return true;
5929 }
5930// [/RLVa:KB]
5931
5403 if (gAgent.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") ) 5932 if (gAgent.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") )
5404 { 5933 {
5405 // zoom in if we're looking at the avatar 5934 // zoom in if we're looking at the avatar
@@ -5484,6 +6013,18 @@ private:
5484 LLViewerJointAttachment* attachment_point = NULL; 6013 LLViewerJointAttachment* attachment_point = NULL;
5485 if (index > 0) 6014 if (index > 0)
5486 attachment_point = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL); 6015 attachment_point = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL);
6016
6017// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6018 if ( (rlv_handler_t::isEnabled()) &&
6019 ( ((index == 0) && (gRlvHandler.hasLockedAttachment())) || // Can't wear on default attach point
6020 ((index > 0) && (!gRlvHandler.isDetachable(attachment_point->getObject()))) || // Can't replace locked attachment
6021 (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) ) ) // Attach on rezzed object == "Take"
6022 {
6023 setObjectSelection(NULL); // Clear the selection or it'll get stuck
6024 return true;
6025 }
6026// [/RLVa:KB]
6027
5487 confirm_replace_attachment(0, attachment_point); 6028 confirm_replace_attachment(0, attachment_point);
5488 } 6029 }
5489 return true; 6030 return true;
@@ -5591,6 +6132,24 @@ class LLAttachmentDrop : public view_listener_t
5591 return true; 6132 return true;
5592 } 6133 }
5593 6134
6135// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6136 if (rlv_handler_t::isEnabled())
6137 {
6138 if (gRlvHandler.hasLockedAttachment())
6139 {
6140 // NOTE: copy/paste of the code in enable_detach()
6141 LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection();
6142 RlvSelectHasLockedAttach functor;
6143 if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&functor, FALSE)) )
6144 return true;
6145 }
6146 else if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ))
6147 {
6148 return true;
6149 }
6150 }
6151// [/RLVa:KB]
6152
5594 // The sendDropAttachment() method works on the list of selected 6153 // The sendDropAttachment() method works on the list of selected
5595 // objects. Thus we need to clear the list, make sure it only 6154 // objects. Thus we need to clear the list, make sure it only
5596 // contains the object the user clicked, send the message, 6155 // contains the object the user clicked, send the message,
@@ -5609,6 +6168,13 @@ void handle_detach_from_avatar(void* user_data)
5609 6168
5610 if (attached_object) 6169 if (attached_object)
5611 { 6170 {
6171// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0d
6172 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(attached_object)) )
6173 {
6174 return;
6175 }
6176// [/RLVa:KB]
6177
5612 gMessageSystem->newMessage("ObjectDetach"); 6178 gMessageSystem->newMessage("ObjectDetach");
5613 gMessageSystem->nextBlockFast(_PREHASH_AgentData); 6179 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
5614 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); 6180 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
@@ -5691,6 +6257,17 @@ class LLAttachmentDetach : public view_listener_t
5691 return true; 6257 return true;
5692 } 6258 }
5693 6259
6260// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6261 // NOTE: copy/paste of the code in enable_detach()
6262 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) )
6263 {
6264 LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection();
6265 RlvSelectHasLockedAttach functor;
6266 if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&functor, FALSE)) )
6267 return FALSE;
6268 }
6269// [/RLVa:KB]
6270
5694 // The sendDetach() method works on the list of selected 6271 // The sendDetach() method works on the list of selected
5695 // objects. Thus we need to clear the list, make sure it only 6272 // objects. Thus we need to clear the list, make sure it only
5696 // contains the object the user clicked, send the message, 6273 // contains the object the user clicked, send the message,
@@ -5774,7 +6351,10 @@ class LLAttachmentEnableDrop : public view_listener_t
5774 } 6351 }
5775 6352
5776 //now check to make sure that the item is actually in the inventory before we enable dropping it 6353 //now check to make sure that the item is actually in the inventory before we enable dropping it
5777 bool new_value = enable_detach(NULL) && can_build && item; 6354// bool new_value = enable_detach(NULL) && can_build && item;
6355// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
6356 bool new_value = enable_detach(NULL) && can_build && item && (!gRlvHandler.hasBehaviour(RLV_BHVR_REZ));
6357// [/RLVa:KB]
5778 6358
5779 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 6359 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
5780 return true; 6360 return true;
@@ -5794,6 +6374,20 @@ BOOL enable_detach(void*)
5794 // ...if it's you, good to detach 6374 // ...if it's you, good to detach
5795 if (avatar->getID() == gAgent.getID()) 6375 if (avatar->getID() == gAgent.getID())
5796 { 6376 {
6377// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6378 // NOTE: this code is reused as-is in LLAttachmentDetach::handleEvent() and LLAttachmentDrop::handleEvent()
6379 // so any changes here should be reflected there as well (I think it's in a number of other places as well by now)
6380
6381 // RELEASE-RLVa: LLSelectMgr::sendDetach() and LLSelectMgr::sendDropAttachment() call sendListToRegions with
6382 // SEND_ONLY_ROOTS so we only need to examine the roots which saves us time
6383 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) )
6384 {
6385 LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection();
6386 RlvSelectHasLockedAttach functor;
6387 if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&functor, FALSE)) )
6388 return FALSE;
6389 }
6390// [/RLVa:KB]
5797 return TRUE; 6391 return TRUE;
5798 } 6392 }
5799 6393
@@ -5816,6 +6410,25 @@ class LLAttachmentEnableDetach : public view_listener_t
5816// Used to tell if the selected object can be attached to your avatar. 6410// Used to tell if the selected object can be attached to your avatar.
5817BOOL object_selected_and_point_valid(void *user_data) 6411BOOL object_selected_and_point_valid(void *user_data)
5818{ 6412{
6413// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
6414 if (rlv_handler_t::isEnabled())
6415 {
6416 // RELEASE-RLVa: look at the caller graph for this function on every new release
6417 // -> 1.22.11 and 1.23.4
6418 // - object_is_wearable() => dead code [user_data == NULL => default attach point => OK!]
6419 // - LLObjectEnableWear::handleEvent() => Rezzed prim / right-click / "Wear" [user_data == NULL => see above]
6420 // - enabler set up in LLVOAvatar::buildCharacter() => Rezzed prim / right-click / "Attach >" [user_data == pAttachPt]
6421 // - enabler set up in LLVOAvatar::buildCharacter() => Rezzed prim / Edit menu / "Attach Object" [user_data == pAttachPt]
6422 LLViewerJointAttachment* pAttachPt = (LLViewerJointAttachment*)user_data;
6423 if ( ((!pAttachPt) && (gRlvHandler.hasLockedAttachment())) || // Don't allow attach to default attach point
6424 ((pAttachPt) && (!gRlvHandler.isDetachable(pAttachPt->getObject()))) || // Don't allow replacing of locked attachment
6425 (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) ) // Attaching a rezzed object == "Take"
6426 {
6427 return FALSE;
6428 }
6429 }
6430// [/RLVa:KB]
6431
5819 //LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; 6432 //LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
5820 LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); 6433 LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
5821 for (LLObjectSelection::root_iterator iter = selection->root_begin(); 6434 for (LLObjectSelection::root_iterator iter = selection->root_begin();
@@ -5883,7 +6496,13 @@ BOOL object_attached(void *user_data)
5883{ 6496{
5884 LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; 6497 LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
5885 6498
5886 return attachment->getObject() != NULL; 6499// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6500 return (
6501 (attachment->getObject() != NULL) &&
6502 ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isDetachable(attachment->getObject())) )
6503 );
6504// [/RLVa:KB]
6505// return attachment->getObject() != NULL;
5887} 6506}
5888 6507
5889class LLAvatarSendIM : public view_listener_t 6508class LLAvatarSendIM : public view_listener_t
@@ -5891,6 +6510,12 @@ class LLAvatarSendIM : public view_listener_t
5891 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 6510 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
5892 { 6511 {
5893 LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); 6512 LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
6513// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e)
6514 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
6515 {
6516 return true;
6517 }
6518// [/RLVa:KB]
5894 if(avatar) 6519 if(avatar)
5895 { 6520 {
5896 std::string name("IM"); 6521 std::string name("IM");
@@ -6026,6 +6651,16 @@ class LLToolsSelectedScriptAction : public view_listener_t
6026{ 6651{
6027 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 6652 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
6028 { 6653 {
6654// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6655 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) )
6656 {
6657 LLObjectSelectionHandle selectHandle = LLSelectMgr::getInstance()->getSelection();
6658 RlvSelectHasLockedAttach functor;
6659 if ( (selectHandle->isAttachment()) && (selectHandle->getFirstNode(&functor)) )
6660 return true;
6661 }
6662// [/RLVa:KB]
6663
6029 std::string action = userdata.asString(); 6664 std::string action = userdata.asString();
6030 if (action == "compile mono") 6665 if (action == "compile mono")
6031 { 6666 {
@@ -6110,12 +6745,30 @@ void handle_dump_image_list(void*)
6110 6745
6111void handle_test_male(void*) 6746void handle_test_male(void*)
6112{ 6747{
6748// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6749 if ( (rlv_handler_t::isEnabled()) &&
6750 ( (gRlvHandler.hasLockedAttachment()) ||
6751 (gRlvHandler.hasBehaviour(RLV_BHVR_ADDOUTFIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_REMOUTFIT)) ) )
6752 {
6753 return;
6754 }
6755// [/RLVa:KB]
6756
6113 wear_outfit_by_name("Male Shape & Outfit"); 6757 wear_outfit_by_name("Male Shape & Outfit");
6114 //gGestureList.requestResetFromServer( TRUE ); 6758 //gGestureList.requestResetFromServer( TRUE );
6115} 6759}
6116 6760
6117void handle_test_female(void*) 6761void handle_test_female(void*)
6118{ 6762{
6763// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
6764 if ( (rlv_handler_t::isEnabled()) &&
6765 ( (gRlvHandler.hasLockedAttachment()) ||
6766 (gRlvHandler.hasBehaviour(RLV_BHVR_ADDOUTFIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_REMOUTFIT)) ) )
6767 {
6768 return;
6769 }
6770// [/RLVa:KB]
6771
6119 wear_outfit_by_name("Female Shape & Outfit"); 6772 wear_outfit_by_name("Female Shape & Outfit");
6120 //gGestureList.requestResetFromServer( FALSE ); 6773 //gGestureList.requestResetFromServer( FALSE );
6121} 6774}
@@ -6258,6 +6911,22 @@ BOOL enable_more_than_one_selected(void* )
6258 6911
6259static bool is_editable_selected() 6912static bool is_editable_selected()
6260{ 6913{
6914// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-1.0.0c
6915 // RELEASE-RLVa: check that this still isn't called by anything but script actions in the Tools menu
6916 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) )
6917 {
6918 LLObjectSelectionHandle selectHandle = LLSelectMgr::getInstance()->getSelection();
6919
6920 // NOTE: this is called for 5 different menu items so we'll trade accuracy for efficiency and only
6921 // examine root nodes (LLToolsSelectedScriptAction::handleEvent() will catch what we miss)
6922 RlvSelectHasLockedAttach functor;
6923 if ( (selectHandle->isAttachment()) && (selectHandle->getFirstRootNode(&functor)) )
6924 {
6925 return false;
6926 }
6927 }
6928// [/RLVa:KB]
6929
6261 return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL); 6930 return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL);
6262} 6931}
6263 6932
@@ -6304,7 +6973,12 @@ class LLToolsEnableTakeCopy : public view_listener_t
6304 { 6973 {
6305 virtual bool apply(LLViewerObject* obj) 6974 virtual bool apply(LLViewerObject* obj)
6306 { 6975 {
6307 return (!obj->permCopy() || obj->isAttachment()); 6976// return (!obj->permCopy() || obj->isAttachment());
6977// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
6978 return (!obj->permCopy() || obj->isAttachment()) ||
6979 ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) &&
6980 (gAgent.getAvatarObject()->getRoot() == obj) );
6981// [/RLVa:KB]
6308 } 6982 }
6309 } func; 6983 } func;
6310 const bool firstonly = true; 6984 const bool firstonly = true;
@@ -6507,6 +7181,9 @@ class LLWorldEnableCreateLandmark : public view_listener_t
6507 { 7181 {
6508 bool new_value = gAgent.isGodlike() || 7182 bool new_value = gAgent.isGodlike() ||
6509 (gAgent.getRegion() && gAgent.getRegion()->getAllowLandmark()); 7183 (gAgent.getRegion() && gAgent.getRegion()->getAllowLandmark());
7184// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
7185 new_value &= !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC);
7186// [/RLVa:KB]
6510 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); 7187 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
6511 return true; 7188 return true;
6512 } 7189 }
@@ -6559,7 +7236,11 @@ BOOL enable_god_customer_service(void*)
6559 7236
6560BOOL enable_god_basic(void*) 7237BOOL enable_god_basic(void*)
6561{ 7238{
6562 return gAgent.getGodLevel() > GOD_NOT; 7239// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
7240 // RELEASE-RLVa: check that this function isn't used for anything other than to enable/disable showing the "God Tools..." floater
7241 return (gAgent.getGodLevel() > GOD_NOT) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC));
7242// [/RLVa:KB]
7243 //return gAgent.getGodLevel() > GOD_NOT;
6563} 7244}
6564 7245
6565#if 0 // 1.9.2 7246#if 0 // 1.9.2
@@ -7070,6 +7751,13 @@ class LLViewHighlightTransparent : public view_listener_t
7070{ 7751{
7071 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 7752 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
7072 { 7753 {
7754// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b)
7755 if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT))
7756 {
7757 return true;
7758 }
7759// [/RLVa:KB]
7760
7073 LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha; 7761 LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha;
7074 return true; 7762 return true;
7075 } 7763 }
@@ -7117,6 +7805,13 @@ class LLViewShowHUDAttachments : public view_listener_t
7117{ 7805{
7118 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 7806 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
7119 { 7807 {
7808// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
7809 if ( (LLPipeline::sShowHUDAttachments) && (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedHUD()) )
7810 {
7811 return true;
7812 }
7813// [/RLVa:KB]
7814
7120 LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments; 7815 LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments;
7121 return true; 7816 return true;
7122 } 7817 }
@@ -7175,6 +7870,15 @@ class LLEditEnableTakeOff : public view_listener_t
7175 { 7870 {
7176 new_value = LLAgent::selfHasWearable((void *)WT_SKIRT); 7871 new_value = LLAgent::selfHasWearable((void *)WT_SKIRT);
7177 } 7872 }
7873
7874// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d)
7875 // Why aren't they using LLWearable::typeNameToType()? *confuzzled*
7876 if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isRemovable(LLWearable::typeNameToType(clothing))) )
7877 {
7878 new_value = false;
7879 }
7880// [/RLVa:KB]
7881
7178 gMenuHolder->findControl(control_name)->setValue(new_value); 7882 gMenuHolder->findControl(control_name)->setValue(new_value);
7179 return true; 7883 return true;
7180 } 7884 }
@@ -7272,6 +7976,13 @@ class LLWorldEnvSettings : public view_listener_t
7272{ 7976{
7273 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 7977 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
7274 { 7978 {
7979// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
7980 if (gRlvHandler.hasBehaviour(RLV_BHVR_SETENV))
7981 {
7982 return true;
7983 }
7984// [/RLVa:KB]
7985
7275 std::string tod = userdata.asString(); 7986 std::string tod = userdata.asString();
7276 LLVector3 sun_direction; 7987 LLVector3 sun_direction;
7277 7988
@@ -7349,6 +8060,13 @@ class LLWorldWaterSettings : public view_listener_t
7349{ 8060{
7350 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 8061 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
7351 { 8062 {
8063// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
8064 if (gRlvHandler.hasBehaviour(RLV_BHVR_SETENV))
8065 {
8066 return true;
8067 }
8068// [/RLVa:KB]
8069
7352 // if not there or is hidden, show it 8070 // if not there or is hidden, show it
7353 if( !LLFloaterWater::isOpen() || 8071 if( !LLFloaterWater::isOpen() ||
7354 !LLFloaterWater::instance()->getVisible()) { 8072 !LLFloaterWater::instance()->getVisible()) {
@@ -7379,6 +8097,13 @@ class LLWorldDayCycle : public view_listener_t
7379{ 8097{
7380 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 8098 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
7381 { 8099 {
8100// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
8101 if (gRlvHandler.hasBehaviour(RLV_BHVR_SETENV))
8102 {
8103 return true;
8104 }
8105// [/RLVa:KB]
8106
7382 LLFloaterDayCycle::show(); 8107 LLFloaterDayCycle::show();
7383 return true; 8108 return true;
7384 } 8109 }
@@ -9613,6 +10338,49 @@ class LLAvatarReportAbuse : public view_listener_t
9613 10338
9614 10339
9615 10340
10341///////////////
10342// RLVa Main //
10343///////////////
10344
10345
10346class RLVaMainToggle : public view_listener_t
10347{
10348 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
10349 {
10350 rlvDbgToggleEnabled(NULL);
10351 return true;
10352 }
10353};
10354
10355class RLVaMainCheck : public view_listener_t
10356{
10357 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
10358 {
10359 bool new_value = rlvDbgGetEnabled(NULL);
10360 std::string control_name = userdata["control"].asString();
10361 gMenuHolder->findControl(control_name)->setValue(new_value);
10362 return true;
10363 }
10364};
10365
10366
10367
10368////////////////////
10369// RLVa BEHAVIORS //
10370////////////////////
10371
10372
10373class RLVaBehaviorsShow : public view_listener_t
10374{
10375 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
10376 {
10377 RlvFloaterBehaviour::show(NULL);
10378 return true;
10379 }
10380};
10381
10382
10383
9616static void addMenu(view_listener_t *menu, const char *name) 10384static void addMenu(view_listener_t *menu, const char *name)
9617{ 10385{
9618 sMenus.push_back(menu); 10386 sMenus.push_back(menu);
@@ -9778,6 +10546,10 @@ void initialize_menus()
9778 addMenu(new LLObjectBuy(), "Object.Buy"); 10546 addMenu(new LLObjectBuy(), "Object.Buy");
9779 addMenu(new LLObjectEdit(), "Object.Edit"); 10547 addMenu(new LLObjectEdit(), "Object.Edit");
9780 addMenu(new LLObjectInspect(), "Object.Inspect"); 10548 addMenu(new LLObjectInspect(), "Object.Inspect");
10549 addMenu(new LLObjectCopyUUID(), "Object.CopyUUID");
10550 addMenu(new LLObjectExport(), "Object.Export");
10551 addMenu(new LLObjectImport(), "Object.Import");
10552 addMenu(new LLObjectImportUpload(), "Object.ImportUpload");
9781 10553
9782 addMenu(new LLObjectEnableOpen(), "Object.EnableOpen"); 10554 addMenu(new LLObjectEnableOpen(), "Object.EnableOpen");
9783 addMenu(new LLObjectEnableTouch(), "Object.EnableTouch"); 10555 addMenu(new LLObjectEnableTouch(), "Object.EnableTouch");
@@ -9788,6 +10560,9 @@ void initialize_menus()
9788 addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse"); 10560 addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse");
9789 addMenu(new LLObjectEnableMute(), "Object.EnableMute"); 10561 addMenu(new LLObjectEnableMute(), "Object.EnableMute");
9790 addMenu(new LLObjectEnableBuy(), "Object.EnableBuy"); 10562 addMenu(new LLObjectEnableBuy(), "Object.EnableBuy");
10563 addMenu(new LLObjectEnableCopyUUID(), "Object.EnableCopyUUID");
10564 addMenu(new LLObjectEnableExport(), "Object.EnableExport");
10565 addMenu(new LLObjectEnableImport(), "Object.EnableImport");
9791 10566
9792 /*addMenu(new LLObjectVisibleTouch(), "Object.VisibleTouch"); 10567 /*addMenu(new LLObjectVisibleTouch(), "Object.VisibleTouch");
9793 addMenu(new LLObjectVisibleCustomTouch(), "Object.VisibleCustomTouch"); 10568 addMenu(new LLObjectVisibleCustomTouch(), "Object.VisibleCustomTouch");
@@ -9988,4 +10763,11 @@ void initialize_menus()
9988 addMenu(new LLAdvancedCheckViewAdminOptions(), "Advanced.CheckViewAdminOptions"); 10763 addMenu(new LLAdvancedCheckViewAdminOptions(), "Advanced.CheckViewAdminOptions");
9989 addMenu(new LLAdvancedRequestAdminStatus(), "Advanced.RequestAdminStatus"); 10764 addMenu(new LLAdvancedRequestAdminStatus(), "Advanced.RequestAdminStatus");
9990 addMenu(new LLAdvancedLeaveAdminStatus(), "Advanced.LeaveAdminStatus"); 10765 addMenu(new LLAdvancedLeaveAdminStatus(), "Advanced.LeaveAdminStatus");
10766
10767
10768 // RLVa
10769 addMenu(new RLVaMainToggle(), "RLVa.Main.Toggle");
10770 addMenu(new RLVaMainCheck(), "RLVa.Main.Enabled");
10771 addMenu(new RLVaBehaviorsShow(), "RLVa.Behaviors.Show");
10772
9991} 10773}
diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp
index 815dc49..e326dac 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)
@@ -1854,6 +1973,17 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
1854 return; 1973 return;
1855 } 1974 }
1856 { 1975 {
1976// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e)
1977 // TODO-RLVa: what actually generates this?
1978 if (rlv_handler_t::isEnabled())
1979 {
1980 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
1981 gRlvHandler.filterLocation(message);
1982 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
1983 gRlvHandler.filterNames(message);
1984 }
1985// [/RLVa:KB]
1986
1857 // Construct a viewer alert for this message. 1987 // Construct a viewer alert for this message.
1858 args["[NAME]"] = name; 1988 args["[NAME]"] = name;
1859 args["[MESSAGE]"] = message; 1989 args["[MESSAGE]"] = message;
@@ -1886,12 +2016,48 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
1886 } 2016 }
1887 else 2017 else
1888 { 2018 {
1889 // *TODO:translate -> [FIRST] [LAST] (maybe) 2019// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d)
1890 LLLureInfo* info = new LLLureInfo(from_id, session_id, FALSE); 2020 if (rlv_handler_t::isEnabled())
1891 args["[NAME]"] = name; 2021 {
1892 args["[MESSAGE]"] = message; 2022 // Disallow if: 1) @tplure=n restricted (sender isn't an exception), or 2) @unsit=n restricted and currently sitting
1893 LLNotifyBox::showXml("OfferTeleport", args, 2023 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
1894 lure_callback, (void*)info); 2024 if ( ( (gRlvHandler.hasBehaviour(RLV_BHVR_TPLURE)) && (!gRlvHandler.isException(RLV_BHVR_TPLURE, from_id)) ) ||
2025 ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (pAvatar) && (pAvatar->mIsSitting) ) )
2026 {
2027 rlvSendBusyMessage(from_id, rlv_handler_t::cstrMsgTpLure);
2028 return;
2029 }
2030
2031 // Censor teleport message if: 1) @revcim=n restricted (sender isn't an exception), or 2) @showloc=n restricted
2032 if ( ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) && (!gRlvHandler.isException(RLV_BHVR_RECVIM, from_id)) ) ||
2033 (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) )
2034 {
2035 message = rlv_handler_t::cstrHidden;
2036 }
2037 }
2038// [/RLVa:KB]
2039
2040// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.0b
2041 if ( (rlv_handler_t::isEnabled()) &&
2042 ((gRlvHandler.hasBehaviour(RLV_BHVR_ACCEPTTP)) || (gRlvHandler.isException(RLV_BHVR_ACCEPTTP, from_id))) )
2043 {
2044 gRlvHandler.setCanCancelTp(false);
2045 // (see IM_GODLIKE_LURE_USER below)
2046 LLLureInfo* info = new LLLureInfo(from_id, session_id, TRUE);
2047 lure_callback(0, (void*)info);
2048 }
2049 else
2050 {
2051// [/RLVa:KB]
2052 // *TODO:translate -> [FIRST] [LAST] (maybe)
2053 LLLureInfo* info = new LLLureInfo(from_id, session_id, FALSE);
2054 args["[NAME]"] = name;
2055 args["[MESSAGE]"] = message;
2056 LLNotifyBox::showXml("OfferTeleport", args,
2057 lure_callback, (void*)info);
2058// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.0b
2059 }
2060// [/RLVa:KB]
1895 } 2061 }
1896 } 2062 }
1897 break; 2063 break;
@@ -2236,8 +2402,13 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
2236 chat.mPosAgent = chatter->getPositionAgent(); 2402 chat.mPosAgent = chatter->getPositionAgent();
2237 2403
2238 // Make swirly things only for talking objects. (not script debug messages, though) 2404 // Make swirly things only for talking objects. (not script debug messages, though)
2239 if (chat.mSourceType == CHAT_SOURCE_OBJECT 2405// if (chat.mSourceType == CHAT_SOURCE_OBJECT
2240 && chat.mChatType != CHAT_TYPE_DEBUG_MSG) 2406// && chat.mChatType != CHAT_TYPE_DEBUG_MSG)
2407// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
2408 // Don't show swirly things for llOwnerSay() chat here because we handle those further down
2409 if ( (chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mChatType != CHAT_TYPE_DEBUG_MSG) &&
2410 ((!rlv_handler_t::isEnabled()) || (CHAT_TYPE_OWNER != chat.mChatType)) )
2411// [/RLVa:KB]
2241 { 2412 {
2242 LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent()); 2413 LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent());
2243 psc->setSourceObject(chatter); 2414 psc->setSourceObject(chatter);
@@ -2270,6 +2441,50 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
2270 color.setVec(1.f,1.f,1.f,1.f); 2441 color.setVec(1.f,1.f,1.f,1.f);
2271 msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, mesg); 2442 msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, mesg);
2272 2443
2444// [RLVa:KB] - Checked: 2009-08-04 (RLVa-1.0.1d) | Modified: RLVa-1.0.1d
2445 if ( (rlv_handler_t::isEnabled()) &&
2446 (CHAT_TYPE_START != chat.mChatType) && (CHAT_TYPE_STOP != chat.mChatType) && (CHAT_TYPE_OWNER != chat.mChatType) )
2447 {
2448 // NOTE: chatter can be NULL (may not have rezzed yet, or could be another avie's HUD attachment)
2449 BOOL is_attachment = (chatter) ? chatter->isAttachment() : FALSE;
2450
2451 // Filtering "rules":
2452 // avatar => filter all avie text (unless it's this avie or they're an exemption)
2453 // objects => filter everything except attachments this avie owns
2454 if ( ((CHAT_SOURCE_AGENT == chat.mSourceType) && (from_id != gAgent.getID())) || (!is_owned_by_me) || (!is_attachment) )
2455 {
2456 if (!rlvIsEmote(mesg))
2457 {
2458 if ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVCHAT)) && (!gRlvHandler.isException(RLV_BHVR_RECVCHAT, from_id)) )
2459 gRlvHandler.filterChat(mesg, false);
2460 }
2461 else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVEMOTE)) && (!gRlvHandler.isException(RLV_BHVR_RECVEMOTE, from_id)) )
2462 {
2463 mesg = "/me ...";
2464 }
2465 }
2466
2467 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
2468 {
2469 // Filtering "rules":
2470 // avatar => filter only their name (unless it's this avie)
2471 // other => filter everything except attachments this avie owns but then we still do filter their text
2472 if (CHAT_SOURCE_AGENT == chat.mSourceType)
2473 {
2474 if (chat.mFromID != gAgent.getID())
2475 from_name = gRlvHandler.getAnonym(from_name);
2476 }
2477 else
2478 {
2479 if ( (!is_owned_by_me) || (!is_attachment) )
2480 gRlvHandler.filterNames(from_name);
2481 gRlvHandler.filterNames(mesg);
2482 }
2483 chat.mRlvNamesFiltered = true;
2484 }
2485 }
2486// [/RLVa:KB]
2487
2273 BOOL ircstyle = FALSE; 2488 BOOL ircstyle = FALSE;
2274 2489
2275 // Look for IRC-style emotes here so chatbubbles work 2490 // Look for IRC-style emotes here so chatbubbles work
@@ -2334,8 +2549,76 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
2334 case CHAT_TYPE_WHISPER: 2549 case CHAT_TYPE_WHISPER:
2335 verb = " " + LLTrans::getString("whisper") + " "; 2550 verb = " " + LLTrans::getString("whisper") + " ";
2336 break; 2551 break;
2337 case CHAT_TYPE_DEBUG_MSG:
2338 case CHAT_TYPE_OWNER: 2552 case CHAT_TYPE_OWNER:
2553// [RLVa:KB] - Checked: 2009-08-05 (RLVa-1.0.1e) | Modified: RLVa-1.0.1e
2554 if ( (rlv_handler_t::isEnabled()) && (mesg.length() > 3) && (RLV_CMD_PREFIX == mesg[0]) )
2555 {
2556 mesg.erase(0, 1);
2557 LLStringUtil::toLower(mesg);
2558
2559 std::string strExecuted, strFailed, strRetained, *pstr;
2560
2561 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
2562 boost::char_separator<char> sep(",", "", boost::drop_empty_tokens);
2563 tokenizer tokens(mesg, sep);
2564 for (tokenizer::iterator itToken = tokens.begin(); itToken != tokens.end(); ++itToken)
2565 {
2566 if (LLStartUp::getStartupState() == STATE_STARTED)
2567 {
2568 if (gRlvHandler.processCommand(from_id, *itToken, true))
2569 pstr = &strExecuted;
2570 else
2571 pstr = &strFailed;
2572 }
2573 else
2574 {
2575 gRlvHandler.retainCommand(from_name, from_id, *itToken);
2576 pstr = &strRetained;
2577 }
2578
2579 if (!pstr->empty())
2580 pstr->push_back(',');
2581 pstr->append(*itToken);
2582 }
2583
2584 if (!RlvSettings::getDebug())
2585 return;
2586
2587 // Silly people want comprehensive debug messages, blah :p
2588 if ( (!strExecuted.empty()) && (strFailed.empty()) && (strRetained.empty()) )
2589 verb = " executes: @";
2590 else if ( (strExecuted.empty()) && (!strFailed.empty()) && (strRetained.empty()) )
2591 verb = " failed: @";
2592 else if ( (strExecuted.empty()) && (strFailed.empty()) && (!strRetained.empty()) )
2593 verb = " retained: @";
2594 else
2595 {
2596 verb = ": @";
2597 if (!strExecuted.empty())
2598 mesg += "\n - executed: @" + strExecuted;
2599 if (!strFailed.empty())
2600 mesg += "\n - failed: @" + strFailed;
2601 if (!strRetained.empty())
2602 mesg += "\n - retained: @" + strRetained;
2603 }
2604
2605 break;
2606 }
2607// [/RLVa:KB]
2608// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
2609 // Copy/paste from above
2610 if ( (chatter) && (chat.mChatType != CHAT_TYPE_DEBUG_MSG) )
2611 {
2612 LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent());
2613 psc->setSourceObject(chatter);
2614 psc->setColor(color);
2615 //We set the particles to be owned by the object's owner,
2616 //just in case they should be muted by the mute list
2617 psc->setOwnerUUID(owner_id);
2618 LLViewerPartSim::getInstance()->addPartSource(psc);
2619 }
2620// [/RLVa:KB]
2621 case CHAT_TYPE_DEBUG_MSG:
2339 case CHAT_TYPE_NORMAL: 2622 case CHAT_TYPE_NORMAL:
2340 verb = ": "; 2623 verb = ": ";
2341 break; 2624 break;
@@ -2404,7 +2687,10 @@ void process_teleport_start(LLMessageSystem *msg, void**)
2404 U32 teleport_flags = 0x0; 2687 U32 teleport_flags = 0x0;
2405 msg->getU32("Info", "TeleportFlags", teleport_flags); 2688 msg->getU32("Info", "TeleportFlags", teleport_flags);
2406 2689
2407 if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) 2690 //if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL)
2691// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.0b
2692 if ( (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) || (!gRlvHandler.getCanCancelTp()) )
2693// [/RLVa:KB]
2408 { 2694 {
2409 gViewerWindow->setProgressCancelButtonVisible(FALSE); 2695 gViewerWindow->setProgressCancelButtonVisible(FALSE);
2410 } 2696 }
@@ -2439,7 +2725,10 @@ void process_teleport_progress(LLMessageSystem* msg, void**)
2439 } 2725 }
2440 U32 teleport_flags = 0x0; 2726 U32 teleport_flags = 0x0;
2441 msg->getU32("Info", "TeleportFlags", teleport_flags); 2727 msg->getU32("Info", "TeleportFlags", teleport_flags);
2442 if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) 2728 //if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL)
2729// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.0b
2730 if ( (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) || (!gRlvHandler.getCanCancelTp()) )
2731// [/RLVa:KB]
2443 { 2732 {
2444 gViewerWindow->setProgressCancelButtonVisible(FALSE); 2733 gViewerWindow->setProgressCancelButtonVisible(FALSE);
2445 } 2734 }
@@ -2780,7 +3069,10 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
2780 // know what you look like. 3069 // know what you look like.
2781 gAgent.sendAgentSetAppearance(); 3070 gAgent.sendAgentSetAppearance();
2782 3071
2783 if (avatarp) 3072// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
3073 if ( (avatarp) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) )
3074// [/RLVa:KB]
3075// if (avatarp)
2784 { 3076 {
2785 // Chat the "back" SLURL. (DEV-4907) 3077 // Chat the "back" SLURL. (DEV-4907)
2786 LLChat chat("Teleport completed from " + gAgent.getTeleportSourceSLURL()); 3078 LLChat chat("Teleport completed from " + gAgent.getTeleportSourceSLURL());
@@ -4360,7 +4652,13 @@ void notify_cautioned_script_question(LLScriptQuestionCBData* cbdata, S32 orig_q
4360 if (viewregion) 4652 if (viewregion)
4361 { 4653 {
4362 // got the region, so include the region and 3d coordinates of the object 4654 // got the region, so include the region and 3d coordinates of the object
4363 notice.setArg("[REGIONNAME]", viewregion->getName()); 4655 notice.setArg("[REGIONNAME]", viewregion->getName());
4656// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
4657 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) )
4658 {
4659 notice.setArg("[REGIONNAME]", rlv_handler_t::cstrHiddenRegion);
4660 }
4661// [/RLVa:KB]
4364 std::string formatpos = llformat("%.1f, %.1f,%.1f", objpos[VX], objpos[VY], objpos[VZ]); 4662 std::string formatpos = llformat("%.1f, %.1f,%.1f", objpos[VX], objpos[VY], objpos[VZ]);
4365 notice.setArg("[REGIONPOS]", formatpos); 4663 notice.setArg("[REGIONPOS]", formatpos);
4366 4664
@@ -4565,8 +4863,31 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
4565 4863
4566 LLScriptQuestionCBData *cbdata = new LLScriptQuestionCBData(taskid, itemid, sender, questions, object_name, owner_name); 4864 LLScriptQuestionCBData *cbdata = new LLScriptQuestionCBData(taskid, itemid, sender, questions, object_name, owner_name);
4567 4865
4866// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0e
4867 S32 rlvQuestionsOther = questions;
4868
4869 if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour("acceptpermission")) )
4870 {
4871 LLViewerObject* pObj = gObjectList.findObject(taskid);
4872 if (pObj)
4873 {
4874 if (pObj->permYouOwner())
4875 {
4876 // PERMISSION_TAKE_CONTROLS and PERMISSION_ATTACH are only auto-granted to objects this avie owns
4877 rlvQuestionsOther &= ~(LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TAKE_CONTROLS] |
4878 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_ATTACH]);
4879 }
4880 }
4881 }
4882
4883 if ( (!caution) && (!rlvQuestionsOther) )
4884 {
4885 script_question_cb(0, cbdata);
4886 }
4887 else if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
4888// [/RLVa:KB]
4568 // check whether cautions are even enabled or not 4889 // check whether cautions are even enabled or not
4569 if (gSavedSettings.getBOOL("PermissionsCautionEnabled")) 4890 //if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
4570 { 4891 {
4571 if (caution) 4892 if (caution)
4572 { 4893 {
@@ -4858,6 +5179,21 @@ void handle_lure_callback(S32 option, const std::string& text, void* userdata)
4858 5179
4859 if(0 == option) 5180 if(0 == option)
4860 { 5181 {
5182// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0b
5183 bool fRlvCensorMessage = false;
5184 if (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIM))
5185 {
5186 for (LLDynamicArray<LLUUID>::iterator it = invitees->begin(); it != invitees->end(); ++it)
5187 {
5188 if (!gRlvHandler.isException(RLV_BHVR_SENDIM, *it))
5189 {
5190 fRlvCensorMessage = true;
5191 break;
5192 }
5193 }
5194 }
5195// [/RLVa:KB]
5196
4861 LLMessageSystem* msg = gMessageSystem; 5197 LLMessageSystem* msg = gMessageSystem;
4862 msg->newMessageFast(_PREHASH_StartLure); 5198 msg->newMessageFast(_PREHASH_StartLure);
4863 msg->nextBlockFast(_PREHASH_AgentData); 5199 msg->nextBlockFast(_PREHASH_AgentData);
@@ -4865,7 +5201,10 @@ void handle_lure_callback(S32 option, const std::string& text, void* userdata)
4865 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); 5201 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
4866 msg->nextBlockFast(_PREHASH_Info); 5202 msg->nextBlockFast(_PREHASH_Info);
4867 msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in. 5203 msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in.
4868 msg->addStringFast(_PREHASH_Message, text); 5204// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0b
5205 msg->addStringFast(_PREHASH_Message, (!fRlvCensorMessage) ? text : rlv_handler_t::cstrHidden);
5206// [/RLVa:KB]
5207 //msg->addStringFast(_PREHASH_Message, text);
4869 for(LLDynamicArray<LLUUID>::iterator itr = invitees->begin(); itr != invitees->end(); ++itr) 5208 for(LLDynamicArray<LLUUID>::iterator itr = invitees->begin(); itr != invitees->end(); ++itr)
4870 { 5209 {
4871 msg->nextBlockFast(_PREHASH_TargetData); 5210 msg->nextBlockFast(_PREHASH_TargetData);
@@ -4895,8 +5234,28 @@ void handle_lure(LLDynamicArray<LLUUID>& ids)
4895{ 5234{
4896 LLDynamicArray<LLUUID>* userdata = new LLDynamicArray<LLUUID>(ids); 5235 LLDynamicArray<LLUUID>* userdata = new LLDynamicArray<LLUUID>(ids);
4897 5236
5237// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-1.0.0a
5238 // Only allow offering teleports if everyone is a @tplure exception or able to map this avie under @showloc=n
5239 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
5240 {
5241 for (LLDynamicArray<LLUUID>::iterator it = ids.begin(); it != ids.end(); ++it)
5242 {
5243 const LLRelationship* pBuddyInfo = LLAvatarTracker::instance().getBuddyInfo(*it);
5244 if ( (!gRlvHandler.isException(RLV_BHVR_TPLURE, *it)) &&
5245 ((!pBuddyInfo) || (!pBuddyInfo->isOnline()) || (!pBuddyInfo->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION))) )
5246 {
5247 delete userdata;
5248 return;
5249 }
5250 }
5251 }
5252// [/RLVa:KB]
5253
4898 LLStringUtil::format_map_t edit_args; 5254 LLStringUtil::format_map_t edit_args;
4899 edit_args["[REGION]"] = gAgent.getRegion()->getName(); 5255// [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-1.0.0a
5256 edit_args["[REGION]"] = (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? gAgent.getRegion()->getName() : rlv_handler_t::cstrHidden;
5257// [/RLVa:KB]
5258 //edit_args["[REGION]"] = gAgent.getRegion()->getName();
4900 if (gAgent.isGodlike()) 5259 if (gAgent.isGodlike())
4901 { 5260 {
4902 gViewerWindow->alertXmlEditText("OfferTeleportFromGod", edit_args, 5261 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/llviewerobjectlist.cpp b/linden/indra/newview/llviewerobjectlist.cpp
index 9ccbf99..78c1730 100644
--- a/linden/indra/newview/llviewerobjectlist.cpp
+++ b/linden/indra/newview/llviewerobjectlist.cpp
@@ -74,6 +74,8 @@
74 74
75#include "llappviewer.h" 75#include "llappviewer.h"
76 76
77#include "primbackup.h"
78
77extern F32 gMinObjectDistance; 79extern F32 gMinObjectDistance;
78extern BOOL gAnimateTextures; 80extern BOOL gAnimateTextures;
79 81
@@ -163,8 +165,6 @@ U64 LLViewerObjectList::getIndex(const U32 local_id,
163 165
164BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object) 166BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object)
165{ 167{
166 if(object.getRegion())
167 {
168 U32 local_id = object.mLocalID; 168 U32 local_id = object.mLocalID;
169 LLHost region_host = object.getRegion()->getHost(); 169 LLHost region_host = object.getRegion()->getHost();
170 U32 ip = region_host.getAddress(); 170 U32 ip = region_host.getAddress();
@@ -176,9 +176,6 @@ BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object)
176 return sIndexAndLocalIDToUUID.erase(indexid) > 0 ? TRUE : FALSE; 176 return sIndexAndLocalIDToUUID.erase(indexid) > 0 ? TRUE : FALSE;
177 } 177 }
178 178
179 return FALSE ;
180}
181
182void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id, 179void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id,
183 const U32 local_id, 180 const U32 local_id,
184 const U32 ip, 181 const U32 ip,
@@ -222,6 +219,11 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,
222 219
223 updateActive(objectp); 220 updateActive(objectp);
224 221
222 if(!just_created)
223 primbackup::getInstance()->prim_update(objectp);
224
225
226
225 if (just_created) 227 if (just_created)
226 { 228 {
227 gPipeline.addObject(objectp); 229 gPipeline.addObject(objectp);
@@ -251,6 +253,9 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,
251 objectp->mCreateSelected = false; 253 objectp->mCreateSelected = false;
252 gViewerWindow->getWindow()->decBusyCount(); 254 gViewerWindow->getWindow()->decBusyCount();
253 gViewerWindow->getWindow()->setCursor( UI_CURSOR_ARROW ); 255 gViewerWindow->getWindow()->setCursor( UI_CURSOR_ARROW );
256
257 primbackup::getInstance()->newprim(objectp);
258
254 } 259 }
255} 260}
256 261
@@ -827,17 +832,10 @@ void LLViewerObjectList::removeDrawable(LLDrawable* drawablep)
827 832
828 for (S32 i = 0; i < drawablep->getNumFaces(); i++) 833 for (S32 i = 0; i < drawablep->getNumFaces(); i++)
829 { 834 {
830 LLFace* facep = drawablep->getFace(i) ; 835 LLViewerObject* objectp = drawablep->getFace(i)->getViewerObject();
831 if(facep)
832 {
833 LLViewerObject* objectp = facep->getViewerObject();
834 if(objectp)
835 {
836 mSelectPickList.erase(objectp); 836 mSelectPickList.erase(objectp);
837 } 837 }
838 } 838 }
839 }
840}
841 839
842BOOL LLViewerObjectList::killObject(LLViewerObject *objectp) 840BOOL LLViewerObjectList::killObject(LLViewerObject *objectp)
843{ 841{
@@ -914,7 +912,7 @@ void LLViewerObjectList::killAllObjects()
914 if (!mMapObjects.empty()) 912 if (!mMapObjects.empty())
915 { 913 {
916 llwarns << "Some objects still on map object list!" << llendl; 914 llwarns << "Some objects still on map object list!" << llendl;
917 mMapObjects.clear(); 915 mActiveObjects.clear();
918 } 916 }
919} 917}
920 918
diff --git a/linden/indra/newview/llviewertexteditor.cpp b/linden/indra/newview/llviewertexteditor.cpp
index 54b7743..76b752c 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 3b23bb9..2240d44 100644
--- a/linden/indra/newview/llviewerwindow.cpp
+++ b/linden/indra/newview/llviewerwindow.cpp
@@ -2993,6 +2993,16 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls,
2993 { 2993 {
2994 moveable_object_selected = TRUE; 2994 moveable_object_selected = TRUE;
2995 this_object_movable = TRUE; 2995 this_object_movable = TRUE;
2996
2997// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0g
2998 if ( (rlv_handler_t::isEnabled()) &&
2999 ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP))) )
3000 {
3001 LLVOAvatar* pAvatar = gAgent.getAvatarObject();
3002 if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == object->getRootEdit()) )
3003 moveable_object_selected = this_object_movable = FALSE;
3004 }
3005// [/RLVa:KB]
2996 } 3006 }
2997 all_selected_objects_move = all_selected_objects_move && this_object_movable; 3007 all_selected_objects_move = all_selected_objects_move && this_object_movable;
2998 all_selected_objects_modify = all_selected_objects_modify && object->permModify(); 3008 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/primbackup.cpp b/linden/indra/newview/primbackup.cpp
new file mode 100644
index 0000000..78fd482
--- /dev/null
+++ b/linden/indra/newview/primbackup.cpp
@@ -0,0 +1,1105 @@
1
2#include "llviewerprecompiledheaders.h"
3#include "llviewermenu.h"
4
5
6// system library includes
7#include <iostream>
8#include <fstream>
9#include <sstream>
10
11// linden library includes
12#include "llfilepicker.h"
13#include "indra_constants.h"
14#include "llsdserialize.h"
15#include "llsdutil.h"
16
17#include "llcallbacklist.h"
18
19// newview includes
20#include "llagent.h"
21#include "llselectmgr.h"
22#include "lltoolplacer.h"
23
24#include "lltexturecache.h"
25
26#include "llnotify.h"
27
28#include "llapr.h"
29#include "lldir.h"
30#include "llimage.h"
31#include "lllfsthread.h"
32#include "llviewercontrol.h"
33#include "llassetuploadresponders.h"
34#include "lleconomy.h"
35#include "llhttpclient.h"
36#include "lluploaddialog.h"
37#include "lldir.h"
38#include "llinventorymodel.h" // gInventory
39#include "llviewercontrol.h" // gSavedSettings
40#include "llviewermenu.h" // gMenuHolder
41#include "llagent.h"
42#include "llfilepicker.h"
43#include "llfloateranimpreview.h"
44#include "llfloaterbuycurrency.h"
45#include "llfloaterimagepreview.h"
46#include "llfloaternamedesc.h"
47#include "llfloatersnapshot.h"
48#include "llinventorymodel.h" // gInventory
49#include "llresourcedata.h"
50#include "llstatusbar.h"
51#include "llviewercontrol.h" // gSavedSettings
52#include "llviewerimagelist.h"
53#include "lluictrlfactory.h"
54#include "llviewermenu.h" // gMenuHolder
55#include "llviewerregion.h"
56#include "llviewerstats.h"
57#include "llviewerwindow.h"
58#include "llappviewer.h"
59#include "lluploaddialog.h"
60// Included to allow LLTextureCache::purgeTextures() to pause watchdog timeout
61#include "llappviewer.h"
62#include "lltransactiontypes.h"
63
64#include "primbackup.h"
65
66#include "llviewerobjectlist.h"
67
68primbackup* primbackup::sInstance = 0;
69
70class importResponder: public LLNewAgentInventoryResponder
71{
72 public:
73
74 importResponder(const LLSD& post_data,
75 const LLUUID& vfile_id,
76 LLAssetType::EType asset_type)
77 : LLNewAgentInventoryResponder(post_data, vfile_id, asset_type)
78 {
79 }
80
81
82 //virtual
83 virtual void uploadComplete(const LLSD& content)
84 {
85 lldebugs << "LLNewAgentInventoryResponder::result from capabilities" << llendl;
86
87 LLAssetType::EType asset_type = LLAssetType::lookup(mPostData["asset_type"].asString());
88 LLInventoryType::EType inventory_type = LLInventoryType::lookup(mPostData["inventory_type"].asString());
89
90 // Update L$ and ownership credit information
91 // since it probably changed on the server
92 if (asset_type == LLAssetType::AT_TEXTURE ||
93 asset_type == LLAssetType::AT_SOUND ||
94 asset_type == LLAssetType::AT_ANIMATION)
95 {
96 gMessageSystem->newMessageFast(_PREHASH_MoneyBalanceRequest);
97 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
98 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
99 gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
100 gMessageSystem->nextBlockFast(_PREHASH_MoneyData);
101 gMessageSystem->addUUIDFast(_PREHASH_TransactionID, LLUUID::null );
102 gAgent.sendReliableMessage();
103
104// LLStringUtil::format_map_t args;
105// args["[AMOUNT]"] = llformat("%d",LLGlobalEconomy::Singleton::getInstance()->getPriceUpload());
106// LLNotifyBox::showXml("UploadPayment", args);
107 }
108
109 // Actually add the upload to viewer inventory
110 llinfos << "Adding " << content["new_inventory_item"].asUUID() << " "
111 << content["new_asset"].asUUID() << " to inventory." << llendl;
112 if(mPostData["folder_id"].asUUID().notNull())
113 {
114 LLPermissions perm;
115 U32 next_owner_perm;
116 perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null);
117 if (mPostData["inventory_type"].asString() == "snapshot")
118 {
119 next_owner_perm = PERM_ALL;
120 }
121 else
122 {
123 next_owner_perm = PERM_MOVE | PERM_TRANSFER;
124 }
125 perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, next_owner_perm);
126 S32 creation_date_now = time_corrected();
127 LLPointer<LLViewerInventoryItem> item
128 = new LLViewerInventoryItem(content["new_inventory_item"].asUUID(),
129 mPostData["folder_id"].asUUID(),
130 perm,
131 content["new_asset"].asUUID(),
132 asset_type,
133 inventory_type,
134 mPostData["name"].asString(),
135 mPostData["description"].asString(),
136 LLSaleInfo::DEFAULT,
137 LLInventoryItem::II_FLAGS_NONE,
138 creation_date_now);
139 gInventory.updateItem(item);
140 gInventory.notifyObservers();
141 }
142 else
143 {
144 llwarns << "Can't find a folder to put it in" << llendl;
145 }
146
147 // remove the "Uploading..." message
148 LLUploadDialog::modalUploadFinished();
149
150 primbackup::getInstance()->update_map(content["new_asset"].asUUID());
151 primbackup::getInstance()->upload_next_asset();
152
153 }
154
155};
156
157
158
159class CacheReadResponder : public LLTextureCache::ReadResponder
160 {
161 public:
162 CacheReadResponder(const LLUUID& id, LLImageFormatted* image)
163 : mFormattedImage(image), mID(id)
164 {
165 setImage(image);
166 }
167 void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal)
168 {
169 if(imageformat==IMG_CODEC_TGA && mFormattedImage->getCodec()==IMG_CODEC_J2C)
170 {
171 llwarns<<"Bleh its a tga not saving"<<llendl;
172 mFormattedImage=NULL;
173 mImageSize=0;
174 return;
175 }
176
177 if (mFormattedImage.notNull())
178 {
179 llassert_always(mFormattedImage->getCodec() == imageformat);
180 mFormattedImage->appendData(data, datasize);
181 }
182 else
183 {
184 mFormattedImage = LLImageFormatted::createFromType(imageformat);
185 mFormattedImage->setData(data,datasize);
186 }
187 mImageSize = imagesize;
188 mImageLocal = imagelocal;
189 }
190
191 virtual void completed(bool success)
192 {
193 if(success && (mFormattedImage.notNull()) && mImageSize>0)
194 {
195
196 llinfos << "SUCCESS getting texture "<<mID<< llendl;
197
198 std::string name;
199 mID.toString(name);
200 llinfos << "Saving to "<<(primbackup::getInstance()->getfolder()+"//"+name)<<llendl;
201 if(!mFormattedImage->save(primbackup::getInstance()->getfolder()+"//"+name))
202 {
203 llinfos << "FAIL saving texture "<<mID<< llendl;
204 }
205
206 }
207 else
208 {
209 if(!success)
210 llwarns << "FAIL NOT SUCCESSFUL getting texture "<<mID<< llendl;
211 if(mFormattedImage.isNull())
212 llwarns << "FAIL image is NULL "<<mID<< llendl;
213 }
214
215 primbackup::getInstance()->m_nexttextureready=true;
216 //JUST SAY NO TO APR DEADLOCKING
217 //primbackup::getInstance()->export_next_texture();
218 }
219 private:
220 LLPointer<LLImageFormatted> mFormattedImage;
221 LLUUID mID;
222 };
223
224
225
226primbackup::primbackup()
227: LLFloater( std::string("Prim Import Floater") )
228{
229 LLUICtrlFactory::getInstance()->buildFloater( this, "floater_prim_import.xml" );
230
231 // reposition floater from saved settings
232 //LLRect rect = gSavedSettings.getRect( "FloaterPrimImport" );
233 //reshape( rect.getWidth(), rect.getHeight(), FALSE );
234 //setRect( rect );
235
236 running=false;
237 textures.clear();
238 assetmap.clear();
239 current_asset=LLUUID::null;
240 m_retexture=false;
241 close();
242}
243
244
245////////////////////////////////////////////////////////////////////////////////
246//
247primbackup* primbackup::getInstance()
248{
249 if ( ! sInstance )
250 sInstance = new primbackup();
251
252 return sInstance;
253}
254
255primbackup::~primbackup()
256{
257 // save position of floater
258 gSavedSettings.setRect( "FloaterPrimImport", getRect() );
259 sInstance = 0;
260}
261
262void primbackup::draw()
263{
264 LLFloater::draw();
265}
266
267void primbackup::show()
268{
269 // set the title
270 setTitle( "stuff" );
271 m_curobject=1;
272 m_curprim=0;
273 m_objects=0;
274 m_prims=0;
275 m_textures=0;
276 m_curtexture=0;
277 rezcount=0;
278
279 // make floater appear
280 setVisibleAndFrontmost();
281}
282
283
284void primbackup::onClose( bool app_quitting )
285{
286 setVisible( false );
287 // HACK for fast XML iteration replace with:
288 // destroy();
289}
290
291void primbackup::updateexportnumbers()
292{
293
294 std::stringstream sstr;
295 LLUICtrl * ctrl=this->getChild<LLUICtrl>("name_label");
296
297 sstr<<"Export Progress \n";
298
299 sstr << "Remaining Textures "<<textures.size()<<"\n";
300 ctrl->setValue(LLSD("Text")=sstr.str());
301
302}
303
304
305void primbackup::updateimportnumbers()
306{
307 std::stringstream sstr;
308 LLUICtrl * ctrl=this->getChild<LLUICtrl>("name_label");
309
310 if(m_retexture)
311 {
312 sstr << " Textures uploads remaining : "<<textures.size()<<"\n";
313 ctrl->setValue(LLSD("Text")=sstr.str());
314 }
315 else
316 {
317 sstr << " Textures uploads N/A \n";
318 ctrl->setValue(LLSD("Text")=sstr.str());
319 }
320 sstr << " Objects "<<this->m_curobject<<"/"<<this->m_objects<<"\n";
321 ctrl->setValue(LLSD("Text")=sstr.str());
322
323 sstr << " Rez "<<this->rezcount<<"/"<<this->m_prims;
324 ctrl->setValue(LLSD("Text")=sstr.str());
325
326 sstr << " Build "<<this->m_curprim<<"/"<<this->m_prims;
327 ctrl->setValue(LLSD("Text")=sstr.str());
328
329
330}
331
332void primbackup::pre_export_object()
333{
334 textures.clear();
335 llsd.clear();
336 this_group.clear();
337
338 // Open the file save dialog
339 LLFilePicker& file_picker = LLFilePicker::instance();
340 if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_XML ) )
341 {
342 // User canceled save.
343 return;
344 }
345
346 file_name = file_picker.getCurFile();
347 folder = gDirUtilp->getDirName(file_name);
348
349 export_state=EXPORT_INIT;
350 gIdleCallbacks.addFunction(exportworker, NULL);
351}
352
353void primbackup::exportworker(void *userdata)
354{
355 primbackup::getInstance()->updateexportnumbers();
356
357 switch(primbackup::getInstance()->export_state)
358 {
359 case EXPORT_INIT:
360 {
361 primbackup::getInstance()->show();
362 LLSelectMgr::getInstance()->getSelection()->ref();
363
364 struct ff : public LLSelectedNodeFunctor
365 {
366 virtual bool apply(LLSelectNode* node)
367 {
368 if(gAgent.getID()!=node->mPermissions->getOwner())
369 {
370 #ifdef LL_GRID_PERMISSIONS
371 return false;
372 #else
373 return true;
374 #endif
375 }
376 else if(581632==node->mPermissions->getMaskOwner() || 2147483647==node->mPermissions->getMaskOwner())
377 {
378 return true;
379 }
380 return false;
381 }
382 } func;
383
384 if(LLSelectMgr::getInstance()->getSelection()->applyToNodes(&func,false))
385 primbackup::getInstance()->export_state=EXPORT_STRUCTURE;
386 else
387 {
388 llwarns<<"Incorrect permission to export"<<llendl;
389 primbackup::getInstance()->export_state=EXPORT_DONE;
390 primbackup::getInstance()->close();
391 gIdleCallbacks.deleteFunction(exportworker);
392 LLSelectMgr::getInstance()->getSelection()->unref();
393
394 }
395 break;
396 }
397
398 break;
399 case EXPORT_STRUCTURE:
400 {
401 struct ff : public LLSelectedObjectFunctor
402 {
403 virtual bool apply(LLViewerObject* object)
404 {
405 object->boostTexturePriority(TRUE);
406 LLViewerObject::child_list_t children = object->getChildren();
407 children.push_front(object); //push root onto list
408 LLSD prim_llsd=primbackup::getInstance()->prims_to_llsd(children);
409 LLSD stuff;
410 stuff["root_position"] = object->getPosition().getValue();
411 stuff["root_rotation"] = ll_sd_from_quaternion(object->getRotation());
412 stuff["group_body"] = prim_llsd;
413 primbackup::getInstance()->llsd["data"].append(stuff);
414 return true;
415 }
416 } func;
417
418 primbackup::getInstance()->export_state=EXPORT_LLSD;
419 LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func,false);
420 LLSelectMgr::getInstance()->getSelection()->unref();
421
422 break;
423 }
424 case EXPORT_TEXTURES:
425 if(primbackup::getInstance()->m_nexttextureready==false)
426 return;
427
428 //Ok we got work to do
429 primbackup::getInstance()->m_nexttextureready=false;
430
431 if(primbackup::getInstance()->textures.empty())
432 {
433 primbackup::getInstance()->export_state=EXPORT_DONE;
434 return;
435 }
436
437 primbackup::getInstance()->export_next_texture();
438 break;
439
440 case EXPORT_LLSD:
441 {
442 // Create a file stream and write to it
443 llofstream export_file(primbackup::getInstance()->file_name);
444 LLSDSerialize::toPrettyXML(primbackup::getInstance()->llsd, export_file);
445 export_file.close();
446 primbackup::getInstance()->m_nexttextureready=true;
447 primbackup::getInstance()->export_state=EXPORT_TEXTURES;
448 }
449 break;
450 case EXPORT_DONE:
451 llinfos<<"Backup complete"<<llendl
452 gIdleCallbacks.deleteFunction(exportworker);
453 primbackup::getInstance()->close();
454 break;
455 }
456}
457
458LLSD primbackup::prims_to_llsd(LLViewerObject::child_list_t child_list)
459{
460
461 LLViewerObject* object;
462 LLSD llsd;
463
464 char localid[16];
465
466 for (LLViewerObject::child_list_t::iterator i = child_list.begin(); i != child_list.end(); ++i)
467 {
468 object=(*i);
469 LLUUID id = object->getID();
470
471 llinfos << "Exporting prim " << object->getID().asString() << llendl;
472
473 // Create an LLSD object that represents this prim. It will be injected in to the overall LLSD
474 // tree structure
475 LLSD prim_llsd;
476
477 if (!object->isRoot())
478 {
479
480 // Parent id
481 snprintf(localid, sizeof(localid), "%u", object->getSubParent()->getLocalID());
482 prim_llsd["parent"] = localid;
483 }
484
485 // Transforms
486 prim_llsd["position"] = object->getPosition().getValue();
487 prim_llsd["scale"] = object->getScale().getValue();
488 prim_llsd["rotation"] = ll_sd_from_quaternion(object->getRotation());
489
490 // Flags
491 prim_llsd["shadows"] = object->flagCastShadows();
492 prim_llsd["phantom"] = object->flagPhantom();
493 prim_llsd["physical"] = (BOOL)(object->mFlags & FLAGS_USE_PHYSICS);
494
495 // Volume params
496 LLVolumeParams params = object->getVolume()->getParams();
497 prim_llsd["volume"] = params.asLLSD();
498
499 // Extra paramsb6fab961-af18-77f8-cf08-f021377a7244
500 if (object->isFlexible())
501 {
502 // Flexible
503 LLFlexibleObjectData* flex = (LLFlexibleObjectData*)object->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
504 prim_llsd["flexible"] = flex->asLLSD();
505 }
506 if (object->getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT))
507 {
508 // Light
509 LLLightParams* light = (LLLightParams*)object->getParameterEntry(LLNetworkData::PARAMS_LIGHT);
510 prim_llsd["light"] = light->asLLSD();
511 }
512 if (object->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT))
513 {
514 // Sculpt
515 LLSculptParams* sculpt = (LLSculptParams*)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
516 prim_llsd["sculpt"] = sculpt->asLLSD();
517
518 LLUUID sculpt_texture=sculpt->getSculptTexture();
519 bool alreadyseen=false;
520 std::list<LLUUID>::iterator iter;
521 for(iter = textures.begin(); iter != textures.end() ; iter++)
522 {
523 if( (*iter)==sculpt_texture)
524 alreadyseen=true;
525 }
526 if(alreadyseen==false)
527 {
528 llinfos << "Found a sculpt texture, adding to list "<<sculpt_texture<<llendl;
529 textures.push_back(sculpt_texture);
530 }
531 }
532
533 // Textures
534 LLSD te_llsd;
535 U8 te_count = object->getNumTEs();
536 for (U8 i = 0; i < te_count; i++)
537 {
538 bool alreadyseen=false;
539 te_llsd.append(object->getTE(i)->asLLSD());
540 std::list<LLUUID>::iterator iter;
541 for(iter = textures.begin(); iter != textures.end() ; iter++)
542 {
543 if( (*iter)==object->getTE(i)->getID())
544 alreadyseen=true;
545 }
546 if(alreadyseen==false)
547 textures.push_back(object->getTE(i)->getID());
548 }
549 prim_llsd["textures"] = te_llsd;
550
551 // The keys in the primitive maps do not have to be localids, they can be any
552 // string. We simply use localids because they are a unique identifier
553 snprintf(localid, sizeof(localid), "%u", object->getLocalID());
554 llsd[(const char*)localid] = prim_llsd;
555 }
556
557 updateexportnumbers();
558
559 return llsd;
560}
561
562
563void primbackup::export_next_texture()
564{
565 if(textures.empty())
566 {
567 llinfos << "Finished exporting textures "<<llendl;
568 return;
569 }
570
571 std::list<LLUUID>::iterator iter;
572 iter = textures.begin();
573
574 LLUUID id;
575
576 while(1)
577 {
578 if(iter==textures.end())
579 {
580 m_nexttextureready=true;
581 return;
582 }
583
584 id=(*iter);
585
586 LLViewerImage * imagep = gImageList.hasImage(id);
587 if(imagep!=NULL)
588 {
589 S32 cur_discard = imagep->getDiscardLevel();
590 if(cur_discard>0)
591 {
592 if(imagep->getBoostLevel()!=LLViewerImage::BOOST_PREVIEW)
593 imagep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); //we want to force discard 0 this one does this.
594 }
595 else
596 {
597 break;
598 }
599 }
600 else
601 {
602 llwarns<<" We *DONT* have the texture "<<llendl;
603 }
604 iter++;
605 }
606
607 textures.remove(id);
608
609 llinfos<<"Requesting texture "<<id<<llendl;
610 LLImageJ2C * mFormattedImage = new LLImageJ2C;
611 CacheReadResponder* responder = new CacheReadResponder(id, mFormattedImage);
612 LLAppViewer::getTextureCache()->readFromCache(id,LLWorkerThread::PRIORITY_HIGH,0,999999,responder);
613}
614
615
616
617void primbackup::import_object(bool upload)
618{
619 textures.clear();
620 assetmap.clear();
621 current_asset=LLUUID::null;
622
623 this->m_retexture=upload;
624
625 // Open the file open dialog
626 LLFilePicker& file_picker = LLFilePicker::instance();
627 if( !file_picker.getOpenFile( LLFilePicker::FFLOAD_XML ) )
628 {
629 // User canceled save.
630 return;
631 }
632 std::string file_name = file_picker.getFirstFile().c_str();
633 folder = gDirUtilp->getDirName(file_name);
634
635 llifstream import_file(file_name);
636 LLSDSerialize::fromXML(llsd, import_file);
637 import_file.close();
638
639 show();
640
641 //Get the texture map
642
643 LLSD::map_const_iterator prim_it;
644 LLSD::array_const_iterator prim_arr_it;
645
646 this->m_curobject=1;
647 this->m_curprim=1;
648 this->m_objects=llsd["data"].size();
649 this->m_prims=0;
650 rezcount=0;
651
652 updateimportnumbers();
653
654 for( prim_arr_it = llsd["data"].beginArray(); prim_arr_it != llsd["data"].endArray(); prim_arr_it++)
655 {
656
657 LLSD llsd2;
658 llsd2=(*prim_arr_it)["group_body"];
659
660 for( prim_it = llsd2.beginMap(); prim_it != llsd2.endMap(); prim_it++)
661 {
662 LLSD prim_llsd;
663 prim_llsd=llsd2[prim_it->first];
664 LLSD::array_iterator text_it;
665 std::list<LLUUID>::iterator iter;
666
667 if(prim_llsd.has("sculpt"))
668 {
669 LLSculptParams* sculpt=new LLSculptParams();
670 sculpt->fromLLSD(prim_llsd["sculpt"]);
671 LLUUID orig=sculpt->getSculptTexture();
672 bool alreadyseen=false;
673 for(iter = textures.begin(); iter != textures.end() ; iter++)
674 {
675 if( (*iter)==orig)
676 alreadyseen=true;
677 }
678 if(alreadyseen==false)
679 {
680 llinfos << "Found a new SCULPT texture to upload "<<orig<<llendl;
681 textures.push_back(orig);
682 }
683 }
684
685
686 LLSD te_llsd;
687 te_llsd=prim_llsd["textures"];
688
689
690 for(text_it=te_llsd.beginArray(); text_it !=te_llsd.endArray(); text_it++)
691 {
692 LLSD the_te;
693 the_te=(*text_it);
694 LLTextureEntry te;
695 te.fromLLSD(the_te);
696
697 te.getID();
698 bool alreadyseen=false;
699
700 for(iter = textures.begin(); iter != textures.end() ; iter++)
701 {
702 if( (*iter)==te.getID())
703 alreadyseen=true;
704 }
705 if(alreadyseen==false)
706 {
707 llinfos << "Found a new texture to upload "<<te.getID()<<llendl;
708 textures.push_back(te.getID());
709 }
710 }
711
712 }
713 }
714
715 if(m_retexture==TRUE)
716 upload_next_asset();
717 else
718 import_object1a();
719}
720
721LLVector3 primbackup::offset_agent(LLVector3 offset)
722{
723 LLVector3 pos= gAgent.getPositionAgent();
724 LLQuaternion agent_rot=LLQuaternion(gAgent.getAtAxis(),gAgent.getLeftAxis(),gAgent.getUpAxis());
725 pos=(offset*agent_rot+pos);
726 return pos;
727}
728
729void primbackup::rez_agent_offset(LLVector3 offset)
730{
731 // This will break for a sitting agent
732 LLToolPlacer* mPlacer = new LLToolPlacer();
733 mPlacer->setObjectType(LL_PCODE_CUBE);
734 //LLVector3 pos=offset_agent(offset);
735 mPlacer->placeObject((S32)(offset.mV[0]), (S32)(offset.mV[1]), 0);
736}
737
738void primbackup::import_object1a()
739{
740 running=true;
741
742 show();
743
744 group_prim_import_iter=llsd["data"].beginArray();
745 root_root_pos=(*group_prim_import_iter)["root_position"];
746
747 this->m_objects=llsd["data"].size();
748 this->m_curobject=1;
749 import_next_object();
750}
751
752void primbackup::import_next_object()
753{
754 toselect.clear();
755 rezcount=0;
756
757 this_group=(*group_prim_import_iter)["group_body"];
758 prim_import_iter=this_group.beginMap();
759
760 m_curprim=0;
761 m_prims=this_group.size();
762 updateimportnumbers();
763 LLVector3 lgpos=(*group_prim_import_iter)["root_position"];
764
765 group_offset=lgpos-root_root_pos;
766 root_pos=offset_agent(LLVector3(2.0,0,0));
767 root_rot=ll_quaternion_from_sd((*group_prim_import_iter)["root_rotation"]);
768
769 rez_agent_offset(LLVector3(0.0,2.0,0.0));
770 // Now we must wait for the callback when ViewerObjectList gets the new objects and we have the correct number selected
771}
772
773// This function takes a pointer to a viewerobject and applys the prim definition that prim_llsd has
774void primbackup::xmltoprim(LLSD prim_llsd,LLViewerObject * object)
775{
776 LLUUID id = object->getID();
777 expecting_update = object->getID();
778 LLSelectMgr::getInstance()->selectObjectAndFamily(object);
779
780 if(prim_llsd.has("parent"))
781 {
782 //we are not the root node.
783 LLVector3 pos=prim_llsd["position"];
784 LLQuaternion rot=ll_quaternion_from_sd(prim_llsd["rotation"]);
785 object->setPositionRegion((pos*root_rot)+(root_pos+group_offset));
786 object->setRotation(rot*root_rot);
787 }
788 else
789 {
790 object->setPositionRegion(root_pos+group_offset);
791 LLQuaternion rot=ll_quaternion_from_sd(prim_llsd["rotation"]);
792 object->setRotation(rot);
793 }
794
795 object->setScale(prim_llsd["scale"]);
796
797 if(prim_llsd.has("shadows"))
798 if(prim_llsd["shadows"].asInteger()==1)
799 object->setFlags(FLAGS_CAST_SHADOWS,true);
800
801 if(prim_llsd.has("phantom"))
802 if(prim_llsd["phantom"].asInteger()==1)
803 object->setFlags(FLAGS_PHANTOM,true);
804
805 if(prim_llsd.has("physical"))
806 if(prim_llsd["physical"].asInteger()==1)
807 object->setFlags(FLAGS_USE_PHYSICS,true);
808
809 // Volume params
810 LLVolumeParams volume_params = object->getVolume()->getParams();
811 volume_params.fromLLSD(prim_llsd["volume"]) ;
812 object->updateVolume(volume_params);
813
814 if(prim_llsd.has("sculpt"))
815 {
816 LLSculptParams* sculpt=new LLSculptParams();
817 sculpt->fromLLSD(prim_llsd["sculpt"]);
818
819 //TODO check if map is valid and only set texture is map is valid and changes
820
821 if(assetmap[sculpt->getSculptTexture()].notNull())
822 {
823 LLUUID replacment=assetmap[sculpt->getSculptTexture()];
824 sculpt->setSculptTexture(replacment);
825 }
826
827 object->setParameterEntry(LLNetworkData::PARAMS_SCULPT,(LLNetworkData&)(*sculpt),true);
828 }
829
830 if(prim_llsd.has("light"))
831 {
832 LLLightParams * light=new LLLightParams();
833 light->fromLLSD(prim_llsd["light"]);
834 object->setParameterEntry(LLNetworkData::PARAMS_LIGHT,(LLNetworkData&)(*light),true);
835 }
836
837 if(prim_llsd.has("flexible"))
838 {
839 LLFlexibleObjectData* flex=new LLFlexibleObjectData();
840 flex->fromLLSD(prim_llsd["flexible"]);
841 object->setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE,(LLNetworkData&)(*flex),true);
842 }
843
844
845 // Textures
846 LLSD te_llsd;
847 llinfos << "Processing textures for prim" << llendl;
848
849 te_llsd=prim_llsd["textures"];
850
851 LLSD::array_iterator text_it;
852 U8 i=0;
853 i=0;
854
855 for(text_it=te_llsd.beginArray(); text_it !=te_llsd.endArray(); text_it++)
856 {
857 LLSD the_te;
858 the_te=(*text_it);
859 LLTextureEntry te;
860 te.fromLLSD(the_te);
861
862 if(assetmap[te.getID()].notNull())
863 {
864 LLUUID replacment=assetmap[te.getID()];
865 te.setID(replacment);
866 }
867
868 object->setTE(i,te); //
869 i++;
870 }
871
872 llinfos << "Textures done!" << llendl;
873
874 //bump the iterator now so the callbacks hook together nicely
875 //if(prim_import_iter!=this_group.endMap())
876 // prim_import_iter++;
877
878 object->sendRotationUpdate();
879 object->sendTEUpdate();
880 object->sendShapeUpdate();
881 LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_SCALE |UPD_POSITION);
882
883 LLSelectMgr::getInstance()->deselectAll();
884}
885
886//This is fired when the update packet is processed so we know the prim settings have stuck
887void primbackup::prim_update(LLViewerObject* object)
888{
889 if(!running)
890 return;
891
892 if(object!=NULL)
893 if(object->mID!=expecting_update)
894 return;
895
896 m_curprim++;
897 updateimportnumbers();
898
899 prim_import_iter++;
900
901 LLUUID x;
902 expecting_update=x.null;
903
904 if(prim_import_iter==this_group.endMap())
905 {
906 llinfos<<"Trying to link"<<llendl;
907
908 if(toselect.size()>1)
909 {
910 std::reverse(toselect.begin(),toselect.end());
911 //Now link
912 LLSelectMgr::getInstance()->deselectAll();
913 LLSelectMgr::getInstance()->selectObjectAndFamily(toselect,true);
914 LLSelectMgr::getInstance()->sendLink();
915 LLViewerObject * root=toselect.back();
916 root->setRotation(root_rot);
917 }
918
919 this->m_curobject++;
920 group_prim_import_iter++;
921 if(group_prim_import_iter!=llsd["data"].endArray())
922 {
923 import_next_object();
924 return;
925 }
926
927 running=false;
928 this->close();
929 return;
930 }
931
932 LLSD prim_llsd;
933 prim_llsd=this_group[prim_import_iter->first];
934
935 if(toselect.empty())
936 {
937 llwarns << "error: ran out of objects to mod" << llendl;
938 return;
939 }
940
941 if(prim_import_iter!=this_group.endMap())
942 {
943 //rez_agent_offset(LLVector3(1.0,0,0));
944 LLSD prim_llsd=this_group[prim_import_iter->first];
945 process_iter++;
946 xmltoprim(prim_llsd,(*process_iter));
947 }
948}
949
950// Callback when we rez a new object when the importer is running.
951bool primbackup::newprim(LLViewerObject * pobject)
952{
953 if(running)
954 {
955 rezcount++;
956 toselect.push_back(pobject);
957 updateimportnumbers();
958 prim_import_iter++;
959
960 if(prim_import_iter!=this_group.endMap())
961 {
962
963 pobject->setPosition(this->offset_agent(LLVector3(0,1.0,0)));
964 LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION);
965
966 rez_agent_offset(LLVector3(1.0,0,0));
967 }
968 else
969 {
970 llinfos << "All prims rezed, moving to build stage" <<llendl;
971 prim_import_iter=this_group.beginMap();
972 LLSD prim_llsd=this_group[prim_import_iter->first];
973 process_iter=toselect.begin();
974 xmltoprim(prim_llsd,(*process_iter));
975 }
976 }
977
978 return true;
979}
980
981void primbackup::update_map(LLUUID uploaded_asset)
982{
983 if(current_asset.isNull())
984 return;
985
986 assetmap.insert(std::pair<LLUUID,LLUUID>(current_asset,uploaded_asset));
987 llinfos << "Mapping "<<current_asset<<" to "<<uploaded_asset<<llendl;
988
989}
990
991
992void myupload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type,
993 std::string name,
994 std::string desc, S32 compression_info,
995 LLAssetType::EType destination_folder_type,
996 LLInventoryType::EType inv_type,
997 U32 next_owner_perm,
998 const std::string& display_name,
999 LLAssetStorage::LLStoreAssetCallback callback,
1000 void *userdata)
1001{
1002 if(gDisconnected)
1003 {
1004 return ;
1005 }
1006
1007 LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID());
1008
1009 // At this point, we're ready for the upload.
1010 std::string upload_message = "Uploading...\n\n";
1011 upload_message.append(display_name);
1012 LLUploadDialog::modalUploadDialog(upload_message);
1013
1014 std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory");
1015 if (!url.empty())
1016 {
1017 LLSD body;
1018 body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type);
1019 body["asset_type"] = LLAssetType::lookup(asset_type);
1020 body["inventory_type"] = LLInventoryType::lookup(inv_type);
1021 body["name"] = name;
1022 body["description"] = desc;
1023
1024 std::ostringstream llsdxml;
1025 LLSDSerialize::toXML(body, llsdxml);
1026 lldebugs << "posting body to capability: " << llsdxml.str() << llendl;
1027 //LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type));
1028 LLHTTPClient::post(url, body, new importResponder(body, uuid, asset_type));
1029
1030 }
1031 else
1032 {
1033 llinfos << "NewAgentInventory capability not found, FUCK!" << llendl;
1034 }
1035}
1036
1037
1038
1039void primbackup::upload_next_asset()
1040{
1041 if(textures.empty())
1042 {
1043 llinfos<<" Texture list is empty, moving to rez statge"<< llendl;
1044 current_asset=LLUUID::null;
1045 import_object1a();
1046 return;
1047 }
1048
1049 this->updateimportnumbers();
1050
1051 std::list<LLUUID>::iterator iter;
1052 iter=textures.begin();
1053 LLUUID id=(*iter);
1054 textures.pop_front();
1055
1056 llinfos<<"Got texture ID "<<id<< "trying to upload"<<llendl;
1057
1058 current_asset=id;
1059 std::string struid;
1060 id.toString(struid);
1061 std::string filename=folder+"//"+struid;
1062
1063
1064 LLAssetID uuid;
1065 LLTransactionID tid;
1066
1067 // gen a new transaction ID for this asset
1068 tid.generate();
1069 uuid = tid.makeAssetID(gAgent.getSecureSessionID());
1070
1071 S32 file_size;
1072 apr_file_t* fp = ll_apr_file_open(filename, LL_APR_RB, &file_size);
1073 if (fp)
1074 {
1075 const S32 buf_size = 65536;
1076 U8 copy_buf[buf_size];
1077 LLVFile file(gVFS, uuid, LLAssetType::AT_TEXTURE, LLVFile::WRITE);
1078 file.setMaxSize(file_size);
1079
1080 while ((file_size = ll_apr_file_read(fp, copy_buf, buf_size)))
1081 {
1082 file.write(copy_buf, file_size);
1083 }
1084 apr_file_close(fp);
1085 }
1086 else
1087 {
1088 llwarns<<"Unable to access output file "<<filename<<llendl;
1089 upload_next_asset();
1090 return;
1091 }
1092
1093 myupload_new_resource(
1094 tid, LLAssetType::AT_TEXTURE, struid,
1095 struid, 0,
1096 LLAssetType::AT_TEXTURE,
1097 LLInventoryType::defaultForAssetType(LLAssetType::AT_TEXTURE),
1098 0x0,
1099 "Uploaded texture",
1100 NULL,
1101 NULL);
1102
1103
1104}
1105
diff --git a/linden/indra/newview/primbackup.h b/linden/indra/newview/primbackup.h
new file mode 100644
index 0000000..fddc35f
--- /dev/null
+++ b/linden/indra/newview/primbackup.h
@@ -0,0 +1,132 @@
1
2#include "llviewerinventory.h"
3
4#define LL_GRID_PERMISSIONS 1
5
6enum export_states {EXPORT_INIT,EXPORT_STRUCTURE,EXPORT_TEXTURES,EXPORT_LLSD,EXPORT_DONE};
7
8class primbackup : public LLFloater
9
10{
11 public:
12 //Export state machine
13 enum export_states export_state;
14
15 //Export idle callback
16 static void exportworker(void *userdata);
17
18 //Static accessor
19 static primbackup* getInstance();
20
21 virtual ~primbackup();
22
23 //Floater stuff
24 virtual void show();
25 virtual void draw();
26 virtual void onClose( bool app_quitting );
27
28 //Import entry point
29 void import_object(bool upload=FALSE);
30
31 //Export entry point
32 void pre_export_object();
33
34 //Update map from texture worker
35 void update_map(LLUUID uploaded_asset);
36
37 //Move to next texture upload
38 void upload_next_asset();
39
40 // is ready for next texture?
41 bool m_nexttextureready;
42
43 //Folder public geter
44 std::string getfolder() {return folder;};
45
46 //Prim updated callback
47 void prim_update(LLViewerObject* object);
48
49 //New prim call back
50 bool newprim(LLViewerObject * pobject);
51
52private:
53
54 //Static singleton stuff
55 primbackup();
56 static primbackup* sInstance;
57
58 // are we active flag
59 bool running;
60
61 //file and folder name control
62 std::string file_name;
63 std::string folder;
64
65 // True if we need to rebase the assets
66 bool m_retexture;
67
68 //Counts of import and export objects and textures and prims
69 int m_objects,m_curobject;
70 int m_prims,m_curprim;
71 int m_textures,m_curtexture;
72
73 // No prims rezed
74 int rezcount;
75
76 // Update the floater with status numbers
77 void updateimportnumbers();
78 void updateexportnumbers();
79
80 //Convert a selection list of objects to LLSD
81 LLSD prims_to_llsd(LLViewerObject::child_list_t child_list);
82
83 // Start the import process
84 void import_object1a();
85
86 //Export the next texture in list
87 void export_next_texture();
88
89 //apply LLSD to object
90 void xmltoprim(LLSD prim_llsd,LLViewerObject * pobject);
91
92
93 //rez a prim at a given position (note not agent offset X/Y screen for raycast)
94 void rez_agent_offset(LLVector3 offset);
95
96 //Move to the next import group
97 void import_next_object();
98
99 //Get an offset from the agent based on rotation and current pos
100 LLVector3 offset_agent(LLVector3 offset);
101
102 // Rebase map
103 std::map<LLUUID,LLUUID> assetmap;
104
105 //Export texture list
106 std::list<LLUUID> textures;
107
108 //Import object tracking
109 std::vector<LLViewerObject *> toselect;
110 std::vector<LLViewerObject *>::iterator process_iter;
111
112 //Working LLSD holders
113 LLUUID current_asset;
114 LLSD llsd;
115 LLSD this_group;
116 LLUUID expecting_update;
117
118 //working llsd itterators for objects and linksets
119 LLSD::map_const_iterator prim_import_iter;
120 LLSD::array_const_iterator group_prim_import_iter;
121
122 // Root pos and central root pos for link set
123 LLVector3 root_pos;
124 LLVector3 root_root_pos;
125 LLVector3 group_offset;
126
127 //Agent inital pos and rot when starting import
128 LLQuaternion root_rot;
129 LLQuaternion agent_rot;
130
131};
132
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_prim_import.xml b/linden/indra/newview/skins/default/xui/en-us/floater_prim_import.xml
new file mode 100644
index 0000000..191b31e
--- /dev/null
+++ b/linden/indra/newview/skins/default/xui/en-us/floater_prim_import.xml
@@ -0,0 +1,5 @@
1<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
2<floater can_close="true" can_drag_on_left="true" can_minimize="false"
3 can_resize="false" height="80" name="Import" title="Import progress" width="200" mouse_opaque="true">
4 <text height="15" left="10" name="name_label" top="-10"> Progress </text>
5</floater>
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
diff --git a/linden/indra/newview/skins/default/xui/en-us/menu_pie_object.xml b/linden/indra/newview/skins/default/xui/en-us/menu_pie_object.xml
index 765529d..15cdc9e 100644
--- a/linden/indra/newview/skins/default/xui/en-us/menu_pie_object.xml
+++ b/linden/indra/newview/skins/default/xui/en-us/menu_pie_object.xml
@@ -44,7 +44,11 @@
44 <on_enable function="Object.EnableReturn" /> 44 <on_enable function="Object.EnableReturn" />
45 </menu_item_call> 45 </menu_item_call>
46 <pie_menu label="More &gt;" name="Rate Menu"> 46 <pie_menu label="More &gt;" name="Rate Menu">
47 <menu_item_separator /> 47 <menu_item_call label="Backup" enabled="false" hidden="false"
48 mouse_opaqu="true" name="Export">
49 <on_click function="Object.Export" />
50 <on_enable function="Object.EnableExport" />
51 </menu_item_call>
48 <menu_item_call enabled="false" label="Mute" mouse_opaque="true" name="Object Mute"> 52 <menu_item_call enabled="false" label="Mute" mouse_opaque="true" name="Object Mute">
49 <on_click function="Object.Mute" /> 53 <on_click function="Object.Mute" />
50 <on_enable function="Object.EnableMute" /> 54 <on_enable function="Object.EnableMute" />
diff --git a/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml b/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml
index a53e339..81c49e7 100644
--- a/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml
+++ b/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml
@@ -8,6 +8,14 @@
8 8
9 <menu name="File" create_jump_keys="true" label="File" 9 <menu name="File" create_jump_keys="true" label="File"
10 opaque="true" tear_off="true"> 10 opaque="true" tear_off="true">
11 <menu_item_call enabled="false" hidden="false" label="Import" mouse_opaque="true" name="Import">
12 <on_click function="Object.Import" />
13 <on_enable function="Object.EnableImport" />
14 </menu_item_call>
15 <menu_item_call enabled="false" hidden="false" label="Upload + Import" mouse_opaque="true" name="Import">
16 <on_click function="Object.ImportUpload" />
17 <on_enable function="Object.EnableImport" />
18 </menu_item_call>
11 <menu_item_call name="Upload Image" 19 <menu_item_call name="Upload Image"
12 label="Upload Image (L$[COST])..." 20 label="Upload Image (L$[COST])..."
13 shortcut="control|U"> 21 shortcut="control|U">
@@ -1386,6 +1394,42 @@
1386 </menu> 1394 </menu>
1387 1395
1388 1396
1397 <!-- RLVa -->
1398
1399 <menu name="RLVa" drop_shadow="true" opaque="true" tear_off="true">
1400
1401 <menu_item_check name="Enable Wear" label="Enable Wear">
1402 <on_click function="ToggleControl" userdata="RLVaEnableWear" />
1403 <on_check control="RLVaEnableWear" />
1404 </menu_item_check>
1405
1406 <menu_item_check name="Hide locked layers" label="Hide locked layers">
1407 <on_click function="ToggleControl" userdata="RLVaHideLockedLayers" />
1408 <on_check control="RLVaHideLockedLayers" />
1409 </menu_item_check>
1410
1411 <menu_item_check name="Hide locked attachments"
1412 label="Hide locked attachments">
1413 <on_click function="ToggleControl"
1414 userdata="RLVaHideLockedAttachments" />
1415 <on_check control="RLVaHideLockedAttachments" />
1416 </menu_item_check>
1417
1418 <!--
1419 <menu_item_check name="Hide locked inventory"
1420 label="Hide locked inventory">
1421 <on_click function="ToggleControl"
1422 userdata="RLVaHideLockedInventory" />
1423 <on_check control="RLVaHideLockedInventory" />
1424 </menu_item_check>
1425 -->
1426
1427 <menu_item_call name="Restrictions..." label="Restrictions...">
1428 <on_click function="RLVa.Behaviors.Show" userdata="" />
1429 </menu_item_call>
1430
1431 </menu>
1432
1389 1433
1390 <!-- UI --> 1434 <!-- UI -->
1391 1435
@@ -1905,6 +1949,13 @@
1905 userdata="ShowConsoleWindow" /> 1949 userdata="ShowConsoleWindow" />
1906 <on_check control="ShowConsoleWindow" /> 1950 <on_check control="ShowConsoleWindow" />
1907 </menu_item_check> 1951 </menu_item_check>
1952
1953 <menu_item_check name="Restrained Life Active"
1954 label="Restrained Life Active">
1955 <on_click function="RLVa.Main.Toggle" />
1956 <on_check function="RLVa.Main.Enabled" />
1957 </menu_item_check>
1958
1908 <menu_item_check name="Output Debug Minidump" 1959 <menu_item_check name="Output Debug Minidump"
1909 label="Output Debug Minidump"> 1960 label="Output Debug Minidump">
1910 <on_click function="ToggleControl" 1961 <on_click function="ToggleControl"