diff options
author | Jacek Antonelli | 2009-09-04 01:56:20 -0500 |
---|---|---|
committer | Jacek Antonelli | 2009-09-04 03:39:51 -0500 |
commit | 89a510de10c48ebcf82b98a962e4bf66477dcc93 (patch) | |
tree | d30f79f433badffe36a67fc155e70a0e29dd2dc4 | |
parent | Backported 1.23 fix for animation joint assertion crash. (diff) | |
download | meta-impy-89a510de10c48ebcf82b98a962e4bf66477dcc93.zip meta-impy-89a510de10c48ebcf82b98a962e4bf66477dcc93.tar.gz meta-impy-89a510de10c48ebcf82b98a962e4bf66477dcc93.tar.bz2 meta-impy-89a510de10c48ebcf82b98a962e4bf66477dcc93.tar.xz |
Applied Kitty Barnett's RLVa 1.0.1h (Restrained Life) patch.
Made a few non-functional changes to help it apply.
Diffstat (limited to '')
86 files changed, 8594 insertions, 128 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt index 31bce3d..37b2666 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt | |||
@@ -1,3 +1,95 @@ | |||
1 | 2009-09-04 Jacek Antonelli <jacek.antonelli@gmail.com> | ||
2 | |||
3 | * Applied Kitty Barnett's RLVa 1.0.1h (Restrained Life) patch. | ||
4 | Made a few non-functional changes to help it apply. | ||
5 | |||
6 | modified: linden/indra/llcommon/llchat.h | ||
7 | modified: linden/indra/newview/CMakeLists.txt | ||
8 | modified: linden/indra/newview/app_settings/settings.xml | ||
9 | modified: linden/indra/newview/app_settings/settings_per_account.xml | ||
10 | modified: linden/indra/newview/llagent.cpp | ||
11 | modified: linden/indra/newview/llagent.h | ||
12 | modified: linden/indra/newview/llappviewer.cpp | ||
13 | modified: linden/indra/newview/llchatbar.cpp | ||
14 | modified: linden/indra/newview/llfloaterabout.cpp | ||
15 | modified: linden/indra/newview/llfloateractivespeakers.cpp | ||
16 | modified: linden/indra/newview/llfloaterbeacons.cpp | ||
17 | modified: linden/indra/newview/llfloaterchat.cpp | ||
18 | modified: linden/indra/newview/llfloaterinspect.cpp | ||
19 | modified: linden/indra/newview/llfloaterland.cpp | ||
20 | modified: linden/indra/newview/llfloaterland.h | ||
21 | modified: linden/indra/newview/llfloatermap.cpp | ||
22 | modified: linden/indra/newview/llfloatermap.h | ||
23 | modified: linden/indra/newview/llfloateropenobject.cpp | ||
24 | modified: linden/indra/newview/llfloaterproperties.cpp | ||
25 | modified: linden/indra/newview/llfloaterregioninfo.cpp | ||
26 | modified: linden/indra/newview/llfloaterregioninfo.h | ||
27 | modified: linden/indra/newview/llfloaterreporter.cpp | ||
28 | modified: linden/indra/newview/llfloatersettingsdebug.cpp | ||
29 | modified: linden/indra/newview/llfloaterwindlight.cpp | ||
30 | modified: linden/indra/newview/llfloaterworldmap.cpp | ||
31 | modified: linden/indra/newview/llglsandbox.cpp | ||
32 | modified: linden/indra/newview/llhoverview.cpp | ||
33 | modified: linden/indra/newview/llhudtext.cpp | ||
34 | modified: linden/indra/newview/llhudtext.h | ||
35 | modified: linden/indra/newview/llimpanel.cpp | ||
36 | modified: linden/indra/newview/llimview.cpp | ||
37 | modified: linden/indra/newview/llinventorybridge.cpp | ||
38 | modified: linden/indra/newview/llinventorymodel.cpp | ||
39 | modified: linden/indra/newview/llinventoryview.cpp | ||
40 | modified: linden/indra/newview/llinventoryview.h | ||
41 | modified: linden/indra/newview/llmaniptranslate.cpp | ||
42 | modified: linden/indra/newview/llnetmap.cpp | ||
43 | modified: linden/indra/newview/llnotify.cpp | ||
44 | modified: linden/indra/newview/lloverlaybar.cpp | ||
45 | modified: linden/indra/newview/llpanelavatar.cpp | ||
46 | modified: linden/indra/newview/llpanelclassified.cpp | ||
47 | modified: linden/indra/newview/llpanelcontents.cpp | ||
48 | modified: linden/indra/newview/llpaneldisplay.cpp | ||
49 | modified: linden/indra/newview/llpanelinventory.cpp | ||
50 | modified: linden/indra/newview/llpanelland.cpp | ||
51 | modified: linden/indra/newview/llpanellogin.cpp | ||
52 | modified: linden/indra/newview/llpanelobject.cpp | ||
53 | modified: linden/indra/newview/llpanelpermissions.cpp | ||
54 | modified: linden/indra/newview/llpanelpick.cpp | ||
55 | modified: linden/indra/newview/llprefsim.cpp | ||
56 | modified: linden/indra/newview/llpreviewscript.cpp | ||
57 | modified: linden/indra/newview/llselectmgr.cpp | ||
58 | modified: linden/indra/newview/llstartup.cpp | ||
59 | modified: linden/indra/newview/llstatusbar.cpp | ||
60 | modified: linden/indra/newview/lltoolbar.cpp | ||
61 | modified: linden/indra/newview/lltooldraganddrop.cpp | ||
62 | modified: linden/indra/newview/lltoolface.cpp | ||
63 | modified: linden/indra/newview/lltoolgrab.cpp | ||
64 | modified: linden/indra/newview/lltoolpie.cpp | ||
65 | modified: linden/indra/newview/lltoolplacer.cpp | ||
66 | modified: linden/indra/newview/lltoolselect.cpp | ||
67 | modified: linden/indra/newview/lltracker.cpp | ||
68 | modified: linden/indra/newview/llviewercontrol.cpp | ||
69 | modified: linden/indra/newview/llviewerdisplay.cpp | ||
70 | modified: linden/indra/newview/llviewermenu.cpp | ||
71 | modified: linden/indra/newview/llviewermessage.cpp | ||
72 | modified: linden/indra/newview/llviewerobject.cpp | ||
73 | modified: linden/indra/newview/llviewertexteditor.cpp | ||
74 | modified: linden/indra/newview/llviewerwindow.cpp | ||
75 | modified: linden/indra/newview/llvoavatar.cpp | ||
76 | modified: linden/indra/newview/llvovolume.cpp | ||
77 | modified: linden/indra/newview/llworldmapview.cpp | ||
78 | modified: linden/indra/newview/pipeline.cpp | ||
79 | new file: linden/indra/newview/rlvevent.h | ||
80 | new file: linden/indra/newview/rlvextensions.cpp | ||
81 | new file: linden/indra/newview/rlvextensions.h | ||
82 | new file: linden/indra/newview/rlvfloaterbehaviour.cpp | ||
83 | new file: linden/indra/newview/rlvfloaterbehaviour.h | ||
84 | new file: linden/indra/newview/rlvhandler.cpp | ||
85 | new file: linden/indra/newview/rlvhandler.h | ||
86 | new file: linden/indra/newview/rlvhelper.cpp | ||
87 | new file: linden/indra/newview/rlvhelper.h | ||
88 | new file: linden/indra/newview/rlvmultistringsearch.cpp | ||
89 | new file: linden/indra/newview/rlvmultistringsearch.h | ||
90 | new file: linden/indra/newview/skins/default/xui/en-us/floater_rlv_behaviour.xml | ||
91 | |||
92 | |||
1 | 2009-09-03 Jacek Antonelli <jacek.antonelli@gmail.com> | 93 | 2009-09-03 Jacek Antonelli <jacek.antonelli@gmail.com> |
2 | 94 | ||
3 | * Backported 1.23 fix for animation joint assertion crash. | 95 | * Backported 1.23 fix for animation joint assertion crash. |
diff --git a/linden/indra/llcommon/llchat.h b/linden/indra/llcommon/llchat.h index 1bb3f3b..aa4469c 100644 --- a/linden/indra/llcommon/llchat.h +++ b/linden/indra/llcommon/llchat.h | |||
@@ -72,6 +72,10 @@ public: | |||
72 | : mText(text), | 72 | : mText(text), |
73 | mFromName(), | 73 | mFromName(), |
74 | mFromID(), | 74 | mFromID(), |
75 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | ||
76 | mRlvLocFiltered(FALSE), | ||
77 | mRlvNamesFiltered(FALSE), | ||
78 | // [/RLVa:KB] | ||
75 | mSourceType(CHAT_SOURCE_AGENT), | 79 | mSourceType(CHAT_SOURCE_AGENT), |
76 | mChatType(CHAT_TYPE_NORMAL), | 80 | mChatType(CHAT_TYPE_NORMAL), |
77 | mAudible(CHAT_AUDIBLE_FULLY), | 81 | mAudible(CHAT_AUDIBLE_FULLY), |
@@ -83,6 +87,10 @@ public: | |||
83 | std::string mText; // UTF-8 line of text | 87 | std::string mText; // UTF-8 line of text |
84 | std::string mFromName; // agent or object name | 88 | std::string mFromName; // agent or object name |
85 | LLUUID mFromID; // agent id or object id | 89 | LLUUID mFromID; // agent id or object id |
90 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | ||
91 | BOOL mRlvLocFiltered; | ||
92 | BOOL mRlvNamesFiltered; | ||
93 | // [/RLVa:KB] | ||
86 | EChatSourceType mSourceType; | 94 | EChatSourceType mSourceType; |
87 | EChatType mChatType; | 95 | EChatType mChatType; |
88 | EChatAudible mAudible; | 96 | EChatAudible mAudible; |
diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index 34aa29f..1fc7549 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt | |||
@@ -431,6 +431,11 @@ set(viewer_SOURCE_FILES | |||
431 | llxmlrpctransaction.cpp | 431 | llxmlrpctransaction.cpp |
432 | noise.cpp | 432 | noise.cpp |
433 | pipeline.cpp | 433 | pipeline.cpp |
434 | rlvhandler.cpp | ||
435 | rlvhelper.cpp | ||
436 | rlvmultistringsearch.cpp | ||
437 | rlvextensions.cpp | ||
438 | rlvfloaterbehaviour.cpp | ||
434 | ) | 439 | ) |
435 | 440 | ||
436 | set(VIEWER_BINARY_NAME "imprudence-bin" CACHE STRING | 441 | set(VIEWER_BINARY_NAME "imprudence-bin" CACHE STRING |
@@ -834,6 +839,12 @@ set(viewer_HEADER_FILES | |||
834 | randgauss.h | 839 | randgauss.h |
835 | VertexCache.h | 840 | VertexCache.h |
836 | VorbisFramework.h | 841 | VorbisFramework.h |
842 | rlvevent.h | ||
843 | rlvhandler.h | ||
844 | rlvhelper.h | ||
845 | rlvmultistringsearch.h | ||
846 | rlvextensions.h | ||
847 | rlvfloaterbehaviour.h | ||
837 | ) | 848 | ) |
838 | 849 | ||
839 | source_group("CMake Rules" FILES ViewerInstall.cmake) | 850 | source_group("CMake Rules" FILES ViewerInstall.cmake) |
diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml index 5c76185..628936c 100644 --- a/linden/indra/newview/app_settings/settings.xml +++ b/linden/indra/newview/app_settings/settings.xml | |||
@@ -1,7 +1,106 @@ | |||
1 | <?xml version="1.0" ?> | 1 | <?xml version="1.0" ?> |
2 | <llsd> | 2 | <llsd> |
3 | <map> | 3 | <map> |
4 | <key>AFKTimeout</key> | 4 | <key>RestrainedLife</key> |
5 | <map> | ||
6 | <key>Comment</key> | ||
7 | <string>Toggles the RestrainedLife features (BDSM lockable toys support). Needs a restart of the viewer.</string> | ||
8 | <key>Persist</key> | ||
9 | <integer>1</integer> | ||
10 | <key>Type</key> | ||
11 | <string>Boolean</string> | ||
12 | <key>Value</key> | ||
13 | <integer>0</integer> | ||
14 | </map> | ||
15 | <key>RestrainedLifeDebug</key> | ||
16 | <map> | ||
17 | <key>Comment</key> | ||
18 | <string>Toggles the RestrainedLife debug mode (displays the commands when in debug mode).</string> | ||
19 | <key>Persist</key> | ||
20 | <integer>1</integer> | ||
21 | <key>Type</key> | ||
22 | <string>Boolean</string> | ||
23 | <key>Value</key> | ||
24 | <integer>0</integer> | ||
25 | </map> | ||
26 | <key>RestrainedLifeNoSetEnv</key> | ||
27 | <map> | ||
28 | <key>Comment</key> | ||
29 | <string>When TRUE, forbids to set the environment (time of day and Windlight settings) via RestrainedLife. Needs a restart of the viewer.</string> | ||
30 | <key>Persist</key> | ||
31 | <integer>1</integer> | ||
32 | <key>Type</key> | ||
33 | <string>Boolean</string> | ||
34 | <key>Value</key> | ||
35 | <integer>0</integer> | ||
36 | </map> | ||
37 | <key>RestrainedLifeForbidGiveToRLV</key> | ||
38 | <map> | ||
39 | <key>Comment</key> | ||
40 | <string>When FALSE, allows to give sub-folders to the #RLV RestrainedLife folder.</string> | ||
41 | <key>Persist</key> | ||
42 | <integer>1</integer> | ||
43 | <key>Type</key> | ||
44 | <string>Boolean</string> | ||
45 | <key>Value</key> | ||
46 | <integer>1</integer> | ||
47 | </map> | ||
48 | <key>RLVaEnableLegacyNaming</key> | ||
49 | <map> | ||
50 | <key>Comment</key> | ||
51 | <string>Enables legacy naming convention for folders</string> | ||
52 | <key>Persist</key> | ||
53 | <integer>1</integer> | ||
54 | <key>Type</key> | ||
55 | <string>Boolean</string> | ||
56 | <key>Value</key> | ||
57 | <integer>1</integer> | ||
58 | </map> | ||
59 | <key>RLVaEnableWear</key> | ||
60 | <map> | ||
61 | <key>Comment</key> | ||
62 | <string>When TRUE, enables the "Wear" option on the inventory item context menu for attachments.</string> | ||
63 | <key>Persist</key> | ||
64 | <integer>1</integer> | ||
65 | <key>Type</key> | ||
66 | <string>Boolean</string> | ||
67 | <key>Value</key> | ||
68 | <integer>0</integer> | ||
69 | </map> | ||
70 | <key>RLVaHideLockedLayers</key> | ||
71 | <map> | ||
72 | <key>Comment</key> | ||
73 | <string>When TRUE, hides worn but "remove outfit" restricted clothing layers from @getoufit</string> | ||
74 | <key>Persist</key> | ||
75 | <integer>1</integer> | ||
76 | <key>Type</key> | ||
77 | <string>Boolean</string> | ||
78 | <key>Value</key> | ||
79 | <integer>0</integer> | ||
80 | </map> | ||
81 | <key>RLVaHideLockedAttachments</key> | ||
82 | <map> | ||
83 | <key>Comment</key> | ||
84 | <string>When TRUE, hides worn but "no detach" restricted attachments from @getattach</string> | ||
85 | <key>Persist</key> | ||
86 | <integer>1</integer> | ||
87 | <key>Type</key> | ||
88 | <string>Boolean</string> | ||
89 | <key>Value</key> | ||
90 | <integer>0</integer> | ||
91 | </map> | ||
92 | <key>RLVaShowNameTags</key> | ||
93 | <map> | ||
94 | <key>Comment</key> | ||
95 | <string>Display of names above avatars is subject to the general "Show Names" setting when @shownames=n restricted</string> | ||
96 | <key>Persist</key> | ||
97 | <integer>1</integer> | ||
98 | <key>Type</key> | ||
99 | <string>Boolean</string> | ||
100 | <key>Value</key> | ||
101 | <integer>0</integer> | ||
102 | </map> | ||
103 | <key>AFKTimeout</key> | ||
5 | <map> | 104 | <map> |
6 | <key>Comment</key> | 105 | <key>Comment</key> |
7 | <string>Time before automatically setting AFK (away from keyboard) mode (seconds)</string> | 106 | <string>Time before automatically setting AFK (away from keyboard) mode (seconds)</string> |
diff --git a/linden/indra/newview/app_settings/settings_per_account.xml b/linden/indra/newview/app_settings/settings_per_account.xml index 90c7b11..59caac4 100644 --- a/linden/indra/newview/app_settings/settings_per_account.xml +++ b/linden/indra/newview/app_settings/settings_per_account.xml | |||
@@ -1,6 +1,17 @@ | |||
1 | <llsd> | 1 | <llsd> |
2 | <map> | 2 | <map> |
3 | <key>BusyModeResponse</key> | 3 | <key>RLVaLoginLastLocation</key> |
4 | <map> | ||
5 | <key>Comment</key> | ||
6 | <string>Determines whether the next login will be forced to the last logoff location (set by the viewer)</string> | ||
7 | <key>Persist</key> | ||
8 | <integer>1</integer> | ||
9 | <key>Type</key> | ||
10 | <string>Boolean</string> | ||
11 | <key>Value</key> | ||
12 | <integer>1</integer> | ||
13 | </map> | ||
14 | <key>BusyModeResponse</key> | ||
4 | <map> | 15 | <map> |
5 | <key>Comment</key> | 16 | <key>Comment</key> |
6 | <string>Auto response to instant messages while in busy mode.</string> | 17 | <string>Auto response to instant messages while in busy mode.</string> |
diff --git a/linden/indra/newview/llagent.cpp b/linden/indra/newview/llagent.cpp index 5f0a875..e71f1b7 100644 --- a/linden/indra/newview/llagent.cpp +++ b/linden/indra/newview/llagent.cpp | |||
@@ -757,6 +757,9 @@ void LLAgent::movePitch(S32 direction) | |||
757 | // Does this parcel allow you to fly? | 757 | // Does this parcel allow you to fly? |
758 | BOOL LLAgent::canFly() | 758 | BOOL LLAgent::canFly() |
759 | { | 759 | { |
760 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0c) | ||
761 | if (gRlvHandler.hasBehaviour(RLV_BHVR_FLY)) return FALSE; | ||
762 | // [/RLVa:KB] | ||
760 | if (isGodlike()) return TRUE; | 763 | if (isGodlike()) return TRUE; |
761 | 764 | ||
762 | LLViewerRegion* regionp = getRegion(); | 765 | LLViewerRegion* regionp = getRegion(); |
@@ -796,6 +799,13 @@ void LLAgent::setFlying(BOOL fly) | |||
796 | 799 | ||
797 | if (fly) | 800 | if (fly) |
798 | { | 801 | { |
802 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0c) | ||
803 | if (gRlvHandler.hasBehaviour(RLV_BHVR_FLY)) | ||
804 | { | ||
805 | return; | ||
806 | } | ||
807 | // [/RLVa:KB] | ||
808 | |||
799 | BOOL was_flying = getFlying(); | 809 | BOOL was_flying = getFlying(); |
800 | if (!canFly() && !was_flying) | 810 | if (!canFly() && !was_flying) |
801 | { | 811 | { |
@@ -4213,6 +4223,13 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_ani | |||
4213 | return; | 4223 | return; |
4214 | } | 4224 | } |
4215 | 4225 | ||
4226 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
4227 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (mAvatarObject.notNull()) && (mAvatarObject->mIsSitting) ) | ||
4228 | { | ||
4229 | return; | ||
4230 | } | ||
4231 | // [/RLVa:KB] | ||
4232 | |||
4216 | setControlFlags(AGENT_CONTROL_STAND_UP); // force stand up | 4233 | setControlFlags(AGENT_CONTROL_STAND_UP); // force stand up |
4217 | gViewerWindow->getWindow()->resetBusyCount(); | 4234 | gViewerWindow->getWindow()->resetBusyCount(); |
4218 | 4235 | ||
@@ -5007,6 +5024,14 @@ BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOO | |||
5007 | // utility to build a location string | 5024 | // utility to build a location string |
5008 | void LLAgent::buildLocationString(std::string& str) | 5025 | void LLAgent::buildLocationString(std::string& str) |
5009 | { | 5026 | { |
5027 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | ||
5028 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) | ||
5029 | { | ||
5030 | str = rlv_handler_t::cstrHidden; | ||
5031 | return; | ||
5032 | } | ||
5033 | // [/RLVa:KB] | ||
5034 | |||
5010 | const LLVector3& agent_pos_region = getPositionAgent(); | 5035 | const LLVector3& agent_pos_region = getPositionAgent(); |
5011 | S32 pos_x = S32(agent_pos_region.mV[VX]); | 5036 | S32 pos_x = S32(agent_pos_region.mV[VX]); |
5012 | S32 pos_y = S32(agent_pos_region.mV[VY]); | 5037 | S32 pos_y = S32(agent_pos_region.mV[VY]); |
@@ -5889,6 +5914,15 @@ void LLAgent::teleportRequest( | |||
5889 | // Landmark ID = LLUUID::null means teleport home | 5914 | // Landmark ID = LLUUID::null means teleport home |
5890 | void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) | 5915 | void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) |
5891 | { | 5916 | { |
5917 | // [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | ||
5918 | if ( (rlv_handler_t::isEnabled()) && | ||
5919 | ( (gRlvHandler.hasBehaviour("tplm")) || | ||
5920 | ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (mAvatarObject.notNull()) && (mAvatarObject->mIsSitting)) )) | ||
5921 | { | ||
5922 | return; | ||
5923 | } | ||
5924 | // [/RLVa:KB] | ||
5925 | |||
5892 | LLViewerRegion *regionp = getRegion(); | 5926 | LLViewerRegion *regionp = getRegion(); |
5893 | if(regionp && teleportCore()) | 5927 | if(regionp && teleportCore()) |
5894 | { | 5928 | { |
@@ -5953,6 +5987,17 @@ void LLAgent::teleportCancel() | |||
5953 | 5987 | ||
5954 | void LLAgent::teleportViaLocation(const LLVector3d& pos_global) | 5988 | void LLAgent::teleportViaLocation(const LLVector3d& pos_global) |
5955 | { | 5989 | { |
5990 | // [RLVa:KB] - Alternate: Snowglobe-1.0 | Checked: 2009-07-07 (RLVa-1.0.0d) | ||
5991 | // If we're getting teleported due to @tpto we should disregard any @tploc=n or @unsit=n restrictions from the same object | ||
5992 | if ( (rlv_handler_t::isEnabled()) && | ||
5993 | ( (gRlvHandler.hasBehaviourExcept("tploc", gRlvHandler.getCurrentObject())) || | ||
5994 | ( (mAvatarObject.notNull()) && (mAvatarObject->mIsSitting) && | ||
5995 | (gRlvHandler.hasBehaviourExcept(RLV_BHVR_UNSIT, gRlvHandler.getCurrentObject()))) ) ) | ||
5996 | { | ||
5997 | return; | ||
5998 | } | ||
5999 | // [/RLVa:KB] | ||
6000 | |||
5956 | LLViewerRegion* regionp = getRegion(); | 6001 | LLViewerRegion* regionp = getRegion(); |
5957 | LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); | 6002 | LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); |
5958 | if(regionp && info) | 6003 | if(regionp && info) |
@@ -6027,6 +6072,13 @@ void LLAgent::setTeleportState(ETeleportState state) | |||
6027 | // We're outa here. Save "back" slurl. | 6072 | // We're outa here. Save "back" slurl. |
6028 | mTeleportSourceSLURL = getSLURL(); | 6073 | mTeleportSourceSLURL = getSLURL(); |
6029 | } | 6074 | } |
6075 | |||
6076 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.0b | ||
6077 | if ( (rlv_handler_t::isEnabled()) && (TELEPORT_NONE == mTeleportState) ) | ||
6078 | { | ||
6079 | gRlvHandler.setCanCancelTp(true); | ||
6080 | } | ||
6081 | // [/RLVa:KB] | ||
6030 | } | 6082 | } |
6031 | 6083 | ||
6032 | void LLAgent::stopCurrentAnimations() | 6084 | void LLAgent::stopCurrentAnimations() |
@@ -6654,10 +6706,17 @@ void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void | |||
6654 | } | 6706 | } |
6655 | 6707 | ||
6656 | // now that we have the asset ids...request the wearable assets | 6708 | // now that we have the asset ids...request the wearable assets |
6709 | // [RLVa:KB] - Checked: 2009-08-08 (RLVa-1.0.1g) | Added: RLVa-1.0.1g | ||
6710 | LLInventoryFetchObserver::item_ref_t rlvItems; | ||
6711 | // [/RLVa:KB] | ||
6657 | for( i = 0; i < WT_COUNT; i++ ) | 6712 | for( i = 0; i < WT_COUNT; i++ ) |
6658 | { | 6713 | { |
6659 | if( !gAgent.mWearableEntry[i].mItemID.isNull() ) | 6714 | if( !gAgent.mWearableEntry[i].mItemID.isNull() ) |
6660 | { | 6715 | { |
6716 | // [RLVa:KB] - Checked: 2009-08-08 (RLVa-1.0.1g) | Added: RLVa-1.0.1g | ||
6717 | if (rlv_handler_t::isEnabled()) | ||
6718 | rlvItems.push_back(gAgent.mWearableEntry[i].mItemID); | ||
6719 | // [/RLVa:KB] | ||
6661 | gWearableList.getAsset( | 6720 | gWearableList.getAsset( |
6662 | asset_id_array[i], | 6721 | asset_id_array[i], |
6663 | LLStringUtil::null, | 6722 | LLStringUtil::null, |
@@ -6665,6 +6724,15 @@ void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void | |||
6665 | LLAgent::onInitialWearableAssetArrived, (void*)(intptr_t)i ); | 6724 | LLAgent::onInitialWearableAssetArrived, (void*)(intptr_t)i ); |
6666 | } | 6725 | } |
6667 | } | 6726 | } |
6727 | |||
6728 | // [RLVa:KB] - Checked: 2009-08-08 (RLVa-1.0.1g) | Added: RLVa-1.0.1g | ||
6729 | // TODO-RLVa: checking that we're in STATE_STARTED is probably not needed, but leave it until we can be absolutely sure | ||
6730 | if ( (rlv_handler_t::isEnabled()) && (LLStartUp::getStartupState() == STATE_STARTED) ) | ||
6731 | { | ||
6732 | RlvCurrentlyWorn f; | ||
6733 | f.fetchItems(rlvItems); | ||
6734 | } | ||
6735 | // [/RLVa:KB] | ||
6668 | } | 6736 | } |
6669 | } | 6737 | } |
6670 | 6738 | ||
@@ -7162,6 +7230,13 @@ void LLAgent::removeWearable( EWearableType type ) | |||
7162 | return; | 7230 | return; |
7163 | } | 7231 | } |
7164 | 7232 | ||
7233 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | ||
7234 | if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isRemovable(type)) ) | ||
7235 | { | ||
7236 | return; | ||
7237 | } | ||
7238 | // [/RLVa:KB] | ||
7239 | |||
7165 | if( old_wearable ) | 7240 | if( old_wearable ) |
7166 | { | 7241 | { |
7167 | if( old_wearable->isDirty() ) | 7242 | if( old_wearable->isDirty() ) |
@@ -7284,15 +7359,17 @@ void LLAgent::setWearableOutfit( | |||
7284 | wearables_to_remove[WT_SKIN] = FALSE; | 7359 | wearables_to_remove[WT_SKIN] = FALSE; |
7285 | wearables_to_remove[WT_HAIR] = FALSE; | 7360 | wearables_to_remove[WT_HAIR] = FALSE; |
7286 | wearables_to_remove[WT_EYES] = FALSE; | 7361 | wearables_to_remove[WT_EYES] = FALSE; |
7287 | wearables_to_remove[WT_SHIRT] = remove; | 7362 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.2a |
7288 | wearables_to_remove[WT_PANTS] = remove; | 7363 | wearables_to_remove[WT_SHIRT] = remove && gRlvHandler.isRemovable(WT_SHIRT); |
7289 | wearables_to_remove[WT_SHOES] = remove; | 7364 | wearables_to_remove[WT_PANTS] = remove && gRlvHandler.isRemovable(WT_PANTS); |
7290 | wearables_to_remove[WT_SOCKS] = remove; | 7365 | wearables_to_remove[WT_SHOES] = remove && gRlvHandler.isRemovable(WT_SHOES); |
7291 | wearables_to_remove[WT_JACKET] = remove; | 7366 | wearables_to_remove[WT_SOCKS] = remove && gRlvHandler.isRemovable(WT_SOCKS); |
7292 | wearables_to_remove[WT_GLOVES] = remove; | 7367 | wearables_to_remove[WT_JACKET] = remove && gRlvHandler.isRemovable(WT_JACKET); |
7293 | wearables_to_remove[WT_UNDERSHIRT] = (!gAgent.isTeen()) & remove; | 7368 | wearables_to_remove[WT_GLOVES] = remove && gRlvHandler.isRemovable(WT_GLOVES); |
7294 | wearables_to_remove[WT_UNDERPANTS] = (!gAgent.isTeen()) & remove; | 7369 | wearables_to_remove[WT_UNDERSHIRT] = (!gAgent.isTeen()) && remove && gRlvHandler.isRemovable(WT_UNDERSHIRT); |
7295 | wearables_to_remove[WT_SKIRT] = remove; | 7370 | wearables_to_remove[WT_UNDERPANTS] = (!gAgent.isTeen()) && remove && gRlvHandler.isRemovable(WT_UNDERPANTS); |
7371 | wearables_to_remove[WT_SKIRT] = remove && gRlvHandler.isRemovable(WT_SKIRT); | ||
7372 | // [/RLVa:KB] | ||
7296 | 7373 | ||
7297 | S32 count = wearables.count(); | 7374 | S32 count = wearables.count(); |
7298 | llassert( items.count() == count ); | 7375 | llassert( items.count() == count ); |
@@ -7384,6 +7461,15 @@ void LLAgent::setWearable( LLInventoryItem* new_item, LLWearable* new_wearable ) | |||
7384 | EWearableType type = new_wearable->getType(); | 7461 | EWearableType type = new_wearable->getType(); |
7385 | 7462 | ||
7386 | LLWearable* old_wearable = mWearableEntry[ type ].mWearable; | 7463 | LLWearable* old_wearable = mWearableEntry[ type ].mWearable; |
7464 | |||
7465 | // [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | ||
7466 | // Block if: we can't wear on that layer; or we're already wearing something there we can't take off | ||
7467 | if ( (rlv_handler_t::isEnabled()) && ((!gRlvHandler.isWearable(type)) || ((old_wearable) && (!gRlvHandler.isRemovable(type)))) ) | ||
7468 | { | ||
7469 | return; | ||
7470 | } | ||
7471 | // [/RLVa:KB] | ||
7472 | |||
7387 | if( old_wearable ) | 7473 | if( old_wearable ) |
7388 | { | 7474 | { |
7389 | const LLUUID& old_item_id = mWearableEntry[ type ].mItemID; | 7475 | const LLUUID& old_item_id = mWearableEntry[ type ].mItemID; |
@@ -7592,10 +7678,13 @@ void LLAgent::userRemoveAllAttachments( void* userdata ) | |||
7592 | return; | 7678 | return; |
7593 | } | 7679 | } |
7594 | 7680 | ||
7595 | gMessageSystem->newMessage("ObjectDetach"); | 7681 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.0c |
7596 | gMessageSystem->nextBlockFast(_PREHASH_AgentData); | 7682 | // NOTE-RLVa: This function is called from inside RlvHandler as well, hence the rather heavy modifications |
7597 | gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); | 7683 | std::list<U32> rlvAttachments; |
7598 | gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | 7684 | // TODO-RLVa: Once we have the improved "removeWearable" logic implemented we can just get rid of the whole "rlvCompFolders" hassle |
7685 | #ifdef RLV_EXPERIMENTAL_COMPOSITES | ||
7686 | std::list<LLUUID> rlvCompFolders; | ||
7687 | #endif // RLV_EXPERIMENTAL_COMPOSITES | ||
7599 | 7688 | ||
7600 | for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); | 7689 | for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); |
7601 | iter != avatarp->mAttachmentPoints.end(); ) | 7690 | iter != avatarp->mAttachmentPoints.end(); ) |
@@ -7605,11 +7694,78 @@ void LLAgent::userRemoveAllAttachments( void* userdata ) | |||
7605 | LLViewerObject* objectp = attachment->getObject(); | 7694 | LLViewerObject* objectp = attachment->getObject(); |
7606 | if (objectp) | 7695 | if (objectp) |
7607 | { | 7696 | { |
7697 | if (rlv_handler_t::isEnabled()) | ||
7698 | { | ||
7699 | if (!gRlvHandler.isDetachable(curiter->first)) | ||
7700 | continue; | ||
7701 | |||
7702 | // Check if we're being called in response to an RLV command (that would be @detach=force) | ||
7703 | if ( (gRlvHandler.getCurrentCommand()) && (attachment->getItemID().notNull()) ) | ||
7704 | { | ||
7705 | if (!gRlvHandler.isStrippable(attachment->getItemID())) // "nostrip" can be taken off by the user but not @detach | ||
7706 | continue; | ||
7707 | |||
7708 | #ifdef RLV_EXPERIMENTAL_COMPOSITES | ||
7709 | LLViewerInventoryCategory* pFolder; | ||
7710 | if (gRlvHandler.getCompositeInfo(attachment->getItemID(), NULL, &pFolder)) | ||
7711 | { | ||
7712 | #ifdef RLV_EXPERIMENTAL_COMPOSITE_LOCKING | ||
7713 | if (!gRlvHandler.canTakeOffComposite(pFolder)) | ||
7714 | continue; | ||
7715 | #endif // RLV_EXPERIMENTAL_COMPOSITE_LOCKING | ||
7716 | |||
7717 | // The attachment belongs to a composite folder so there may be additional things we need to take off | ||
7718 | if (std::find(rlvCompFolders.begin(), rlvCompFolders.end(), pFolder->getUUID()) != rlvCompFolders.end()) | ||
7719 | rlvCompFolders.push_back(pFolder->getUUID()); | ||
7720 | } | ||
7721 | #endif // RLV_EXPERIMENTAL_COMPOSITES | ||
7722 | } | ||
7723 | } | ||
7724 | rlvAttachments.push_back(objectp->getLocalID()); | ||
7725 | } | ||
7726 | } | ||
7727 | |||
7728 | // Only send the message if we actually have something to detach | ||
7729 | if (rlvAttachments.size() > 0) | ||
7730 | { | ||
7731 | gMessageSystem->newMessage("ObjectDetach"); | ||
7732 | gMessageSystem->nextBlockFast(_PREHASH_AgentData); | ||
7733 | gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); | ||
7734 | gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
7735 | |||
7736 | for (std::list<U32>::const_iterator itAttach = rlvAttachments.begin(); itAttach != rlvAttachments.end(); ++itAttach) | ||
7737 | { | ||
7608 | gMessageSystem->nextBlockFast(_PREHASH_ObjectData); | 7738 | gMessageSystem->nextBlockFast(_PREHASH_ObjectData); |
7609 | gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID()); | 7739 | gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, *itAttach); |
7610 | } | 7740 | } |
7741 | |||
7742 | gMessageSystem->sendReliable( gAgent.getRegionHost() ); | ||
7611 | } | 7743 | } |
7612 | gMessageSystem->sendReliable( gAgent.getRegionHost() ); | 7744 | |
7745 | #ifdef RLV_EXPERIMENTAL_COMPOSITES | ||
7746 | if (rlv_handler_t::isEnabled) | ||
7747 | { | ||
7748 | // If we encountered any composite folders then we need to @detach all of them | ||
7749 | for (std::list<LLUUID>::const_iterator itFolder = rlvCompFolders.begin(); itFolder != rlvCompFolders.end(); ++itFolder) | ||
7750 | { | ||
7751 | std::string strFolder = gRlvHandler.getSharedPath(*itFolder); | ||
7752 | |||
7753 | // It shouldn't happen but make absolutely sure that we don't issue @detach:=force and reenter this function | ||
7754 | if (!strFolder.empty()) | ||
7755 | { | ||
7756 | std::string strCmd = "detach:" + strFolder + "=force"; | ||
7757 | #ifdef RLV_DEBUG | ||
7758 | RLV_INFOS << "\t- detaching composite folder: @" << strCmd << LL_ENDL; | ||
7759 | #endif // RLV_DEBUG | ||
7760 | |||
7761 | // HACK-RLV: executing a command while another command is currently executing isn't the best thing to do, however | ||
7762 | // in this specific case it is safe (and still better than making processForceCommand public) | ||
7763 | gRlvHandler.processCommand(gRlvHandler.getCurrentObject(), strCmd); | ||
7764 | } | ||
7765 | } | ||
7766 | } | ||
7767 | #endif // RLV_EXPERIMENTAL_COMPOSITES | ||
7768 | // [/RLVa:KB] | ||
7613 | } | 7769 | } |
7614 | 7770 | ||
7615 | void LLAgent::observeFriends() | 7771 | void LLAgent::observeFriends() |
diff --git a/linden/indra/newview/llagent.h b/linden/indra/newview/llagent.h index a4a930f..f64bf95 100644 --- a/linden/indra/newview/llagent.h +++ b/linden/indra/newview/llagent.h | |||
@@ -67,6 +67,10 @@ | |||
67 | #include "llfollowcam.h" | 67 | #include "llfollowcam.h" |
68 | // end Ventrella | 68 | // end Ventrella |
69 | 69 | ||
70 | // [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | ||
71 | #include "rlvhandler.h" | ||
72 | // [/RLVa:KB] | ||
73 | |||
70 | const U8 AGENT_STATE_TYPING = 0x04; // Typing indication | 74 | const U8 AGENT_STATE_TYPING = 0x04; // Typing indication |
71 | const U8 AGENT_STATE_EDITING = 0x10; // Set when agent has objects selected | 75 | const U8 AGENT_STATE_EDITING = 0x10; // Set when agent has objects selected |
72 | 76 | ||
diff --git a/linden/indra/newview/llappviewer.cpp b/linden/indra/newview/llappviewer.cpp index 4d53c88..81c3f92 100644 --- a/linden/indra/newview/llappviewer.cpp +++ b/linden/indra/newview/llappviewer.cpp | |||
@@ -3829,4 +3829,21 @@ void LLAppViewer::handleLoginComplete() | |||
3829 | gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState(); | 3829 | gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState(); |
3830 | } | 3830 | } |
3831 | writeDebugInfo(); | 3831 | writeDebugInfo(); |
3832 | |||
3833 | // [RLVa:KB] - Alternate: Snowglobe-1.0 | Checked: 2009-08-05 (RLVa-1.0.1e) | Modified: RLVa-1.0.1e | ||
3834 | // TODO-RLVa: find some way to initialize the lookup table when we need them *and* support toggling RLVa at runtime | ||
3835 | gRlvHandler.initLookupTables(); | ||
3836 | |||
3837 | if (rlv_handler_t::isEnabled()) | ||
3838 | { | ||
3839 | RlvCurrentlyWorn::fetchWorn(); | ||
3840 | rlv_handler_t::fetchSharedInventory(); | ||
3841 | |||
3842 | #ifdef RLV_EXTENSION_STARTLOCATION | ||
3843 | RlvSettings::updateLoginLastLocation(); | ||
3844 | #endif // RLV_EXTENSION_STARTLOCATION | ||
3845 | |||
3846 | gRlvHandler.processRetainedCommands(); | ||
3847 | } | ||
3848 | // [/RLVa:KB] | ||
3832 | } | 3849 | } |
diff --git a/linden/indra/newview/llchatbar.cpp b/linden/indra/newview/llchatbar.cpp index 59aa572..eb1da05 100644 --- a/linden/indra/newview/llchatbar.cpp +++ b/linden/indra/newview/llchatbar.cpp | |||
@@ -78,7 +78,10 @@ LLChatBar *gChatBar = NULL; | |||
78 | 78 | ||
79 | // legacy calllback glue | 79 | // legacy calllback glue |
80 | void toggleChatHistory(void* user_data); | 80 | void toggleChatHistory(void* user_data); |
81 | void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); | 81 | //void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); |
82 | // [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.2a | ||
83 | void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channel); | ||
84 | // [/RLVa:KB] | ||
82 | 85 | ||
83 | 86 | ||
84 | class LLChatBarGestureObserver : public LLGestureManagerObserver | 87 | class LLChatBarGestureObserver : public LLGestureManagerObserver |
@@ -482,7 +485,10 @@ void LLChatBar::onInputEditorKeystroke( LLLineEditor* caller, void* userdata ) | |||
482 | 485 | ||
483 | S32 length = raw_text.length(); | 486 | S32 length = raw_text.length(); |
484 | 487 | ||
485 | if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences | 488 | //if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences |
489 | // [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | ||
490 | if ( (length > 0) && (raw_text[0] != '/') && (!gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT)) ) | ||
491 | // [/RLVa:KB] | ||
486 | { | 492 | { |
487 | gAgent.startTyping(); | 493 | gAgent.startTyping(); |
488 | } | 494 | } |
@@ -586,6 +592,21 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL | |||
586 | utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); | 592 | utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); |
587 | } | 593 | } |
588 | 594 | ||
595 | // [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.0b | ||
596 | if ( (0 == channel) && (rlv_handler_t::isEnabled()) ) | ||
597 | { | ||
598 | // Adjust the (public) chat "volume" on chat and gestures (also takes care of playing the proper animation) | ||
599 | if ( ((CHAT_TYPE_SHOUT == type) || (CHAT_TYPE_NORMAL == type)) && (gRlvHandler.hasBehaviour("chatnormal")) ) | ||
600 | type = CHAT_TYPE_WHISPER; | ||
601 | else if ( (CHAT_TYPE_SHOUT == type) && (gRlvHandler.hasBehaviour("chatshout")) ) | ||
602 | type = CHAT_TYPE_NORMAL; | ||
603 | else if ( (CHAT_TYPE_WHISPER == type) && (gRlvHandler.hasBehaviour("chatwhisper")) ) | ||
604 | type = CHAT_TYPE_NORMAL; | ||
605 | |||
606 | animate &= !gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT); | ||
607 | } | ||
608 | // [/RLVa:KB] | ||
609 | |||
589 | // Don't animate for chats people can't hear (chat to scripts) | 610 | // Don't animate for chats people can't hear (chat to scripts) |
590 | if (animate && (channel == 0)) | 611 | if (animate && (channel == 0)) |
591 | { | 612 | { |
@@ -621,8 +642,57 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL | |||
621 | send_chat_from_viewer(utf8_out_text, type, channel); | 642 | send_chat_from_viewer(utf8_out_text, type, channel); |
622 | } | 643 | } |
623 | 644 | ||
624 | void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) | 645 | // void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) |
646 | // [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.2a | ||
647 | void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channel) | ||
648 | // [/RLVa:KB] | ||
625 | { | 649 | { |
650 | // [RLVa:KB] - Checked: 2009-08-05 (RLVa-1.0.1e) | Modified: RLVa-1.0.1e | ||
651 | // Only process chat messages (ie not CHAT_TYPE_START, CHAT_TYPE_STOP, etc) | ||
652 | if ( (rlv_handler_t::isEnabled()) && ( (CHAT_TYPE_WHISPER == type) || (CHAT_TYPE_NORMAL == type) || (CHAT_TYPE_SHOUT == type) ) ) | ||
653 | { | ||
654 | if (0 == channel) | ||
655 | { | ||
656 | // (We already did this before, but LLChatHandler::handle() calls this directly) | ||
657 | if ( ((CHAT_TYPE_SHOUT == type) || (CHAT_TYPE_NORMAL == type)) && (gRlvHandler.hasBehaviour("chatnormal")) ) | ||
658 | type = CHAT_TYPE_WHISPER; | ||
659 | else if ( (CHAT_TYPE_SHOUT == type) && (gRlvHandler.hasBehaviour("chatshout")) ) | ||
660 | type = CHAT_TYPE_NORMAL; | ||
661 | else if ( (CHAT_TYPE_WHISPER == type) && (gRlvHandler.hasBehaviour("chatwhisper")) ) | ||
662 | type = CHAT_TYPE_NORMAL; | ||
663 | |||
664 | // Redirect chat if needed | ||
665 | if ( ( (gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT) || (gRlvHandler.hasBehaviour(RLV_BHVR_REDIREMOTE)) ) && | ||
666 | (gRlvHandler.redirectChatOrEmote(utf8_out_text)) ) ) | ||
667 | { | ||
668 | return; | ||
669 | } | ||
670 | |||
671 | // Filter public chat if sendchat restricted (and filter anything that redirchat didn't redirect) | ||
672 | if ( (gRlvHandler.hasBehaviour("sendchat")) || (gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT)) ) | ||
673 | gRlvHandler.filterChat(utf8_out_text, true); | ||
674 | } | ||
675 | else | ||
676 | { | ||
677 | // Don't allow chat on a non-public channel if sendchannel restricted (unless the channel is an exception) | ||
678 | if ( (gRlvHandler.hasBehaviour("sendchannel")) && (!gRlvHandler.hasBehaviour("sendchannel", llformat("%d", channel))) ) | ||
679 | return; | ||
680 | |||
681 | // Don't allow chat on debug channel if @sendchat, @redirchat or @rediremote restricted (shows as public chat on viewers) | ||
682 | if (channel >= CHAT_CHANNEL_DEBUG) | ||
683 | { | ||
684 | bool fIsEmote = rlvIsEmote(utf8_out_text); | ||
685 | if ( (gRlvHandler.hasBehaviour("sendchat")) || | ||
686 | ((!fIsEmote) && (gRlvHandler.hasBehaviour(RLV_BHVR_REDIRCHAT))) || | ||
687 | ((fIsEmote) && (gRlvHandler.hasBehaviour(RLV_BHVR_REDIREMOTE))) ) | ||
688 | { | ||
689 | return; | ||
690 | } | ||
691 | } | ||
692 | } | ||
693 | } | ||
694 | // [/RLVa:KB] | ||
695 | |||
626 | LLMessageSystem* msg = gMessageSystem; | 696 | LLMessageSystem* msg = gMessageSystem; |
627 | msg->newMessageFast(_PREHASH_ChatFromViewer); | 697 | msg->newMessageFast(_PREHASH_ChatFromViewer); |
628 | msg->nextBlockFast(_PREHASH_AgentData); | 698 | msg->nextBlockFast(_PREHASH_AgentData); |
diff --git a/linden/indra/newview/llfloaterabout.cpp b/linden/indra/newview/llfloaterabout.cpp index 37e9c54..63f72af 100644 --- a/linden/indra/newview/llfloaterabout.cpp +++ b/linden/indra/newview/llfloaterabout.cpp | |||
@@ -126,7 +126,15 @@ LLFloaterAbout::LLFloaterAbout() | |||
126 | 126 | ||
127 | // Position | 127 | // Position |
128 | LLViewerRegion* region = gAgent.getRegion(); | 128 | LLViewerRegion* region = gAgent.getRegion(); |
129 | if (region) | 129 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-04 (RLVa-1.0.0a) |
130 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) | ||
131 | { | ||
132 | support.append(rlv_handler_t::cstrHidden); | ||
133 | support.append("\n\n"); | ||
134 | } | ||
135 | else if (region) | ||
136 | // [/RLVa:KB] | ||
137 | // if (region) | ||
130 | { | 138 | { |
131 | LLStyleSP server_link_style(new LLStyle); | 139 | LLStyleSP server_link_style(new LLStyle); |
132 | server_link_style->setVisible(true); | 140 | server_link_style->setVisible(true); |
diff --git a/linden/indra/newview/llfloateractivespeakers.cpp b/linden/indra/newview/llfloateractivespeakers.cpp index a8f3f91..b4d402a 100644 --- a/linden/indra/newview/llfloateractivespeakers.cpp +++ b/linden/indra/newview/llfloateractivespeakers.cpp | |||
@@ -98,6 +98,11 @@ void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const std::string& first, c | |||
98 | if (speaker_ptr) | 98 | if (speaker_ptr) |
99 | { | 99 | { |
100 | speaker_ptr->mDisplayName = first + " " + last; | 100 | speaker_ptr->mDisplayName = first + " " + last; |
101 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-1.0.0g | ||
102 | // TODO-RLVa: this seems to get called per frame which is very likely an LL bug that will eventuall get fixed | ||
103 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) | ||
104 | speaker_ptr->mDisplayName = gRlvHandler.getAnonym(speaker_ptr->mDisplayName); | ||
105 | // [/RLVa:KB] | ||
101 | } | 106 | } |
102 | } | 107 | } |
103 | 108 | ||
@@ -710,6 +715,13 @@ void LLPanelActiveSpeakers::onVolumeChange(LLUICtrl* source, void* user_data) | |||
710 | //static | 715 | //static |
711 | void LLPanelActiveSpeakers::onClickProfile(void* user_data) | 716 | void 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 |
720 | void LLPanelActiveSpeakers::onDoubleClickSpeaker(void* user_data) | 732 | void 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 | ||
41 | LLFloaterBeacons::LLFloaterBeacons(const LLSD& seed) | 44 | LLFloaterBeacons::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. |
73 | void LLFloaterBeacons::open() | 76 | void LLFloaterBeacons::open() |
74 | { | 77 | { |
78 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) | ||
79 | if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) | ||
80 | { | ||
81 | return; | ||
82 | } | ||
83 | // [/RLVa:KB] | ||
84 | |||
75 | LLFloater::open(); | 85 | LLFloater::open(); |
76 | gSavedSettings.setBOOL( "BeaconsEnabled", TRUE); | 86 | gSavedSettings.setBOOL( "BeaconsEnabled", TRUE); |
77 | } | 87 | } |
diff --git a/linden/indra/newview/llfloaterchat.cpp b/linden/indra/newview/llfloaterchat.cpp index 5117b8d..4cc721e 100644 --- a/linden/indra/newview/llfloaterchat.cpp +++ b/linden/indra/newview/llfloaterchat.cpp | |||
@@ -202,7 +202,11 @@ void add_timestamped_line(LLViewerTextEditor* edit, const LLChat &chat, const LL | |||
202 | // extract out the sender name and replace it with the hotlinked name. | 202 | // extract out the sender name and replace it with the hotlinked name. |
203 | if (chat.mSourceType == CHAT_SOURCE_AGENT && | 203 | if (chat.mSourceType == CHAT_SOURCE_AGENT && |
204 | chat.mFromID != LLUUID::null && | 204 | chat.mFromID != LLUUID::null && |
205 | (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0)) | 205 | // (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0)) |
206 | (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0) && | ||
207 | // [RLVa] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e) | ||
208 | (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ) | ||
209 | // [/RLVa] | ||
206 | { | 210 | { |
207 | std::string start_line = line.substr(0, chat.mFromName.length() + 1); | 211 | std::string start_line = line.substr(0, chat.mFromName.length() + 1); |
208 | line = line.substr(chat.mFromName.length() + 1); | 212 | line = line.substr(chat.mFromName.length() + 1); |
@@ -226,6 +230,30 @@ void log_chat_text(const LLChat& chat) | |||
226 | // static | 230 | // static |
227 | void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) | 231 | void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) |
228 | { | 232 | { |
233 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
234 | if (rlv_handler_t::isEnabled()) | ||
235 | { | ||
236 | // TODO-RLVa: we might cast too broad a net by filtering here, needs testing | ||
237 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) && (!chat.mRlvLocFiltered) && (CHAT_SOURCE_AGENT != chat.mSourceType) ) | ||
238 | { | ||
239 | LLChat& rlvChat = const_cast<LLChat&>(chat); | ||
240 | gRlvHandler.filterLocation(rlvChat.mText); | ||
241 | rlvChat.mRlvLocFiltered = TRUE; | ||
242 | } | ||
243 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!chat.mRlvNamesFiltered) ) | ||
244 | { | ||
245 | // NOTE: this will also filter inventory accepted/declined text in the chat history | ||
246 | LLChat& rlvChat = const_cast<LLChat&>(chat); | ||
247 | if (CHAT_SOURCE_AGENT != chat.mSourceType) | ||
248 | { | ||
249 | // Filter object and system chat (names are filtered elsewhere to save ourselves an gObjectList lookup) | ||
250 | gRlvHandler.filterNames(rlvChat.mText); | ||
251 | } | ||
252 | rlvChat.mRlvNamesFiltered = TRUE; | ||
253 | } | ||
254 | } | ||
255 | // [/RLVa:KB] | ||
256 | |||
229 | if ( gSavedPerAccountSettings.getBOOL("LogChat") && log_to_file) | 257 | if ( gSavedPerAccountSettings.getBOOL("LogChat") && log_to_file) |
230 | { | 258 | { |
231 | log_chat_text(chat); | 259 | log_chat_text(chat); |
@@ -356,6 +384,30 @@ void LLFloaterChat::addChat(const LLChat& chat, | |||
356 | chat.mChatType == CHAT_TYPE_DEBUG_MSG | 384 | chat.mChatType == CHAT_TYPE_DEBUG_MSG |
357 | && !gSavedSettings.getBOOL("ScriptErrorsAsChat"); | 385 | && !gSavedSettings.getBOOL("ScriptErrorsAsChat"); |
358 | 386 | ||
387 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
388 | if (rlv_handler_t::isEnabled()) | ||
389 | { | ||
390 | // TODO-RLVa: we might cast too broad a net by filtering here, needs testing | ||
391 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) && (!chat.mRlvLocFiltered) && (CHAT_SOURCE_AGENT != chat.mSourceType) ) | ||
392 | { | ||
393 | LLChat& rlvChat = const_cast<LLChat&>(chat); | ||
394 | if (!from_instant_message) | ||
395 | gRlvHandler.filterLocation(rlvChat.mText); | ||
396 | rlvChat.mRlvLocFiltered = TRUE; | ||
397 | } | ||
398 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!chat.mRlvNamesFiltered) ) | ||
399 | { | ||
400 | LLChat& rlvChat = const_cast<LLChat&>(chat); | ||
401 | if ( (!from_instant_message) && (CHAT_SOURCE_AGENT != chat.mSourceType) ) | ||
402 | { | ||
403 | // Filter object and system chat (names are filtered elsewhere to save ourselves an gObjectList lookup) | ||
404 | gRlvHandler.filterNames(rlvChat.mText); | ||
405 | } | ||
406 | rlvChat.mRlvNamesFiltered = TRUE; | ||
407 | } | ||
408 | } | ||
409 | // [/RLVa:KB] | ||
410 | |||
359 | #if LL_LCD_COMPILE | 411 | #if LL_LCD_COMPILE |
360 | // add into LCD displays | 412 | // add into LCD displays |
361 | if (!invisible_script_debug_chat) | 413 | if (!invisible_script_debug_chat) |
@@ -513,7 +565,11 @@ void LLFloaterChat::onClickToggleActiveSpeakers(void* userdata) | |||
513 | { | 565 | { |
514 | LLFloaterChat* self = (LLFloaterChat*)userdata; | 566 | LLFloaterChat* self = (LLFloaterChat*)userdata; |
515 | 567 | ||
516 | self->childSetVisible("active_speakers_panel", !self->childIsVisible("active_speakers_panel")); | 568 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) |
569 | self->childSetVisible("active_speakers_panel", | ||
570 | (!self->childIsVisible("active_speakers_panel")) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ); | ||
571 | // [/RLVa:KB] | ||
572 | //self->childSetVisible("active_speakers_panel", !self->childIsVisible("active_speakers_panel")); | ||
517 | } | 573 | } |
518 | 574 | ||
519 | //static | 575 | //static |
diff --git a/linden/indra/newview/llfloaterinspect.cpp b/linden/indra/newview/llfloaterinspect.cpp index e1d3c4a..2367b48 100644 --- a/linden/indra/newview/llfloaterinspect.cpp +++ b/linden/indra/newview/llfloaterinspect.cpp | |||
@@ -42,6 +42,10 @@ | |||
42 | #include "llviewerobject.h" | 42 | #include "llviewerobject.h" |
43 | #include "lluictrlfactory.h" | 43 | #include "lluictrlfactory.h" |
44 | 44 | ||
45 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
46 | #include "rlvhandler.h" | ||
47 | // [/RLVa:KB] | ||
48 | |||
45 | LLFloaterInspect* LLFloaterInspect::sInstance = NULL; | 49 | LLFloaterInspect* LLFloaterInspect::sInstance = NULL; |
46 | 50 | ||
47 | LLFloaterInspect::LLFloaterInspect(void) : | 51 | LLFloaterInspect::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(×tamp), MAX_STRING); | 236 | LLStringUtil::copy(time, ctime(×tamp), 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 |
814 | void LLPanelLandGeneral::onClickBuyLand(void* data) | 814 | void 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) | ||
2790 | void 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 | |||
85 | protected: | 89 | protected: |
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) | ||
127 | void 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 | ||
56 | private: | 60 | private: |
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) | |||
207 | void LLFloaterOpenObject::onClickMoveAndWear(void* data) | 207 | void 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) | ||
3197 | void 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() | |||
594 | void LLFloaterReporter::setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id) | 623 | void 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 | |||
42 | LLFloaterSettingsDebug* LLFloaterSettingsDebug::sInstance = NULL; | 47 | LLFloaterSettingsDebug* LLFloaterSettingsDebug::sInstance = NULL; |
43 | 48 | ||
44 | LLFloaterSettingsDebug::LLFloaterSettingsDebug() : LLFloater(std::string("Configuration Editor")) | 49 | LLFloaterSettingsDebug::LLFloaterSettingsDebug() : LLFloater(std::string("Configuration Editor")) |
@@ -239,6 +244,32 @@ void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp) | |||
239 | 244 | ||
240 | if (controlp) | 245 | if (controlp) |
241 | { | 246 | { |
247 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.1d | ||
248 | if (rlv_handler_t::isEnabled()) | ||
249 | { | ||
250 | // Don't allow changing DBG_WRITE debug settings under @setdebug=n | ||
251 | bool fEnable = !( (gRlvHandler.hasBehaviour(RLV_BHVR_SETDEBUG)) && | ||
252 | (RlvExtGetSet::getDebugSettingFlags(controlp->getName()) & RlvExtGetSet::DBG_WRITE) ); | ||
253 | // Don't allow toggling "Basic Shaders" and/or "Atmopsheric Shaders" through the debug settings under @setenv=n | ||
254 | fEnable &= !((gRlvHandler.hasBehaviour(RLV_BHVR_SETENV)) && | ||
255 | (("VertexShaderEnable" == controlp->getName()) || ("WindLightUseAtmosShaders" == controlp->getName()))); | ||
256 | #ifdef RLV_EXTENSION_STARTLOCATION | ||
257 | // Don't allow toggling RestrainedLifeLoginLastLocation | ||
258 | fEnable &= !(RLV_SETTING_LOGINLASTLOCATION == controlp->getName()); | ||
259 | #endif // RLV_EXTENSION_STARTLOCATION | ||
260 | |||
261 | // NOTE: this runs per-frame so there's no need to explictly handle onCommitSettings() or onClickDefault() | ||
262 | spinner1->setEnabled(fEnable); | ||
263 | spinner2->setEnabled(fEnable); | ||
264 | spinner3->setEnabled(fEnable); | ||
265 | spinner4->setEnabled(fEnable); | ||
266 | color_swatch->setEnabled(fEnable); | ||
267 | childSetEnabled("val_text", fEnable); | ||
268 | childSetEnabled("boolean_combo", fEnable); | ||
269 | childSetEnabled("default_btn", fEnable); | ||
270 | } | ||
271 | // [/RLVa:KB] | ||
272 | |||
242 | eControlType type = controlp->type(); | 273 | eControlType type = controlp->type(); |
243 | 274 | ||
244 | //hide combo box only for non booleans, otherwise this will result in the combo box closing every frame | 275 | //hide combo box only for non booleans, otherwise this will result in the combo box closing every frame |
diff --git a/linden/indra/newview/llfloaterwindlight.cpp b/linden/indra/newview/llfloaterwindlight.cpp index 37cd4ef..4b0dd04 100644 --- a/linden/indra/newview/llfloaterwindlight.cpp +++ b/linden/indra/newview/llfloaterwindlight.cpp | |||
@@ -317,6 +317,15 @@ void LLFloaterWindLight::syncMenu() | |||
317 | LLWLParamSet& currentParams = param_mgr->mCurParams; | 317 | LLWLParamSet& currentParams = param_mgr->mCurParams; |
318 | //std::map<std::string, LLVector4> & currentParams = param_mgr->mCurParams.mParamValues; | 318 | //std::map<std::string, LLVector4> & currentParams = param_mgr->mCurParams.mParamValues; |
319 | 319 | ||
320 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
321 | // Fixes LL "bug" (preset name isn't kept synchronized) | ||
322 | LLComboBox* comboBox = getChild<LLComboBox>("WLPresetsCombo"); | ||
323 | if (comboBox->getSelectedItemLabel() != currentParams.mName) | ||
324 | { | ||
325 | comboBox->setSimple(currentParams.mName); | ||
326 | } | ||
327 | // [/RLVa:KB] | ||
328 | |||
320 | // blue horizon | 329 | // blue horizon |
321 | param_mgr->mBlueHorizon = currentParams.getVector(param_mgr->mBlueHorizon.mName, err); | 330 | param_mgr->mBlueHorizon = currentParams.getVector(param_mgr->mBlueHorizon.mName, err); |
322 | childSetValue("WLBlueHorizonR", param_mgr->mBlueHorizon.r / 2.0); | 331 | childSetValue("WLBlueHorizonR", param_mgr->mBlueHorizon.r / 2.0); |
diff --git a/linden/indra/newview/llfloaterworldmap.cpp b/linden/indra/newview/llfloaterworldmap.cpp index bc61d8a..a31dde5 100644 --- a/linden/indra/newview/llfloaterworldmap.cpp +++ b/linden/indra/newview/llfloaterworldmap.cpp | |||
@@ -280,6 +280,13 @@ void LLFloaterWorldMap::onClose(bool app_quitting) | |||
280 | // static | 280 | // static |
281 | void LLFloaterWorldMap::show(void*, BOOL center_on_target) | 281 | void 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 |
167 | void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask) | 167 | void 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 | ||
566 | void LLHUDText::setStringUTF8(const std::string &wtext) | 566 | void 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 | ||
1176 | void 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] | ||
133 | protected: | 138 | protected: |
134 | LLHUDText(const U8 type); | 139 | LLHUDText(const U8 type); |
135 | 140 | ||
@@ -175,6 +180,9 @@ private: | |||
175 | EVertAlignment mVertAlignment; | 180 | EVertAlignment mVertAlignment; |
176 | S32 mLOD; | 181 | S32 mLOD; |
177 | BOOL mHidden; | 182 | BOOL mHidden; |
183 | // [RLVa:KB] - Checked: 2009-07-09 (RLVa-1.0.0f) | Added: RLVa-1.0.0f | ||
184 | std::string mObjText; | ||
185 | // [/RLVa:KB] | ||
178 | 186 | ||
179 | static BOOL sDisplayText ; | 187 | static BOOL sDisplayText ; |
180 | static std::set<LLPointer<LLHUDText> > sTextObjects; | 188 | static std::set<LLPointer<LLHUDText> > sTextObjects; |
diff --git a/linden/indra/newview/llimpanel.cpp b/linden/indra/newview/llimpanel.cpp index f30ae8c..7e4ed19 100644 --- a/linden/indra/newview/llimpanel.cpp +++ b/linden/indra/newview/llimpanel.cpp | |||
@@ -2009,6 +2009,42 @@ void LLFloaterIMPanel::sendMsg() | |||
2009 | std::string utf8_text = wstring_to_utf8str(text); | 2009 | std::string utf8_text = wstring_to_utf8str(text); |
2010 | utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); | 2010 | utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); |
2011 | 2011 | ||
2012 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-1.0.0g | ||
2013 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIM)) | ||
2014 | { | ||
2015 | if (IM_NOTHING_SPECIAL == mDialog) // One-on-one IM: allow if recipient is a sendim exception | ||
2016 | { | ||
2017 | if (!gRlvHandler.isException(RLV_BHVR_SENDIM, mOtherParticipantUUID)) | ||
2018 | utf8_text = rlv_handler_t::cstrBlockedSendIM; | ||
2019 | } | ||
2020 | else if (gAgent.isInGroup(mSessionUUID)) // Group chat: allow if recipient is a sendim exception | ||
2021 | { | ||
2022 | if (!gRlvHandler.isException(RLV_BHVR_SENDIM, mSessionUUID)) | ||
2023 | utf8_text = rlv_handler_t::cstrBlockedSendIM; | ||
2024 | } | ||
2025 | else if (mSpeakers) // Conference chat: allow if all participants are sendim exceptions | ||
2026 | { | ||
2027 | LLSpeakerMgr::speaker_list_t speakers; | ||
2028 | mSpeakers->getSpeakerList(&speakers, TRUE); | ||
2029 | |||
2030 | for (LLSpeakerMgr::speaker_list_t::const_iterator itSpeaker = speakers.begin(); | ||
2031 | itSpeaker != speakers.end(); ++itSpeaker) | ||
2032 | { | ||
2033 | LLSpeaker* pSpeaker = *itSpeaker; | ||
2034 | if ( (gAgent.getID() != pSpeaker->mID) && (!gRlvHandler.isException(RLV_BHVR_SENDIM, pSpeaker->mID)) ) | ||
2035 | { | ||
2036 | utf8_text = rlv_handler_t::cstrBlockedSendIM; | ||
2037 | break; | ||
2038 | } | ||
2039 | } | ||
2040 | } | ||
2041 | else // Catch all fall-through | ||
2042 | { | ||
2043 | utf8_text = rlv_handler_t::cstrBlockedSendIM; | ||
2044 | } | ||
2045 | } | ||
2046 | // [/RLVa:KB] | ||
2047 | |||
2012 | if ( mSessionInitialized ) | 2048 | if ( mSessionInitialized ) |
2013 | { | 2049 | { |
2014 | deliver_message(utf8_text, | 2050 | deliver_message(utf8_text, |
diff --git a/linden/indra/newview/llimview.cpp b/linden/indra/newview/llimview.cpp index 1072b21..20de43e 100644 --- a/linden/indra/newview/llimview.cpp +++ b/linden/indra/newview/llimview.cpp | |||
@@ -1550,6 +1550,19 @@ public: | |||
1550 | { | 1550 | { |
1551 | return; | 1551 | return; |
1552 | } | 1552 | } |
1553 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
1554 | // TODO-RLVa: duplicate from process_improved_im()? | ||
1555 | if (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) | ||
1556 | { | ||
1557 | if (gAgent.isInGroup(session_id)) | ||
1558 | { | ||
1559 | if (!gRlvHandler.isException(RLV_BHVR_RECVIM, session_id)) | ||
1560 | return; | ||
1561 | } | ||
1562 | else if (!gRlvHandler.isException(RLV_BHVR_RECVIM, from_id)) | ||
1563 | message = message.substr(0, message_offset) + rlv_handler_t::cstrBlockedRecvIM; | ||
1564 | } | ||
1565 | // [/RLVa:KB] | ||
1553 | 1566 | ||
1554 | // standard message, not from system | 1567 | // standard message, not from system |
1555 | std::string saved; | 1568 | std::string saved; |
diff --git a/linden/indra/newview/llinventorybridge.cpp b/linden/indra/newview/llinventorybridge.cpp index 52b15cb..dc1e0a1 100644 --- a/linden/indra/newview/llinventorybridge.cpp +++ b/linden/indra/newview/llinventorybridge.cpp | |||
@@ -1921,6 +1921,12 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) | |||
1921 | LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); | 1921 | LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); |
1922 | LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); | 1922 | LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); |
1923 | 1923 | ||
1924 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
1925 | // Fixes LL bug | ||
1926 | mItems.clear(); | ||
1927 | mDisabledItems.clear(); | ||
1928 | // [/RLVa:KB] | ||
1929 | |||
1924 | if (lost_and_found_id == mUUID) | 1930 | if (lost_and_found_id == mUUID) |
1925 | { | 1931 | { |
1926 | // This is the lost+found folder. | 1932 | // This is the lost+found folder. |
@@ -2934,6 +2940,13 @@ void open_notecard(LLViewerInventoryItem* inv_item, | |||
2934 | const LLUUID& source_id, | 2940 | const LLUUID& source_id, |
2935 | BOOL take_focus) | 2941 | BOOL take_focus) |
2936 | { | 2942 | { |
2943 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
2944 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour("viewnote")) ) | ||
2945 | { | ||
2946 | return; | ||
2947 | } | ||
2948 | // [/RLVa:KB] | ||
2949 | |||
2937 | // See if we can bring an existing preview to the front | 2950 | // See if we can bring an existing preview to the front |
2938 | if(!LLPreview::show(inv_item->getUUID(), take_focus)) | 2951 | if(!LLPreview::show(inv_item->getUUID(), take_focus)) |
2939 | { | 2952 | { |
@@ -3259,7 +3272,14 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model | |||
3259 | item = (LLViewerInventoryItem*)gInventory.getItem(object_id); | 3272 | item = (LLViewerInventoryItem*)gInventory.getItem(object_id); |
3260 | if(item && gInventory.isObjectDescendentOf(object_id, gAgent.getInventoryRootID())) | 3273 | if(item && gInventory.isObjectDescendentOf(object_id, gAgent.getInventoryRootID())) |
3261 | { | 3274 | { |
3262 | rez_attachment(item, NULL); | 3275 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) |
3276 | // User picked "Wear" so either nothing is locked, or we need to look up the specific attach point from its name | ||
3277 | // (NOTE: rez_attachment will take care of deciding whether or not we *can* attach) | ||
3278 | rez_attachment(item, | ||
3279 | ((!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedAttachment()) || (RlvSettings::getEnableWear())) | ||
3280 | ? NULL : gRlvHandler.getAttachPoint(item, true)); | ||
3281 | // [/RLVa:KB] | ||
3282 | // rez_attachment(item, NULL); | ||
3263 | } | 3283 | } |
3264 | else if(item && item->isComplete()) | 3284 | else if(item && item->isComplete()) |
3265 | { | 3285 | { |
@@ -3278,6 +3298,15 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model | |||
3278 | else if ("detach" == action) | 3298 | else if ("detach" == action) |
3279 | { | 3299 | { |
3280 | LLInventoryItem* item = gInventory.getItem(mUUID); | 3300 | LLInventoryItem* item = gInventory.getItem(mUUID); |
3301 | |||
3302 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
3303 | // Fall-through: if there's a "Detach from yourself" code path we missed then we'll still disallow the detach here | ||
3304 | if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(item)) ) | ||
3305 | { | ||
3306 | return; | ||
3307 | } | ||
3308 | // [/RLVa:KB] | ||
3309 | |||
3281 | if( item ) | 3310 | if( item ) |
3282 | { | 3311 | { |
3283 | gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); | 3312 | gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); |
@@ -3367,11 +3396,24 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach | |||
3367 | rez_action->mAttachPt = attach_pt; | 3396 | rez_action->mAttachPt = attach_pt; |
3368 | if (attachment && attachment->getObject()) | 3397 | if (attachment && attachment->getObject()) |
3369 | { | 3398 | { |
3370 | gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action); | 3399 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) |
3400 | if ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isDetachable(attach_pt)) ) | ||
3401 | gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action); | ||
3402 | else | ||
3403 | delete rez_action; | ||
3404 | // [/RLVa] | ||
3405 | // gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action); | ||
3371 | } | 3406 | } |
3372 | else | 3407 | else |
3373 | { | 3408 | { |
3374 | confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action); | 3409 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) |
3410 | // Don't allow wear to default attach point if there are any locked attachments | ||
3411 | if ( (!rlv_handler_t::isEnabled()) || (0 != attach_pt) || (!gRlvHandler.hasLockedAttachment()) || (RlvSettings::getEnableWear()) ) | ||
3412 | confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action); | ||
3413 | else | ||
3414 | delete rez_action; | ||
3415 | // [/RLVa] | ||
3416 | // confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action); | ||
3375 | } | 3417 | } |
3376 | } | 3418 | } |
3377 | 3419 | ||
@@ -3440,6 +3482,11 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) | |||
3440 | if( avatarp->isWearingAttachment( mUUID ) ) | 3482 | if( avatarp->isWearingAttachment( mUUID ) ) |
3441 | { | 3483 | { |
3442 | items.push_back(std::string("Detach From Yourself")); | 3484 | items.push_back(std::string("Detach From Yourself")); |
3485 | |||
3486 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
3487 | if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(item)) ) | ||
3488 | disabled_items.push_back(std::string("Detach From Yourself")); | ||
3489 | // [/RLVa:KB] | ||
3443 | } | 3490 | } |
3444 | else | 3491 | else |
3445 | if( !isInTrash() ) | 3492 | if( !isInTrash() ) |
@@ -3451,6 +3498,16 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) | |||
3451 | items.push_back(std::string("RestoreToWorld Separator")); | 3498 | items.push_back(std::string("RestoreToWorld Separator")); |
3452 | items.push_back(std::string("Restore to Last Position")); | 3499 | items.push_back(std::string("Restore to Last Position")); |
3453 | 3500 | ||
3501 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0c | ||
3502 | // Only enable "Wear" if there is an attach point name *and* there isn't a worn attachment there that's currently locked | ||
3503 | if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getEnableWear()) && (gRlvHandler.hasLockedAttachment()) ) | ||
3504 | { | ||
3505 | LLViewerJointAttachment* pAttachPt = gRlvHandler.getAttachPoint(item, true); | ||
3506 | if ( (!pAttachPt) || (!gRlvHandler.isDetachable(pAttachPt->getObject())) ) | ||
3507 | disabled_items.push_back(std::string("Object Wear")); | ||
3508 | } | ||
3509 | // [/RLVa:KB] | ||
3510 | |||
3454 | LLMenuGL* attach_menu = menu.getChildMenuByName("Attach To", TRUE); | 3511 | LLMenuGL* attach_menu = menu.getChildMenuByName("Attach To", TRUE); |
3455 | LLMenuGL* attach_hud_menu = menu.getChildMenuByName("Attach To HUD", TRUE); | 3512 | LLMenuGL* attach_hud_menu = menu.getChildMenuByName("Attach To HUD", TRUE); |
3456 | LLVOAvatar *avatarp = gAgent.getAvatarObject(); | 3513 | LLVOAvatar *avatarp = gAgent.getAvatarObject(); |
@@ -3466,15 +3523,27 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) | |||
3466 | LLMenuItemCallGL *new_item; | 3523 | LLMenuItemCallGL *new_item; |
3467 | if (attachment->getIsHUDAttachment()) | 3524 | if (attachment->getIsHUDAttachment()) |
3468 | { | 3525 | { |
3526 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
3469 | attach_hud_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(), | 3527 | attach_hud_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(), |
3470 | NULL, //&LLObjectBridge::attachToAvatar, | 3528 | NULL, //&LLObjectBridge::attachToAvatar, |
3471 | NULL, &attach_label, (void*)attachment)); | 3529 | (rlv_handler_t::isEnabled()) ? &rlvAttachToEnabler : NULL, |
3530 | &attach_label, (void*)attachment)); | ||
3531 | // [/RLVa:KB] | ||
3532 | //attach_hud_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(), | ||
3533 | // NULL, //&LLObjectBridge::attachToAvatar, | ||
3534 | // NULL, &attach_label, (void*)attachment)); | ||
3472 | } | 3535 | } |
3473 | else | 3536 | else |
3474 | { | 3537 | { |
3538 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
3475 | attach_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(), | 3539 | attach_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(), |
3476 | NULL, //&LLObjectBridge::attachToAvatar, | 3540 | NULL, //&LLObjectBridge::attachToAvatar, |
3477 | NULL, &attach_label, (void*)attachment)); | 3541 | (rlv_handler_t::isEnabled()) ? &rlvAttachToEnabler : NULL, |
3542 | &attach_label, (void*)attachment)); | ||
3543 | // [/RLVa:KB] | ||
3544 | //attach_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(), | ||
3545 | // NULL, //&LLObjectBridge::attachToAvatar, | ||
3546 | // NULL, &attach_label, (void*)attachment)); | ||
3478 | } | 3547 | } |
3479 | 3548 | ||
3480 | LLSimpleListener* callback = mInventoryPanel->getListenerByName("Inventory.AttachObject"); | 3549 | LLSimpleListener* callback = mInventoryPanel->getListenerByName("Inventory.AttachObject"); |
@@ -3954,6 +4023,20 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata ) | |||
3954 | is_gesture); | 4023 | is_gesture); |
3955 | S32 gest_count = gest_item_array.count(); | 4024 | S32 gest_count = gest_item_array.count(); |
3956 | 4025 | ||
4026 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-1.0.0c | ||
4027 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) && (!RlvSettings::getEnableWear()) ) | ||
4028 | { | ||
4029 | // Filter anything that doesn't specify an attachment point (or that specifies one that's currently locked) | ||
4030 | for (S32 idxObj = obj_item_array.count() - 1; idxObj >= 0; idxObj--) | ||
4031 | { | ||
4032 | LLViewerJointAttachment* pAttachPt = gRlvHandler.getAttachPoint(obj_item_array.get(idxObj).get(), true); | ||
4033 | if ( ((!pAttachPt) || (!gRlvHandler.isDetachable(pAttachPt->getObject()))) ) | ||
4034 | obj_item_array.remove(idxObj); | ||
4035 | } | ||
4036 | obj_count = obj_item_array.count(); | ||
4037 | } | ||
4038 | // [/RLVa:KB] | ||
4039 | |||
3957 | if( !wearable_count && !obj_count && !gest_count) | 4040 | if( !wearable_count && !obj_count && !gest_count) |
3958 | { | 4041 | { |
3959 | gViewerWindow->alertXml("CouldNotPutOnOutfit"); | 4042 | gViewerWindow->alertXml("CouldNotPutOnOutfit"); |
@@ -4058,14 +4141,24 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata ) | |||
4058 | msg->nextBlockFast(_PREHASH_HeaderData); | 4141 | msg->nextBlockFast(_PREHASH_HeaderData); |
4059 | msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id ); | 4142 | msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id ); |
4060 | msg->addU8Fast(_PREHASH_TotalObjects, obj_count ); | 4143 | msg->addU8Fast(_PREHASH_TotalObjects, obj_count ); |
4061 | msg->addBOOLFast(_PREHASH_FirstDetachAll, !wear_info->mAppend ); | 4144 | // msg->addBOOLFast(_PREHASH_FirstDetachAll, !wear_info->mAppend ); |
4145 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.2a | ||
4146 | // This really should just *always* be FALSE since TRUE can result in loss of the current asset state | ||
4147 | msg->addBOOLFast(_PREHASH_FirstDetachAll, (!wear_info->mAppend) && (!gRlvHandler.hasLockedAttachment()) ); | ||
4148 | // [/RLVa:KB] | ||
4062 | } | 4149 | } |
4063 | 4150 | ||
4064 | LLInventoryItem* item = obj_item_array.get(i); | 4151 | LLInventoryItem* item = obj_item_array.get(i); |
4065 | msg->nextBlockFast(_PREHASH_ObjectData ); | 4152 | msg->nextBlockFast(_PREHASH_ObjectData ); |
4066 | msg->addUUIDFast(_PREHASH_ItemID, item->getUUID() ); | 4153 | msg->addUUIDFast(_PREHASH_ItemID, item->getUUID() ); |
4067 | msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); | 4154 | msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); |
4068 | msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // Wear at the previous or default attachment point | 4155 | // msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // Wear at the previous or default attachment point |
4156 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.2a | ||
4157 | msg->addU8Fast(_PREHASH_AttachmentPt, | ||
4158 | ( (!rlv_handler_t::isEnabled()) || (RlvSettings::getEnableWear()) || (!gRlvHandler.hasLockedAttachment()) ) | ||
4159 | ? 0 | ||
4160 | : gRlvHandler.getAttachPointIndex(gRlvHandler.getAttachPoint(item, true))); | ||
4161 | // [/RLVa:KB] | ||
4069 | pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); | 4162 | pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); |
4070 | msg->addStringFast(_PREHASH_Name, item->getName()); | 4163 | msg->addStringFast(_PREHASH_Name, item->getName()); |
4071 | msg->addStringFast(_PREHASH_Description, item->getDescription()); | 4164 | msg->addStringFast(_PREHASH_Description, item->getDescription()); |
@@ -4141,6 +4234,13 @@ void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, B | |||
4141 | // item->setAssetUUID(wearable->getID()); | 4234 | // item->setAssetUUID(wearable->getID()); |
4142 | // item->updateAssetOnServer(); | 4235 | // item->updateAssetOnServer(); |
4143 | // } | 4236 | // } |
4237 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-1.0.0c | ||
4238 | if ( (!gRlvHandler.isWearable(wearable->getType())) || | ||
4239 | ( (!gRlvHandler.isRemovable(wearable->getType())) && (gAgent.getWearable(wearable->getType())) ) ) | ||
4240 | { | ||
4241 | continue; | ||
4242 | } | ||
4243 | // [/RLVa:KB] | ||
4144 | items.put(item); | 4244 | items.put(item); |
4145 | wearables.put(wearable); | 4245 | wearables.put(wearable); |
4146 | } | 4246 | } |
@@ -4229,7 +4329,11 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata) | |||
4229 | { | 4329 | { |
4230 | for(i = 0; i < wearable_count; ++i) | 4330 | for(i = 0; i < wearable_count; ++i) |
4231 | { | 4331 | { |
4232 | if( gAgent.isWearingItem (item_array.get(i)->getUUID()) ) | 4332 | // if( gAgent.isWearingItem (item_array.get(i)->getUUID()) ) |
4333 | // [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.2a | ||
4334 | LLWearable* pWearable = gAgent.getWearableFromWearableItem(item_array.get(i)->getUUID()); | ||
4335 | if ( (pWearable) && ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isRemovable(pWearable->getType()))) ) | ||
4336 | // [/RLVa:KB] | ||
4233 | { | 4337 | { |
4234 | gWearableList.getAsset(item_array.get(i)->getAssetUUID(), | 4338 | gWearableList.getAsset(item_array.get(i)->getAssetUUID(), |
4235 | item_array.get(i)->getName(), | 4339 | item_array.get(i)->getName(), |
@@ -4246,6 +4350,18 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata) | |||
4246 | { | 4350 | { |
4247 | for(i = 0; i < obj_count; ++i) | 4351 | for(i = 0; i < obj_count; ++i) |
4248 | { | 4352 | { |
4353 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.2a | ||
4354 | // TODO-RLVa: is there a reason why LL doesn't bother checking to see if you're actually wearing the object? | ||
4355 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) ) | ||
4356 | { | ||
4357 | LLVOAvatar* pAvatar = gAgent.getAvatarObject(); | ||
4358 | if ( (!pAvatar) || (!pAvatar->isWearingAttachment(obj_item_array.get(i)->getUUID())) || | ||
4359 | (!gRlvHandler.isDetachable(obj_item_array.get(i).get())) ) // Why does LLPointer have a cast to BOOL aka S32??? | ||
4360 | { | ||
4361 | continue; | ||
4362 | } | ||
4363 | } | ||
4364 | // [/RVLa:KB] | ||
4249 | gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); | 4365 | gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); |
4250 | gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); | 4366 | gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); |
4251 | gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); | 4367 | gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); |
@@ -4638,8 +4754,11 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, | |||
4638 | { | 4754 | { |
4639 | EWearableType type = wearable->getType(); | 4755 | EWearableType type = wearable->getType(); |
4640 | 4756 | ||
4641 | if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR ) ) //&& | 4757 | //if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR ) ) //&& |
4642 | //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) ) | 4758 | //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) ) |
4759 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.2a | SL big fix | ||
4760 | if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES) ) | ||
4761 | // [/RLVa:KB] | ||
4643 | { | 4762 | { |
4644 | gAgent.removeWearable( type ); | 4763 | gAgent.removeWearable( type ); |
4645 | } | 4764 | } |
diff --git a/linden/indra/newview/llinventorymodel.cpp b/linden/indra/newview/llinventorymodel.cpp index 1029a3c..e662058 100644 --- a/linden/indra/newview/llinventorymodel.cpp +++ b/linden/indra/newview/llinventorymodel.cpp | |||
@@ -2876,6 +2876,14 @@ void LLInventoryModel::processSaveAssetIntoInventory(LLMessageSystem* msg, | |||
2876 | llinfos << "LLInventoryModel::processSaveAssetIntoInventory item" | 2876 | llinfos << "LLInventoryModel::processSaveAssetIntoInventory item" |
2877 | " not found: " << item_id << llendl; | 2877 | " not found: " << item_id << llendl; |
2878 | } | 2878 | } |
2879 | |||
2880 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0e | ||
2881 | if (rlv_handler_t::isEnabled()) | ||
2882 | { | ||
2883 | gRlvHandler.onSavedAssetIntoInventory(item_id); | ||
2884 | } | ||
2885 | // [/RLVa:KB] | ||
2886 | |||
2879 | if(gViewerWindow) | 2887 | if(gViewerWindow) |
2880 | { | 2888 | { |
2881 | gViewerWindow->getWindow()->decBusyCount(); | 2889 | gViewerWindow->getWindow()->decBusyCount(); |
@@ -2918,6 +2926,23 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) | |||
2918 | // << llendl; | 2926 | // << llendl; |
2919 | if(tfolder->getUUID().notNull()) | 2927 | if(tfolder->getUUID().notNull()) |
2920 | { | 2928 | { |
2929 | // [RLVa:KB] - Checked: 2009-08-07 (RLVa-1.0.1f) | Added: RLVa-1.0.0f | ||
2930 | // TODO-RLVa: this really shouldn't go here, but if the inventory offer spans multiple BulkUpdateInventory messages | ||
2931 | // then the second message will cause the viewer to show the folder under its original name even though | ||
2932 | // it is renamed properly on the inventory server | ||
2933 | if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getForbidGiveToRLV()) ) | ||
2934 | { | ||
2935 | LLViewerInventoryCategory* pRlvRoot = gRlvHandler.getSharedRoot(); | ||
2936 | std::string strName = tfolder->getName(); | ||
2937 | if ((pRlvRoot) && (pRlvRoot->getUUID() == tfolder->getParentUUID() ) && (strName.find(RLV_PUTINV_PREFIX) == 0)) | ||
2938 | { | ||
2939 | strName.erase(0, strName.find(RLV_FOLDER_PREFIX_PUTINV)); // Strips the prefix while retaining while the '~' | ||
2940 | tfolder->rename(strName); | ||
2941 | tfolder->updateServer(FALSE); | ||
2942 | } | ||
2943 | } | ||
2944 | // [/RLVa:KB] | ||
2945 | |||
2921 | folders.push_back(tfolder); | 2946 | folders.push_back(tfolder); |
2922 | LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID()); | 2947 | LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID()); |
2923 | if(folderp) | 2948 | if(folderp) |
diff --git a/linden/indra/newview/llinventoryview.cpp b/linden/indra/newview/llinventoryview.cpp index 0f1eb2b..8e8e894 100644 --- a/linden/indra/newview/llinventoryview.cpp +++ b/linden/indra/newview/llinventoryview.cpp | |||
@@ -765,7 +765,17 @@ void LLInventoryView::setVisible( BOOL visible ) | |||
765 | // Destroy all but the last floater, which is made invisible. | 765 | // Destroy all but the last floater, which is made invisible. |
766 | void LLInventoryView::onClose(bool app_quitting) | 766 | void LLInventoryView::onClose(bool app_quitting) |
767 | { | 767 | { |
768 | S32 count = sActiveViews.count(); | 768 | // S32 count = sActiveViews.count(); |
769 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
770 | // See LLInventoryView::closeAll() on why we're doing it this way | ||
771 | S32 count = 0; | ||
772 | for (S32 idx = 0, cnt = sActiveViews.count(); idx < cnt; idx++) | ||
773 | { | ||
774 | if (!sActiveViews.get(idx)->isDead()) | ||
775 | count++; | ||
776 | } | ||
777 | // [/RLVa:KB] | ||
778 | |||
769 | if (count > 1) | 779 | if (count > 1) |
770 | { | 780 | { |
771 | destroy(); | 781 | destroy(); |
@@ -843,6 +853,13 @@ LLInventoryView* LLInventoryView::showAgentInventory(BOOL take_keyboard_focus) | |||
843 | return NULL; | 853 | return NULL; |
844 | } | 854 | } |
845 | 855 | ||
856 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
857 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWINV)) | ||
858 | { | ||
859 | return NULL; | ||
860 | } | ||
861 | // [/RLVa:KB] | ||
862 | |||
846 | LLInventoryView* iv = LLInventoryView::getActiveInventory(); | 863 | LLInventoryView* iv = LLInventoryView::getActiveInventory(); |
847 | #if 0 && !LL_RELEASE_FOR_DOWNLOAD | 864 | #if 0 && !LL_RELEASE_FOR_DOWNLOAD |
848 | if (sActiveViews.count() == 1) | 865 | if (sActiveViews.count() == 1) |
diff --git a/linden/indra/newview/llinventoryview.h b/linden/indra/newview/llinventoryview.h index bdc24e0..1762165 100644 --- a/linden/indra/newview/llinventoryview.h +++ b/linden/indra/newview/llinventoryview.h | |||
@@ -225,6 +225,34 @@ public: | |||
225 | static void toggleVisibility(); | 225 | static void toggleVisibility(); |
226 | static void toggleVisibility(void*) { toggleVisibility(); } | 226 | static void toggleVisibility(void*) { toggleVisibility(); } |
227 | 227 | ||
228 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
229 | static void closeAll() | ||
230 | { | ||
231 | // If there are mulitple inventory floaters open then clicking the "Inventory" button will close | ||
232 | // them one by one (see LLToolBar::onClickInventory() => toggleVisibility() ) until we get to the | ||
233 | // last one which will just be hidden instead of closed/destroyed (see LLInventoryView::onClose) | ||
234 | // | ||
235 | // However the view isn't removed from sActiveViews until its destructor is called and since | ||
236 | // 'LLMortician::sDestroyImmediate == FALSE' while the viewer is running the destructor won't be | ||
237 | // called right away | ||
238 | // | ||
239 | // Result: we can't call close() on the last (sActiveViews.count() will still be > 1) because | ||
240 | // onClose() would take the wrong branch and destroy() it as well | ||
241 | // | ||
242 | // Workaround: "fix" onClose() to count only views that aren't marked as "dead" | ||
243 | |||
244 | LLInventoryView* pView; U8 flagsSound; | ||
245 | for (S32 idx = sActiveViews.count() - 1; idx >= 0; idx--) | ||
246 | { | ||
247 | pView = sActiveViews.get(idx); | ||
248 | flagsSound = pView->getSoundFlags(); | ||
249 | pView->setSoundFlags(LLView::SILENT); // Suppress the window close sound | ||
250 | pView->close(); // onClose() protects against closing the last inventory floater | ||
251 | pView->setSoundFlags(flagsSound); // One view won't be destroy()'ed so it needs its sound flags restored | ||
252 | } | ||
253 | } | ||
254 | // [/RLVa:KB] | ||
255 | |||
228 | // Final cleanup, destroy all open inventory views. | 256 | // Final cleanup, destroy all open inventory views. |
229 | static void cleanup(); | 257 | static void cleanup(); |
230 | 258 | ||
diff --git a/linden/indra/newview/llmaniptranslate.cpp b/linden/indra/newview/llmaniptranslate.cpp index fd02be6..fa66b05 100644 --- a/linden/indra/newview/llmaniptranslate.cpp +++ b/linden/indra/newview/llmaniptranslate.cpp | |||
@@ -463,8 +463,15 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) | |||
463 | if (mask == MASK_COPY) | 463 | if (mask == MASK_COPY) |
464 | { | 464 | { |
465 | // ...we're trying to make a copy | 465 | // ...we're trying to make a copy |
466 | LLSelectMgr::getInstance()->selectDuplicate(LLVector3::zero, FALSE); | 466 | // LLSelectMgr::getInstance()->selectDuplicate(LLVector3::zero, FALSE); |
467 | mCopyMadeThisDrag = TRUE; | 467 | // mCopyMadeThisDrag = TRUE; |
468 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
469 | if (!gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) | ||
470 | { | ||
471 | LLSelectMgr::getInstance()->selectDuplicate(LLVector3::zero, FALSE); | ||
472 | mCopyMadeThisDrag = TRUE; | ||
473 | } | ||
474 | // [/RLVa:KB] | ||
468 | 475 | ||
469 | // When we make the copy, we don't want to do any other processing. | 476 | // When we make the copy, we don't want to do any other processing. |
470 | // If so, the object will also be moved, and the copy will be offset. | 477 | // If so, the object will also be moved, and the copy will be offset. |
diff --git a/linden/indra/newview/llnetmap.cpp b/linden/indra/newview/llnetmap.cpp index 6fa6745..8f5d90d 100644 --- a/linden/indra/newview/llnetmap.cpp +++ b/linden/indra/newview/llnetmap.cpp | |||
@@ -355,6 +355,16 @@ void LLNetMap::draw() | |||
355 | glyph_color = avatar_color; | 355 | glyph_color = avatar_color; |
356 | } | 356 | } |
357 | 357 | ||
358 | // [RLVa:KB] | ||
359 | if ( !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) ) | ||
360 | { | ||
361 | // User is not allowed to see who it is, or even if it's a friend, | ||
362 | // due to RLV settings. | ||
363 | glyph_color = avatar_color; | ||
364 | } | ||
365 | // [/RLVa:KB] | ||
366 | |||
367 | |||
358 | LLWorldMapView::drawAvatar( | 368 | LLWorldMapView::drawAvatar( |
359 | pos_map.mV[VX], pos_map.mV[VY], | 369 | pos_map.mV[VX], pos_map.mV[VY], |
360 | glyph_color, | 370 | glyph_color, |
@@ -551,11 +561,33 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rec | |||
551 | std::string fullname; | 561 | std::string fullname; |
552 | if(mClosestAgentToCursor.notNull() && gCacheName->getFullName(mClosestAgentToCursor, fullname)) | 562 | if(mClosestAgentToCursor.notNull() && gCacheName->getFullName(mClosestAgentToCursor, fullname)) |
553 | { | 563 | { |
554 | msg.append(fullname); | 564 | // [RLVa:KB] |
555 | msg.append("\n"); | 565 | if ( !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) ) |
566 | { | ||
567 | // User is not allowed to see who it is, due to RLV settings. | ||
568 | msg.append(rlv_handler_t::cstrHidden); | ||
569 | } | ||
570 | else | ||
571 | { | ||
572 | msg.append(fullname); | ||
573 | msg.append("\n"); | ||
574 | } | ||
575 | // [/RLVa:KB] | ||
556 | } | 576 | } |
557 | msg.append( region->getName() ); | ||
558 | 577 | ||
578 | // [RLVa:KB] | ||
579 | if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) | ||
580 | { | ||
581 | // User is not allowed to see where they are, due to RLV settings. | ||
582 | msg.append( rlv_handler_t::cstrHidden ); | ||
583 | } | ||
584 | else | ||
585 | { | ||
586 | msg.append( region->getName() ); | ||
587 | } | ||
588 | // [/RLVa:KB] | ||
589 | |||
590 | |||
559 | msg.append("\n"); | 591 | msg.append("\n"); |
560 | gSavedSettings.getBOOL( "MiniMapTeleport" ) ? | 592 | gSavedSettings.getBOOL( "MiniMapTeleport" ) ? |
561 | msg.append(getString("tooltip_tp")) : msg.append(getString("tooltip_map")); | 593 | msg.append(getString("tooltip_tp")) : msg.append(getString("tooltip_map")); |
diff --git a/linden/indra/newview/llnotify.cpp b/linden/indra/newview/llnotify.cpp index 9e837a6..5590ab1 100644 --- a/linden/indra/newview/llnotify.cpp +++ b/linden/indra/newview/llnotify.cpp | |||
@@ -54,6 +54,10 @@ | |||
54 | #include "lloverlaybar.h" // for gOverlayBar | 54 | #include "lloverlaybar.h" // for gOverlayBar |
55 | #include "lluictrlfactory.h" | 55 | #include "lluictrlfactory.h" |
56 | 56 | ||
57 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0e) | Added: RLVa-0.2.0b | ||
58 | #include "rlvhandler.h" | ||
59 | // [/RLVa:KB] | ||
60 | |||
57 | // Globals | 61 | // Globals |
58 | LLNotifyBoxView* gNotifyBoxView = NULL; | 62 | LLNotifyBoxView* gNotifyBoxView = NULL; |
59 | 63 | ||
@@ -328,6 +332,13 @@ LLNotifyBox::LLNotifyBox(LLPointer<LLNotifyBoxTemplate> xml_template, const LLSt | |||
328 | // TODO: Make a separate archive for these. | 332 | // TODO: Make a separate archive for these. |
329 | LLChat chat(mMessage); | 333 | LLChat chat(mMessage); |
330 | chat.mSourceType = CHAT_SOURCE_SYSTEM; | 334 | chat.mSourceType = CHAT_SOURCE_SYSTEM; |
335 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0e) | Added: RLVa-0.2.0b | ||
336 | if (rlv_handler_t::isEnabled()) | ||
337 | { | ||
338 | // Notices should already have their contents filtered where necessary | ||
339 | chat.mRlvLocFiltered = chat.mRlvNamesFiltered = TRUE; | ||
340 | } | ||
341 | // [/RLVa:KB] | ||
331 | LLFloaterChat::getInstance(LLSD())->addChatHistory(chat); | 342 | LLFloaterChat::getInstance(LLSD())->addChatHistory(chat); |
332 | } | 343 | } |
333 | else | 344 | else |
diff --git a/linden/indra/newview/lloverlaybar.cpp b/linden/indra/newview/lloverlaybar.cpp index 91a7375..91ac440 100644 --- a/linden/indra/newview/lloverlaybar.cpp +++ b/linden/indra/newview/lloverlaybar.cpp | |||
@@ -256,7 +256,10 @@ void LLOverlayBar::refresh() | |||
256 | BOOL sitting = FALSE; | 256 | BOOL sitting = FALSE; |
257 | if (gAgent.getAvatarObject()) | 257 | if (gAgent.getAvatarObject()) |
258 | { | 258 | { |
259 | sitting = gAgent.getAvatarObject()->mIsSitting; | 259 | // sitting = gAgent.getAvatarObject()->mIsSitting; |
260 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
261 | sitting = gAgent.getAvatarObject()->mIsSitting && !gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT); | ||
262 | // [/RLVa:KB] | ||
260 | } | 263 | } |
261 | button = getChild<LLButton>("Stand Up"); | 264 | button = getChild<LLButton>("Stand Up"); |
262 | 265 | ||
@@ -336,6 +339,13 @@ void LLOverlayBar::onClickMouselook(void*) | |||
336 | //static | 339 | //static |
337 | void LLOverlayBar::onClickStandUp(void*) | 340 | void LLOverlayBar::onClickStandUp(void*) |
338 | { | 341 | { |
342 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
343 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->mIsSitting) ) | ||
344 | { | ||
345 | return; | ||
346 | } | ||
347 | // [/RLVa:KB] | ||
348 | |||
339 | LLSelectMgr::getInstance()->deselectAllForStandingUp(); | 349 | LLSelectMgr::getInstance()->deselectAllForStandingUp(); |
340 | gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); | 350 | gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); |
341 | } | 351 | } |
diff --git a/linden/indra/newview/llpanelavatar.cpp b/linden/indra/newview/llpanelavatar.cpp index d48237f..8c367fa 100644 --- a/linden/indra/newview/llpanelavatar.cpp +++ b/linden/indra/newview/llpanelavatar.cpp | |||
@@ -789,6 +789,9 @@ void LLPanelAvatarClassified::refresh() | |||
789 | S32 tab_count = tabs ? tabs->getTabCount() : 0; | 789 | S32 tab_count = tabs ? tabs->getTabCount() : 0; |
790 | 790 | ||
791 | bool allow_new = tab_count < MAX_CLASSIFIEDS; | 791 | bool allow_new = tab_count < MAX_CLASSIFIEDS; |
792 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | ||
793 | allow_new &= !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC); | ||
794 | // [/RLVa:KB] | ||
792 | bool allow_delete = (tab_count > 0); | 795 | bool allow_delete = (tab_count > 0); |
793 | bool show_help = (tab_count == 0); | 796 | bool show_help = (tab_count == 0); |
794 | 797 | ||
@@ -924,6 +927,12 @@ void LLPanelAvatarClassified::processAvatarClassifiedReply(LLMessageSystem* msg, | |||
924 | // static | 927 | // static |
925 | void LLPanelAvatarClassified::onClickNew(void* data) | 928 | void LLPanelAvatarClassified::onClickNew(void* data) |
926 | { | 929 | { |
930 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-04 (RLVa-1.0.0a) | ||
931 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) | ||
932 | { | ||
933 | return; | ||
934 | } | ||
935 | // [/RLVa:KB] | ||
927 | LLPanelAvatarClassified* self = (LLPanelAvatarClassified*)data; | 936 | LLPanelAvatarClassified* self = (LLPanelAvatarClassified*)data; |
928 | 937 | ||
929 | gViewerWindow->alertXml("AddClassified",callbackNew,self); | 938 | gViewerWindow->alertXml("AddClassified",callbackNew,self); |
@@ -1020,7 +1029,10 @@ void LLPanelAvatarPicks::refresh() | |||
1020 | BOOL self = (gAgent.getID() == getPanelAvatar()->getAvatarID()); | 1029 | BOOL self = (gAgent.getID() == getPanelAvatar()->getAvatarID()); |
1021 | LLTabContainer* tabs = getChild<LLTabContainer>("picks tab"); | 1030 | LLTabContainer* tabs = getChild<LLTabContainer>("picks tab"); |
1022 | S32 tab_count = tabs ? tabs->getTabCount() : 0; | 1031 | S32 tab_count = tabs ? tabs->getTabCount() : 0; |
1023 | childSetEnabled("New...", self && tab_count < MAX_AVATAR_PICKS); | 1032 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) |
1033 | childSetEnabled("New...", self && tab_count < MAX_AVATAR_PICKS && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ); | ||
1034 | // [/RLVa:KB] | ||
1035 | //childSetEnabled("New...", self && tab_count < MAX_AVATAR_PICKS); | ||
1024 | childSetEnabled("Delete...", self && tab_count > 0); | 1036 | childSetEnabled("Delete...", self && tab_count > 0); |
1025 | childSetVisible("New...", self && getPanelAvatar()->isEditable()); | 1037 | childSetVisible("New...", self && getPanelAvatar()->isEditable()); |
1026 | childSetVisible("Delete...", self && getPanelAvatar()->isEditable()); | 1038 | childSetVisible("Delete...", self && getPanelAvatar()->isEditable()); |
@@ -1098,6 +1110,12 @@ void LLPanelAvatarPicks::processAvatarPicksReply(LLMessageSystem* msg, void**) | |||
1098 | // static | 1110 | // static |
1099 | void LLPanelAvatarPicks::onClickNew(void* data) | 1111 | void LLPanelAvatarPicks::onClickNew(void* data) |
1100 | { | 1112 | { |
1113 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | ||
1114 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) | ||
1115 | { | ||
1116 | return; | ||
1117 | } | ||
1118 | // [/RLVa:KB] | ||
1101 | LLPanelAvatarPicks* self = (LLPanelAvatarPicks*)data; | 1119 | LLPanelAvatarPicks* self = (LLPanelAvatarPicks*)data; |
1102 | LLPanelPick* panel_pick = new LLPanelPick(FALSE); | 1120 | LLPanelPick* panel_pick = new LLPanelPick(FALSE); |
1103 | LLTabContainer* tabs = self->getChild<LLTabContainer>("picks tab"); | 1121 | LLTabContainer* tabs = self->getChild<LLTabContainer>("picks tab"); |
diff --git a/linden/indra/newview/llpanelclassified.cpp b/linden/indra/newview/llpanelclassified.cpp index 4d28be5..3760815 100644 --- a/linden/indra/newview/llpanelclassified.cpp +++ b/linden/indra/newview/llpanelclassified.cpp | |||
@@ -760,7 +760,10 @@ void LLPanelClassified::refresh() | |||
760 | mClickThroughText->setVisible(is_self); | 760 | mClickThroughText->setVisible(is_self); |
761 | 761 | ||
762 | mSetBtn->setVisible(is_self); | 762 | mSetBtn->setVisible(is_self); |
763 | mSetBtn->setEnabled(is_self); | 763 | //mSetBtn->setEnabled(is_self); |
764 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | ||
765 | mSetBtn->setEnabled(is_self && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ); | ||
766 | // [/RLVa:KB] | ||
764 | 767 | ||
765 | mUpdateBtn->setEnabled(is_self && checkDirty()); | 768 | mUpdateBtn->setEnabled(is_self && checkDirty()); |
766 | mUpdateBtn->setVisible(is_self); | 769 | mUpdateBtn->setVisible(is_self); |
@@ -964,6 +967,12 @@ void LLPanelClassified::onClickLandmark(void* data) | |||
964 | // static | 967 | // static |
965 | void LLPanelClassified::onClickSet(void* data) | 968 | void LLPanelClassified::onClickSet(void* data) |
966 | { | 969 | { |
970 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | ||
971 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) | ||
972 | { | ||
973 | return; | ||
974 | } | ||
975 | // [/RLVa:KB] | ||
967 | LLPanelClassified* self = (LLPanelClassified*)data; | 976 | LLPanelClassified* self = (LLPanelClassified*)data; |
968 | 977 | ||
969 | // Save location for later. | 978 | // Save location for later. |
diff --git a/linden/indra/newview/llpanelcontents.cpp b/linden/indra/newview/llpanelcontents.cpp index d91790e..e13ec46 100644 --- a/linden/indra/newview/llpanelcontents.cpp +++ b/linden/indra/newview/llpanelcontents.cpp | |||
@@ -66,6 +66,10 @@ | |||
66 | #include "lltoolcomp.h" | 66 | #include "lltoolcomp.h" |
67 | #include "llpanelinventory.h" | 67 | #include "llpanelinventory.h" |
68 | 68 | ||
69 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
70 | #include "llvoavatar.h" | ||
71 | // [/RLVa:KB] | ||
72 | |||
69 | // | 73 | // |
70 | // Imported globals | 74 | // Imported globals |
71 | // | 75 | // |
@@ -117,6 +121,24 @@ void LLPanelContents::getState(LLViewerObject *objectp ) | |||
117 | && ( objectp->permYouOwner() || ( !group_id.isNull() && gAgent.isInGroup(group_id) ))); // solves SL-23488 | 121 | && ( objectp->permYouOwner() || ( !group_id.isNull() && gAgent.isInGroup(group_id) ))); // solves SL-23488 |
118 | BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ); | 122 | BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ); |
119 | 123 | ||
124 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0g | ||
125 | if ( (rlv_handler_t::isEnabled()) && (editable) ) | ||
126 | { | ||
127 | // Don't allow creation of new scripts if it's undetachable | ||
128 | editable = gRlvHandler.isDetachable(objectp); | ||
129 | |||
130 | // Don't allow creation of new scripts if we're @unsit=n or @sittp=n restricted and we're sitting on the selection | ||
131 | if ( (editable) && ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP))) ) | ||
132 | { | ||
133 | LLVOAvatar* pAvatar = gAgent.getAvatarObject(); | ||
134 | // Only check the first (non-)root object because nothing else would result in enabling the button (see below) | ||
135 | LLViewerObject* pObj = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(TRUE); | ||
136 | |||
137 | editable = (pObj) && (pAvatar) && ((!pAvatar->mIsSitting) || (pAvatar->getRoot() != pObj->getRootEdit())); | ||
138 | } | ||
139 | } | ||
140 | // [/RLVa:KB] | ||
141 | |||
120 | // Edit script button - ok if object is editable and there's an | 142 | // Edit script button - ok if object is editable and there's an |
121 | // unambiguous destination for the object. | 143 | // unambiguous destination for the object. |
122 | if( editable && | 144 | if( editable && |
@@ -160,6 +182,22 @@ void LLPanelContents::onClickNewScript(void *userdata) | |||
160 | LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(children_ok); | 182 | LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(children_ok); |
161 | if(object) | 183 | if(object) |
162 | { | 184 | { |
185 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
186 | if (rlv_handler_t::isEnabled()) // Fallback code [see LLPanelContents::getState()] | ||
187 | { | ||
188 | if (!gRlvHandler.isDetachable(object)) | ||
189 | { | ||
190 | return; // Disallow creating new scripts in a locked attachment | ||
191 | } | ||
192 | else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) ) | ||
193 | { | ||
194 | LLVOAvatar* pAvatar = gAgent.getAvatarObject(); | ||
195 | if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == object->getRootEdit()) ) | ||
196 | return; // .. or in a linkset the avie is sitting on under @unsit=n/@sittp=n | ||
197 | } | ||
198 | } | ||
199 | // [/RLVa:KB] | ||
200 | |||
163 | LLPermissions perm; | 201 | LLPermissions perm; |
164 | perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); | 202 | perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); |
165 | perm.initMasks( | 203 | perm.initMasks( |
diff --git a/linden/indra/newview/llpaneldisplay.cpp b/linden/indra/newview/llpaneldisplay.cpp index d510775..14e295c 100644 --- a/linden/indra/newview/llpaneldisplay.cpp +++ b/linden/indra/newview/llpaneldisplay.cpp | |||
@@ -475,7 +475,12 @@ void LLPanelDisplay::refreshEnabledState() | |||
475 | } | 475 | } |
476 | 476 | ||
477 | // Vertex Shaders | 477 | // Vertex Shaders |
478 | mCtrlShaderEnable->setEnabled(LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable")); | 478 | // mCtrlShaderEnable->setEnabled(LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable")); |
479 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0a | ||
480 | // "Basic Shaders" can't be disabled - but can be enabled - under @setenv=n | ||
481 | bool fCtrlShaderEnable = LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable"); | ||
482 | mCtrlShaderEnable->setEnabled(fCtrlShaderEnable && (!gRlvHandler.hasBehaviour(RLV_BHVR_SETENV) || !mShaderEnable)); | ||
483 | // [/RLVa:KB] | ||
479 | 484 | ||
480 | BOOL shaders = mCtrlShaderEnable->get(); | 485 | BOOL shaders = mCtrlShaderEnable->get(); |
481 | if (shaders) | 486 | if (shaders) |
@@ -490,7 +495,12 @@ void LLPanelDisplay::refreshEnabledState() | |||
490 | 495 | ||
491 | // *HACK just checks to see if we can use shaders... | 496 | // *HACK just checks to see if we can use shaders... |
492 | // maybe some cards that use shaders, but don't support windlight | 497 | // maybe some cards that use shaders, but don't support windlight |
493 | mCtrlWindLight->setEnabled(mCtrlShaderEnable->getEnabled() && shaders); | 498 | // mCtrlWindLight->setEnabled(mCtrlShaderEnable->getEnabled() && shaders); |
499 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0a | ||
500 | // "Atmospheric Shaders" can't be disabled - but can be enabled - under @setenv=n | ||
501 | bool fCtrlWindLightEnable = fCtrlShaderEnable && shaders; | ||
502 | mCtrlWindLight->setEnabled(fCtrlWindLightEnable && (!gRlvHandler.hasBehaviour(RLV_BHVR_SETENV) || !mWindLight)); | ||
503 | // [/RLVa:KB] | ||
494 | 504 | ||
495 | // turn off sky detail if atmostpherics isn't on | 505 | // turn off sky detail if atmostpherics isn't on |
496 | mCtrlSkyFactor->setEnabled(gSavedSettings.getBOOL("WindLightUseAtmosShaders")); | 506 | mCtrlSkyFactor->setEnabled(gSavedSettings.getBOOL("WindLightUseAtmosShaders")); |
diff --git a/linden/indra/newview/llpanelinventory.cpp b/linden/indra/newview/llpanelinventory.cpp index c53395d..7ab850f 100644 --- a/linden/indra/newview/llpanelinventory.cpp +++ b/linden/indra/newview/llpanelinventory.cpp | |||
@@ -81,6 +81,10 @@ | |||
81 | #include "llviewerwindow.h" | 81 | #include "llviewerwindow.h" |
82 | #include "llwearable.h" | 82 | #include "llwearable.h" |
83 | 83 | ||
84 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
85 | #include "llvoavatar.h" | ||
86 | // [/RLVa:KB] | ||
87 | |||
84 | ///---------------------------------------------------------------------------- | 88 | ///---------------------------------------------------------------------------- |
85 | /// Local function declarations, constants, enums, and typedefs | 89 | /// Local function declarations, constants, enums, and typedefs |
86 | ///---------------------------------------------------------------------------- | 90 | ///---------------------------------------------------------------------------- |
@@ -364,8 +368,16 @@ void LLTaskInvFVBridge::previewItem() | |||
364 | 368 | ||
365 | BOOL LLTaskInvFVBridge::isItemRenameable() const | 369 | BOOL 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 | |||
382 | BOOL LLTaskInvFVBridge::renameItem(const std::string& new_name) | 394 | BOOL 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 | ||
414 | BOOL LLTaskInvFVBridge::isItemRemovable() | 451 | BOOL 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 | ||
1181 | void LLTaskLSLBridge::openItem() | 1249 | void 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 |
231 | void LLPanelLandInfo::onClickClaim(void*) | 231 | void 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 | ||
79 | std::string load_password_from_disk(void); | 83 | std::string load_password_from_disk(void); |
@@ -797,6 +801,18 @@ void LLPanelLogin::refreshLocation( bool force_visible ) | |||
797 | if ( ! force_visible ) | 801 | if ( ! force_visible ) |
798 | show_start = gSavedSettings.getBOOL("ShowStartLocation"); | 802 | show_start = gSavedSettings.getBOOL("ShowStartLocation"); |
799 | 803 | ||
804 | |||
805 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
806 | // TODO-RLVa: figure out some way to make this work with RLV_EXTENSION_STARTLOCATION | ||
807 | #ifndef RLV_EXTENSION_STARTLOCATION | ||
808 | if (rlv_handler_t::isEnabled()) | ||
809 | { | ||
810 | show_start = FALSE; | ||
811 | } | ||
812 | #endif // RLV_EXTENSION_STARTLOCATION | ||
813 | // [/RLVa:KB] | ||
814 | |||
815 | |||
800 | sInstance->childSetVisible("start_location_combo", show_start); | 816 | sInstance->childSetVisible("start_location_combo", show_start); |
801 | sInstance->childSetVisible("start_location_text", show_start); | 817 | sInstance->childSetVisible("start_location_text", show_start); |
802 | 818 | ||
diff --git a/linden/indra/newview/llpanelobject.cpp b/linden/indra/newview/llpanelobject.cpp index 5c70590..dd71a0e 100644 --- a/linden/indra/newview/llpanelobject.cpp +++ b/linden/indra/newview/llpanelobject.cpp | |||
@@ -75,6 +75,10 @@ | |||
75 | 75 | ||
76 | #include "lldrawpool.h" | 76 | #include "lldrawpool.h" |
77 | 77 | ||
78 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
79 | #include "llvoavatar.h" | ||
80 | // [/RLVa:KB] | ||
81 | |||
78 | // | 82 | // |
79 | // Constants | 83 | // Constants |
80 | // | 84 | // |
@@ -385,6 +389,15 @@ void LLPanelObject::getState( ) | |||
385 | enable_rotate = FALSE; | 389 | enable_rotate = FALSE; |
386 | } | 390 | } |
387 | 391 | ||
392 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
393 | if ( (rlv_handler_t::isEnabled()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP))) ) | ||
394 | { | ||
395 | LLVOAvatar* pAvatar = gAgent.getAvatarObject(); | ||
396 | if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == objectp->getRootEdit()) ) | ||
397 | enable_move = enable_scale = enable_rotate = FALSE; | ||
398 | } | ||
399 | // [/RLVa:KB] | ||
400 | |||
388 | LLVector3 vec; | 401 | LLVector3 vec; |
389 | if (enable_move) | 402 | if (enable_move) |
390 | { | 403 | { |
diff --git a/linden/indra/newview/llpanelpermissions.cpp b/linden/indra/newview/llpanelpermissions.cpp index c430922..66c6cdd 100644 --- a/linden/indra/newview/llpanelpermissions.cpp +++ b/linden/indra/newview/llpanelpermissions.cpp | |||
@@ -322,9 +322,26 @@ void LLPanelPermissions::refresh() | |||
322 | } | 322 | } |
323 | } | 323 | } |
324 | 324 | ||
325 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
326 | bool fRlvEnableOwner = true; | ||
327 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ) | ||
328 | { | ||
329 | // Only filter the owner name if: the selection is all owned by the same avie and not group owned | ||
330 | if ( (owners_identical) && (!LLSelectMgr::getInstance()->selectIsGroupOwned()) ) | ||
331 | { | ||
332 | owner_name = gRlvHandler.getAnonym(owner_name); | ||
333 | fRlvEnableOwner = false; | ||
334 | } | ||
335 | } | ||
336 | // [/RLVa:KB] | ||
337 | |||
325 | childSetText("Owner Name",owner_name); | 338 | childSetText("Owner Name",owner_name); |
326 | childSetEnabled("Owner Name",TRUE); | 339 | childSetEnabled("Owner Name",TRUE); |
327 | childSetEnabled("button owner profile",owners_identical && (mOwnerID.notNull() || LLSelectMgr::getInstance()->selectIsGroupOwned())); | 340 | // childSetEnabled("button owner profile",owners_identical && (mOwnerID.notNull() || LLSelectMgr::getInstance()->selectIsGroupOwned())); |
341 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
342 | childSetEnabled("button owner profile", | ||
343 | fRlvEnableOwner && owners_identical && (mOwnerID.notNull() || LLSelectMgr::getInstance()->selectIsGroupOwned())); | ||
344 | // [/RLVa:KB] | ||
328 | 345 | ||
329 | // update group text field | 346 | // update group text field |
330 | childSetEnabled("Group:",true); | 347 | childSetEnabled("Group:",true); |
@@ -861,7 +878,13 @@ void LLPanelPermissions::onClickOwner(void *data) | |||
861 | } | 878 | } |
862 | else | 879 | else |
863 | { | 880 | { |
864 | LLFloaterAvatarInfo::showFromObject(self->mOwnerID); | 881 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) |
882 | if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) | ||
883 | { | ||
884 | LLFloaterAvatarInfo::showFromObject(self->mOwnerID); | ||
885 | } | ||
886 | // [/RLVa:KB] | ||
887 | // LLFloaterAvatarInfo::showFromObject(self->mOwnerID); | ||
865 | } | 888 | } |
866 | } | 889 | } |
867 | 890 | ||
diff --git a/linden/indra/newview/llpanelpick.cpp b/linden/indra/newview/llpanelpick.cpp index 480f703..57ce6d5 100644 --- a/linden/indra/newview/llpanelpick.cpp +++ b/linden/indra/newview/llpanelpick.cpp | |||
@@ -400,7 +400,10 @@ void LLPanelPick::refresh() | |||
400 | mEnabledCheck->setEnabled(godlike); | 400 | mEnabledCheck->setEnabled(godlike); |
401 | 401 | ||
402 | mSetBtn->setVisible(godlike); | 402 | mSetBtn->setVisible(godlike); |
403 | mSetBtn->setEnabled(godlike); | 403 | //mSetBtn->setEnabled(godlike); |
404 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | ||
405 | mSetBtn->setEnabled(godlike && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ); | ||
406 | // [/RLVa:KB] | ||
404 | } | 407 | } |
405 | else | 408 | else |
406 | { | 409 | { |
@@ -417,7 +420,10 @@ void LLPanelPick::refresh() | |||
417 | mEnabledCheck->setEnabled(FALSE); | 420 | mEnabledCheck->setEnabled(FALSE); |
418 | 421 | ||
419 | mSetBtn->setVisible(is_self); | 422 | mSetBtn->setVisible(is_self); |
420 | mSetBtn->setEnabled(is_self); | 423 | //mSetBtn->setEnabled(is_self); |
424 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | ||
425 | mSetBtn->setEnabled(is_self && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ); | ||
426 | // [/RLVa] | ||
421 | } | 427 | } |
422 | } | 428 | } |
423 | 429 | ||
@@ -455,6 +461,12 @@ void LLPanelPick::onClickLandmark(void* data) | |||
455 | // static | 461 | // static |
456 | void LLPanelPick::onClickSet(void* data) | 462 | void LLPanelPick::onClickSet(void* data) |
457 | { | 463 | { |
464 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | ||
465 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) | ||
466 | { | ||
467 | return; | ||
468 | } | ||
469 | // [/RLVa:KB] | ||
458 | LLPanelPick* self = (LLPanelPick*)data; | 470 | LLPanelPick* self = (LLPanelPick*)data; |
459 | 471 | ||
460 | // Save location for later. | 472 | // Save location for later. |
diff --git a/linden/indra/newview/llprefsim.cpp b/linden/indra/newview/llprefsim.cpp index 39619b7..429bed9 100644 --- a/linden/indra/newview/llprefsim.cpp +++ b/linden/indra/newview/llprefsim.cpp | |||
@@ -259,6 +259,12 @@ void LLPrefsIMImpl::setPersonalInfo(const std::string& visibility, bool im_via_e | |||
259 | LLWStringUtil::replaceChar(busy_response, '^', '\n'); | 259 | LLWStringUtil::replaceChar(busy_response, '^', '\n'); |
260 | LLWStringUtil::replaceChar(busy_response, '%', ' '); | 260 | LLWStringUtil::replaceChar(busy_response, '%', ' '); |
261 | childSetText("busy_response", wstring_to_utf8str(busy_response)); | 261 | childSetText("busy_response", wstring_to_utf8str(busy_response)); |
262 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
263 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIM)) | ||
264 | { | ||
265 | childDisable("busy_response"); | ||
266 | } | ||
267 | // [/RLVa:KB] | ||
262 | 268 | ||
263 | enableHistory(); | 269 | enableHistory(); |
264 | 270 | ||
diff --git a/linden/indra/newview/llpreviewscript.cpp b/linden/indra/newview/llpreviewscript.cpp index af52a4b..1e9def3 100644 --- a/linden/indra/newview/llpreviewscript.cpp +++ b/linden/indra/newview/llpreviewscript.cpp | |||
@@ -1925,6 +1925,12 @@ void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata ) | |||
1925 | LLCheckBoxCtrl* runningCheckbox = self->getChild<LLCheckBoxCtrl>("running"); | 1925 | LLCheckBoxCtrl* runningCheckbox = self->getChild<LLCheckBoxCtrl>("running"); |
1926 | BOOL running = runningCheckbox->get(); | 1926 | BOOL running = runningCheckbox->get(); |
1927 | //self->mRunningCheckbox->get(); | 1927 | //self->mRunningCheckbox->get(); |
1928 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
1929 | if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(object)) ) | ||
1930 | { | ||
1931 | return; | ||
1932 | } | ||
1933 | // [/RLVa:KB] | ||
1928 | if( object ) | 1934 | if( object ) |
1929 | { | 1935 | { |
1930 | LLMessageSystem* msg = gMessageSystem; | 1936 | LLMessageSystem* msg = gMessageSystem; |
@@ -1950,6 +1956,12 @@ void LLLiveLSLEditor::onReset(void *userdata) | |||
1950 | LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata; | 1956 | LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata; |
1951 | 1957 | ||
1952 | LLViewerObject* object = gObjectList.findObject( self->mObjectID ); | 1958 | LLViewerObject* object = gObjectList.findObject( self->mObjectID ); |
1959 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
1960 | if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(object)) ) | ||
1961 | { | ||
1962 | return; | ||
1963 | } | ||
1964 | // [/RLV:KB] | ||
1953 | if(object) | 1965 | if(object) |
1954 | { | 1966 | { |
1955 | LLMessageSystem* msg = gMessageSystem; | 1967 | LLMessageSystem* msg = gMessageSystem; |
@@ -2371,6 +2383,14 @@ void LLLiveLSLEditor::onLoad(void* userdata) | |||
2371 | void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save) | 2383 | void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save) |
2372 | { | 2384 | { |
2373 | LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; | 2385 | LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; |
2386 | |||
2387 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
2388 | if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(gObjectList.findObject(self->mObjectID))) ) | ||
2389 | { | ||
2390 | return; | ||
2391 | } | ||
2392 | // [/RLV:KB] | ||
2393 | |||
2374 | self->mCloseAfterSave = close_after_save; | 2394 | self->mCloseAfterSave = close_after_save; |
2375 | self->saveIfNeeded(); | 2395 | self->saveIfNeeded(); |
2376 | } | 2396 | } |
diff --git a/linden/indra/newview/llselectmgr.cpp b/linden/indra/newview/llselectmgr.cpp index 998cc50..82aeee6 100644 --- a/linden/indra/newview/llselectmgr.cpp +++ b/linden/indra/newview/llselectmgr.cpp | |||
@@ -3451,12 +3451,20 @@ void LLSelectMgr::deselectAllIfTooFar() | |||
3451 | } | 3451 | } |
3452 | 3452 | ||
3453 | LLVector3d selectionCenter = getSelectionCenterGlobal(); | 3453 | LLVector3d selectionCenter = getSelectionCenterGlobal(); |
3454 | if (gSavedSettings.getBOOL("LimitSelectDistance") | 3454 | |
3455 | // if (gSavedSettings.getBOOL("LimitSelectDistance") | ||
3456 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f | ||
3457 | BOOL fRlvFartouch = gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH) && gFloaterTools->getVisible(); | ||
3458 | if ( (gSavedSettings.getBOOL("LimitSelectDistance") || (fRlvFartouch) ) | ||
3459 | // [/RLVa:KB] | ||
3455 | && (!mSelectedObjects->getPrimaryObject() || !mSelectedObjects->getPrimaryObject()->isAvatar()) | 3460 | && (!mSelectedObjects->getPrimaryObject() || !mSelectedObjects->getPrimaryObject()->isAvatar()) |
3456 | && !mSelectedObjects->isAttachment() | 3461 | && !mSelectedObjects->isAttachment() |
3457 | && !selectionCenter.isExactlyZero()) | 3462 | && !selectionCenter.isExactlyZero()) |
3458 | { | 3463 | { |
3459 | F32 deselect_dist = gSavedSettings.getF32("MaxSelectDistance"); | 3464 | // F32 deselect_dist = gSavedSettings.getF32("MaxSelectDistance"); |
3465 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f | ||
3466 | F32 deselect_dist = (!fRlvFartouch) ? gSavedSettings.getF32("MaxSelectDistance") : 1.5f; | ||
3467 | // [/RLVa:KB] | ||
3460 | F32 deselect_dist_sq = deselect_dist * deselect_dist; | 3468 | F32 deselect_dist_sq = deselect_dist * deselect_dist; |
3461 | 3469 | ||
3462 | LLVector3d select_delta = gAgent.getPositionGlobal() - selectionCenter; | 3470 | LLVector3d select_delta = gAgent.getPositionGlobal() - selectionCenter; |
diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp index aca3cac..2dc4e74 100644 --- a/linden/indra/newview/llstartup.cpp +++ b/linden/indra/newview/llstartup.cpp | |||
@@ -384,6 +384,11 @@ bool idle_startup() | |||
384 | // Initialize stuff that doesn't need data from simulators | 384 | // Initialize stuff that doesn't need data from simulators |
385 | // | 385 | // |
386 | 386 | ||
387 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.1d | ||
388 | if ( (gSavedSettings.controlExists(RLV_SETTING_MAIN)) && (gSavedSettings.getBOOL(RLV_SETTING_MAIN)) ) | ||
389 | rlv_handler_t::setEnabled(TRUE); | ||
390 | // [/RLVa:KB] | ||
391 | |||
387 | if (LLFeatureManager::getInstance()->isSafe()) | 392 | if (LLFeatureManager::getInstance()->isSafe()) |
388 | { | 393 | { |
389 | gViewerWindow->alertXml("DisplaySetToSafe"); | 394 | gViewerWindow->alertXml("DisplaySetToSafe"); |
@@ -924,6 +929,23 @@ bool idle_startup() | |||
924 | // their last location, or some URL "-url //sim/x/y[/z]" | 929 | // their last location, or some URL "-url //sim/x/y[/z]" |
925 | // All accounts have both a home and a last location, and we don't support | 930 | // All accounts have both a home and a last location, and we don't support |
926 | // more locations than that. Choose the appropriate one. JC | 931 | // more locations than that. Choose the appropriate one. JC |
932 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.1d | ||
933 | #ifndef RLV_EXTENSION_STARTLOCATION | ||
934 | if (rlv_handler_t::isEnabled()) | ||
935 | #else | ||
936 | if ( (rlv_handler_t::isEnabled()) && (RlvSettings::getLoginLastLocation()) ) | ||
937 | #endif // RLV_EXTENSION_STARTLOCATION | ||
938 | { | ||
939 | // Force login at the last location | ||
940 | agent_location_id = START_LOCATION_ID_LAST; | ||
941 | location_which = START_LOCATION_ID_LAST; | ||
942 | gSavedSettings.setBOOL("LoginLastLocation", FALSE); | ||
943 | |||
944 | // Clear some things that would cause us to divert to a user-specified location | ||
945 | LLURLSimString::setString(LLURLSimString::sLocationStringLast); | ||
946 | LLStartUp::sSLURLCommand.clear(); | ||
947 | } else | ||
948 | // [/RLVa:KB] | ||
927 | if (LLURLSimString::parse()) | 949 | if (LLURLSimString::parse()) |
928 | { | 950 | { |
929 | // a startup URL was specified | 951 | // a startup URL was specified |
diff --git a/linden/indra/newview/llstatusbar.cpp b/linden/indra/newview/llstatusbar.cpp index b0ef61f..012db6f 100644 --- a/linden/indra/newview/llstatusbar.cpp +++ b/linden/indra/newview/llstatusbar.cpp | |||
@@ -568,6 +568,15 @@ void LLStatusBar::refresh() | |||
568 | mRegionDetails.mTraffic = 0.0f; | 568 | mRegionDetails.mTraffic = 0.0f; |
569 | } | 569 | } |
570 | 570 | ||
571 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Modified: RLVa-1.0.0a | ||
572 | if ( (region) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ) // region == NULL if we loose our connection to the grid | ||
573 | { | ||
574 | // TODO-RLVa: find out whether the LCD code is still used because if so then we need to filter that as well | ||
575 | location_name = llformat("%s (%s) - %s", | ||
576 | rlv_handler_t::cstrHiddenRegion.c_str(), region->getSimAccessString().c_str(), rlv_handler_t::cstrHidden.c_str()); | ||
577 | } | ||
578 | // [/RLVa:KB] | ||
579 | |||
571 | mTextParcelName->setText(location_name); | 580 | mTextParcelName->setText(location_name); |
572 | 581 | ||
573 | 582 | ||
@@ -814,6 +823,12 @@ static void onClickScripts(void*) | |||
814 | 823 | ||
815 | static void onClickBuyLand(void*) | 824 | static 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( | |||
2013 | EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand( | 2051 | EAcceptance 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( | |||
2076 | EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject( | 2121 | EAcceptance 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( | |||
2645 | EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnLand( | 2712 | EAcceptance 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( | |||
2666 | EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnObject( | 2741 | EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnObject( |
2667 | LLViewerObject* obj, S32 face, MASK mask, BOOL drop) | 2742 | LLViewerObject* obj, S32 face, MASK mask, BOOL drop) |
2668 | { | 2743 | { |
2744 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
2745 | // NOTE: it looks like this is only ever called from LLToolDragAndDrop::dad3dRezObjectOnObject) making this a bit redundant | ||
2746 | if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) | ||
2747 | { | ||
2748 | return ACCEPT_NO_LOCKED; | ||
2749 | } | ||
2750 | // [/RLVa:KB] | ||
2751 | |||
2669 | lldebugs << "LLToolDragAndDrop::dad3dRezFromObjectOnObject()" << llendl; | 2752 | lldebugs << "LLToolDragAndDrop::dad3dRezFromObjectOnObject()" << llendl; |
2670 | LLViewerInventoryItem* item; | 2753 | LLViewerInventoryItem* item; |
2671 | LLViewerInventoryCategory* cat; | 2754 | LLViewerInventoryCategory* cat; |
diff --git a/linden/indra/newview/lltoolface.cpp b/linden/indra/newview/lltoolface.cpp index d5e4f81..41f2b0d 100644 --- a/linden/indra/newview/lltoolface.cpp +++ b/linden/indra/newview/lltoolface.cpp | |||
@@ -99,6 +99,16 @@ void LLToolFace::pickCallback(const LLPickInfo& pick_info) | |||
99 | return; | 99 | return; |
100 | } | 100 | } |
101 | 101 | ||
102 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f | ||
103 | if ( (rlv_handler_t::isEnabled()) && | ||
104 | ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) || | ||
105 | ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && ((!hit_obj->isAttachment()) || (!hit_obj->permYouOwner())) && | ||
106 | (dist_vec_squared(gAgent.getPositionAgent(), hit_obj->getPositionRegion() + pick_info.mObjectOffset) > 1.5f * 1.5f) ))) | ||
107 | { | ||
108 | return; | ||
109 | } | ||
110 | // [/RLVa:KB] | ||
111 | |||
102 | // ...clicked on a world object, try to pick the appropriate face | 112 | // ...clicked on a world object, try to pick the appropriate face |
103 | 113 | ||
104 | if (pick_info.mKeyMask & MASK_SHIFT) | 114 | if (pick_info.mKeyMask & MASK_SHIFT) |
diff --git a/linden/indra/newview/lltoolgrab.cpp b/linden/indra/newview/lltoolgrab.cpp index a6695f9..6c0a557 100644 --- a/linden/indra/newview/lltoolgrab.cpp +++ b/linden/indra/newview/lltoolgrab.cpp | |||
@@ -185,7 +185,12 @@ BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info) | |||
185 | return FALSE; | 185 | return FALSE; |
186 | } | 186 | } |
187 | 187 | ||
188 | if (objectp->isAvatar()) | 188 | //if (objectp->isAvatar()) |
189 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f | ||
190 | if ( (objectp->isAvatar()) || | ||
191 | ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && ((!objectp->isAttachment()) || (!objectp->permYouOwner())) && | ||
192 | (dist_vec_squared(gAgent.getPositionAgent(), mGrabPick.mIntersection) > 1.5f * 1.5f) ) ) | ||
193 | // [/RLVa:KB] | ||
189 | { | 194 | { |
190 | if (gGrabTransientTool) | 195 | if (gGrabTransientTool) |
191 | { | 196 | { |
@@ -420,6 +425,23 @@ BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask) | |||
420 | return TRUE; | 425 | return TRUE; |
421 | } | 426 | } |
422 | 427 | ||
428 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f | ||
429 | // Don't allow dragging beyond 1.5m under @fartouch=n | ||
430 | LLViewerObject* pObj; | ||
431 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && (GRAB_INACTIVE != mMode) && (hasMouseCapture()) && | ||
432 | ((pObj = mGrabPick.getObject()) != NULL) && (!pObj->isDead()) && (!pObj->isHUDAttachment()) && | ||
433 | (dist_vec_squared(gAgent.getPositionAgent(), pObj->getPositionRegion() + mGrabPick.mObjectOffset) > 1.5f * 1.5f) ) | ||
434 | { | ||
435 | if (gGrabTransientTool) | ||
436 | { | ||
437 | // Prevent the grab tool from popping up as soon as we kill the drag operation | ||
438 | gBasicToolset->selectTool(gGrabTransientTool); | ||
439 | gGrabTransientTool = NULL; | ||
440 | } | ||
441 | setMouseCapture(FALSE); | ||
442 | } | ||
443 | // [/RLVa:KB] | ||
444 | |||
423 | // Do the right hover based on mode | 445 | // Do the right hover based on mode |
424 | switch( mMode ) | 446 | switch( mMode ) |
425 | { | 447 | { |
diff --git a/linden/indra/newview/lltoolpie.cpp b/linden/indra/newview/lltoolpie.cpp index 27d1c4c..93f0254 100644 --- a/linden/indra/newview/lltoolpie.cpp +++ b/linden/indra/newview/lltoolpie.cpp | |||
@@ -165,6 +165,15 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) | |||
165 | // If it's a left-click, and we have a special action, do it. | 165 | // If it's a left-click, and we have a special action, do it. |
166 | if (useClickAction(always_show, mask, object, parent)) | 166 | if (useClickAction(always_show, mask, object, parent)) |
167 | { | 167 | { |
168 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f | ||
169 | // Block left-click special actions (fallback code really since LLToolSelect::handleObjectSelection() wouldn't select it anyway) | ||
170 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && | ||
171 | (dist_vec_squared(gAgent.getPositionAgent(), mPick.mIntersection) > 1.5f * 1.5f) ) | ||
172 | { | ||
173 | return TRUE; | ||
174 | } | ||
175 | // [/RLVa:KB] | ||
176 | |||
168 | mClickAction = 0; | 177 | mClickAction = 0; |
169 | if (object && object->getClickAction()) | 178 | if (object && object->getClickAction()) |
170 | { | 179 | { |
@@ -344,7 +353,22 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) | |||
344 | //gMutePieMenu->setLabel("Mute"); | 353 | //gMutePieMenu->setLabel("Mute"); |
345 | } | 354 | } |
346 | 355 | ||
347 | gPieAvatar->show(x, y, mPieMouseButtonDown); | 356 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f |
357 | #ifdef RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK | ||
358 | // If we have an empty selection under @fartouch=n don't show the pie menu but play the "operation block" sound | ||
359 | if ( (!gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) || (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) ) | ||
360 | { | ||
361 | #endif // RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK | ||
362 | gPieAvatar->show(x, y, mPieMouseButtonDown); | ||
363 | #ifdef RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK | ||
364 | } | ||
365 | else | ||
366 | { | ||
367 | make_ui_sound("UISndInvalidOp"); | ||
368 | } | ||
369 | #endif // RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK | ||
370 | // [/RLVa:KB] | ||
371 | |||
348 | } | 372 | } |
349 | else if (object->isAttachment() && !object->isHUDAttachment()) | 373 | else if (object->isAttachment() && !object->isHUDAttachment()) |
350 | { | 374 | { |
@@ -374,15 +398,32 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) | |||
374 | //gMuteObjectPieMenu->setLabel("Mute"); | 398 | //gMuteObjectPieMenu->setLabel("Mute"); |
375 | } | 399 | } |
376 | 400 | ||
377 | gPieObject->show(x, y, mPieMouseButtonDown); | 401 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f |
378 | 402 | #ifdef RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK | |
379 | // VEFFECT: ShowPie object | 403 | // If we have an empty selection under @fartouch=n don't show the pie menu but play the "operation block" sound |
380 | // Don't show when you click on someone else, it freaks them | 404 | // (not entirely accurate in case of Tools / Select Only XXX [see LLToolSelect::handleObjectSelection()] |
381 | // out. | 405 | if ( (!gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) || (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) ) |
382 | LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE); | 406 | { |
383 | effectp->setPositionGlobal(mPick.mPosGlobal); | 407 | #endif // RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK |
384 | effectp->setColor(LLColor4U(gAgent.getEffectColor())); | 408 | // [/RLVa:KB] |
385 | effectp->setDuration(0.25f); | 409 | gPieObject->show(x, y, mPieMouseButtonDown); |
410 | |||
411 | // VEFFECT: ShowPie object | ||
412 | // Don't show when you click on someone else, it freaks them | ||
413 | // out. | ||
414 | LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE); | ||
415 | effectp->setPositionGlobal(mPick.mPosGlobal); | ||
416 | effectp->setColor(LLColor4U(gAgent.getEffectColor())); | ||
417 | effectp->setDuration(0.25f); | ||
418 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f | ||
419 | #ifdef RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK | ||
420 | } | ||
421 | else | ||
422 | { | ||
423 | make_ui_sound("UISndInvalidOp"); | ||
424 | } | ||
425 | #endif // RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK | ||
426 | // [/RLVa:KB] | ||
386 | } | 427 | } |
387 | } | 428 | } |
388 | 429 | ||
diff --git a/linden/indra/newview/lltoolplacer.cpp b/linden/indra/newview/lltoolplacer.cpp index 297556e..840de23 100644 --- a/linden/indra/newview/lltoolplacer.cpp +++ b/linden/indra/newview/lltoolplacer.cpp | |||
@@ -124,6 +124,14 @@ BOOL LLToolPlacer::raycastForNewObjPos( S32 x, S32 y, LLViewerObject** hit_obj, | |||
124 | return FALSE; | 124 | return FALSE; |
125 | } | 125 | } |
126 | 126 | ||
127 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f | ||
128 | // NOTE: don't use surface_pos_global since for prims it will be the center of the prim while we need center + offset | ||
129 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && (dist_vec_squared(gAgent.getPositionGlobal(), pick.mPosGlobal) > 1.5f * 1.5f) ) | ||
130 | { | ||
131 | return FALSE; | ||
132 | } | ||
133 | // [/RLVa:KB] | ||
134 | |||
127 | // Find the sim where the surface lives. | 135 | // Find the sim where the surface lives. |
128 | LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(surface_pos_global); | 136 | LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(surface_pos_global); |
129 | if (!regionp) | 137 | if (!regionp) |
@@ -255,7 +263,10 @@ BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics ) | |||
255 | { | 263 | { |
256 | flags |= FLAGS_USE_PHYSICS; | 264 | flags |= FLAGS_USE_PHYSICS; |
257 | } | 265 | } |
258 | if (create_selected) | 266 | //if (create_selected) |
267 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) | Added: RLVa-1.0.0b | ||
268 | if ( (create_selected) && (!gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) ) | ||
269 | // [/RLVa:KB] | ||
259 | { | 270 | { |
260 | flags |= FLAGS_CREATE_SELECTED; | 271 | flags |= FLAGS_CREATE_SELECTED; |
261 | } | 272 | } |
@@ -513,6 +524,13 @@ BOOL LLToolPlacer::placeObject(S32 x, S32 y, MASK mask) | |||
513 | { | 524 | { |
514 | BOOL added = TRUE; | 525 | BOOL added = TRUE; |
515 | 526 | ||
527 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
528 | if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) | ||
529 | { | ||
530 | return TRUE; // Callers seem to expect a "did you handle it?" so we return TRUE rather than FALSE | ||
531 | } | ||
532 | // [/RLVa:KB] | ||
533 | |||
516 | if (gSavedSettings.getBOOL("CreateToolCopySelection")) | 534 | if (gSavedSettings.getBOOL("CreateToolCopySelection")) |
517 | { | 535 | { |
518 | added = addDuplicate(x, y); | 536 | added = addDuplicate(x, y); |
diff --git a/linden/indra/newview/lltoolselect.cpp b/linden/indra/newview/lltoolselect.cpp index b4e9562..389ae59 100644 --- a/linden/indra/newview/lltoolselect.cpp +++ b/linden/indra/newview/lltoolselect.cpp | |||
@@ -50,6 +50,10 @@ | |||
50 | #include "llvoavatar.h" | 50 | #include "llvoavatar.h" |
51 | #include "llworld.h" | 51 | #include "llworld.h" |
52 | 52 | ||
53 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
54 | #include "llfloatertools.h" | ||
55 | // [/RLVa:KB] | ||
56 | |||
53 | // Globals | 57 | // Globals |
54 | extern BOOL gAllowSelectAvatar; | 58 | extern 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 | ||
427 | bool rlvHandleEnableLegacyNamingChanged(const LLSD& newvalue) | ||
428 | { | ||
429 | rlv_handler_t::fLegacyNaming = newvalue.asBoolean(); | ||
430 | return true; | ||
431 | } | ||
432 | |||
433 | bool rlvHandleShowNameTagsChanged(const LLSD& newvalue) | ||
434 | { | ||
435 | RlvSettings::fShowNameTags = newvalue.asBoolean(); | ||
436 | return true; | ||
437 | } | ||
438 | // [/RLVa:KB] | ||
439 | |||
426 | bool handleMediaDebugLevelChanged(const LLSD& newvalue) | 440 | bool 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 | ||
571 | template <> eControlType get_control_type<U32>(const U32& in, LLSD& out) | 592 | template <> eControlType get_control_type<U32>(const U32& in, LLSD& out) |
diff --git a/linden/indra/newview/llviewerdisplay.cpp b/linden/indra/newview/llviewerdisplay.cpp index 96591a2..4b352a4 100644 --- a/linden/indra/newview/llviewerdisplay.cpp +++ b/linden/indra/newview/llviewerdisplay.cpp | |||
@@ -675,7 +675,10 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) | |||
675 | gSky.updateSky(); | 675 | gSky.updateSky(); |
676 | } | 676 | } |
677 | 677 | ||
678 | if(gUseWireframe) | 678 | // if(gUseWireframe) |
679 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
680 | if ( (gUseWireframe) && ( (!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedAttachment()) ) ) | ||
681 | // [/RLVa:KB] | ||
679 | { | 682 | { |
680 | glClearColor(0.5f, 0.5f, 0.5f, 0.f); | 683 | glClearColor(0.5f, 0.5f, 0.5f, 0.f); |
681 | glClear(GL_COLOR_BUFFER_BIT); | 684 | glClear(GL_COLOR_BUFFER_BIT); |
@@ -802,7 +805,12 @@ void render_hud_attachments() | |||
802 | glh::matrix4f current_mod = glh_get_current_modelview(); | 805 | glh::matrix4f current_mod = glh_get_current_modelview(); |
803 | 806 | ||
804 | // clamp target zoom level to reasonable values | 807 | // clamp target zoom level to reasonable values |
805 | gAgent.mHUDTargetZoom = llclamp(gAgent.mHUDTargetZoom, 0.1f, 1.f); | 808 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) |
809 | // TODO-RLVa: while hasLockedHUD() isn't slow this is called per frame so find a better way | ||
810 | gAgent.mHUDTargetZoom = llclamp(gAgent.mHUDTargetZoom, | ||
811 | ( (!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedHUD()) ) ? 0.1f : 0.85f, 1.f); | ||
812 | // [/RLVa:KB] | ||
813 | //gAgent.mHUDTargetZoom = llclamp(gAgent.mHUDTargetZoom, 0.1f, 1.f); | ||
806 | // smoothly interpolate current zoom level | 814 | // smoothly interpolate current zoom level |
807 | gAgent.mHUDCurZoom = lerp(gAgent.mHUDCurZoom, gAgent.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f)); | 815 | gAgent.mHUDCurZoom = lerp(gAgent.mHUDCurZoom, gAgent.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f)); |
808 | 816 | ||
diff --git a/linden/indra/newview/llviewermenu.cpp b/linden/indra/newview/llviewermenu.cpp index 2940bdd..6bd38e6 100644 --- a/linden/indra/newview/llviewermenu.cpp +++ b/linden/indra/newview/llviewermenu.cpp | |||
@@ -219,6 +219,13 @@ void init_debug_ui_menu(LLMenuGL* menu); | |||
219 | void init_debug_xui_menu(LLMenuGL* menu); | 219 | void init_debug_xui_menu(LLMenuGL* menu); |
220 | void init_debug_avatar_menu(LLMenuGL* menu); | 220 | void init_debug_avatar_menu(LLMenuGL* menu); |
221 | void init_debug_baked_texture_menu(LLMenuGL* menu); | 221 | void init_debug_baked_texture_menu(LLMenuGL* menu); |
222 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
223 | #ifdef RLV_DEBUG_TESTS | ||
224 | #include "rlvtest.h" | ||
225 | #endif // RLV_DEBUG_TESTS | ||
226 | #include "rlvfloaterbehaviour.h" | ||
227 | void init_debug_rlva_menu(LLMenuGL* menu); | ||
228 | // [/RLVa:KB] | ||
222 | 229 | ||
223 | BOOL enable_land_build(void*); | 230 | BOOL enable_land_build(void*); |
224 | BOOL enable_object_build(void*); | 231 | BOOL enable_object_build(void*); |
@@ -825,6 +832,19 @@ void init_client_menu(LLMenuGL* menu) | |||
825 | init_debug_world_menu(sub_menu); | 832 | init_debug_world_menu(sub_menu); |
826 | menu->appendMenu(sub_menu); | 833 | menu->appendMenu(sub_menu); |
827 | 834 | ||
835 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.1b | ||
836 | #ifdef RLV_ADVANCED_MENU | ||
837 | if (rlv_handler_t::isEnabled()) | ||
838 | { | ||
839 | sub_menu = new LLMenuGL("RLVa"); | ||
840 | init_debug_rlva_menu(sub_menu); | ||
841 | menu->appendMenu(sub_menu); | ||
842 | sub_menu->setVisible(rlv_handler_t::isEnabled()); | ||
843 | sub_menu->setEnabled(rlv_handler_t::isEnabled()); | ||
844 | } | ||
845 | #endif // RLV_ADVANCED_MENU | ||
846 | // [/RLVa:KB] | ||
847 | |||
828 | sub_menu = new LLMenuGL("UI"); | 848 | sub_menu = new LLMenuGL("UI"); |
829 | init_debug_ui_menu(sub_menu); | 849 | init_debug_ui_menu(sub_menu); |
830 | menu->appendMenu(sub_menu); | 850 | menu->appendMenu(sub_menu); |
@@ -919,6 +939,13 @@ void init_client_menu(LLMenuGL* menu) | |||
919 | &menu_check_control, | 939 | &menu_check_control, |
920 | (void*)"ShowConsoleWindow")); | 940 | (void*)"ShowConsoleWindow")); |
921 | 941 | ||
942 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-1.0.0e | ||
943 | #ifdef RLV_ADVANCED_TOGGLE_RLVA | ||
944 | if (gSavedSettings.controlExists(RLV_SETTING_MAIN)) | ||
945 | menu->append(new LLMenuItemCheckGL("Restrained Life API", &rlvDbgToggleEnabled, NULL, &rlvDbgGetEnabled, NULL)); | ||
946 | #endif // RLV_ADVANCED_TOGGLE_RLVA | ||
947 | // [/RLVa:KB] | ||
948 | |||
922 | if(gSavedSettings.getBOOL("QAMode")) | 949 | if(gSavedSettings.getBOOL("QAMode")) |
923 | { | 950 | { |
924 | LLMenuGL* sub = NULL; | 951 | LLMenuGL* sub = NULL; |
@@ -1366,6 +1393,53 @@ void init_debug_baked_texture_menu(LLMenuGL* menu) | |||
1366 | menu->createJumpKeys(); | 1393 | menu->createJumpKeys(); |
1367 | } | 1394 | } |
1368 | 1395 | ||
1396 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-1.0.0g | ||
1397 | void init_debug_rlva_menu(LLMenuGL* menu) | ||
1398 | { | ||
1399 | // Experimental feature toggles | ||
1400 | { | ||
1401 | /* | ||
1402 | #ifdef RLV_EXPERIMENTAL | ||
1403 | LLMenuGL* sub_menu = new LLMenuGL("Experimental"); | ||
1404 | |||
1405 | menu->appendMenu(sub_menu); | ||
1406 | #endif // RLV_EXPERIMENTAL | ||
1407 | */ | ||
1408 | } | ||
1409 | |||
1410 | // Unit tests | ||
1411 | { | ||
1412 | #ifdef RLV_DEBUG_TESTS | ||
1413 | init_debug_rlva_tests_menu(menu); | ||
1414 | #endif // RLV_DEBUG_TESTS | ||
1415 | } | ||
1416 | |||
1417 | #ifdef RLV_EXTENSION_ENABLE_WEAR | ||
1418 | if (gSavedSettings.controlExists(RLV_SETTING_ENABLEWEAR)) | ||
1419 | { | ||
1420 | menu->append(new LLMenuItemCheckGL("Enable Wear", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_ENABLEWEAR)); | ||
1421 | menu->appendSeparator(); | ||
1422 | } | ||
1423 | #endif // RLV_EXTENSION_ENABLE_WEAR | ||
1424 | |||
1425 | #ifdef RLV_EXTENSION_HIDELOCKED | ||
1426 | if ( (gSavedSettings.controlExists(RLV_SETTING_HIDELOCKEDLAYER)) && | ||
1427 | (gSavedSettings.controlExists(RLV_SETTING_HIDELOCKEDATTACH)) ) | ||
1428 | { | ||
1429 | menu->append(new LLMenuItemCheckGL("Hide locked layers", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_HIDELOCKEDLAYER)); | ||
1430 | menu->append(new LLMenuItemCheckGL("Hide locked attachments", menu_toggle_control, NULL, menu_check_control, (void*)RLV_SETTING_HIDELOCKEDATTACH)); | ||
1431 | //sub_menu->append(new LLMenuItemToggleGL("Hide locked inventory", &rlv_handler_t::fHideLockedInventory)); | ||
1432 | menu->appendSeparator(); | ||
1433 | } | ||
1434 | #endif // RLV_EXTENSION_HIDELOCKED | ||
1435 | |||
1436 | #ifdef RLV_EXTENSION_FLOATER_RESTRICTIONS | ||
1437 | // TODO-RLVa: figure out a way to tell if floater_rlv_behaviour.xml exists | ||
1438 | menu->append(new LLMenuItemCallGL("Restrictions...", RlvFloaterBehaviour::show, NULL, NULL)); | ||
1439 | #endif // RLV_EXTENSION_FLOATER_RESTRICTIONS | ||
1440 | } | ||
1441 | // [/RLVa:KB] | ||
1442 | |||
1369 | void init_server_menu(LLMenuGL* menu) | 1443 | void init_server_menu(LLMenuGL* menu) |
1370 | { | 1444 | { |
1371 | { | 1445 | { |
@@ -1518,6 +1592,16 @@ class LLObjectTouch : public view_listener_t | |||
1518 | 1592 | ||
1519 | LLPickInfo pick = LLToolPie::getInstance()->getPick(); | 1593 | LLPickInfo pick = LLToolPie::getInstance()->getPick(); |
1520 | 1594 | ||
1595 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f | ||
1596 | // TODO-RLVa: this code is rather redundant since we'll never get an active selection to show a pie menu for | ||
1597 | // [msg->addVector3("Position", pick.mIntersection) <- see llDetectedTouchPos()] | ||
1598 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && ((!object->isAttachment()) || (!object->permYouOwner())) && | ||
1599 | (dist_vec_squared(gAgent.getPositionAgent(), pick.mIntersection) > 1.5f * 1.5f) ) | ||
1600 | { | ||
1601 | return true; // Can't touch in-world objects (or other avie's attachments) farther than 1.5m away under @fartouch=n | ||
1602 | } | ||
1603 | // [/RLVa:KB] | ||
1604 | |||
1521 | LLMessageSystem *msg = gMessageSystem; | 1605 | LLMessageSystem *msg = gMessageSystem; |
1522 | 1606 | ||
1523 | msg->newMessageFast(_PREHASH_ObjectGrab); | 1607 | msg->newMessageFast(_PREHASH_ObjectGrab); |
@@ -1566,6 +1650,14 @@ class LLObjectEnableTouch : public view_listener_t | |||
1566 | { | 1650 | { |
1567 | LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); | 1651 | LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); |
1568 | bool new_value = obj && obj->flagHandleTouch(); | 1652 | bool new_value = obj && obj->flagHandleTouch(); |
1653 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f | ||
1654 | // TODO-RLVa: this code is rather redundant since we'll never get an active selection to show a pie menu for | ||
1655 | if ( (new_value) && (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && ((!obj->isAttachment()) || (!obj->permYouOwner())) && | ||
1656 | (dist_vec_squared(gAgent.getPositionAgent(), LLToolPie::getInstance()->getPick().mIntersection) > 1.5f * 1.5f) ) | ||
1657 | { | ||
1658 | new_value = false; // Can't touch in-world objects (or other avie's attachments) farther than 1.5m away under @fartouch=n | ||
1659 | } | ||
1660 | // [/RLVa:KB] | ||
1569 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | 1661 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); |
1570 | 1662 | ||
1571 | // Update label based on the node touch name if available. | 1663 | // Update label based on the node touch name if available. |
@@ -1634,6 +1726,14 @@ class LLObjectOpen : public view_listener_t | |||
1634 | { | 1726 | { |
1635 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 1727 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
1636 | { | 1728 | { |
1729 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) | ||
1730 | // TODO-RLVa: shouldn't we be checking for fartouch here as well? | ||
1731 | if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) | ||
1732 | { | ||
1733 | return true; | ||
1734 | } | ||
1735 | // [/RLVa:KB] | ||
1736 | |||
1637 | return handle_object_open(); | 1737 | return handle_object_open(); |
1638 | } | 1738 | } |
1639 | }; | 1739 | }; |
@@ -1652,6 +1752,12 @@ class LLObjectEnableOpen : public view_listener_t | |||
1652 | if (!root) new_value = false; | 1752 | if (!root) new_value = false; |
1653 | else new_value = root->allowOpen(); | 1753 | else new_value = root->allowOpen(); |
1654 | } | 1754 | } |
1755 | |||
1756 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) | Modified: RLVa-1.0.0b | ||
1757 | // TODO-RLV: shouldn't we be checking for fartouch here as well? (and LLViewerObject::allowOpen() makes this redundant?) | ||
1758 | new_value &= !gRlvHandler.hasBehaviour(RLV_BHVR_EDIT); | ||
1759 | // [/RLVa:KB] | ||
1760 | |||
1655 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | 1761 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); |
1656 | return true; | 1762 | return true; |
1657 | } | 1763 | } |
@@ -1713,7 +1819,13 @@ bool toggle_build_mode() | |||
1713 | } | 1819 | } |
1714 | } | 1820 | } |
1715 | 1821 | ||
1716 | 1822 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | |
1823 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (LLSelectMgr::getInstance()) ) | ||
1824 | { | ||
1825 | LLSelectMgr::getInstance()->deselectAll(); | ||
1826 | } | ||
1827 | // [/RLVa:KB] | ||
1828 | |||
1717 | LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); | 1829 | LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); |
1718 | LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() ); | 1830 | LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() ); |
1719 | 1831 | ||
@@ -1813,6 +1925,23 @@ class LLObjectEdit : public view_listener_t | |||
1813 | { | 1925 | { |
1814 | LLViewerParcelMgr::getInstance()->deselectLand(); | 1926 | LLViewerParcelMgr::getInstance()->deselectLand(); |
1815 | 1927 | ||
1928 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f | ||
1929 | if (rlv_handler_t::isEnabled()) | ||
1930 | { | ||
1931 | if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) | ||
1932 | { | ||
1933 | return true; // Can't edit any object under @edit=n | ||
1934 | } | ||
1935 | else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && | ||
1936 | (SELECT_TYPE_WORLD == LLSelectMgr::getInstance()->getSelection()->getSelectType()) && | ||
1937 | (dist_vec_squared(gAgent.getPositionAgent(), LLToolPie::getInstance()->getPick().mIntersection) > 1.5f * 1.5f) ) | ||
1938 | { | ||
1939 | // TODO-RLVa: this code is rather redundant since we'll never get an active selection to show a pie menu for | ||
1940 | return true; // Can't edit in-world objects farther than 1.5m away under @fartouch=n | ||
1941 | } | ||
1942 | } | ||
1943 | // [/RLVa:KB] | ||
1944 | |||
1816 | if (gAgent.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit()) | 1945 | if (gAgent.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit()) |
1817 | { | 1946 | { |
1818 | LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); | 1947 | LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); |
@@ -1962,6 +2091,22 @@ class LLEnableEdit : public view_listener_t | |||
1962 | enable = LLViewerParcelMgr::getInstance()->agentCanBuild() | 2091 | enable = LLViewerParcelMgr::getInstance()->agentCanBuild() |
1963 | || LLSelectMgr::getInstance()->getSelection()->isAttachment(); | 2092 | || LLSelectMgr::getInstance()->getSelection()->isAttachment(); |
1964 | } | 2093 | } |
2094 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
2095 | // TODO-RLV: include fartouch here? | ||
2096 | if ( (rlv_handler_t::isEnabled()) && (enable) ) | ||
2097 | { | ||
2098 | // We have no way of knowing whether we're being called for "Create" or for "Edit", but we can | ||
2099 | // make an educated guess based on the currently active selection which puts us halfway there. | ||
2100 | BOOL fActiveSelection = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); | ||
2101 | |||
2102 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) ) | ||
2103 | enable = false; // Edit and rez restricted, disable them both | ||
2104 | else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (fActiveSelection) ) | ||
2105 | enable = false; // Edit restricted and there's an active selection => disable Edit and Create | ||
2106 | else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) && (!fActiveSelection) ) | ||
2107 | enable = false; // Rez restricted and there's no active selection => disable Create | ||
2108 | } | ||
2109 | // [/RLVa:KB] | ||
1965 | gMenuHolder->findControl(userdata["control"].asString())->setValue(enable); | 2110 | gMenuHolder->findControl(userdata["control"].asString())->setValue(enable); |
1966 | return true; | 2111 | return true; |
1967 | } | 2112 | } |
@@ -1989,7 +2134,10 @@ class LLSelfEnableRemoveAllAttachments : public view_listener_t | |||
1989 | { | 2134 | { |
1990 | LLVOAvatar::attachment_map_t::iterator curiter = iter++; | 2135 | LLVOAvatar::attachment_map_t::iterator curiter = iter++; |
1991 | LLViewerJointAttachment* attachment = curiter->second; | 2136 | LLViewerJointAttachment* attachment = curiter->second; |
1992 | if (attachment->getObject()) | 2137 | // if (attachment->getObject()) |
2138 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0c | ||
2139 | if ( (attachment->getObject()) && ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isDetachable(curiter->first)) ) ) | ||
2140 | // [/RLVa:KB] | ||
1993 | { | 2141 | { |
1994 | new_value = true; | 2142 | new_value = true; |
1995 | break; | 2143 | break; |
@@ -2036,6 +2184,9 @@ class LLObjectEnableMute : public view_listener_t | |||
2036 | BOOL is_linden = lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden"); | 2184 | BOOL is_linden = lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden"); |
2037 | BOOL is_self = avatar->isSelf(); | 2185 | BOOL is_self = avatar->isSelf(); |
2038 | new_value = !is_linden && !is_self; | 2186 | new_value = !is_linden && !is_self; |
2187 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
2188 | new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)); | ||
2189 | // [/RLVa:KB] | ||
2039 | } | 2190 | } |
2040 | } | 2191 | } |
2041 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | 2192 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); |
@@ -2056,6 +2207,12 @@ class LLObjectMute : public view_listener_t | |||
2056 | LLVOAvatar* avatar = find_avatar_from_object(object); | 2207 | LLVOAvatar* avatar = find_avatar_from_object(object); |
2057 | if (avatar) | 2208 | if (avatar) |
2058 | { | 2209 | { |
2210 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-1.0.0e | ||
2211 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) | ||
2212 | { | ||
2213 | return true; // Fallback code [see LLObjectEnableMute::handleEvent()] | ||
2214 | } | ||
2215 | // [/RLVa:KB] | ||
2059 | id = avatar->getID(); | 2216 | id = avatar->getID(); |
2060 | 2217 | ||
2061 | LLNameValue *firstname = avatar->getNVPair("FirstName"); | 2218 | LLNameValue *firstname = avatar->getNVPair("FirstName"); |
@@ -2106,6 +2263,13 @@ class LLObjectMute : public view_listener_t | |||
2106 | 2263 | ||
2107 | bool handle_go_to() | 2264 | bool handle_go_to() |
2108 | { | 2265 | { |
2266 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
2267 | if ( (rlv_handler_t::isEnabled()) && gAgent.forwardGrabbed() && (gRlvHandler.hasLockedAttachment()) ) | ||
2268 | { | ||
2269 | return true; | ||
2270 | } | ||
2271 | // [/RLVa:KB] | ||
2272 | |||
2109 | // JAMESDEBUG try simulator autopilot | 2273 | // JAMESDEBUG try simulator autopilot |
2110 | std::vector<std::string> strings; | 2274 | std::vector<std::string> strings; |
2111 | std::string val; | 2275 | std::string val; |
@@ -2188,6 +2352,12 @@ class LLAvatarFreeze : public view_listener_t | |||
2188 | { | 2352 | { |
2189 | LLUUID* avatar_id = new LLUUID( avatar->getID() ); | 2353 | LLUUID* avatar_id = new LLUUID( avatar->getID() ); |
2190 | std::string fullname = avatar->getFullname(); | 2354 | std::string fullname = avatar->getFullname(); |
2355 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e) | ||
2356 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!fullname.empty()) ) | ||
2357 | { | ||
2358 | fullname = gRlvHandler.getAnonym(fullname); | ||
2359 | } | ||
2360 | // [/RLVa:KB] | ||
2191 | 2361 | ||
2192 | if (!fullname.empty()) | 2362 | if (!fullname.empty()) |
2193 | { | 2363 | { |
@@ -2213,7 +2383,11 @@ class LLAvatarVisibleDebug : public view_listener_t | |||
2213 | { | 2383 | { |
2214 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 2384 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
2215 | { | 2385 | { |
2216 | bool new_value = gAgent.isGodlike(); | 2386 | //bool new_value = gAgent.isGodlike(); |
2387 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
2388 | // TODO-RLVa: can you actually use this to cheat anything? | ||
2389 | bool new_value = gAgent.isGodlike() && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)); | ||
2390 | // [/RLVa:KB] | ||
2217 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | 2391 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); |
2218 | return true; | 2392 | return true; |
2219 | } | 2393 | } |
@@ -2325,6 +2499,12 @@ class LLAvatarEject : public view_listener_t | |||
2325 | MenuCallbackData *data = new MenuCallbackData; | 2499 | MenuCallbackData *data = new MenuCallbackData; |
2326 | (*data).avatar_id = avatar->getID(); | 2500 | (*data).avatar_id = avatar->getID(); |
2327 | std::string fullname = avatar->getFullname(); | 2501 | std::string fullname = avatar->getFullname(); |
2502 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e) | ||
2503 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!fullname.empty()) ) | ||
2504 | { | ||
2505 | fullname = gRlvHandler.getAnonym(fullname); | ||
2506 | } | ||
2507 | // [/RLVa:KB] | ||
2328 | 2508 | ||
2329 | const LLVector3d& pos = avatar->getPositionGlobal(); | 2509 | const LLVector3d& pos = avatar->getPositionGlobal(); |
2330 | LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel(); | 2510 | LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel(); |
@@ -2406,6 +2586,13 @@ class LLAvatarGiveCard : public view_listener_t | |||
2406 | { | 2586 | { |
2407 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 2587 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
2408 | { | 2588 | { |
2589 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
2590 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) | ||
2591 | { | ||
2592 | return true; | ||
2593 | } | ||
2594 | // [/RLVa:KB] | ||
2595 | |||
2409 | llinfos << "handle_give_card()" << llendl; | 2596 | llinfos << "handle_give_card()" << llendl; |
2410 | LLViewerObject* dest = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); | 2597 | LLViewerObject* dest = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); |
2411 | if(dest && dest->isAvatar()) | 2598 | if(dest && dest->isAvatar()) |
@@ -2655,6 +2842,13 @@ class LLSelfStandUp : public view_listener_t | |||
2655 | { | 2842 | { |
2656 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 2843 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
2657 | { | 2844 | { |
2845 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
2846 | if (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) | ||
2847 | { | ||
2848 | return true; | ||
2849 | } | ||
2850 | // [/RLVa:KB] | ||
2851 | |||
2658 | gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); | 2852 | gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); |
2659 | return true; | 2853 | return true; |
2660 | } | 2854 | } |
@@ -2664,7 +2858,10 @@ class LLSelfEnableStandUp : public view_listener_t | |||
2664 | { | 2858 | { |
2665 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 2859 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
2666 | { | 2860 | { |
2667 | bool new_value = gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting; | 2861 | // bool new_value = gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting; |
2862 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
2863 | bool new_value = gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting && !gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT); | ||
2864 | // [/RLVa:KB] | ||
2668 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | 2865 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); |
2669 | return true; | 2866 | return true; |
2670 | } | 2867 | } |
@@ -2839,6 +3036,11 @@ class LLAvatarEnableAddFriend : public view_listener_t | |||
2839 | { | 3036 | { |
2840 | LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); | 3037 | LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); |
2841 | bool new_value = avatar && !is_agent_friend(avatar->getID()); | 3038 | bool new_value = avatar && !is_agent_friend(avatar->getID()); |
3039 | |||
3040 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
3041 | new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)); | ||
3042 | // [/RLVa:KB] | ||
3043 | |||
2842 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | 3044 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); |
2843 | return true; | 3045 | return true; |
2844 | } | 3046 | } |
@@ -2897,6 +3099,15 @@ bool handle_sit_or_stand() | |||
2897 | return true; | 3099 | return true; |
2898 | } | 3100 | } |
2899 | 3101 | ||
3102 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0c) | ||
3103 | if ( (rlv_handler_t::isEnabled()) && | ||
3104 | ( ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->mIsSitting)) || | ||
3105 | (gRlvHandler.hasBehaviour(RLV_BHVR_SIT)) ) ) | ||
3106 | { | ||
3107 | return true; | ||
3108 | } | ||
3109 | // [/RLVa:KB] | ||
3110 | |||
2900 | if (sitting_on_selection()) | 3111 | if (sitting_on_selection()) |
2901 | { | 3112 | { |
2902 | gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); | 3113 | gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); |
@@ -2907,6 +3118,15 @@ bool handle_sit_or_stand() | |||
2907 | 3118 | ||
2908 | if (object && object->getPCode() == LL_PCODE_VOLUME) | 3119 | if (object && object->getPCode() == LL_PCODE_VOLUME) |
2909 | { | 3120 | { |
3121 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0g | ||
3122 | if ( (rlv_handler_t::isEnabled()) && | ||
3123 | ((gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) || (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH))) && | ||
3124 | (dist_vec_squared(gAgent.getPositionGlobal(), object->getPositionGlobal() + LLVector3d(pick.mObjectOffset)) > 1.5f * 1.5f) ) | ||
3125 | { | ||
3126 | return true; // Don't allow sitting farther away than 1.5m under @sittp=n or @fartouch=n | ||
3127 | } | ||
3128 | // [/RLVa:KB] | ||
3129 | |||
2910 | gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit); | 3130 | gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit); |
2911 | gMessageSystem->nextBlockFast(_PREHASH_AgentData); | 3131 | gMessageSystem->nextBlockFast(_PREHASH_AgentData); |
2912 | gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | 3132 | gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); |
@@ -2944,6 +3164,13 @@ class LLLandSit : public view_listener_t | |||
2944 | { | 3164 | { |
2945 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 3165 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
2946 | { | 3166 | { |
3167 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
3168 | if (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) | ||
3169 | { | ||
3170 | return true; | ||
3171 | } | ||
3172 | // [/RLVa:KB] | ||
3173 | |||
2947 | gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); | 3174 | gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); |
2948 | LLViewerParcelMgr::getInstance()->deselectLand(); | 3175 | LLViewerParcelMgr::getInstance()->deselectLand(); |
2949 | 3176 | ||
@@ -3254,6 +3481,14 @@ class LLEditDuplicate : public view_listener_t | |||
3254 | { | 3481 | { |
3255 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 3482 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
3256 | { | 3483 | { |
3484 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
3485 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) && | ||
3486 | (LLEditMenuHandler::gEditMenuHandler == LLSelectMgr::getInstance()) ) | ||
3487 | { | ||
3488 | return true; | ||
3489 | } | ||
3490 | // [/RLVa:KB] | ||
3491 | |||
3257 | if(LLEditMenuHandler::gEditMenuHandler) | 3492 | if(LLEditMenuHandler::gEditMenuHandler) |
3258 | { | 3493 | { |
3259 | LLEditMenuHandler::gEditMenuHandler->duplicate(); | 3494 | LLEditMenuHandler::gEditMenuHandler->duplicate(); |
@@ -3267,6 +3502,13 @@ class LLEditEnableDuplicate : public view_listener_t | |||
3267 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 3502 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
3268 | { | 3503 | { |
3269 | bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDuplicate(); | 3504 | bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDuplicate(); |
3505 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
3506 | if ( (new_value) && (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) && | ||
3507 | (LLEditMenuHandler::gEditMenuHandler == LLSelectMgr::getInstance()) ) | ||
3508 | { | ||
3509 | new_value = false; | ||
3510 | } | ||
3511 | // [/RLVa:KB] | ||
3270 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | 3512 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); |
3271 | return true; | 3513 | return true; |
3272 | } | 3514 | } |
@@ -3652,6 +3894,11 @@ class LLToolsTakeCopy : public view_listener_t | |||
3652 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 3894 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
3653 | { | 3895 | { |
3654 | if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true; | 3896 | if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true; |
3897 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | Modified: RLVa-1.0.0b | ||
3898 | // NOTE: we need to handle "Take Copy" because it will force a sim-side unsit if we're sitting on the selection, | ||
3899 | // but we do want to allow "Take Copy" under @rez=n so that's why we explicitly check for @unsit=n here | ||
3900 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (!rlvCanDeleteOrReturn()) ) return true; | ||
3901 | // [/RLVa:KB] | ||
3655 | 3902 | ||
3656 | const LLUUID& category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT); | 3903 | const LLUUID& category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT); |
3657 | derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id); | 3904 | derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id); |
@@ -3667,6 +3914,9 @@ class LLObjectReturn : public view_listener_t | |||
3667 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 3914 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
3668 | { | 3915 | { |
3669 | if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true; | 3916 | if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true; |
3917 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-05 (RLVa-1.0.0b) | ||
3918 | if ( (rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn()) ) return true; | ||
3919 | // [/RLVa:KB] | ||
3670 | 3920 | ||
3671 | mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); | 3921 | mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); |
3672 | 3922 | ||
@@ -3736,6 +3986,14 @@ class LLObjectEnableReturn : public view_listener_t | |||
3736 | } | 3986 | } |
3737 | } | 3987 | } |
3738 | #endif | 3988 | #endif |
3989 | |||
3990 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
3991 | if ( (new_value) && (rlv_handler_t::isEnabled()) ) | ||
3992 | { | ||
3993 | new_value = rlvCanDeleteOrReturn(); | ||
3994 | } | ||
3995 | // [/RLVa:KB] | ||
3996 | |||
3739 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | 3997 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); |
3740 | return true; | 3998 | return true; |
3741 | } | 3999 | } |
@@ -3757,6 +4015,13 @@ void handle_take() | |||
3757 | return; | 4015 | return; |
3758 | } | 4016 | } |
3759 | 4017 | ||
4018 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
4019 | if ( (rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn()) ) | ||
4020 | { | ||
4021 | return; | ||
4022 | } | ||
4023 | // [/RLVa:KB] | ||
4024 | |||
3760 | BOOL you_own_everything = TRUE; | 4025 | BOOL you_own_everything = TRUE; |
3761 | BOOL locked_but_takeable_object = FALSE; | 4026 | BOOL locked_but_takeable_object = FALSE; |
3762 | LLUUID category_id; | 4027 | LLUUID category_id; |
@@ -3878,6 +4143,13 @@ BOOL enable_take() | |||
3878 | return FALSE; | 4143 | return FALSE; |
3879 | } | 4144 | } |
3880 | 4145 | ||
4146 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
4147 | if ( (rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn()) ) | ||
4148 | { | ||
4149 | return FALSE; | ||
4150 | } | ||
4151 | // [/RLVa:KB] | ||
4152 | |||
3881 | for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin(); | 4153 | for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin(); |
3882 | iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++) | 4154 | iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++) |
3883 | { | 4155 | { |
@@ -4199,6 +4471,21 @@ class LLToolsEnableUnlink : public view_listener_t | |||
4199 | new_value = true; | 4471 | new_value = true; |
4200 | } | 4472 | } |
4201 | } | 4473 | } |
4474 | |||
4475 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0g | ||
4476 | // The user might not be allowed to unlink this object due to RLV settings, | ||
4477 | // because it would unsit them if they are sitting on the object. | ||
4478 | if ( (new_value) && (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && | ||
4479 | (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->mIsSitting) ) | ||
4480 | { | ||
4481 | // Allow if the avie isn't sitting on any of the selected objects | ||
4482 | LLObjectSelectionHandle handleSel = LLSelectMgr::getInstance()->getSelection(); | ||
4483 | RlvSelectIsSittingOn func(gAgent.getAvatarObject()->getRoot()); | ||
4484 | if (handleSel->getFirstRootNode(&func, TRUE)) | ||
4485 | new_value = false; | ||
4486 | } | ||
4487 | // [/RLVa:KB] | ||
4488 | |||
4202 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | 4489 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); |
4203 | return true; | 4490 | return true; |
4204 | } | 4491 | } |
@@ -4208,6 +4495,19 @@ class LLToolsUnlink : public view_listener_t | |||
4208 | { | 4495 | { |
4209 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 4496 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
4210 | { | 4497 | { |
4498 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0g | ||
4499 | // The user might not be allowed to unlink this object due to RLV settings, | ||
4500 | // because it would unsit them if they are sitting on the object. | ||
4501 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->mIsSitting) ) | ||
4502 | { | ||
4503 | // Allow if the avie isn't sitting on any of the selected objects | ||
4504 | LLObjectSelectionHandle handleSel = LLSelectMgr::getInstance()->getSelection(); | ||
4505 | RlvSelectIsSittingOn func(gAgent.getAvatarObject()->getRoot()); | ||
4506 | if (handleSel->getFirstRootNode(&func, TRUE)) | ||
4507 | return true; | ||
4508 | } | ||
4509 | // [/RLVa:KB] | ||
4510 | |||
4211 | LLSelectMgr::getInstance()->sendDelink(); | 4511 | LLSelectMgr::getInstance()->sendDelink(); |
4212 | return true; | 4512 | return true; |
4213 | } | 4513 | } |
@@ -4227,6 +4527,13 @@ class LLToolsReleaseKeys : public view_listener_t | |||
4227 | { | 4527 | { |
4228 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 4528 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
4229 | { | 4529 | { |
4530 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
4531 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) ) | ||
4532 | { | ||
4533 | return true; | ||
4534 | } | ||
4535 | // [/RLVa:KB] | ||
4536 | |||
4230 | gAgent.forceReleaseControls(); | 4537 | gAgent.forceReleaseControls(); |
4231 | 4538 | ||
4232 | return true; | 4539 | return true; |
@@ -4237,7 +4544,11 @@ class LLToolsEnableReleaseKeys : public view_listener_t | |||
4237 | { | 4544 | { |
4238 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 4545 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
4239 | { | 4546 | { |
4240 | gMenuHolder->findControl(userdata["control"].asString())->setValue( gAgent.anyControlGrabbed() ); | 4547 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) |
4548 | gMenuHolder->findControl(userdata["control"].asString())->setValue( | ||
4549 | gAgent.anyControlGrabbed() && ( (!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasLockedAttachment() ) ) ); | ||
4550 | // [/RLVa:KB] | ||
4551 | //gMenuHolder->findControl(userdata["control"].asString())->setValue( gAgent.anyControlGrabbed() ); | ||
4241 | return true; | 4552 | return true; |
4242 | } | 4553 | } |
4243 | }; | 4554 | }; |
@@ -4345,6 +4656,15 @@ class LLEditEnableDelete : public view_listener_t | |||
4345 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 4656 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
4346 | { | 4657 | { |
4347 | bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete(); | 4658 | bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete(); |
4659 | |||
4660 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
4661 | // NOTE: we want to disable delete on objects but not disable delete on text | ||
4662 | if ( (new_value) && (rlv_handler_t::isEnabled()) && (LLEditMenuHandler::gEditMenuHandler == LLSelectMgr::getInstance()) ) | ||
4663 | { | ||
4664 | new_value = rlvCanDeleteOrReturn(); | ||
4665 | } | ||
4666 | // [/RLVa:KB] | ||
4667 | |||
4348 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | 4668 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); |
4349 | return true; | 4669 | return true; |
4350 | } | 4670 | } |
@@ -4354,6 +4674,15 @@ class LLEditDelete : public view_listener_t | |||
4354 | { | 4674 | { |
4355 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 4675 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
4356 | { | 4676 | { |
4677 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
4678 | // NOTE: we want to disable delete on objects but not disable delete on text | ||
4679 | if ( (rlv_handler_t::isEnabled()) && (LLEditMenuHandler::gEditMenuHandler == LLSelectMgr::getInstance()) && | ||
4680 | (!rlvCanDeleteOrReturn()) ) | ||
4681 | { | ||
4682 | return true; | ||
4683 | } | ||
4684 | // [/RLVa:KB] | ||
4685 | |||
4357 | // If a text field can do a deletion, it gets precedence over deleting | 4686 | // If a text field can do a deletion, it gets precedence over deleting |
4358 | // an object in the world. | 4687 | // an object in the world. |
4359 | if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete()) | 4688 | if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete()) |
@@ -4385,6 +4714,12 @@ class LLObjectEnableDelete : public view_listener_t | |||
4385 | # endif | 4714 | # endif |
4386 | LLSelectMgr::getInstance()->canDoDelete(); | 4715 | LLSelectMgr::getInstance()->canDoDelete(); |
4387 | #endif | 4716 | #endif |
4717 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
4718 | if ( (new_value) && (rlv_handler_t::isEnabled()) ) | ||
4719 | { | ||
4720 | new_value = rlvCanDeleteOrReturn(); | ||
4721 | } | ||
4722 | // [/RLVa:KB] | ||
4388 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | 4723 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); |
4389 | return true; | 4724 | return true; |
4390 | } | 4725 | } |
@@ -4403,6 +4738,13 @@ class LLObjectDelete : public view_listener_t | |||
4403 | { | 4738 | { |
4404 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 4739 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
4405 | { | 4740 | { |
4741 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
4742 | if ( (rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn()) ) | ||
4743 | { | ||
4744 | return true; | ||
4745 | } | ||
4746 | // [/RLVa:KB] | ||
4747 | |||
4406 | if (LLSelectMgr::getInstance()) | 4748 | if (LLSelectMgr::getInstance()) |
4407 | { | 4749 | { |
4408 | LLSelectMgr::getInstance()->doDelete(); | 4750 | LLSelectMgr::getInstance()->doDelete(); |
@@ -4752,6 +5094,12 @@ class LLWorldCreateLandmark : public view_listener_t | |||
4752 | { | 5094 | { |
4753 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 5095 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
4754 | { | 5096 | { |
5097 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | ||
5098 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) | ||
5099 | { | ||
5100 | return true; | ||
5101 | } | ||
5102 | // [/RLVa:KB] | ||
4755 | LLViewerRegion* agent_region = gAgent.getRegion(); | 5103 | LLViewerRegion* agent_region = gAgent.getRegion(); |
4756 | if(!agent_region) | 5104 | if(!agent_region) |
4757 | { | 5105 | { |
@@ -4859,6 +5207,13 @@ class LLAvatarInviteToGroup : public view_listener_t | |||
4859 | { | 5207 | { |
4860 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 5208 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
4861 | { | 5209 | { |
5210 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
5211 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) | ||
5212 | { | ||
5213 | return true; | ||
5214 | } | ||
5215 | // [/RLVa:KB] | ||
5216 | |||
4862 | LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); | 5217 | LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); |
4863 | if(avatar) | 5218 | if(avatar) |
4864 | { | 5219 | { |
@@ -4872,6 +5227,13 @@ class LLAvatarAddFriend : public view_listener_t | |||
4872 | { | 5227 | { |
4873 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 5228 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
4874 | { | 5229 | { |
5230 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
5231 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) | ||
5232 | { | ||
5233 | return true; // Fallback code [see LLAvatarEnableAddFriend::handleEvent()] | ||
5234 | } | ||
5235 | // [/RLVa:KB] | ||
5236 | |||
4875 | LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); | 5237 | LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); |
4876 | if(avatar && !is_agent_friend(avatar->getID())) | 5238 | if(avatar && !is_agent_friend(avatar->getID())) |
4877 | { | 5239 | { |
@@ -4959,6 +5321,12 @@ class LLEnablePayObject : public view_listener_t | |||
4959 | } | 5321 | } |
4960 | } | 5322 | } |
4961 | } | 5323 | } |
5324 | |||
5325 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
5326 | // Don't enable "Pay..." on the avatar pie menu under @shownames=n | ||
5327 | new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) || (avatar == NULL); | ||
5328 | // [/RLVa:KB] | ||
5329 | |||
4962 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | 5330 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); |
4963 | return true; | 5331 | return true; |
4964 | } | 5332 | } |
@@ -5147,6 +5515,12 @@ class LLShowFloater : public view_listener_t | |||
5147 | } | 5515 | } |
5148 | else if (floater_name == "buy land") | 5516 | else if (floater_name == "buy land") |
5149 | { | 5517 | { |
5518 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | ||
5519 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) | ||
5520 | { | ||
5521 | return true; | ||
5522 | } | ||
5523 | // [/RLVa:KB] | ||
5150 | if (LLViewerParcelMgr::getInstance()->selectionEmpty()) | 5524 | if (LLViewerParcelMgr::getInstance()->selectionEmpty()) |
5151 | { | 5525 | { |
5152 | LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal()); | 5526 | LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal()); |
@@ -5324,6 +5698,13 @@ class LLShowAgentProfile : public view_listener_t | |||
5324 | } | 5698 | } |
5325 | else if (userdata.asString() == "hit object") | 5699 | else if (userdata.asString() == "hit object") |
5326 | { | 5700 | { |
5701 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
5702 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) | ||
5703 | { | ||
5704 | return true; | ||
5705 | } | ||
5706 | // [/RLVa:KB] | ||
5707 | |||
5327 | LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); | 5708 | LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); |
5328 | if (objectp) | 5709 | if (objectp) |
5329 | { | 5710 | { |
@@ -5383,6 +5764,13 @@ class LLLandEdit : public view_listener_t | |||
5383 | { | 5764 | { |
5384 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 5765 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
5385 | { | 5766 | { |
5767 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) | ||
5768 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) ) | ||
5769 | { | ||
5770 | return true; | ||
5771 | } | ||
5772 | // [/RLVa:KB] | ||
5773 | |||
5386 | if (gAgent.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") ) | 5774 | if (gAgent.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") ) |
5387 | { | 5775 | { |
5388 | // zoom in if we're looking at the avatar | 5776 | // zoom in if we're looking at the avatar |
@@ -5468,6 +5856,18 @@ private: | |||
5468 | LLViewerJointAttachment* attachment_point = NULL; | 5856 | LLViewerJointAttachment* attachment_point = NULL; |
5469 | if (index > 0) | 5857 | if (index > 0) |
5470 | attachment_point = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL); | 5858 | attachment_point = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL); |
5859 | |||
5860 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
5861 | if ( (rlv_handler_t::isEnabled()) && | ||
5862 | ( ((index == 0) && (gRlvHandler.hasLockedAttachment())) || // Can't wear on default attach point | ||
5863 | ((index > 0) && (!gRlvHandler.isDetachable(attachment_point->getObject()))) || // Can't replace locked attachment | ||
5864 | (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) ) ) // Attach on rezzed object == "Take" | ||
5865 | { | ||
5866 | setObjectSelection(NULL); // Clear the selection or it'll get stuck | ||
5867 | return true; | ||
5868 | } | ||
5869 | // [/RLVa:KB] | ||
5870 | |||
5471 | confirm_replace_attachment(0, attachment_point); | 5871 | confirm_replace_attachment(0, attachment_point); |
5472 | } | 5872 | } |
5473 | return true; | 5873 | return true; |
@@ -5575,6 +5975,24 @@ class LLAttachmentDrop : public view_listener_t | |||
5575 | return true; | 5975 | return true; |
5576 | } | 5976 | } |
5577 | 5977 | ||
5978 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
5979 | if (rlv_handler_t::isEnabled()) | ||
5980 | { | ||
5981 | if (gRlvHandler.hasLockedAttachment()) | ||
5982 | { | ||
5983 | // NOTE: copy/paste of the code in enable_detach() | ||
5984 | LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection(); | ||
5985 | RlvSelectHasLockedAttach functor; | ||
5986 | if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&functor, FALSE)) ) | ||
5987 | return true; | ||
5988 | } | ||
5989 | else if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) | ||
5990 | { | ||
5991 | return true; | ||
5992 | } | ||
5993 | } | ||
5994 | // [/RLVa:KB] | ||
5995 | |||
5578 | // The sendDropAttachment() method works on the list of selected | 5996 | // The sendDropAttachment() method works on the list of selected |
5579 | // objects. Thus we need to clear the list, make sure it only | 5997 | // objects. Thus we need to clear the list, make sure it only |
5580 | // contains the object the user clicked, send the message, | 5998 | // contains the object the user clicked, send the message, |
@@ -5593,6 +6011,13 @@ void handle_detach_from_avatar(void* user_data) | |||
5593 | 6011 | ||
5594 | if (attached_object) | 6012 | if (attached_object) |
5595 | { | 6013 | { |
6014 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-0.2.0d | ||
6015 | if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isDetachable(attached_object)) ) | ||
6016 | { | ||
6017 | return; | ||
6018 | } | ||
6019 | // [/RLVa:KB] | ||
6020 | |||
5596 | gMessageSystem->newMessage("ObjectDetach"); | 6021 | gMessageSystem->newMessage("ObjectDetach"); |
5597 | gMessageSystem->nextBlockFast(_PREHASH_AgentData); | 6022 | gMessageSystem->nextBlockFast(_PREHASH_AgentData); |
5598 | gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); | 6023 | gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); |
@@ -5675,6 +6100,17 @@ class LLAttachmentDetach : public view_listener_t | |||
5675 | return true; | 6100 | return true; |
5676 | } | 6101 | } |
5677 | 6102 | ||
6103 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
6104 | // NOTE: copy/paste of the code in enable_detach() | ||
6105 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) ) | ||
6106 | { | ||
6107 | LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection(); | ||
6108 | RlvSelectHasLockedAttach functor; | ||
6109 | if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&functor, FALSE)) ) | ||
6110 | return FALSE; | ||
6111 | } | ||
6112 | // [/RLVa:KB] | ||
6113 | |||
5678 | // The sendDetach() method works on the list of selected | 6114 | // The sendDetach() method works on the list of selected |
5679 | // objects. Thus we need to clear the list, make sure it only | 6115 | // objects. Thus we need to clear the list, make sure it only |
5680 | // contains the object the user clicked, send the message, | 6116 | // contains the object the user clicked, send the message, |
@@ -5758,7 +6194,10 @@ class LLAttachmentEnableDrop : public view_listener_t | |||
5758 | } | 6194 | } |
5759 | 6195 | ||
5760 | //now check to make sure that the item is actually in the inventory before we enable dropping it | 6196 | //now check to make sure that the item is actually in the inventory before we enable dropping it |
5761 | bool new_value = enable_detach(NULL) && can_build && item; | 6197 | // bool new_value = enable_detach(NULL) && can_build && item; |
6198 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
6199 | bool new_value = enable_detach(NULL) && can_build && item && (!gRlvHandler.hasBehaviour(RLV_BHVR_REZ)); | ||
6200 | // [/RLVa:KB] | ||
5762 | 6201 | ||
5763 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | 6202 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); |
5764 | return true; | 6203 | return true; |
@@ -5778,6 +6217,20 @@ BOOL enable_detach(void*) | |||
5778 | // ...if it's you, good to detach | 6217 | // ...if it's you, good to detach |
5779 | if (avatar->getID() == gAgent.getID()) | 6218 | if (avatar->getID() == gAgent.getID()) |
5780 | { | 6219 | { |
6220 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
6221 | // NOTE: this code is reused as-is in LLAttachmentDetach::handleEvent() and LLAttachmentDrop::handleEvent() | ||
6222 | // so any changes here should be reflected there as well (I think it's in a number of other places as well by now) | ||
6223 | |||
6224 | // RELEASE-RLVa: LLSelectMgr::sendDetach() and LLSelectMgr::sendDropAttachment() call sendListToRegions with | ||
6225 | // SEND_ONLY_ROOTS so we only need to examine the roots which saves us time | ||
6226 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) ) | ||
6227 | { | ||
6228 | LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection(); | ||
6229 | RlvSelectHasLockedAttach functor; | ||
6230 | if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&functor, FALSE)) ) | ||
6231 | return FALSE; | ||
6232 | } | ||
6233 | // [/RLVa:KB] | ||
5781 | return TRUE; | 6234 | return TRUE; |
5782 | } | 6235 | } |
5783 | 6236 | ||
@@ -5800,6 +6253,25 @@ class LLAttachmentEnableDetach : public view_listener_t | |||
5800 | // Used to tell if the selected object can be attached to your avatar. | 6253 | // Used to tell if the selected object can be attached to your avatar. |
5801 | BOOL object_selected_and_point_valid(void *user_data) | 6254 | BOOL object_selected_and_point_valid(void *user_data) |
5802 | { | 6255 | { |
6256 | // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) | ||
6257 | if (rlv_handler_t::isEnabled()) | ||
6258 | { | ||
6259 | // RELEASE-RLVa: look at the caller graph for this function on every new release | ||
6260 | // -> 1.22.11 and 1.23.4 | ||
6261 | // - object_is_wearable() => dead code [user_data == NULL => default attach point => OK!] | ||
6262 | // - LLObjectEnableWear::handleEvent() => Rezzed prim / right-click / "Wear" [user_data == NULL => see above] | ||
6263 | // - enabler set up in LLVOAvatar::buildCharacter() => Rezzed prim / right-click / "Attach >" [user_data == pAttachPt] | ||
6264 | // - enabler set up in LLVOAvatar::buildCharacter() => Rezzed prim / Edit menu / "Attach Object" [user_data == pAttachPt] | ||
6265 | LLViewerJointAttachment* pAttachPt = (LLViewerJointAttachment*)user_data; | ||
6266 | if ( ((!pAttachPt) && (gRlvHandler.hasLockedAttachment())) || // Don't allow attach to default attach point | ||
6267 | ((pAttachPt) && (!gRlvHandler.isDetachable(pAttachPt->getObject()))) || // Don't allow replacing of locked attachment | ||
6268 | (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) ) // Attaching a rezzed object == "Take" | ||
6269 | { | ||
6270 | return FALSE; | ||
6271 | } | ||
6272 | } | ||
6273 | // [/RLVa:KB] | ||
6274 | |||
5803 | //LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; | 6275 | //LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; |
5804 | LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); | 6276 | LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); |
5805 | for (LLObjectSelection::root_iterator iter = selection->root_begin(); | 6277 | for (LLObjectSelection::root_iterator iter = selection->root_begin(); |
@@ -5867,7 +6339,13 @@ BOOL object_attached(void *user_data) | |||
5867 | { | 6339 | { |
5868 | LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; | 6340 | LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; |
5869 | 6341 | ||
5870 | return attachment->getObject() != NULL; | 6342 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) |
6343 | return ( | ||
6344 | (attachment->getObject() != NULL) && | ||
6345 | ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.isDetachable(attachment->getObject())) ) | ||
6346 | ); | ||
6347 | // [/RLVa:KB] | ||
6348 | // return attachment->getObject() != NULL; | ||
5871 | } | 6349 | } |
5872 | 6350 | ||
5873 | class LLAvatarSendIM : public view_listener_t | 6351 | class LLAvatarSendIM : public view_listener_t |
@@ -5875,6 +6353,12 @@ class LLAvatarSendIM : public view_listener_t | |||
5875 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 6353 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
5876 | { | 6354 | { |
5877 | LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); | 6355 | LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); |
6356 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
6357 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) | ||
6358 | { | ||
6359 | return true; | ||
6360 | } | ||
6361 | // [/RLVa:KB] | ||
5878 | if(avatar) | 6362 | if(avatar) |
5879 | { | 6363 | { |
5880 | std::string name("IM"); | 6364 | std::string name("IM"); |
@@ -6010,6 +6494,16 @@ class LLToolsSelectedScriptAction : public view_listener_t | |||
6010 | { | 6494 | { |
6011 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 6495 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
6012 | { | 6496 | { |
6497 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
6498 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) ) | ||
6499 | { | ||
6500 | LLObjectSelectionHandle selectHandle = LLSelectMgr::getInstance()->getSelection(); | ||
6501 | RlvSelectHasLockedAttach functor; | ||
6502 | if ( (selectHandle->isAttachment()) && (selectHandle->getFirstNode(&functor)) ) | ||
6503 | return true; | ||
6504 | } | ||
6505 | // [/RLVa:KB] | ||
6506 | |||
6013 | std::string action = userdata.asString(); | 6507 | std::string action = userdata.asString(); |
6014 | if (action == "compile mono") | 6508 | if (action == "compile mono") |
6015 | { | 6509 | { |
@@ -6091,12 +6585,30 @@ void handle_dump_image_list(void*) | |||
6091 | 6585 | ||
6092 | void handle_test_male(void*) | 6586 | void handle_test_male(void*) |
6093 | { | 6587 | { |
6588 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
6589 | if ( (rlv_handler_t::isEnabled()) && | ||
6590 | ( (gRlvHandler.hasLockedAttachment()) || | ||
6591 | (gRlvHandler.hasBehaviour(RLV_BHVR_ADDOUTFIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_REMOUTFIT)) ) ) | ||
6592 | { | ||
6593 | return; | ||
6594 | } | ||
6595 | // [/RLVa:KB] | ||
6596 | |||
6094 | wear_outfit_by_name("Male Shape & Outfit"); | 6597 | wear_outfit_by_name("Male Shape & Outfit"); |
6095 | //gGestureList.requestResetFromServer( TRUE ); | 6598 | //gGestureList.requestResetFromServer( TRUE ); |
6096 | } | 6599 | } |
6097 | 6600 | ||
6098 | void handle_test_female(void*) | 6601 | void handle_test_female(void*) |
6099 | { | 6602 | { |
6603 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
6604 | if ( (rlv_handler_t::isEnabled()) && | ||
6605 | ( (gRlvHandler.hasLockedAttachment()) || | ||
6606 | (gRlvHandler.hasBehaviour(RLV_BHVR_ADDOUTFIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_REMOUTFIT)) ) ) | ||
6607 | { | ||
6608 | return; | ||
6609 | } | ||
6610 | // [/RLVa:KB] | ||
6611 | |||
6100 | wear_outfit_by_name("Female Shape & Outfit"); | 6612 | wear_outfit_by_name("Female Shape & Outfit"); |
6101 | //gGestureList.requestResetFromServer( FALSE ); | 6613 | //gGestureList.requestResetFromServer( FALSE ); |
6102 | } | 6614 | } |
@@ -6239,6 +6751,22 @@ BOOL enable_more_than_one_selected(void* ) | |||
6239 | 6751 | ||
6240 | static bool is_editable_selected() | 6752 | static bool is_editable_selected() |
6241 | { | 6753 | { |
6754 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Modified: RLVa-1.0.0c | ||
6755 | // RELEASE-RLVa: check that this still isn't called by anything but script actions in the Tools menu | ||
6756 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedAttachment()) ) | ||
6757 | { | ||
6758 | LLObjectSelectionHandle selectHandle = LLSelectMgr::getInstance()->getSelection(); | ||
6759 | |||
6760 | // NOTE: this is called for 5 different menu items so we'll trade accuracy for efficiency and only | ||
6761 | // examine root nodes (LLToolsSelectedScriptAction::handleEvent() will catch what we miss) | ||
6762 | RlvSelectHasLockedAttach functor; | ||
6763 | if ( (selectHandle->isAttachment()) && (selectHandle->getFirstRootNode(&functor)) ) | ||
6764 | { | ||
6765 | return false; | ||
6766 | } | ||
6767 | } | ||
6768 | // [/RLVa:KB] | ||
6769 | |||
6242 | return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL); | 6770 | return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL); |
6243 | } | 6771 | } |
6244 | 6772 | ||
@@ -6285,7 +6813,12 @@ class LLToolsEnableTakeCopy : public view_listener_t | |||
6285 | { | 6813 | { |
6286 | virtual bool apply(LLViewerObject* obj) | 6814 | virtual bool apply(LLViewerObject* obj) |
6287 | { | 6815 | { |
6288 | return (!obj->permCopy() || obj->isAttachment()); | 6816 | // return (!obj->permCopy() || obj->isAttachment()); |
6817 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
6818 | return (!obj->permCopy() || obj->isAttachment()) || | ||
6819 | ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) && | ||
6820 | (gAgent.getAvatarObject()->getRoot() == obj) ); | ||
6821 | // [/RLVa:KB] | ||
6289 | } | 6822 | } |
6290 | } func; | 6823 | } func; |
6291 | const bool firstonly = true; | 6824 | const bool firstonly = true; |
@@ -6488,6 +7021,9 @@ class LLWorldEnableCreateLandmark : public view_listener_t | |||
6488 | { | 7021 | { |
6489 | bool new_value = gAgent.isGodlike() || | 7022 | bool new_value = gAgent.isGodlike() || |
6490 | (gAgent.getRegion() && gAgent.getRegion()->getAllowLandmark()); | 7023 | (gAgent.getRegion() && gAgent.getRegion()->getAllowLandmark()); |
7024 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | ||
7025 | new_value &= !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC); | ||
7026 | // [/RLVa:KB] | ||
6491 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | 7027 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); |
6492 | return true; | 7028 | return true; |
6493 | } | 7029 | } |
@@ -6540,7 +7076,11 @@ BOOL enable_god_customer_service(void*) | |||
6540 | 7076 | ||
6541 | BOOL enable_god_basic(void*) | 7077 | BOOL enable_god_basic(void*) |
6542 | { | 7078 | { |
6543 | return gAgent.getGodLevel() > GOD_NOT; | 7079 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) |
7080 | // RELEASE-RLVa: check that this function isn't used for anything other than to enable/disable showing the "God Tools..." floater | ||
7081 | return (gAgent.getGodLevel() > GOD_NOT) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)); | ||
7082 | // [/RLVa:KB] | ||
7083 | //return gAgent.getGodLevel() > GOD_NOT; | ||
6544 | } | 7084 | } |
6545 | 7085 | ||
6546 | #if 0 // 1.9.2 | 7086 | #if 0 // 1.9.2 |
@@ -7051,6 +7591,13 @@ class LLViewHighlightTransparent : public view_listener_t | |||
7051 | { | 7591 | { |
7052 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 7592 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
7053 | { | 7593 | { |
7594 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) | ||
7595 | if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) | ||
7596 | { | ||
7597 | return true; | ||
7598 | } | ||
7599 | // [/RLVa:KB] | ||
7600 | |||
7054 | LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha; | 7601 | LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha; |
7055 | return true; | 7602 | return true; |
7056 | } | 7603 | } |
@@ -7098,6 +7645,13 @@ class LLViewShowHUDAttachments : public view_listener_t | |||
7098 | { | 7645 | { |
7099 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 7646 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
7100 | { | 7647 | { |
7648 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
7649 | if ( (LLPipeline::sShowHUDAttachments) && (rlv_handler_t::isEnabled()) && (gRlvHandler.hasLockedHUD()) ) | ||
7650 | { | ||
7651 | return true; | ||
7652 | } | ||
7653 | // [/RLVa:KB] | ||
7654 | |||
7101 | LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments; | 7655 | LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments; |
7102 | return true; | 7656 | return true; |
7103 | } | 7657 | } |
@@ -7156,6 +7710,15 @@ class LLEditEnableTakeOff : public view_listener_t | |||
7156 | { | 7710 | { |
7157 | new_value = LLAgent::selfHasWearable((void *)WT_SKIRT); | 7711 | new_value = LLAgent::selfHasWearable((void *)WT_SKIRT); |
7158 | } | 7712 | } |
7713 | |||
7714 | // [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | ||
7715 | // Why aren't they using LLWearable::typeNameToType()? *confuzzled* | ||
7716 | if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isRemovable(LLWearable::typeNameToType(clothing))) ) | ||
7717 | { | ||
7718 | new_value = false; | ||
7719 | } | ||
7720 | // [/RLVa:KB] | ||
7721 | |||
7159 | gMenuHolder->findControl(control_name)->setValue(new_value); | 7722 | gMenuHolder->findControl(control_name)->setValue(new_value); |
7160 | return true; | 7723 | return true; |
7161 | } | 7724 | } |
@@ -7253,6 +7816,13 @@ class LLWorldEnvSettings : public view_listener_t | |||
7253 | { | 7816 | { |
7254 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 7817 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
7255 | { | 7818 | { |
7819 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
7820 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SETENV)) | ||
7821 | { | ||
7822 | return true; | ||
7823 | } | ||
7824 | // [/RLVa:KB] | ||
7825 | |||
7256 | std::string tod = userdata.asString(); | 7826 | std::string tod = userdata.asString(); |
7257 | LLVector3 sun_direction; | 7827 | LLVector3 sun_direction; |
7258 | 7828 | ||
@@ -7330,6 +7900,13 @@ class LLWorldWaterSettings : public view_listener_t | |||
7330 | { | 7900 | { |
7331 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 7901 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
7332 | { | 7902 | { |
7903 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
7904 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SETENV)) | ||
7905 | { | ||
7906 | return true; | ||
7907 | } | ||
7908 | // [/RLVa:KB] | ||
7909 | |||
7333 | // if not there or is hidden, show it | 7910 | // if not there or is hidden, show it |
7334 | if( !LLFloaterWater::isOpen() || | 7911 | if( !LLFloaterWater::isOpen() || |
7335 | !LLFloaterWater::instance()->getVisible()) { | 7912 | !LLFloaterWater::instance()->getVisible()) { |
@@ -7360,6 +7937,13 @@ class LLWorldDayCycle : public view_listener_t | |||
7360 | { | 7937 | { |
7361 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | 7938 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) |
7362 | { | 7939 | { |
7940 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
7941 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SETENV)) | ||
7942 | { | ||
7943 | return true; | ||
7944 | } | ||
7945 | // [/RLVa:KB] | ||
7946 | |||
7363 | LLFloaterDayCycle::show(); | 7947 | LLFloaterDayCycle::show(); |
7364 | return true; | 7948 | return true; |
7365 | } | 7949 | } |
diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp index 3fb8e9a..1b2ba22 100644 --- a/linden/indra/newview/llviewermessage.cpp +++ b/linden/indra/newview/llviewermessage.cpp | |||
@@ -140,6 +140,11 @@ | |||
140 | #include "llwindebug.h" // For the invalid message handler | 140 | #include "llwindebug.h" // For the invalid message handler |
141 | #endif | 141 | #endif |
142 | 142 | ||
143 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
144 | #include "llfloateravatarinfo.h" | ||
145 | extern LLMap< const LLUUID, LLFloaterAvatarInfo* > gAvatarInfoInstances; // Only defined in llfloateravatarinfo.cpp | ||
146 | // [/RLVa:KB] | ||
147 | |||
143 | // | 148 | // |
144 | // Constants | 149 | // Constants |
145 | // | 150 | // |
@@ -1007,8 +1012,17 @@ void inventory_offer_callback(S32 button, void* user_data) | |||
1007 | std::string first_name, last_name; | 1012 | std::string first_name, last_name; |
1008 | if (gCacheName->getName(info->mFromID, first_name, last_name)) | 1013 | if (gCacheName->getName(info->mFromID, first_name, last_name)) |
1009 | { | 1014 | { |
1010 | from_string = std::string("An object named '") + info->mFromName + "' owned by " + first_name + " " + last_name; | 1015 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e) |
1011 | chatHistory_string = info->mFromName + " owned by " + first_name + " " + last_name; | 1016 | std::string full_name = first_name + " " + last_name; |
1017 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (gRlvHandler.isAgentNearby(info->mFromID)) ) | ||
1018 | { | ||
1019 | full_name = gRlvHandler.getAnonym(full_name); | ||
1020 | } | ||
1021 | from_string = std::string("An object named '") + info->mFromName + "' owned by " + full_name; | ||
1022 | chatHistory_string = info->mFromName + " owned by " + full_name; | ||
1023 | // [/RLVa:KB] | ||
1024 | //from_string = std::string("An object named '") + info->mFromName + "' owned by " + first_name + " " + last_name; | ||
1025 | //chatHistory_string = info->mFromName + " owned by " + first_name + " " + last_name; | ||
1012 | } | 1026 | } |
1013 | else | 1027 | else |
1014 | { | 1028 | { |
@@ -1027,6 +1041,21 @@ void inventory_offer_callback(S32 button, void* user_data) | |||
1027 | switch(button) | 1041 | switch(button) |
1028 | { | 1042 | { |
1029 | case IOR_ACCEPT: | 1043 | case IOR_ACCEPT: |
1044 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.2a | ||
1045 | // Only change the inventory offer's destination folder to the shared root if: | ||
1046 | // - the user has enabled the feature | ||
1047 | // - the inventory offer came from a script (and specifies a folder) | ||
1048 | // - the name starts with the prefix [mDesc format (quotes are part of the string): "[OBJECTNAME] ( http://slurl.com/... )"] | ||
1049 | if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getForbidGiveToRLV()) && | ||
1050 | (IM_TASK_INVENTORY_OFFERED == info->mIM) && (LLAssetType::AT_CATEGORY == info->mType) && (info->mDesc.find(RLV_PUTINV_PREFIX) == 1) ) | ||
1051 | { | ||
1052 | LLViewerInventoryCategory* pRlvRoot = gRlvHandler.getSharedRoot(); | ||
1053 | if (pRlvRoot) | ||
1054 | { | ||
1055 | info->mFolderID = pRlvRoot->getUUID(); | ||
1056 | } | ||
1057 | } | ||
1058 | // [/RLVa:KB] | ||
1030 | // ACCEPT. The math for the dialog works, because the accept | 1059 | // ACCEPT. The math for the dialog works, because the accept |
1031 | // for inventory_offered, task_inventory_offer or | 1060 | // for inventory_offered, task_inventory_offer or |
1032 | // group_notice_inventory is 1 greater than the offer integer value. | 1061 | // group_notice_inventory is 1 greater than the offer integer value. |
@@ -1189,6 +1218,13 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task) | |||
1189 | if(indx >= 0) | 1218 | if(indx >= 0) |
1190 | { | 1219 | { |
1191 | LLStringUtil::truncate(msg, indx); | 1220 | LLStringUtil::truncate(msg, indx); |
1221 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-1.0.0a | ||
1222 | // TODO-RLVa: needs revisiting when LL saves open notifications to disk to accept them on the next relog | ||
1223 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) | ||
1224 | { | ||
1225 | gRlvHandler.filterLocation(info->mDesc); | ||
1226 | } | ||
1227 | // [/RLVa:KB] | ||
1192 | } | 1228 | } |
1193 | 1229 | ||
1194 | LLStringUtil::format_map_t args; | 1230 | LLStringUtil::format_map_t args; |
@@ -1229,6 +1265,13 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task) | |||
1229 | std::string first_name, last_name; | 1265 | std::string first_name, last_name; |
1230 | if (gCacheName->getName(info->mFromID, first_name, last_name)) | 1266 | if (gCacheName->getName(info->mFromID, first_name, last_name)) |
1231 | { | 1267 | { |
1268 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e) | ||
1269 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (gRlvHandler.isAgentNearby(info->mFromID)) ) | ||
1270 | { | ||
1271 | first_name = gRlvHandler.getAnonym(first_name.append(" ").append(last_name)); | ||
1272 | last_name.clear(); | ||
1273 | } | ||
1274 | // [/RLVa:KB] | ||
1232 | args["[FIRST]"] = first_name; | 1275 | args["[FIRST]"] = first_name; |
1233 | args["[LAST]"] = last_name; | 1276 | args["[LAST]"] = last_name; |
1234 | name_found = TRUE; | 1277 | name_found = TRUE; |
@@ -1243,7 +1286,13 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task) | |||
1243 | else | 1286 | else |
1244 | { | 1287 | { |
1245 | // *TODO:translate -> [FIRST] [LAST] | 1288 | // *TODO:translate -> [FIRST] [LAST] |
1246 | args["[NAME]"] = info->mFromName; | 1289 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e) |
1290 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (gRlvHandler.isAgentNearby(info->mFromID)) ) | ||
1291 | { | ||
1292 | args["[NAME]"] = gRlvHandler.getAnonym(info->mFromName); | ||
1293 | } | ||
1294 | // [/RLVa:KB] | ||
1295 | //args["[NAME]"] = info->mFromName; | ||
1247 | LLNotifyBox::showXml("UserGiveItem", args, | 1296 | LLNotifyBox::showXml("UserGiveItem", args, |
1248 | &inventory_offer_callback, (void*)info); | 1297 | &inventory_offer_callback, (void*)info); |
1249 | } | 1298 | } |
@@ -1411,7 +1460,20 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) | |||
1411 | // do nothing -- don't distract newbies in | 1460 | // do nothing -- don't distract newbies in |
1412 | // Prelude with global IMs | 1461 | // Prelude with global IMs |
1413 | } | 1462 | } |
1414 | else if (offline == IM_ONLINE && !is_linden && is_busy && name != SYSTEM_FROM) | 1463 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) |
1464 | else if ( (rlv_handler_t::isEnabled()) && (offline == IM_ONLINE) && ("@version" == message) ) | ||
1465 | { | ||
1466 | rlvSendBusyMessage(from_id, gRlvHandler.getVersionString(), session_id); | ||
1467 | // We won't receive a typing stop message, so do that manually (see comment at the end of LLFloaterIMPanel::sendMsg) | ||
1468 | LLPointer<LLIMInfo> im_info = new LLIMInfo(gMessageSystem); | ||
1469 | gIMMgr->processIMTypingStop(im_info); | ||
1470 | } | ||
1471 | // [/RLVa:KB] | ||
1472 | // else if (offline == IM_ONLINE && !is_linden && is_busy && name != SYSTEM_FROM) | ||
1473 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
1474 | else if ( (offline == IM_ONLINE && !is_linden && is_busy && name != SYSTEM_FROM) && | ||
1475 | ( (!gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) || (gRlvHandler.isException(RLV_BHVR_RECVIM, from_id))) ) | ||
1476 | // [/RLVa:KB] | ||
1415 | { | 1477 | { |
1416 | // return a standard "busy" message, but only do it to online IM | 1478 | // return a standard "busy" message, but only do it to online IM |
1417 | // (i.e. not other auto responses and not store-and-forward IM) | 1479 | // (i.e. not other auto responses and not store-and-forward IM) |
@@ -1468,6 +1530,21 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) | |||
1468 | } | 1530 | } |
1469 | else if (to_id.isNull()) | 1531 | else if (to_id.isNull()) |
1470 | { | 1532 | { |
1533 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e) | ||
1534 | // Filter region messages that weren't sent by a Linden | ||
1535 | if ( (rlv_handler_t::isEnabled()) && (LLMuteList::getInstance()) && | ||
1536 | (!LLMuteList::getInstance()->isLinden(name)) && (from_id != gAgent.getID()) ) | ||
1537 | { | ||
1538 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) | ||
1539 | gRlvHandler.filterLocation(message); | ||
1540 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) | ||
1541 | { | ||
1542 | name = gRlvHandler.getAnonym(name); | ||
1543 | gRlvHandler.filterNames(message); | ||
1544 | } | ||
1545 | } | ||
1546 | // [/RLVa:KB] | ||
1547 | |||
1471 | // Message to everyone from GOD | 1548 | // Message to everyone from GOD |
1472 | args["[NAME]"] = name; | 1549 | args["[NAME]"] = name; |
1473 | args["[MESSAGE]"] = message; | 1550 | args["[MESSAGE]"] = message; |
@@ -1483,6 +1560,15 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) | |||
1483 | else | 1560 | else |
1484 | { | 1561 | { |
1485 | // standard message, not from system | 1562 | // standard message, not from system |
1563 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
1564 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) && (!gRlvHandler.isException(RLV_BHVR_RECVIM, from_id)) ) | ||
1565 | { | ||
1566 | rlvSendBusyMessage(from_id, rlv_handler_t::cstrMsgRecvIM, session_id); | ||
1567 | |||
1568 | message = message.substr(0, message_offset) + rlv_handler_t::cstrBlockedRecvIM; | ||
1569 | } | ||
1570 | // [/RLVa:KB] | ||
1571 | |||
1486 | std::string saved; | 1572 | std::string saved; |
1487 | if(offline == IM_OFFLINE) | 1573 | if(offline == IM_OFFLINE) |
1488 | { | 1574 | { |
@@ -1688,6 +1774,13 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) | |||
1688 | bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0]; | 1774 | bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0]; |
1689 | info->mType = (LLAssetType::EType) bucketp->asset_type; | 1775 | info->mType = (LLAssetType::EType) bucketp->asset_type; |
1690 | info->mObjectID = bucketp->object_id; | 1776 | info->mObjectID = bucketp->object_id; |
1777 | |||
1778 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | ||
1779 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (gRlvHandler.isAgentNearby(from_id)) ) | ||
1780 | { | ||
1781 | name = gRlvHandler.getAnonym(name); | ||
1782 | } | ||
1783 | // [/RLVa:KB] | ||
1691 | } | 1784 | } |
1692 | else | 1785 | else |
1693 | { | 1786 | { |
@@ -1732,13 +1825,23 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) | |||
1732 | 1825 | ||
1733 | case IM_INVENTORY_ACCEPTED: | 1826 | case IM_INVENTORY_ACCEPTED: |
1734 | { | 1827 | { |
1735 | args["[NAME]"] = name; | 1828 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.0b |
1829 | bool fRlvObfuscate = (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && | ||
1830 | (gRlvHandler.isAgentNearby(from_id)) && (!gAvatarInfoInstances.checkData(from_id)); | ||
1831 | args["[NAME]"] = (!fRlvObfuscate) ? name : gRlvHandler.getAnonym(name); | ||
1832 | // [/RLVa:KB] | ||
1833 | // args["[NAME]"] = name; | ||
1736 | LLNotifyBox::showXml("InventoryAccepted", args); | 1834 | LLNotifyBox::showXml("InventoryAccepted", args); |
1737 | break; | 1835 | break; |
1738 | } | 1836 | } |
1739 | case IM_INVENTORY_DECLINED: | 1837 | case IM_INVENTORY_DECLINED: |
1740 | { | 1838 | { |
1741 | args["[NAME]"] = name; | 1839 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.0b |
1840 | bool fRlvObfuscate = (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && | ||
1841 | (gRlvHandler.isAgentNearby(from_id)) && (!gAvatarInfoInstances.checkData(from_id)); | ||
1842 | args["[NAME]"] = (!fRlvObfuscate) ? name : gRlvHandler.getAnonym(name); | ||
1843 | // [/RLVa:KB] | ||
1844 | // args["[NAME]"] = name; | ||
1742 | LLNotifyBox::showXml("InventoryDeclined", args); | 1845 | LLNotifyBox::showXml("InventoryDeclined", args); |
1743 | break; | 1846 | break; |
1744 | } | 1847 | } |
@@ -1772,6 +1875,22 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) | |||
1772 | return; | 1875 | return; |
1773 | } | 1876 | } |
1774 | 1877 | ||
1878 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
1879 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) ) | ||
1880 | { | ||
1881 | if (gAgent.isInGroup(session_id)) | ||
1882 | { | ||
1883 | if (!gRlvHandler.isException(RLV_BHVR_RECVIM, session_id)) | ||
1884 | return; | ||
1885 | } | ||
1886 | else | ||
1887 | { | ||
1888 | if ( (from_id != gAgent.getID()) && (!gRlvHandler.isException(RLV_BHVR_RECVIM, from_id)) ) | ||
1889 | message = message.substr(0, message_offset) + rlv_handler_t::cstrBlockedRecvIM; | ||
1890 | } | ||
1891 | } | ||
1892 | // [/RLVa:KB] | ||
1893 | |||
1775 | // standard message, not from system | 1894 | // standard message, not from system |
1776 | std::string saved; | 1895 | std::string saved; |
1777 | if(offline == IM_OFFLINE) | 1896 | if(offline == IM_OFFLINE) |
@@ -1818,6 +1937,17 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) | |||
1818 | return; | 1937 | return; |
1819 | } | 1938 | } |
1820 | { | 1939 | { |
1940 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-08 (RLVa-1.0.0e) | ||
1941 | // TODO-RLVa: what actually generates this? | ||
1942 | if (rlv_handler_t::isEnabled()) | ||
1943 | { | ||
1944 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) | ||
1945 | gRlvHandler.filterLocation(message); | ||
1946 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) | ||
1947 | gRlvHandler.filterNames(message); | ||
1948 | } | ||
1949 | // [/RLVa:KB] | ||
1950 | |||
1821 | // Construct a viewer alert for this message. | 1951 | // Construct a viewer alert for this message. |
1822 | args["[NAME]"] = name; | 1952 | args["[NAME]"] = name; |
1823 | args["[MESSAGE]"] = message; | 1953 | args["[MESSAGE]"] = message; |
@@ -1850,12 +1980,48 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) | |||
1850 | } | 1980 | } |
1851 | else | 1981 | else |
1852 | { | 1982 | { |
1853 | // *TODO:translate -> [FIRST] [LAST] (maybe) | 1983 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) |
1854 | LLLureInfo* info = new LLLureInfo(from_id, session_id, FALSE); | 1984 | if (rlv_handler_t::isEnabled()) |
1855 | args["[NAME]"] = name; | 1985 | { |
1856 | args["[MESSAGE]"] = message; | 1986 | // Disallow if: 1) @tplure=n restricted (sender isn't an exception), or 2) @unsit=n restricted and currently sitting |
1857 | LLNotifyBox::showXml("OfferTeleport", args, | 1987 | LLVOAvatar* pAvatar = gAgent.getAvatarObject(); |
1858 | lure_callback, (void*)info); | 1988 | if ( ( (gRlvHandler.hasBehaviour(RLV_BHVR_TPLURE)) && (!gRlvHandler.isException(RLV_BHVR_TPLURE, from_id)) ) || |
1989 | ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (pAvatar) && (pAvatar->mIsSitting) ) ) | ||
1990 | { | ||
1991 | rlvSendBusyMessage(from_id, rlv_handler_t::cstrMsgTpLure); | ||
1992 | return; | ||
1993 | } | ||
1994 | |||
1995 | // Censor teleport message if: 1) @revcim=n restricted (sender isn't an exception), or 2) @showloc=n restricted | ||
1996 | if ( ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) && (!gRlvHandler.isException(RLV_BHVR_RECVIM, from_id)) ) || | ||
1997 | (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ) | ||
1998 | { | ||
1999 | message = rlv_handler_t::cstrHidden; | ||
2000 | } | ||
2001 | } | ||
2002 | // [/RLVa:KB] | ||
2003 | |||
2004 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.0b | ||
2005 | if ( (rlv_handler_t::isEnabled()) && | ||
2006 | ((gRlvHandler.hasBehaviour(RLV_BHVR_ACCEPTTP)) || (gRlvHandler.isException(RLV_BHVR_ACCEPTTP, from_id))) ) | ||
2007 | { | ||
2008 | gRlvHandler.setCanCancelTp(false); | ||
2009 | // (see IM_GODLIKE_LURE_USER below) | ||
2010 | LLLureInfo* info = new LLLureInfo(from_id, session_id, TRUE); | ||
2011 | lure_callback(0, (void*)info); | ||
2012 | } | ||
2013 | else | ||
2014 | { | ||
2015 | // [/RLVa:KB] | ||
2016 | // *TODO:translate -> [FIRST] [LAST] (maybe) | ||
2017 | LLLureInfo* info = new LLLureInfo(from_id, session_id, FALSE); | ||
2018 | args["[NAME]"] = name; | ||
2019 | args["[MESSAGE]"] = message; | ||
2020 | LLNotifyBox::showXml("OfferTeleport", args, | ||
2021 | lure_callback, (void*)info); | ||
2022 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.0b | ||
2023 | } | ||
2024 | // [/RLVa:KB] | ||
1859 | } | 2025 | } |
1860 | } | 2026 | } |
1861 | break; | 2027 | break; |
@@ -2200,8 +2366,13 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) | |||
2200 | chat.mPosAgent = chatter->getPositionAgent(); | 2366 | chat.mPosAgent = chatter->getPositionAgent(); |
2201 | 2367 | ||
2202 | // Make swirly things only for talking objects. (not script debug messages, though) | 2368 | // Make swirly things only for talking objects. (not script debug messages, though) |
2203 | if (chat.mSourceType == CHAT_SOURCE_OBJECT | 2369 | // if (chat.mSourceType == CHAT_SOURCE_OBJECT |
2204 | && chat.mChatType != CHAT_TYPE_DEBUG_MSG) | 2370 | // && chat.mChatType != CHAT_TYPE_DEBUG_MSG) |
2371 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
2372 | // Don't show swirly things for llOwnerSay() chat here because we handle those further down | ||
2373 | if ( (chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mChatType != CHAT_TYPE_DEBUG_MSG) && | ||
2374 | ((!rlv_handler_t::isEnabled()) || (CHAT_TYPE_OWNER != chat.mChatType)) ) | ||
2375 | // [/RLVa:KB] | ||
2205 | { | 2376 | { |
2206 | LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent()); | 2377 | LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent()); |
2207 | psc->setSourceObject(chatter); | 2378 | psc->setSourceObject(chatter); |
@@ -2234,6 +2405,50 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) | |||
2234 | color.setVec(1.f,1.f,1.f,1.f); | 2405 | color.setVec(1.f,1.f,1.f,1.f); |
2235 | msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, mesg); | 2406 | msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, mesg); |
2236 | 2407 | ||
2408 | // [RLVa:KB] - Checked: 2009-08-04 (RLVa-1.0.1d) | Modified: RLVa-1.0.1d | ||
2409 | if ( (rlv_handler_t::isEnabled()) && | ||
2410 | (CHAT_TYPE_START != chat.mChatType) && (CHAT_TYPE_STOP != chat.mChatType) && (CHAT_TYPE_OWNER != chat.mChatType) ) | ||
2411 | { | ||
2412 | // NOTE: chatter can be NULL (may not have rezzed yet, or could be another avie's HUD attachment) | ||
2413 | BOOL is_attachment = (chatter) ? chatter->isAttachment() : FALSE; | ||
2414 | |||
2415 | // Filtering "rules": | ||
2416 | // avatar => filter all avie text (unless it's this avie or they're an exemption) | ||
2417 | // objects => filter everything except attachments this avie owns | ||
2418 | if ( ((CHAT_SOURCE_AGENT == chat.mSourceType) && (from_id != gAgent.getID())) || (!is_owned_by_me) || (!is_attachment) ) | ||
2419 | { | ||
2420 | if (!rlvIsEmote(mesg)) | ||
2421 | { | ||
2422 | if ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVCHAT)) && (!gRlvHandler.isException(RLV_BHVR_RECVCHAT, from_id)) ) | ||
2423 | gRlvHandler.filterChat(mesg, false); | ||
2424 | } | ||
2425 | else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVEMOTE)) && (!gRlvHandler.isException(RLV_BHVR_RECVEMOTE, from_id)) ) | ||
2426 | { | ||
2427 | mesg = "/me ..."; | ||
2428 | } | ||
2429 | } | ||
2430 | |||
2431 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) | ||
2432 | { | ||
2433 | // Filtering "rules": | ||
2434 | // avatar => filter only their name (unless it's this avie) | ||
2435 | // other => filter everything except attachments this avie owns but then we still do filter their text | ||
2436 | if (CHAT_SOURCE_AGENT == chat.mSourceType) | ||
2437 | { | ||
2438 | if (chat.mFromID != gAgent.getID()) | ||
2439 | from_name = gRlvHandler.getAnonym(from_name); | ||
2440 | } | ||
2441 | else | ||
2442 | { | ||
2443 | if ( (!is_owned_by_me) || (!is_attachment) ) | ||
2444 | gRlvHandler.filterNames(from_name); | ||
2445 | gRlvHandler.filterNames(mesg); | ||
2446 | } | ||
2447 | chat.mRlvNamesFiltered = true; | ||
2448 | } | ||
2449 | } | ||
2450 | // [/RLVa:KB] | ||
2451 | |||
2237 | BOOL ircstyle = FALSE; | 2452 | BOOL ircstyle = FALSE; |
2238 | 2453 | ||
2239 | // Look for IRC-style emotes here so chatbubbles work | 2454 | // Look for IRC-style emotes here so chatbubbles work |
@@ -2298,8 +2513,76 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) | |||
2298 | case CHAT_TYPE_WHISPER: | 2513 | case CHAT_TYPE_WHISPER: |
2299 | verb = " " + LLTrans::getString("whisper") + " "; | 2514 | verb = " " + LLTrans::getString("whisper") + " "; |
2300 | break; | 2515 | break; |
2301 | case CHAT_TYPE_DEBUG_MSG: | ||
2302 | case CHAT_TYPE_OWNER: | 2516 | case CHAT_TYPE_OWNER: |
2517 | // [RLVa:KB] - Checked: 2009-08-05 (RLVa-1.0.1e) | Modified: RLVa-1.0.1e | ||
2518 | if ( (rlv_handler_t::isEnabled()) && (mesg.length() > 3) && (RLV_CMD_PREFIX == mesg[0]) ) | ||
2519 | { | ||
2520 | mesg.erase(0, 1); | ||
2521 | LLStringUtil::toLower(mesg); | ||
2522 | |||
2523 | std::string strExecuted, strFailed, strRetained, *pstr; | ||
2524 | |||
2525 | typedef boost::tokenizer<boost::char_separator<char> > tokenizer; | ||
2526 | boost::char_separator<char> sep(",", "", boost::drop_empty_tokens); | ||
2527 | tokenizer tokens(mesg, sep); | ||
2528 | for (tokenizer::iterator itToken = tokens.begin(); itToken != tokens.end(); ++itToken) | ||
2529 | { | ||
2530 | if (LLStartUp::getStartupState() == STATE_STARTED) | ||
2531 | { | ||
2532 | if (gRlvHandler.processCommand(from_id, *itToken, true)) | ||
2533 | pstr = &strExecuted; | ||
2534 | else | ||
2535 | pstr = &strFailed; | ||
2536 | } | ||
2537 | else | ||
2538 | { | ||
2539 | gRlvHandler.retainCommand(from_name, from_id, *itToken); | ||
2540 | pstr = &strRetained; | ||
2541 | } | ||
2542 | |||
2543 | if (!pstr->empty()) | ||
2544 | pstr->push_back(','); | ||
2545 | pstr->append(*itToken); | ||
2546 | } | ||
2547 | |||
2548 | if (!RlvSettings::getDebug()) | ||
2549 | return; | ||
2550 | |||
2551 | // Silly people want comprehensive debug messages, blah :p | ||
2552 | if ( (!strExecuted.empty()) && (strFailed.empty()) && (strRetained.empty()) ) | ||
2553 | verb = " executes: @"; | ||
2554 | else if ( (strExecuted.empty()) && (!strFailed.empty()) && (strRetained.empty()) ) | ||
2555 | verb = " failed: @"; | ||
2556 | else if ( (strExecuted.empty()) && (strFailed.empty()) && (!strRetained.empty()) ) | ||
2557 | verb = " retained: @"; | ||
2558 | else | ||
2559 | { | ||
2560 | verb = ": @"; | ||
2561 | if (!strExecuted.empty()) | ||
2562 | mesg += "\n - executed: @" + strExecuted; | ||
2563 | if (!strFailed.empty()) | ||
2564 | mesg += "\n - failed: @" + strFailed; | ||
2565 | if (!strRetained.empty()) | ||
2566 | mesg += "\n - retained: @" + strRetained; | ||
2567 | } | ||
2568 | |||
2569 | break; | ||
2570 | } | ||
2571 | // [/RLVa:KB] | ||
2572 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
2573 | // Copy/paste from above | ||
2574 | if ( (chatter) && (chat.mChatType != CHAT_TYPE_DEBUG_MSG) ) | ||
2575 | { | ||
2576 | LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent()); | ||
2577 | psc->setSourceObject(chatter); | ||
2578 | psc->setColor(color); | ||
2579 | //We set the particles to be owned by the object's owner, | ||
2580 | //just in case they should be muted by the mute list | ||
2581 | psc->setOwnerUUID(owner_id); | ||
2582 | LLViewerPartSim::getInstance()->addPartSource(psc); | ||
2583 | } | ||
2584 | // [/RLVa:KB] | ||
2585 | case CHAT_TYPE_DEBUG_MSG: | ||
2303 | case CHAT_TYPE_NORMAL: | 2586 | case CHAT_TYPE_NORMAL: |
2304 | verb = ": "; | 2587 | verb = ": "; |
2305 | break; | 2588 | break; |
@@ -2368,7 +2651,10 @@ void process_teleport_start(LLMessageSystem *msg, void**) | |||
2368 | U32 teleport_flags = 0x0; | 2651 | U32 teleport_flags = 0x0; |
2369 | msg->getU32("Info", "TeleportFlags", teleport_flags); | 2652 | msg->getU32("Info", "TeleportFlags", teleport_flags); |
2370 | 2653 | ||
2371 | if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) | 2654 | //if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) |
2655 | // [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.0b | ||
2656 | if ( (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) || (!gRlvHandler.getCanCancelTp()) ) | ||
2657 | // [/RLVa:KB] | ||
2372 | { | 2658 | { |
2373 | gViewerWindow->setProgressCancelButtonVisible(FALSE); | 2659 | gViewerWindow->setProgressCancelButtonVisible(FALSE); |
2374 | } | 2660 | } |
@@ -2403,7 +2689,10 @@ void process_teleport_progress(LLMessageSystem* msg, void**) | |||
2403 | } | 2689 | } |
2404 | U32 teleport_flags = 0x0; | 2690 | U32 teleport_flags = 0x0; |
2405 | msg->getU32("Info", "TeleportFlags", teleport_flags); | 2691 | msg->getU32("Info", "TeleportFlags", teleport_flags); |
2406 | if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) | 2692 | //if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) |
2693 | // [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.0b | ||
2694 | if ( (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) || (!gRlvHandler.getCanCancelTp()) ) | ||
2695 | // [/RLVa:KB] | ||
2407 | { | 2696 | { |
2408 | gViewerWindow->setProgressCancelButtonVisible(FALSE); | 2697 | gViewerWindow->setProgressCancelButtonVisible(FALSE); |
2409 | } | 2698 | } |
@@ -2740,7 +3029,10 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) | |||
2740 | // know what you look like. | 3029 | // know what you look like. |
2741 | gAgent.sendAgentSetAppearance(); | 3030 | gAgent.sendAgentSetAppearance(); |
2742 | 3031 | ||
2743 | if (avatarp) | 3032 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) |
3033 | if ( (avatarp) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ) | ||
3034 | // [/RLVa:KB] | ||
3035 | // if (avatarp) | ||
2744 | { | 3036 | { |
2745 | // Chat the "back" SLURL. (DEV-4907) | 3037 | // Chat the "back" SLURL. (DEV-4907) |
2746 | LLChat chat("Teleport completed from " + gAgent.getTeleportSourceSLURL()); | 3038 | LLChat chat("Teleport completed from " + gAgent.getTeleportSourceSLURL()); |
@@ -4320,7 +4612,13 @@ void notify_cautioned_script_question(LLScriptQuestionCBData* cbdata, S32 orig_q | |||
4320 | if (viewregion) | 4612 | if (viewregion) |
4321 | { | 4613 | { |
4322 | // got the region, so include the region and 3d coordinates of the object | 4614 | // got the region, so include the region and 3d coordinates of the object |
4323 | notice.setArg("[REGIONNAME]", viewregion->getName()); | 4615 | notice.setArg("[REGIONNAME]", viewregion->getName()); |
4616 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | ||
4617 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ) | ||
4618 | { | ||
4619 | notice.setArg("[REGIONNAME]", rlv_handler_t::cstrHiddenRegion); | ||
4620 | } | ||
4621 | // [/RLVa:KB] | ||
4324 | std::string formatpos = llformat("%.1f, %.1f,%.1f", objpos[VX], objpos[VY], objpos[VZ]); | 4622 | std::string formatpos = llformat("%.1f, %.1f,%.1f", objpos[VX], objpos[VY], objpos[VZ]); |
4325 | notice.setArg("[REGIONPOS]", formatpos); | 4623 | notice.setArg("[REGIONPOS]", formatpos); |
4326 | 4624 | ||
@@ -4525,8 +4823,31 @@ void process_script_question(LLMessageSystem *msg, void **user_data) | |||
4525 | 4823 | ||
4526 | LLScriptQuestionCBData *cbdata = new LLScriptQuestionCBData(taskid, itemid, sender, questions, object_name, owner_name); | 4824 | LLScriptQuestionCBData *cbdata = new LLScriptQuestionCBData(taskid, itemid, sender, questions, object_name, owner_name); |
4527 | 4825 | ||
4826 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0e | ||
4827 | S32 rlvQuestionsOther = questions; | ||
4828 | |||
4829 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour("acceptpermission")) ) | ||
4830 | { | ||
4831 | LLViewerObject* pObj = gObjectList.findObject(taskid); | ||
4832 | if (pObj) | ||
4833 | { | ||
4834 | if (pObj->permYouOwner()) | ||
4835 | { | ||
4836 | // PERMISSION_TAKE_CONTROLS and PERMISSION_ATTACH are only auto-granted to objects this avie owns | ||
4837 | rlvQuestionsOther &= ~(LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TAKE_CONTROLS] | | ||
4838 | LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_ATTACH]); | ||
4839 | } | ||
4840 | } | ||
4841 | } | ||
4842 | |||
4843 | if ( (!caution) && (!rlvQuestionsOther) ) | ||
4844 | { | ||
4845 | script_question_cb(0, cbdata); | ||
4846 | } | ||
4847 | else if (gSavedSettings.getBOOL("PermissionsCautionEnabled")) | ||
4848 | // [/RLVa:KB] | ||
4528 | // check whether cautions are even enabled or not | 4849 | // check whether cautions are even enabled or not |
4529 | if (gSavedSettings.getBOOL("PermissionsCautionEnabled")) | 4850 | //if (gSavedSettings.getBOOL("PermissionsCautionEnabled")) |
4530 | { | 4851 | { |
4531 | if (caution) | 4852 | if (caution) |
4532 | { | 4853 | { |
@@ -4818,6 +5139,21 @@ void handle_lure_callback(S32 option, const std::string& text, void* userdata) | |||
4818 | 5139 | ||
4819 | if(0 == option) | 5140 | if(0 == option) |
4820 | { | 5141 | { |
5142 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0b | ||
5143 | bool fRlvCensorMessage = false; | ||
5144 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIM)) | ||
5145 | { | ||
5146 | for (LLDynamicArray<LLUUID>::iterator it = invitees->begin(); it != invitees->end(); ++it) | ||
5147 | { | ||
5148 | if (!gRlvHandler.isException(RLV_BHVR_SENDIM, *it)) | ||
5149 | { | ||
5150 | fRlvCensorMessage = true; | ||
5151 | break; | ||
5152 | } | ||
5153 | } | ||
5154 | } | ||
5155 | // [/RLVa:KB] | ||
5156 | |||
4821 | LLMessageSystem* msg = gMessageSystem; | 5157 | LLMessageSystem* msg = gMessageSystem; |
4822 | msg->newMessageFast(_PREHASH_StartLure); | 5158 | msg->newMessageFast(_PREHASH_StartLure); |
4823 | msg->nextBlockFast(_PREHASH_AgentData); | 5159 | msg->nextBlockFast(_PREHASH_AgentData); |
@@ -4825,7 +5161,10 @@ void handle_lure_callback(S32 option, const std::string& text, void* userdata) | |||
4825 | msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | 5161 | msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); |
4826 | msg->nextBlockFast(_PREHASH_Info); | 5162 | msg->nextBlockFast(_PREHASH_Info); |
4827 | msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in. | 5163 | msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in. |
4828 | msg->addStringFast(_PREHASH_Message, text); | 5164 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0b |
5165 | msg->addStringFast(_PREHASH_Message, (!fRlvCensorMessage) ? text : rlv_handler_t::cstrHidden); | ||
5166 | // [/RLVa:KB] | ||
5167 | //msg->addStringFast(_PREHASH_Message, text); | ||
4829 | for(LLDynamicArray<LLUUID>::iterator itr = invitees->begin(); itr != invitees->end(); ++itr) | 5168 | for(LLDynamicArray<LLUUID>::iterator itr = invitees->begin(); itr != invitees->end(); ++itr) |
4830 | { | 5169 | { |
4831 | msg->nextBlockFast(_PREHASH_TargetData); | 5170 | msg->nextBlockFast(_PREHASH_TargetData); |
@@ -4855,8 +5194,28 @@ void handle_lure(LLDynamicArray<LLUUID>& ids) | |||
4855 | { | 5194 | { |
4856 | LLDynamicArray<LLUUID>* userdata = new LLDynamicArray<LLUUID>(ids); | 5195 | LLDynamicArray<LLUUID>* userdata = new LLDynamicArray<LLUUID>(ids); |
4857 | 5196 | ||
5197 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-1.0.0a | ||
5198 | // Only allow offering teleports if everyone is a @tplure exception or able to map this avie under @showloc=n | ||
5199 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) | ||
5200 | { | ||
5201 | for (LLDynamicArray<LLUUID>::iterator it = ids.begin(); it != ids.end(); ++it) | ||
5202 | { | ||
5203 | const LLRelationship* pBuddyInfo = LLAvatarTracker::instance().getBuddyInfo(*it); | ||
5204 | if ( (!gRlvHandler.isException(RLV_BHVR_TPLURE, *it)) && | ||
5205 | ((!pBuddyInfo) || (!pBuddyInfo->isOnline()) || (!pBuddyInfo->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION))) ) | ||
5206 | { | ||
5207 | delete userdata; | ||
5208 | return; | ||
5209 | } | ||
5210 | } | ||
5211 | } | ||
5212 | // [/RLVa:KB] | ||
5213 | |||
4858 | LLStringUtil::format_map_t edit_args; | 5214 | LLStringUtil::format_map_t edit_args; |
4859 | edit_args["[REGION]"] = gAgent.getRegion()->getName(); | 5215 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-1.0.0a |
5216 | edit_args["[REGION]"] = (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? gAgent.getRegion()->getName() : rlv_handler_t::cstrHidden; | ||
5217 | // [/RLVa:KB] | ||
5218 | //edit_args["[REGION]"] = gAgent.getRegion()->getName(); | ||
4860 | if (gAgent.isGodlike()) | 5219 | if (gAgent.isGodlike()) |
4861 | { | 5220 | { |
4862 | gViewerWindow->alertXmlEditText("OfferTeleportFromGod", edit_args, | 5221 | gViewerWindow->alertXmlEditText("OfferTeleportFromGod", edit_args, |
diff --git a/linden/indra/newview/llviewerobject.cpp b/linden/indra/newview/llviewerobject.cpp index ca7055a..102b135 100644 --- a/linden/indra/newview/llviewerobject.cpp +++ b/linden/indra/newview/llviewerobject.cpp | |||
@@ -1006,6 +1006,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, | |||
1006 | coloru.mV[3] = 255 - coloru.mV[3]; | 1006 | coloru.mV[3] = 255 - coloru.mV[3]; |
1007 | mText->setColor(LLColor4(coloru)); | 1007 | mText->setColor(LLColor4(coloru)); |
1008 | mText->setStringUTF8(temp_string); | 1008 | mText->setStringUTF8(temp_string); |
1009 | // [RLVa:KB] - Checked: 2009-07-09 (RLVa-1.0.0f) | Added: RLVa-1.0.0f | ||
1010 | if (rlv_handler_t::isEnabled()) | ||
1011 | { | ||
1012 | mText->setObjectText(temp_string); | ||
1013 | } | ||
1014 | // [/RLVa:KB] | ||
1009 | 1015 | ||
1010 | if (mDrawable.notNull()) | 1016 | if (mDrawable.notNull()) |
1011 | { | 1017 | { |
@@ -1423,6 +1429,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, | |||
1423 | coloru.mV[3] = 255 - coloru.mV[3]; | 1429 | coloru.mV[3] = 255 - coloru.mV[3]; |
1424 | mText->setColor(LLColor4(coloru)); | 1430 | mText->setColor(LLColor4(coloru)); |
1425 | mText->setStringUTF8(temp_string); | 1431 | mText->setStringUTF8(temp_string); |
1432 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-09 (RLVa-1.0.0f) | Added: RLVa-1.0.0f | ||
1433 | if (rlv_handler_t::isEnabled()) | ||
1434 | { | ||
1435 | mText->setObjectText(temp_string); | ||
1436 | } | ||
1437 | // [/RLVa:KB] | ||
1426 | 1438 | ||
1427 | setChanged(TEXTURE); | 1439 | setChanged(TEXTURE); |
1428 | } | 1440 | } |
@@ -4795,7 +4807,10 @@ BOOL LLViewerObject::permTransfer() const | |||
4795 | // given you modify rights to. JC | 4807 | // given you modify rights to. JC |
4796 | BOOL LLViewerObject::allowOpen() const | 4808 | BOOL 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 | ||
4801 | LLViewerObject::LLInventoryCallbackInfo::~LLInventoryCallbackInfo() | 4816 | LLViewerObject::LLInventoryCallbackInfo::~LLInventoryCallbackInfo() |
diff --git a/linden/indra/newview/llviewertexteditor.cpp b/linden/indra/newview/llviewertexteditor.cpp index 3e2cc19..cef6926 100644 --- a/linden/indra/newview/llviewertexteditor.cpp +++ b/linden/indra/newview/llviewertexteditor.cpp | |||
@@ -95,6 +95,13 @@ public: | |||
95 | } | 95 | } |
96 | else | 96 | else |
97 | { | 97 | { |
98 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
99 | if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour("viewnote")) ) | ||
100 | { | ||
101 | return; | ||
102 | } | ||
103 | // [/RLVa:KB] | ||
104 | |||
98 | // See if we can bring an existing preview to the front | 105 | // See if we can bring an existing preview to the front |
99 | if(!LLPreview::show(item->getUUID(), true)) | 106 | if(!LLPreview::show(item->getUUID(), true)) |
100 | { | 107 | { |
diff --git a/linden/indra/newview/llviewerwindow.cpp b/linden/indra/newview/llviewerwindow.cpp index 7e6c24f..0ab4ab6 100644 --- a/linden/indra/newview/llviewerwindow.cpp +++ b/linden/indra/newview/llviewerwindow.cpp | |||
@@ -3248,6 +3248,16 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, | |||
3248 | { | 3248 | { |
3249 | moveable_object_selected = TRUE; | 3249 | moveable_object_selected = TRUE; |
3250 | this_object_movable = TRUE; | 3250 | this_object_movable = TRUE; |
3251 | |||
3252 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0g | ||
3253 | if ( (rlv_handler_t::isEnabled()) && | ||
3254 | ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP))) ) | ||
3255 | { | ||
3256 | LLVOAvatar* pAvatar = gAgent.getAvatarObject(); | ||
3257 | if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == object->getRootEdit()) ) | ||
3258 | moveable_object_selected = this_object_movable = FALSE; | ||
3259 | } | ||
3260 | // [/RLVa:KB] | ||
3251 | } | 3261 | } |
3252 | all_selected_objects_move = all_selected_objects_move && this_object_movable; | 3262 | all_selected_objects_move = all_selected_objects_move && this_object_movable; |
3253 | all_selected_objects_modify = all_selected_objects_modify && object->permModify(); | 3263 | all_selected_objects_modify = all_selected_objects_modify && object->permModify(); |
diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp index 3d2523e..158977e 100644 --- a/linden/indra/newview/llvoavatar.cpp +++ b/linden/indra/newview/llvoavatar.cpp | |||
@@ -125,6 +125,10 @@ | |||
125 | #include "llvoicevisualizer.h" | 125 | #include "llvoicevisualizer.h" |
126 | #include "llvoiceclient.h" | 126 | #include "llvoiceclient.h" |
127 | 127 | ||
128 | // [RLVa:KB] | ||
129 | #include "llstartup.h" | ||
130 | // [/RLVa:KB] | ||
131 | |||
128 | LLXmlTree LLVOAvatar::sXMLTree; | 132 | LLXmlTree LLVOAvatar::sXMLTree; |
129 | LLXmlTree LLVOAvatar::sSkeletonXMLTree; | 133 | LLXmlTree LLVOAvatar::sSkeletonXMLTree; |
130 | LLVOAvatarSkeletonInfo* LLVOAvatar::sSkeletonInfo = NULL; | 134 | LLVOAvatarSkeletonInfo* LLVOAvatar::sSkeletonInfo = NULL; |
@@ -2093,9 +2097,15 @@ void LLVOAvatar::buildCharacter() | |||
2093 | if (attachment->getGroup() == i) | 2097 | if (attachment->getGroup() == i) |
2094 | { | 2098 | { |
2095 | LLMenuItemCallGL* item; | 2099 | LLMenuItemCallGL* item; |
2100 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
2101 | // We need the userdata param to disable options in this pie menu later on (Left Hand / Right Hand option) | ||
2096 | item = new LLMenuItemCallGL(attachment->getName(), | 2102 | item = new LLMenuItemCallGL(attachment->getName(), |
2097 | NULL, | 2103 | NULL, |
2098 | object_selected_and_point_valid); | 2104 | object_selected_and_point_valid, attachment); |
2105 | // [/RLVa:KB] | ||
2106 | // item = new LLMenuItemCallGL(attachment->getName(), | ||
2107 | // NULL, | ||
2108 | // object_selected_and_point_valid); | ||
2099 | item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", curiter->first); | 2109 | item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", curiter->first); |
2100 | 2110 | ||
2101 | gAttachPieMenu->append(item); | 2111 | gAttachPieMenu->append(item); |
@@ -2150,9 +2160,15 @@ void LLVOAvatar::buildCharacter() | |||
2150 | if (attachment->getGroup() == 8) | 2160 | if (attachment->getGroup() == 8) |
2151 | { | 2161 | { |
2152 | LLMenuItemCallGL* item; | 2162 | LLMenuItemCallGL* item; |
2163 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
2164 | // We need the userdata param to disable options in this pie menu later on | ||
2153 | item = new LLMenuItemCallGL(attachment->getName(), | 2165 | item = new LLMenuItemCallGL(attachment->getName(), |
2154 | NULL, | 2166 | NULL, |
2155 | object_selected_and_point_valid); | 2167 | object_selected_and_point_valid, attachment); |
2168 | // [/RLVa:KB] | ||
2169 | // item = new LLMenuItemCallGL(attachment->getName(), | ||
2170 | // NULL, | ||
2171 | // object_selected_and_point_valid); | ||
2156 | item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", curiter->first); | 2172 | item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", curiter->first); |
2157 | gAttachScreenPieMenu->append(item); | 2173 | gAttachScreenPieMenu->append(item); |
2158 | gDetachScreenPieMenu->append(new LLMenuItemCallGL(attachment->getName(), | 2174 | gDetachScreenPieMenu->append(new LLMenuItemCallGL(attachment->getName(), |
@@ -2171,6 +2187,7 @@ void LLVOAvatar::buildCharacter() | |||
2171 | { | 2187 | { |
2172 | continue; | 2188 | continue; |
2173 | } | 2189 | } |
2190 | // RELEASE-RLVa: random comment because we want know if LL ever changes this to not include "attachment" as userdata | ||
2174 | LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(), | 2191 | LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(), |
2175 | NULL, &object_selected_and_point_valid, | 2192 | NULL, &object_selected_and_point_valid, |
2176 | &attach_label, attachment); | 2193 | &attach_label, attachment); |
@@ -2230,8 +2247,13 @@ void LLVOAvatar::buildCharacter() | |||
2230 | LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attach_index, (LLViewerJointAttachment*)NULL); | 2247 | LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attach_index, (LLViewerJointAttachment*)NULL); |
2231 | if (attachment) | 2248 | if (attachment) |
2232 | { | 2249 | { |
2250 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
2251 | // We need the userdata param to disable options in this pie menu later on | ||
2233 | LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(), | 2252 | LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(), |
2234 | NULL, object_selected_and_point_valid); | 2253 | NULL, object_selected_and_point_valid, attachment); |
2254 | // [/RLVa:KB] | ||
2255 | // LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(), | ||
2256 | // NULL, object_selected_and_point_valid); | ||
2235 | gAttachBodyPartPieMenus[group]->append(item); | 2257 | gAttachBodyPartPieMenus[group]->append(item); |
2236 | item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", attach_index); | 2258 | item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", attach_index); |
2237 | gDetachBodyPartPieMenus[group]->append(new LLMenuItemCallGL(attachment->getName(), | 2259 | gDetachBodyPartPieMenus[group]->append(new LLMenuItemCallGL(attachment->getName(), |
@@ -3089,10 +3111,16 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) | |||
3089 | const F32 time_visible = mTimeVisible.getElapsedTimeF32(); | 3111 | const F32 time_visible = mTimeVisible.getElapsedTimeF32(); |
3090 | const F32 NAME_SHOW_TIME = gSavedSettings.getF32("RenderNameShowTime"); // seconds | 3112 | const F32 NAME_SHOW_TIME = gSavedSettings.getF32("RenderNameShowTime"); // seconds |
3091 | const F32 FADE_DURATION = gSavedSettings.getF32("RenderNameFadeDuration"); // seconds | 3113 | const F32 FADE_DURATION = gSavedSettings.getF32("RenderNameFadeDuration"); // seconds |
3114 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b | ||
3115 | bool fRlvShowNames = gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES); | ||
3116 | // [/RLVa:KB] | ||
3092 | BOOL visible_avatar = isVisible() || mNeedsAnimUpdate; | 3117 | BOOL visible_avatar = isVisible() || mNeedsAnimUpdate; |
3093 | BOOL visible_chat = gSavedSettings.getBOOL("UseChatBubbles") && (mChats.size() || mTyping); | 3118 | BOOL visible_chat = gSavedSettings.getBOOL("UseChatBubbles") && (mChats.size() || mTyping); |
3094 | BOOL render_name = visible_chat || | 3119 | BOOL render_name = visible_chat || |
3095 | (visible_avatar && | 3120 | (visible_avatar && |
3121 | // [RLVa:KB] - Checked: 2009-08-11 (RLVa-1.0.1h) | Added: RLVa-1.0.0h | ||
3122 | ( (!fRlvShowNames) || (RlvSettings::fShowNameTags) ) && | ||
3123 | // [/RLVa:KB] | ||
3096 | ((sRenderName == RENDER_NAME_ALWAYS) || | 3124 | ((sRenderName == RENDER_NAME_ALWAYS) || |
3097 | (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME))); | 3125 | (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME))); |
3098 | // If it's your own avatar, don't draw in mouselook, and don't | 3126 | // If it's your own avatar, don't draw in mouselook, and don't |
@@ -3113,7 +3141,18 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) | |||
3113 | new_name = TRUE; | 3141 | new_name = TRUE; |
3114 | } | 3142 | } |
3115 | 3143 | ||
3116 | if (sRenderGroupTitles != mRenderGroupTitles) | 3144 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b |
3145 | if (fRlvShowNames) | ||
3146 | { | ||
3147 | if (mRenderGroupTitles) | ||
3148 | { | ||
3149 | mRenderGroupTitles = FALSE; | ||
3150 | new_name = TRUE; | ||
3151 | } | ||
3152 | } | ||
3153 | else if (sRenderGroupTitles != mRenderGroupTitles) | ||
3154 | // [/RLVa] | ||
3155 | //if (sRenderGroupTitles != mRenderGroupTitles) | ||
3117 | { | 3156 | { |
3118 | mRenderGroupTitles = sRenderGroupTitles; | 3157 | mRenderGroupTitles = sRenderGroupTitles; |
3119 | new_name = TRUE; | 3158 | new_name = TRUE; |
@@ -3218,6 +3257,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) | |||
3218 | || is_appearance != mNameAppearance) | 3257 | || is_appearance != mNameAppearance) |
3219 | { | 3258 | { |
3220 | std::string line; | 3259 | std::string line; |
3260 | |||
3221 | if (title && title->getString() && title->getString()[0] != '\0') | 3261 | if (title && title->getString() && title->getString()[0] != '\0') |
3222 | { | 3262 | { |
3223 | line += title->getString(); | 3263 | line += title->getString(); |
@@ -3232,6 +3272,15 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) | |||
3232 | 3272 | ||
3233 | line += " "; | 3273 | line += " "; |
3234 | line += lastname->getString(); | 3274 | line += lastname->getString(); |
3275 | |||
3276 | // [RLVa:KB] | ||
3277 | if (fRlvShowNames) | ||
3278 | { | ||
3279 | // User is not allowed to see who it is, due to RLV settings. | ||
3280 | line = gRlvHandler.getAnonym(line); | ||
3281 | } | ||
3282 | // [/RLVa:KB] | ||
3283 | |||
3235 | BOOL need_comma = FALSE; | 3284 | BOOL need_comma = FALSE; |
3236 | 3285 | ||
3237 | if (is_away || is_muted || is_busy) | 3286 | if (is_away || is_muted || is_busy) |
@@ -6328,6 +6377,40 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object) | |||
6328 | { | 6377 | { |
6329 | updateAttachmentVisibility(gAgent.getCameraMode()); | 6378 | updateAttachmentVisibility(gAgent.getCameraMode()); |
6330 | 6379 | ||
6380 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
6381 | if (rlv_handler_t::isEnabled()) | ||
6382 | { | ||
6383 | static bool fRlvFullyLoaded = false; | ||
6384 | static LLFrameTimer* pRlvFullyLoadedTimer = NULL; | ||
6385 | |||
6386 | // There's no way to know when we're done reattaching what was attached at log-off but this ugly evil bad hack tries anyway | ||
6387 | if (!fRlvFullyLoaded) | ||
6388 | { | ||
6389 | if (pRlvFullyLoadedTimer) | ||
6390 | { | ||
6391 | if (pRlvFullyLoadedTimer->getElapsedTimeF32() > 30.0f) | ||
6392 | { | ||
6393 | fRlvFullyLoaded = true; | ||
6394 | delete pRlvFullyLoadedTimer; | ||
6395 | pRlvFullyLoadedTimer = NULL; | ||
6396 | } | ||
6397 | else | ||
6398 | { | ||
6399 | pRlvFullyLoadedTimer->reset(); | ||
6400 | } | ||
6401 | } | ||
6402 | else if ( (!pRlvFullyLoadedTimer) && | ||
6403 | ( (0 == mPendingAttachment.size()) || | ||
6404 | ((1 == mPendingAttachment.size()) && (mPendingAttachment[0] == viewer_object)) ) ) | ||
6405 | { | ||
6406 | pRlvFullyLoadedTimer = new LLFrameTimer(); | ||
6407 | } | ||
6408 | } | ||
6409 | |||
6410 | gRlvHandler.onAttach(attachment, fRlvFullyLoaded); | ||
6411 | } | ||
6412 | // [/RLVa:KB] | ||
6413 | |||
6331 | // Then make sure the inventory is in sync with the avatar. | 6414 | // Then make sure the inventory is in sync with the avatar. |
6332 | gInventory.addChangedMask( LLInventoryObserver::LABEL, attachment->getItemID() ); | 6415 | gInventory.addChangedMask( LLInventoryObserver::LABEL, attachment->getItemID() ); |
6333 | gInventory.notifyObservers(); | 6416 | gInventory.notifyObservers(); |
@@ -6383,6 +6466,14 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) | |||
6383 | // only one object per attachment point for now | 6466 | // only one object per attachment point for now |
6384 | if (attachment->getObject() == viewer_object) | 6467 | if (attachment->getObject() == viewer_object) |
6385 | { | 6468 | { |
6469 | // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | ||
6470 | // URGENT-RLV: it looks like LLApp::isExiting() isn't always accurate so find something better (if it exists) | ||
6471 | if ( (rlv_handler_t::isEnabled()) && (!LLApp::isExiting()) && (mIsSelf) ) | ||
6472 | { | ||
6473 | gRlvHandler.onDetach(attachment); | ||
6474 | } | ||
6475 | // [/RLVa:KB] | ||
6476 | |||
6386 | LLUUID item_id = attachment->getItemID(); | 6477 | LLUUID item_id = attachment->getItemID(); |
6387 | attachment->removeObject(viewer_object); | 6478 | attachment->removeObject(viewer_object); |
6388 | if (mIsSelf) | 6479 | if (mIsSelf) |
@@ -6441,6 +6532,14 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) | |||
6441 | 6532 | ||
6442 | gPipeline.markMoved(mDrawable, TRUE); | 6533 | gPipeline.markMoved(mDrawable, TRUE); |
6443 | mIsSitting = TRUE; | 6534 | mIsSitting = TRUE; |
6535 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.1d | ||
6536 | #ifdef RLV_EXTENSION_STARTLOCATION | ||
6537 | if (rlv_handler_t::isEnabled()) | ||
6538 | { | ||
6539 | RlvSettings::updateLoginLastLocation(); | ||
6540 | } | ||
6541 | #endif // RLV_EXTENSION_STARTLOCATION | ||
6542 | // [/RLVa:KB] | ||
6444 | mRoot.getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject | 6543 | mRoot.getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject |
6445 | mRoot.setPosition(getPosition()); | 6544 | mRoot.setPosition(getPosition()); |
6446 | mRoot.updateWorldMatrixChildren(); | 6545 | mRoot.updateWorldMatrixChildren(); |
@@ -6502,6 +6601,14 @@ void LLVOAvatar::getOffObject() | |||
6502 | gPipeline.markMoved(mDrawable, TRUE); | 6601 | gPipeline.markMoved(mDrawable, TRUE); |
6503 | 6602 | ||
6504 | mIsSitting = FALSE; | 6603 | mIsSitting = FALSE; |
6604 | // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.1d | ||
6605 | #ifdef RLV_EXTENSION_STARTLOCATION | ||
6606 | if (rlv_handler_t::isEnabled()) | ||
6607 | { | ||
6608 | RlvSettings::updateLoginLastLocation(); | ||
6609 | } | ||
6610 | #endif // RLV_EXTENSION_STARTLOCATION | ||
6611 | // [/RLVa:KB] | ||
6505 | mRoot.getXform()->setParent(NULL); // LLVOAvatar::getOffObject | 6612 | mRoot.getXform()->setParent(NULL); // LLVOAvatar::getOffObject |
6506 | mRoot.setPosition(cur_position_world); | 6613 | mRoot.setPosition(cur_position_world); |
6507 | mRoot.setRotation(cur_rotation_world); | 6614 | mRoot.setRotation(cur_rotation_world); |
diff --git a/linden/indra/newview/llvovolume.cpp b/linden/indra/newview/llvovolume.cpp index ad44356..adf82cd 100644 --- a/linden/indra/newview/llvovolume.cpp +++ b/linden/indra/newview/llvovolume.cpp | |||
@@ -1942,7 +1942,11 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e | |||
1942 | 1942 | ||
1943 | { | 1943 | { |
1944 | if (!mbCanSelect || | 1944 | if (!mbCanSelect || |
1945 | (gHideSelectedObjects && isSelected()) || | 1945 | // (gHideSelectedObjects && isSelected()) || |
1946 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
1947 | ( (gHideSelectedObjects && isSelected()) && | ||
1948 | ((!rlv_handler_t::isEnabled()) || (!isHUDAttachment()) || (gRlvHandler.isDetachable(this))) ) || | ||
1949 | // [/RLVa:KB] | ||
1946 | mDrawable->isDead() || | 1950 | mDrawable->isDead() || |
1947 | !gPipeline.hasRenderType(mDrawable->getRenderType())) | 1951 | !gPipeline.hasRenderType(mDrawable->getRenderType())) |
1948 | { | 1952 | { |
@@ -2084,10 +2088,18 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, | |||
2084 | { | 2088 | { |
2085 | LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); | 2089 | LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); |
2086 | 2090 | ||
2087 | if (facep->getViewerObject()->isSelected() && gHideSelectedObjects) | 2091 | // if (facep->getViewerObject()->isSelected() && gHideSelectedObjects) |
2092 | // { | ||
2093 | // return; | ||
2094 | // } | ||
2095 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
2096 | LLViewerObject* pObj = facep->getViewerObject(); | ||
2097 | if ( (pObj->isSelected() && gHideSelectedObjects) && | ||
2098 | ((!rlv_handler_t::isEnabled()) || (!pObj->isHUDAttachment()) || (gRlvHandler.isDetachable(pObj))) ) | ||
2088 | { | 2099 | { |
2089 | return; | 2100 | return; |
2090 | } | 2101 | } |
2102 | // [/RVLa:KB] | ||
2091 | 2103 | ||
2092 | //add face to drawmap | 2104 | //add face to drawmap |
2093 | LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[type]; | 2105 | LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[type]; |
diff --git a/linden/indra/newview/llworldmapview.cpp b/linden/indra/newview/llworldmapview.cpp index 77833c3..5e51e6f 100644 --- a/linden/indra/newview/llworldmapview.cpp +++ b/linden/indra/newview/llworldmapview.cpp | |||
@@ -640,7 +640,14 @@ void LLWorldMapView::draw() | |||
640 | // info->mAgents, | 640 | // info->mAgents, |
641 | // info->mName.c_str(), | 641 | // info->mName.c_str(), |
642 | // LLViewerRegion::accessToShortString(info->mAccess).c_str() ); | 642 | // LLViewerRegion::accessToShortString(info->mAccess).c_str() ); |
643 | if (info->mAccess == SIM_ACCESS_DOWN) | 643 | // [RLVa:KB] - Alternate: Snowglobe-1.0 | Checked: 2009-07-04 (RLVa-1.0.0a) |
644 | if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) | ||
645 | { | ||
646 | mesg = rlv_handler_t::cstrHidden; | ||
647 | } | ||
648 | else if (info->mAccess == SIM_ACCESS_DOWN) | ||
649 | // [/RLVa:KB] | ||
650 | // if (info->mAccess == SIM_ACCESS_DOWN) | ||
644 | { | 651 | { |
645 | mesg = llformat( "%s (%s)", info->mName.c_str(), sStringsMap["offline"].c_str()); | 652 | mesg = llformat( "%s (%s)", info->mName.c_str(), sStringsMap["offline"].c_str()); |
646 | } | 653 | } |
@@ -1069,7 +1076,10 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4& | |||
1069 | text_x = llclamp(text_x, half_text_width + TEXT_PADDING, getRect().getWidth() - half_text_width - TEXT_PADDING); | 1076 | text_x = llclamp(text_x, half_text_width + TEXT_PADDING, getRect().getWidth() - half_text_width - TEXT_PADDING); |
1070 | text_y = llclamp(text_y + vert_offset, TEXT_PADDING + vert_offset, getRect().getHeight() - llround(font->getLineHeight()) - TEXT_PADDING - vert_offset); | 1077 | text_y = llclamp(text_y + vert_offset, TEXT_PADDING + vert_offset, getRect().getHeight() - llround(font->getLineHeight()) - TEXT_PADDING - vert_offset); |
1071 | 1078 | ||
1072 | if (label != "") | 1079 | //if (label != "") |
1080 | // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-1.0.0a | ||
1081 | if ( (label != "") && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ) | ||
1082 | // [/RLVa:KB] | ||
1073 | { | 1083 | { |
1074 | font->renderUTF8( | 1084 | font->renderUTF8( |
1075 | label, 0, | 1085 | label, 0, |
@@ -1129,7 +1139,10 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* stic | |||
1129 | 1139 | ||
1130 | std::string message = | 1140 | std::string message = |
1131 | llformat("%s (%s)", | 1141 | llformat("%s (%s)", |
1132 | info->mName.c_str(), | 1142 | //info->mName.c_str(), |
1143 | // [RLVa:KB] - Alternate: Snowglobe-1.0 | Checked: 2009-07-04 (RLVa-1.0.0a) | ||
1144 | (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? info->mName.c_str() : rlv_handler_t::cstrHidden.c_str(), | ||
1145 | // [/RLVa:KB] | ||
1133 | LLViewerRegion::accessToString(info->mAccess).c_str()); | 1146 | LLViewerRegion::accessToString(info->mAccess).c_str()); |
1134 | 1147 | ||
1135 | if (info->mAccess != SIM_ACCESS_DOWN) | 1148 | if (info->mAccess != SIM_ACCESS_DOWN) |
diff --git a/linden/indra/newview/pipeline.cpp b/linden/indra/newview/pipeline.cpp index 87b810c..67af961 100644 --- a/linden/indra/newview/pipeline.cpp +++ b/linden/indra/newview/pipeline.cpp | |||
@@ -1795,8 +1795,13 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) | |||
1795 | 1795 | ||
1796 | if (gHideSelectedObjects) | 1796 | if (gHideSelectedObjects) |
1797 | { | 1797 | { |
1798 | if (drawablep->getVObj().notNull() && | 1798 | // if (drawablep->getVObj().notNull() && |
1799 | drawablep->getVObj()->isSelected()) | 1799 | // drawablep->getVObj()->isSelected()) |
1800 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | ||
1801 | LLViewerObject* pObj = drawablep->getVObj(); | ||
1802 | if ( (pObj) && (pObj->isSelected()) && | ||
1803 | ((!rlv_handler_t::isEnabled()) || (!pObj->isHUDAttachment()) || (gRlvHandler.isDetachable(pObj))) ) | ||
1804 | // [/RVLa:KB] | ||
1800 | { | 1805 | { |
1801 | return; | 1806 | return; |
1802 | } | 1807 | } |
diff --git a/linden/indra/newview/rlvevent.h b/linden/indra/newview/rlvevent.h new file mode 100644 index 0000000..c3d9c45 --- /dev/null +++ b/linden/indra/newview/rlvevent.h | |||
@@ -0,0 +1,224 @@ | |||
1 | #ifndef RLV_EVENTEMITTER_H | ||
2 | #define RLV_EVENTEMITTER_H | ||
3 | |||
4 | #include <algorithm> | ||
5 | #include <typeinfo> | ||
6 | #include <list> | ||
7 | |||
8 | #include "lluuid.h" | ||
9 | |||
10 | #include "rlvhelper.h" | ||
11 | |||
12 | // ============================================================================ | ||
13 | /* | ||
14 | * RlvEvent | ||
15 | * ======== | ||
16 | * Passed to observer event handlers (contains the same paramaters as RlvHandler::processXXXCommand) | ||
17 | */ | ||
18 | |||
19 | class RlvEvent | ||
20 | { | ||
21 | public: | ||
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 | |||
28 | protected: | ||
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 | |||
57 | class RlvObserver | ||
58 | { | ||
59 | public: | ||
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 | |||
81 | template < class T > | ||
82 | class 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 | |||
155 | class RlvBehaviourObserver | ||
156 | { | ||
157 | public: | ||
158 | virtual ~RlvBehaviourObserver() {} | ||
159 | virtual void changed(const RlvCommand& rlvCmd, bool fInternal) = 0; | ||
160 | }; | ||
161 | |||
162 | // ============================================================================ | ||
163 | |||
164 | class RlvBehaviourNotifyObserver : public RlvBehaviourObserver | ||
165 | { | ||
166 | public: | ||
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 | } | ||
212 | protected: | ||
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 | |||
13 | std::map<std::string, S16> RlvExtGetSet::m_DbgAllowed; | ||
14 | |||
15 | // Checked: 2009-06-03 (RLVa-0.2.0h) | Modified: RLVa-0.2.0h | ||
16 | RlvExtGetSet::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) | ||
39 | BOOL RlvExtGetSet::onForceCommand(const RlvEvent& rlvEvent) | ||
40 | { | ||
41 | return processCommand(rlvEvent.getSenderID(), rlvEvent.getCommand()); | ||
42 | } | ||
43 | |||
44 | // Checked: 2009-05-17 (RLVa-0.2.0a) | ||
45 | BOOL 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 | ||
51 | BOOL 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 | ||
114 | bool 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 | ||
135 | S16 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 | ||
142 | std::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 | ||
175 | std::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 | ||
187 | void 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 | |||
224 | std::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 | |||
289 | void 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 | |||
15 | class RlvExtGetSet : public RlvObserver | ||
16 | { | ||
17 | public: | ||
18 | RlvExtGetSet(); | ||
19 | virtual ~RlvExtGetSet() {} | ||
20 | |||
21 | virtual BOOL onForceCommand(const RlvEvent& rlvEvent); | ||
22 | virtual BOOL onReplyCommand(const RlvEvent& rlvEvent); | ||
23 | protected: | ||
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 | |||
33 | public: | ||
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 | |||
15 | RlvFloaterBehaviour::RlvFloaterBehaviour(const LLSD& key) | ||
16 | : LLFloater(std::string("rlvBehaviours")) | ||
17 | { | ||
18 | LLUICtrlFactory::getInstance()->buildFloater(this, "floater_rlv_behaviour.xml"); | ||
19 | } | ||
20 | |||
21 | |||
22 | void RlvFloaterBehaviour::show(void*) | ||
23 | { | ||
24 | RlvFloaterBehaviour::showInstance(); | ||
25 | } | ||
26 | |||
27 | void 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 | |||
99 | BOOL RlvFloaterBehaviour::canClose() | ||
100 | { | ||
101 | return !LLApp::isExiting(); | ||
102 | } | ||
103 | |||
104 | void RlvFloaterBehaviour::onOpen() | ||
105 | { | ||
106 | gRlvHandler.addBehaviourObserver(this); | ||
107 | |||
108 | refreshAll(); | ||
109 | } | ||
110 | |||
111 | void 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 | |||
124 | BOOL RlvFloaterBehaviour::postBuild() | ||
125 | { | ||
126 | return TRUE; | ||
127 | } | ||
128 | |||
129 | // ============================================================================ | ||
130 | /* | ||
131 | * RlvBehaviourObserver overrides | ||
132 | */ | ||
133 | |||
134 | void RlvFloaterBehaviour::changed(const RlvCommand& /*rlvCmd*/, bool /*fInternal*/) | ||
135 | { | ||
136 | refreshAll(); | ||
137 | } | ||
138 | |||
139 | // ============================================================================ | ||
140 | |||
141 | void 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 | |||
9 | class RlvFloaterBehaviour : | ||
10 | public LLFloater, | ||
11 | public LLFloaterSingleton<RlvFloaterBehaviour>, | ||
12 | public RlvBehaviourObserver | ||
13 | { | ||
14 | friend class LLUISingleton<RlvFloaterBehaviour, VisibilityPolicy<LLFloater> >; | ||
15 | public: | ||
16 | virtual ~RlvFloaterBehaviour() {} | ||
17 | |||
18 | /* | ||
19 | * LLFloater overrides | ||
20 | */ | ||
21 | public: | ||
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 | */ | ||
30 | public: | ||
31 | /*virtual*/ void changed(const RlvCommand& rlvCmd, bool fInternal); | ||
32 | |||
33 | /* | ||
34 | * Member functions | ||
35 | */ | ||
36 | public: | ||
37 | static void show(void*); | ||
38 | static void onAvatarNameLookup(const LLUUID& uuid, const std::string& strFirst, const std::string& strLast, BOOL fGroup, void* pParam); | ||
39 | protected: | ||
40 | void refreshAll(); | ||
41 | private: | ||
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 | ||
39 | extern const char* NEW_CATEGORY_NAME; | ||
40 | |||
41 | // ============================================================================ | ||
42 | // Static variable initialization | ||
43 | // | ||
44 | |||
45 | BOOL RlvHandler::m_fEnabled = FALSE; | ||
46 | BOOL RlvHandler::fNoSetEnv = FALSE; | ||
47 | BOOL RlvHandler::fLegacyNaming = FALSE; | ||
48 | BOOL RlvHandler::m_fFetchStarted = FALSE; | ||
49 | BOOL RlvHandler::m_fFetchComplete = FALSE; | ||
50 | RlvMultiStringSearch RlvHandler::m_AttachLookup; | ||
51 | |||
52 | const std::string RlvHandler::cstrSharedRoot = RLV_ROOT_FOLDER; | ||
53 | |||
54 | // Keep these consistent with regular RLV | ||
55 | const std::string RlvHandler::cstrBlockedRecvIM = "*** IM blocked by your viewer"; | ||
56 | const std::string RlvHandler::cstrBlockedSendIM = "*** IM blocked by sender's viewer"; | ||
57 | const std::string RlvHandler::cstrHidden = "(Hidden)"; | ||
58 | const std::string RlvHandler::cstrHiddenParcel = "(Hidden parcel)"; | ||
59 | const std::string RlvHandler::cstrHiddenRegion = "(Hidden region)"; | ||
60 | const std::string RlvHandler::cstrMsgRecvIM = | ||
61 | "The Resident you messaged is prevented from reading your instant messages at the moment, please try again later."; | ||
62 | const std::string RlvHandler::cstrMsgTpLure = | ||
63 | "The Resident you invited is prevented from accepting teleport offers. Please try again later."; | ||
64 | |||
65 | const 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 | |||
73 | rlv_handler_t gRlvHandler; | ||
74 | |||
75 | // ============================================================================ | ||
76 | // Helper functions | ||
77 | // | ||
78 | |||
79 | // Checked: 2009-07-12 (RLVa-1.0.0h) | Added: RLVa-0.2.0e | ||
80 | inline 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 | ||
93 | static 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 | ||
118 | RlvHandler::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 | ||
128 | RlvHandler::~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 | ||
140 | inline 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 | ||
148 | LLViewerJointAttachment* 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 | ||
166 | LLViewerJointAttachment* 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 | ||
196 | S32 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 | ||
212 | LLViewerJointAttachment* 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 | |||
241 | bool 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 | |||
257 | bool 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 | ||
264 | bool 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 | ||
278 | bool 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 | |||
344 | bool 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 | |||
352 | bool 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 | |||
360 | bool 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) | ||
373 | void 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) | ||
381 | void 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) | ||
389 | void 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: | ||
399 | BOOL 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 | |||
528 | BOOL 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 | ||
760 | void 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 | |||
770 | BOOL 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 | |||
918 | BOOL 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) | ||
1019 | BOOL 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 | |||
1243 | void 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 | ||
1270 | void 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 | ||
1398 | void 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 | ||
1464 | bool 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 | ||
1503 | void 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 | ||
1533 | size_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 | ||
1546 | std::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 | ||
1566 | void 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 | ||
1599 | void 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 | |||
1615 | void 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 | |||
1657 | const 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 | ||
1670 | bool 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 | |||
1706 | BOOL 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) | ||
1737 | class RlvSharedRootFetcher : public LLInventoryFetchDescendentsObserver | ||
1738 | { | ||
1739 | public: | ||
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) | ||
1753 | void 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 | |||
1788 | bool 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 | ||
1804 | LLViewerInventoryCategory* 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 | ||
1826 | LLViewerInventoryCategory* 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 | ||
1859 | LLViewerInventoryCategory* 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 | ||
1881 | std::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 | ||
2054 | void 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 | ||
2095 | void 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 | ||
2135 | bool 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 | |||
2169 | void 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 | ||
2282 | bool 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 | |||
2341 | struct rlv_wear_info { U32 cntWorn, cntTotal, cntChildWorn, cntChildTotal; }; | ||
2342 | |||
2343 | // Checked: 2009-05-30 (RLVa-0.2.0e) | Modified: RLVa-0.2.0e | ||
2344 | void 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) | ||
2413 | bool 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 | |||
2449 | BOOL 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 | |||
2499 | BOOL RlvHandler::canDisable() | ||
2500 | { | ||
2501 | return TRUE; | ||
2502 | } | ||
2503 | |||
2504 | void 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 | |||
23 | typedef std::map<LLUUID, RlvObject> rlv_object_map_t; | ||
24 | typedef std::multimap<S32, LLUUID> rlv_detach_map_t; | ||
25 | typedef std::map<S32, LLUUID> rlv_reattach_map_t; | ||
26 | typedef std::multimap<LLUUID, ERlvBehaviour> rlv_exception_map_t; | ||
27 | typedef std::map<S32, RlvRedirInfo> rlv_redir_map_t; | ||
28 | |||
29 | class RlvHandler | ||
30 | { | ||
31 | public: | ||
32 | RlvHandler(); | ||
33 | ~RlvHandler(); | ||
34 | |||
35 | // -------------------------------- | ||
36 | |||
37 | /* | ||
38 | * Rule checking functions | ||
39 | */ | ||
40 | public: | ||
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 | */ | ||
117 | public: | ||
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); | ||
147 | protected: | ||
148 | void clearState(); | ||
149 | |||
150 | // -------------------------------- | ||
151 | |||
152 | /* | ||
153 | * Inventory related functions | ||
154 | */ | ||
155 | public: | ||
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; | ||
166 | protected: | ||
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 | */ | ||
182 | public: | ||
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() | ||
194 | protected: | ||
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 | */ | ||
213 | public: | ||
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]; | ||
226 | protected: | ||
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 | */ | ||
263 | public: | ||
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 | |||
275 | typedef RlvHandler rlv_handler_t; | ||
276 | extern rlv_handler_t gRlvHandler; | ||
277 | |||
278 | // ============================================================================ | ||
279 | // Inlined member functions | ||
280 | // | ||
281 | |||
282 | // Checked: 2009-07-09 (RLVa-1.0.0f) | ||
283 | inline 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 | ||
290 | inline 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 | ||
300 | inline 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 | ||
309 | inline 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) | ||
315 | inline 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) | ||
321 | inline 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 | ||
330 | inline 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: | ||
336 | inline bool RlvHandler::hasBehaviour(ERlvBehaviour eBehaviour, const std::string& strOption) const | ||
337 | { | ||
338 | return hasBehaviourExcept(eBehaviour, strOption, LLUUID::null); | ||
339 | } | ||
340 | |||
341 | // Checked: | ||
342 | inline bool RlvHandler::hasBehaviour(const std::string& strBehaviour) const | ||
343 | { | ||
344 | return hasBehaviourExcept(strBehaviour, LLUUID::null); | ||
345 | } | ||
346 | |||
347 | // Checked: | ||
348 | inline bool RlvHandler::hasBehaviour(const std::string& strBehaviour, const std::string& strOption) const | ||
349 | { | ||
350 | return hasBehaviourExcept(strBehaviour, strOption, LLUUID::null); | ||
351 | } | ||
352 | |||
353 | // Checked: | ||
354 | inline 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 | ||
374 | inline bool RlvHandler::isDetachable(LLViewerObject* pObj) const | ||
375 | { | ||
376 | return (pObj == NULL) || (!pObj->isAttachment()) || (isDetachable(getAttachPointIndex(pObj))); | ||
377 | } | ||
378 | |||
379 | // Checked: | ||
380 | inline 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: | ||
392 | inline 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 | ||
398 | inline 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 | ||
413 | inline 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) | ||
429 | inline 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 | ||
446 | inline 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 | ||
455 | inline 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 | |||
17 | RlvMultiStringSearch RlvCommand::m_BhvrLookup; | ||
18 | |||
19 | // ============================================================================ | ||
20 | |||
21 | // Checked: | ||
22 | RlvCommand::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 | |||
58 | RlvCommand::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 | |||
92 | BOOL 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 | |||
125 | void 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) | ||
149 | std::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 | |||
156 | BOOL 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 | |||
176 | BOOL 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 | |||
194 | BOOL 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 | |||
202 | BOOL 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 | |||
210 | BOOL 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 | |||
218 | BOOL 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) | ||
227 | std::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 | ||
252 | S32 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 | ||
272 | const 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 | ||
284 | bool 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 | ||
323 | bool 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 | ||
362 | bool 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 | ||
369 | bool 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 | ||
375 | bool 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 | ||
381 | bool 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 | ||
387 | bool 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) | ||
413 | BOOL 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 | |||
420 | BOOL RlvGCTimer::tick() | ||
421 | { | ||
422 | bool fContinue = gRlvHandler.onGC(); | ||
423 | if (!fContinue) | ||
424 | gRlvHandler.m_pGCTimer = NULL; | ||
425 | return !fContinue; | ||
426 | } | ||
427 | |||
428 | void 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 | ||
460 | void 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 | ||
473 | RlvWLSnapshot* 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 | |||
489 | BOOL 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 | ||
541 | void 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 | |||
558 | void 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 | ||
570 | bool 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) | ||
596 | void 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 | ||
618 | std::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 | ||
646 | std::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 | ||
51 | const S32 RLV_VERSION_MAJOR = 1; | ||
52 | const S32 RLV_VERSION_MINOR = 20; | ||
53 | const S32 RLV_VERSION_PATCH = 0; | ||
54 | |||
55 | // Implementation version | ||
56 | const S32 RLVa_VERSION_MAJOR = 1; | ||
57 | const S32 RLVa_VERSION_MINOR = 0; | ||
58 | const S32 RLVa_VERSION_PATCH = 1; | ||
59 | const 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 | ||
99 | enum 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 | |||
165 | enum 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 | |||
173 | enum 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 | |||
192 | class RlvCommand | ||
193 | { | ||
194 | public: | ||
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 | */ | ||
227 | protected: | ||
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 | |||
247 | typedef std::list<RlvCommand> rlv_command_list_t; | ||
248 | |||
249 | class RlvObject | ||
250 | { | ||
251 | public: | ||
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; } | ||
265 | protected: | ||
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 | |||
282 | class RlvCriteriaCategoryCollector : public LLInventoryCollectFunctor | ||
283 | { | ||
284 | public: | ||
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 | |||
312 | protected: | ||
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 | |||
324 | class RlvWearableItemCollector : public LLInventoryCollectFunctor | ||
325 | { | ||
326 | public: | ||
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; | ||
337 | protected: | ||
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 | |||
358 | struct RlvRetainedCommand | ||
359 | { | ||
360 | public: | ||
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) {} | ||
366 | private: | ||
367 | RlvRetainedCommand(); | ||
368 | }; | ||
369 | typedef std::list<RlvRetainedCommand> rlv_retained_list_t; | ||
370 | |||
371 | // ============================================================================ | ||
372 | /* | ||
373 | * RlvWLSnapshot | ||
374 | * ============= | ||
375 | * | ||
376 | */ | ||
377 | |||
378 | struct RlvWLSnapshot | ||
379 | { | ||
380 | public: | ||
381 | static void restoreSnapshot(const RlvWLSnapshot* pWLSnapshot); | ||
382 | static RlvWLSnapshot* takeSnapshot(); | ||
383 | private: | ||
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 | |||
411 | inline BOOL rlvGetSettingBOOL(const std::string& strSetting, BOOL fDefault) | ||
412 | { | ||
413 | return (gSavedSettings.controlExists(strSetting)) ? gSavedSettings.getBOOL(strSetting) : fDefault; | ||
414 | } | ||
415 | inline BOOL rlvGetPerUserSettingsBOOL(const std::string& strSetting, BOOL fDefault) | ||
416 | { | ||
417 | return (gSavedPerAccountSettings.controlExists(strSetting)) ? gSavedPerAccountSettings.getBOOL(strSetting) : fDefault; | ||
418 | } | ||
419 | |||
420 | class RlvSettings | ||
421 | { | ||
422 | public: | ||
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 | |||
445 | struct RlvRedirInfo | ||
446 | { | ||
447 | S16 nRedirChat; | ||
448 | S16 nRedirEmote; | ||
449 | |||
450 | RlvRedirInfo() : nRedirChat(0), nRedirEmote(0) {} | ||
451 | bool isActive() { return (nRedirChat + nRedirEmote) != 0; } | ||
452 | }; | ||
453 | |||
454 | struct 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 | |||
469 | class RlvGCTimer : public LLEventTimer | ||
470 | { | ||
471 | public: | ||
472 | RlvGCTimer() : LLEventTimer(30.0) {} | ||
473 | virtual BOOL tick(); | ||
474 | }; | ||
475 | |||
476 | class RlvCurrentlyWorn : public LLInventoryFetchObserver | ||
477 | { | ||
478 | public: | ||
479 | RlvCurrentlyWorn() {} | ||
480 | ~RlvCurrentlyWorn() {} | ||
481 | virtual void done() {} | ||
482 | |||
483 | static void fetchWorn(); | ||
484 | void fetchItem(const LLUUID& idItem); | ||
485 | }; | ||
486 | |||
487 | struct RlvSelectHasLockedAttach : public LLSelectedNodeFunctor | ||
488 | { | ||
489 | virtual bool apply(LLSelectNode* pNode); | ||
490 | }; | ||
491 | |||
492 | struct RlvSelectIsOwnedByOrGroupOwned : public LLSelectedNodeFunctor | ||
493 | { | ||
494 | RlvSelectIsOwnedByOrGroupOwned(const LLUUID& uuid) : m_idAgent(uuid) {} | ||
495 | virtual bool apply(LLSelectNode* pNode); | ||
496 | LLUUID m_idAgent; | ||
497 | }; | ||
498 | |||
499 | struct 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 | |||
512 | BOOL rlvAttachToEnabler(void* pParam); | ||
513 | bool rlvCanDeleteOrReturn(); | ||
514 | S32 rlvGetDirectDescendentsCount(const LLInventoryCategory* pFolder, LLAssetType::EType type); | ||
515 | bool rlvIsEmote(const std::string& strUTF8Text); | ||
516 | bool rlvIsValidChannel(S32 nChannel); | ||
517 | bool rlvIsWearingItem(const LLInventoryItem* pItem); | ||
518 | |||
519 | void rlvForceDetach(LLViewerJointAttachment* pAttachPt); | ||
520 | void rlvSendBusyMessage(const LLUUID& idTo, const std::string& strMsg, const LLUUID& idSession = LLUUID::null); | ||
521 | bool rlvSendChatReply(const std::string& strChannel, const std::string& strReply); | ||
522 | bool rlvSendChatReply(S32 nChannel, const std::string& strReply); | ||
523 | |||
524 | void rlvStringReplace(std::string& strText, std::string strFrom, const std::string& strTo); | ||
525 | std::string rlvGetFirstParenthesisedText(const std::string& strText, std::string::size_type* pidxMatch = NULL); | ||
526 | std::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 | |||
538 | inline 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 | |||
545 | inline 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 | |||
559 | inline 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 | ||
565 | inline 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 | ||
571 | inline 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 | |||
21 | RlvMultiStringSearch::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 | |||
27 | void 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") | ||
67 | bool 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 | |||
169 | bool 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 | |||
184 | std::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 | ||
8 | template<typename T> class RlvMultiStringSearchFSM_STL | ||
9 | { | ||
10 | public: | ||
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 | |||
93 | protected: | ||
94 | /* | ||
95 | * Member variables | ||
96 | */ | ||
97 | std::vector<T*> m_arFSM; | ||
98 | }; | ||
99 | |||
100 | // ============================================================================ | ||
101 | |||
102 | struct 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 | |||
114 | class RlvMultiStringSearch | ||
115 | { | ||
116 | public: | ||
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 | |||
156 | protected: | ||
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 | |||
179 | inline bool RlvMultiStringSearch::findFirst(const std::string& strText, RlvMultiStringSearchMatch& match) const | ||
180 | { | ||
181 | return findNext(strText.c_str(), 0, strText.length(), match); | ||
182 | } | ||
183 | |||
184 | inline bool RlvMultiStringSearch::findNext(const std::string& strText, int idxCh, RlvMultiStringSearchMatch& match) const | ||
185 | { | ||
186 | return findNext(strText.c_str(), idxCh, strText.length(), match); | ||
187 | } | ||
188 | |||
189 | // ============================================================================ | ||
190 | |||
191 | #endif // RLV_MULTISTRINGSEARCH_H | ||
diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_rlv_behaviour.xml b/linden/indra/newview/skins/default/xui/en-us/floater_rlv_behaviour.xml new file mode 100644 index 0000000..d9e70e6 --- /dev/null +++ b/linden/indra/newview/skins/default/xui/en-us/floater_rlv_behaviour.xml | |||
@@ -0,0 +1,11 @@ | |||
1 | <?xml version="1.0" encoding="utf-8" standalone="yes" ?> | ||
2 | <floater can_close="true" can_drag_on_left="false" can_minimize="true" can_resize="true" | ||
3 | height="425" min_height="200" min_width="375" name="rlvBehaviours" | ||
4 | title="Active RLV Restrictions" width="350"> | ||
5 | <scroll_list bottom="-400" draw_border="true" draw_heading="true" | ||
6 | follows="top|left|bottom|right" height="365" left="15" multi_select="false" | ||
7 | name="behaviour_list" right="-15"> | ||
8 | <column label="Restriction" name="behaviour" width="170" /> | ||
9 | <column label="Object Name" name="name" width="170" /> | ||
10 | </scroll_list> | ||
11 | </floater> \ No newline at end of file | ||