diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/rlvhandler.h | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/linden/indra/newview/rlvhandler.h b/linden/indra/newview/rlvhandler.h new file mode 100644 index 0000000..5295a72 --- /dev/null +++ b/linden/indra/newview/rlvhandler.h | |||
@@ -0,0 +1,445 @@ | |||
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 | typedef std::map<LLUUID, RlvObject> rlv_object_map_t; | ||
19 | typedef std::multimap<S32, LLUUID> rlv_detach_map_t; | ||
20 | typedef std::map<S32, LLUUID> rlv_reattach_map_t; | ||
21 | typedef std::multimap<ERlvBehaviour, RlvException> rlv_exception_map_t; | ||
22 | |||
23 | class RlvHandler | ||
24 | { | ||
25 | public: | ||
26 | RlvHandler(); | ||
27 | ~RlvHandler(); | ||
28 | |||
29 | // -------------------------------- | ||
30 | |||
31 | /* | ||
32 | * Attachment point helper functions | ||
33 | */ | ||
34 | public: | ||
35 | // Returns a pointer to the attachment point for a supplied parameter | ||
36 | LLViewerJointAttachment* getAttachPoint(const std::string& strText, bool fExact) const; | ||
37 | LLViewerJointAttachment* getAttachPoint(const LLInventoryItem* pItem, bool fStrict) const; | ||
38 | LLViewerJointAttachment* getAttachPoint(const LLInventoryCategory* pFolder, bool fStrict) const; | ||
39 | LLViewerJointAttachment* getAttachPointLegacy(const LLInventoryCategory* pFolder) const; | ||
40 | S32 getAttachPointIndex(std::string strText, bool fExact) const; | ||
41 | S32 getAttachPointIndex(LLViewerObject* pObj) const; | ||
42 | S32 getAttachPointIndex(const LLViewerJointAttachment* pObj) const; | ||
43 | bool hasAttachPointName(const LLInventoryItem* pItem, bool fStrict) const; | ||
44 | |||
45 | // -------------------------------- | ||
46 | |||
47 | /* | ||
48 | * Rule checking functions | ||
49 | */ | ||
50 | // NOTE: - to check @detach=n -> hasLockedAttachment() / hasLockedHUD() / isDetachable() | ||
51 | // - to check exceptions -> isException() | ||
52 | // - to check @addoutfit=n -> isWearable() | ||
53 | // - to check @remoutfit=n -> isRemovable() | ||
54 | public: | ||
55 | // Returns TRUE is at least one object contains the specified behaviour (and optional option) | ||
56 | bool hasBehaviour(ERlvBehaviour eBehaviour) const { return (eBehaviour < RLV_BHVR_COUNT) ? (0 != m_Behaviours[eBehaviour]) : false; } | ||
57 | bool hasBehaviour(ERlvBehaviour eBehaviour, const std::string& strOption) const; | ||
58 | // Returns TRUE if at least one object (except the specified one) contains the specified behaviour (and optional option) | ||
59 | bool hasBehaviourExcept(ERlvBehaviour eBehaviour, const LLUUID& idObj) const; | ||
60 | bool hasBehaviourExcept(ERlvBehaviour eBehaviour, const std::string& strOption, const LLUUID& idObj) const; | ||
61 | |||
62 | // Returns TRUE if there is at least 1 non-detachable attachment | ||
63 | bool hasLockedAttachment() const { return (0 != m_Attachments.size()); } | ||
64 | // Returns TRUE if there is at least 1 non-detachable HUD attachment | ||
65 | bool hasLockedHUD() const; | ||
66 | // Returns TRUE if the specified attachment point is detachable | ||
67 | bool isDetachable(S32 idxAttachPt) const { return (idxAttachPt) && (m_Attachments.find(idxAttachPt) == m_Attachments.end()); } | ||
68 | bool isDetachable(const LLInventoryItem* pItem) const; | ||
69 | bool isDetachable(LLViewerJointAttachment* pAttachPt) const; | ||
70 | bool isDetachable(LLViewerObject* pObj) const; | ||
71 | // Returns TRUE if the specified attachment point is set non-detachable by anything other than pObj (or one of its children) | ||
72 | bool isDetachableExcept(S32 idxAttachPt, LLViewerObject* pObj) const; | ||
73 | // Marks the specified attachment point as (non-)detachable (return value indicates success ; used by unit tests) | ||
74 | bool setDetachable(S32 idxAttachPt, const LLUUID& idRlvObj, bool fDetachable); | ||
75 | bool setDetachable(LLViewerObject* pObj, const LLUUID& idRlvObj, bool fDetachable); | ||
76 | |||
77 | // Adds or removes an exception for the specified behaviour | ||
78 | void addException(const LLUUID& idObj, ERlvBehaviour eBhvr, const RlvExceptionOption& varOption); | ||
79 | void removeException(const LLUUID& idObj, ERlvBehaviour eBhvr, const RlvExceptionOption& varOption); | ||
80 | // Returns TRUE if the specified option was added as an exception for the specified behaviour | ||
81 | bool isException(ERlvBehaviour eBhvr, const RlvExceptionOption& varOption, ERlvExceptionCheck typeCheck = RLV_CHECK_DEFAULT) const; | ||
82 | // Returns TRUE if the specified behaviour should behave "permissive" (rather than "strict"/"secure") | ||
83 | bool isPermissive(ERlvBehaviour eBhvr) const; | ||
84 | |||
85 | // Returns TRUE if the specified layer is removable (use hasBehaviour(RLV_BHVR_REMOUTFIT) for the general case) | ||
86 | bool isRemovable(EWearableType type) const { return (type < WT_COUNT) ? (0 == m_LayersRem[type]) : true; } | ||
87 | // Returns TRUE if the specified layer is not remoutfit blocked by any object (except the one specified by UUID) | ||
88 | bool isRemovableExcept(EWearableType type, const LLUUID& idObj) const; | ||
89 | // Returns TRUE if the inventory item is strippable by @detach or @remoutfit | ||
90 | bool isStrippable(const LLUUID& idItem) const; | ||
91 | // Returns TRUE if the specified layer is wearable (use hasBehaviour(RLV_BHVR_ADDOUTFIT) for the general case) | ||
92 | bool isWearable(EWearableType type) const { return (type < WT_COUNT) ? (0 == m_LayersAdd[type]) : true; } | ||
93 | |||
94 | // Returns TRUE if the composite folder doesn't contain any "locked" items | ||
95 | bool canTakeOffComposite(const LLInventoryCategory* pFolder) const; | ||
96 | // Returns TRUE if the folder is a composite folder and optionally returns the name | ||
97 | bool getCompositeInfo(const LLInventoryCategory* pFolder, std::string* pstrName) const; | ||
98 | // Returns TRUE if the inventory item belongs to a composite folder and optionally returns the name and composite folder | ||
99 | bool getCompositeInfo(const LLUUID& idItem, std::string* pstrName, LLViewerInventoryCategory** ppFolder) const; | ||
100 | // Returns TRUE if the folder is a composite folder | ||
101 | bool isCompositeFolder(const LLInventoryCategory* pFolder) const; | ||
102 | // Returns TRUE if the inventory item belongs to a composite folder | ||
103 | bool isCompositeDescendent(const LLUUID& idItem) const; | ||
104 | // Returns TRUE if the inventory item is part of a folded composite folder and should be hidden from @getoufit or @getattach | ||
105 | bool isHiddenCompositeItem(const LLUUID& idItem, const std::string& strItemType) const; | ||
106 | |||
107 | // -------------------------------- | ||
108 | |||
109 | /* | ||
110 | * Helper functions | ||
111 | */ | ||
112 | public: | ||
113 | // Accessors | ||
114 | bool getCanCancelTp() const { return m_fCanCancelTp; } // @accepttp and @tpto | ||
115 | void setCanCancelTp(bool fAllow) { m_fCanCancelTp = fAllow; } // @accepttp and @tpto | ||
116 | |||
117 | // Command specific helper functions | ||
118 | bool canShowHoverText(LLViewerObject* pObj) const; // @showhovertext* command family | ||
119 | void filterChat(std::string& strUTF8Text, bool fFilterEmote) const; // @sendchat, @recvchat and @redirchat | ||
120 | void filterLocation(std::string& strUTF8Text) const; // @showloc | ||
121 | void filterNames(std::string& strUTF8Text) const; // @shownames | ||
122 | const std::string& getAnonym(const std::string& strName) const; // @shownames | ||
123 | std::string getVersionString() const; // @version | ||
124 | std::string getVersionNumString() const; // @versionnum | ||
125 | BOOL isAgentNearby(const LLUUID& uuid) const; // @shownames | ||
126 | bool redirectChatOrEmote(const std::string& strUTF8Test) const; // @redirchat and @rediremote | ||
127 | |||
128 | // Command processing helper functions | ||
129 | BOOL processCommand(const LLUUID& idObj, const std::string& strCommand, bool fFromObj); | ||
130 | void processRetainedCommands(); | ||
131 | void retainCommand(const std::string& strObj, const LLUUID& idObj, const std::string& strCmd); | ||
132 | |||
133 | // Returns a pointer to the currently executing command (do *not* save this pointer) | ||
134 | const RlvCommand* getCurrentCommand() const { return m_pCurCommand; } | ||
135 | // Returns the UUID of the object we're currently executing a command for | ||
136 | const LLUUID& getCurrentObject() const { return m_idCurObject; } | ||
137 | |||
138 | // Initialization | ||
139 | static BOOL canDisable(); | ||
140 | static BOOL isEnabled() { return m_fEnabled; } | ||
141 | static void initLookupTables(); | ||
142 | static BOOL setEnabled(BOOL fEnable); | ||
143 | protected: | ||
144 | void clearState(); | ||
145 | |||
146 | // -------------------------------- | ||
147 | |||
148 | /* | ||
149 | * Inventory related functions | ||
150 | */ | ||
151 | public: | ||
152 | // Starts a fetch of everything under the shared root (if there is one) | ||
153 | static void fetchSharedInventory(); | ||
154 | // Returns the path of the supplied folder (relative to the shared root) | ||
155 | std::string getSharedPath(const LLViewerInventoryCategory* pFolder) const; | ||
156 | std::string getSharedPath(const LLUUID& idFolder) const; | ||
157 | // Returns a pointer to the shared root folder (if there is one) | ||
158 | static LLViewerInventoryCategory* getSharedRoot(); | ||
159 | // A "folded folder" is a folder whose items logically belong to the grandparent rather than the parent | ||
160 | bool isFoldedFolder(const LLInventoryCategory* pFolder, bool fAttach) const; | ||
161 | bool isFoldedFolderLegacy(const LLInventoryCategory* pFolder, bool fAttach) const; | ||
162 | protected: | ||
163 | // Find all folders that match a supplied criteria (clears the supplied array) | ||
164 | bool findSharedFolders(const std::string& strCriteria, LLInventoryModel::cat_array_t& folders) const; | ||
165 | |||
166 | // Returns a subfolder of idParent that starts with name (exact match > partial match) | ||
167 | LLViewerInventoryCategory* getSharedFolder(const LLUUID& idParent, const std::string& strName) const; | ||
168 | // Looks up a folder from a path (relative to the shared root) | ||
169 | LLViewerInventoryCategory* getSharedFolder(const std::string& strPath) const; | ||
170 | |||
171 | bool getWornInfo(const LLInventoryCategory* pFolder, U8& wiFolder, U8& wiChildren) const; | ||
172 | |||
173 | // -------------------------------- | ||
174 | |||
175 | /* | ||
176 | * Event handling (forwards to registered observers if we don't handle the command) | ||
177 | */ | ||
178 | public: | ||
179 | BOOL addObserver(RlvObserver* pObserver) { return m_Emitter.addObserver(pObserver); } | ||
180 | BOOL removeObserver(RlvObserver* pObserver) { return m_Emitter.remObserver(pObserver); } | ||
181 | void addBehaviourObserver(RlvBehaviourObserver* pBhvrObserver); | ||
182 | void removeBehaviourObserver(RlvBehaviourObserver* pBhvrObserver); | ||
183 | void notifyBehaviourObservers(const RlvCommand& rlvCmd, bool fInternal); | ||
184 | |||
185 | // Externally invoked event handlers | ||
186 | void onAttach(LLViewerJointAttachment* pAttachPt, bool fFullyLoaded); // LLVOAvatar::attachObject() | ||
187 | void onDetach(LLViewerJointAttachment* pAttachPt); // LLVOAvatar::detachObject() | ||
188 | bool onGC(); // RlvGCTimer::tick() | ||
189 | void onSavedAssetIntoInventory(const LLUUID& idItem); // LLInventoryModel::processSaveAssetIntoInventory() | ||
190 | protected: | ||
191 | BOOL processAddCommand(const LLUUID& uuid, const RlvCommand& rlvCmd); | ||
192 | BOOL processRemoveCommand(const LLUUID& uuid, const RlvCommand& rlvCmd); | ||
193 | BOOL processClearCommand(const LLUUID& idObj, const RlvCommand& rlvCmd); | ||
194 | BOOL processReplyCommand(const LLUUID& uuid, const RlvCommand& rlvCmd) const; | ||
195 | BOOL processForceCommand(const LLUUID& uuid, const RlvCommand& rlvCmd) const; | ||
196 | |||
197 | // Command handlers (exist for no other reason than to keep the length of the processXXX functions down) | ||
198 | void onForceDetach(const LLUUID& idObj, const std::string& strOption) const; | ||
199 | void onForceRemOutfit(const LLUUID& idObj, const std::string& strOption) const; | ||
200 | bool onForceSit(const LLUUID& uuid, const std::string& strOption) const; | ||
201 | void onForceWear(const std::string& strPath, bool fAttach, bool fMatchAll) const; | ||
202 | bool onGetPath(const LLUUID& uuid, const std::string& strOption, std::string& strReply) const; | ||
203 | void onGetInvWorn(const std::string& strPath, std::string &strReply) const; | ||
204 | |||
205 | // -------------------------------- | ||
206 | |||
207 | /* | ||
208 | * Member variables | ||
209 | */ | ||
210 | public: | ||
211 | static BOOL fNoSetEnv; | ||
212 | static BOOL fLegacyNaming; | ||
213 | |||
214 | static const std::string cstrSharedRoot; // Name of the shared root folder | ||
215 | static const std::string cstrBlockedRecvIM; // Stand-in text for incoming IM when recvim restricted | ||
216 | static const std::string cstrBlockedSendIM; // Stand-in text for outgoing IM when sendim restricted | ||
217 | static const std::string cstrHidden; // General purpose "this was censored" text | ||
218 | static const std::string cstrHiddenParcel; | ||
219 | static const std::string cstrHiddenRegion; | ||
220 | static const std::string cstrMsgRecvIM; // Message sent to IM sender when sendim restricted | ||
221 | static const std::string cstrMsgTpLure; // Message sent to tplure sender when tplure restricted | ||
222 | static const std::string cstrAnonyms[28]; | ||
223 | protected: | ||
224 | rlv_object_map_t m_Objects; // Map of objects that have active restrictions (by UUID) | ||
225 | rlv_exception_map_t m_Exceptions; // Map of UUIDs that are exempt from the associated ERlvBehaviour | ||
226 | rlv_detach_map_t m_Attachments; // Map of locked attachments (attachment point index -> object that issued @detach=n) | ||
227 | S16 m_LayersAdd[WT_COUNT]; // Array of locked layers (reference counted) | ||
228 | S16 m_LayersRem[WT_COUNT]; // Array of locked layers (reference counted) | ||
229 | S16 m_Behaviours[RLV_BHVR_COUNT]; | ||
230 | |||
231 | rlv_retained_list_t m_Retained; | ||
232 | rlv_reattach_map_t m_AttachPending; | ||
233 | rlv_reattach_map_t m_DetachPending; | ||
234 | RlvGCTimer* m_pGCTimer; | ||
235 | RlvWLSnapshot* m_pWLSnapshot; | ||
236 | |||
237 | RlvCommand* m_pCurCommand; // Convenience (see @tpto) | ||
238 | LLUUID m_idCurObject; // Convenience (see @tpto) | ||
239 | |||
240 | mutable RlvEventEmitter<RlvObserver> m_Emitter; | ||
241 | mutable std::list<RlvBehaviourObserver*> m_BhvrObservers; | ||
242 | RlvBehaviourNotifyObserver* m_pBhvrNotify; | ||
243 | |||
244 | static BOOL m_fEnabled; // Use setEnabled() to toggle this | ||
245 | static BOOL m_fFetchStarted; // TRUE if we fired off an inventory fetch | ||
246 | static BOOL m_fFetchComplete; // TRUE if everything was fetched | ||
247 | static RlvMultiStringSearch m_AttachLookup; // Lookup table for attachment names (lower case) | ||
248 | |||
249 | bool m_fCanCancelTp; | ||
250 | |||
251 | friend class RlvSharedRootFetcher; // Fetcher needs access to m_fFetchComplete | ||
252 | friend class RlvGCTimer; // Timer clear its own point at destruction | ||
253 | |||
254 | // -------------------------------- | ||
255 | |||
256 | /* | ||
257 | * Internal access functions used by unit tests | ||
258 | */ | ||
259 | public: | ||
260 | const rlv_object_map_t* getObjectMap() const { return &m_Objects; } | ||
261 | const rlv_exception_map_t* getExceptionMap() const { return &m_Exceptions; } | ||
262 | const rlv_detach_map_t* getDetachMap() const { return &m_Attachments; } | ||
263 | #ifdef RLV_DEBUG_TESTS | ||
264 | const S16* getAddLayers() const { return m_LayersAdd; } | ||
265 | const S16* getRemLayers() const { return m_LayersRem; } | ||
266 | const S16* getBehaviours() const { return m_Behaviours; } | ||
267 | const rlv_retained_list_t* getRetainedList() const { return &m_Retained; } | ||
268 | #endif // RLV_DEBUG_TESTS | ||
269 | }; | ||
270 | |||
271 | typedef RlvHandler rlv_handler_t; | ||
272 | extern rlv_handler_t gRlvHandler; | ||
273 | |||
274 | // ============================================================================ | ||
275 | // Inlined member functions | ||
276 | // | ||
277 | |||
278 | // Checked: 2009-10-04 (RLVa-1.0.4a) | Modified: RLVa-1.0.4a | ||
279 | inline void RlvHandler::addException(const LLUUID& idObj, ERlvBehaviour eBhvr, const RlvExceptionOption& varOption) | ||
280 | { | ||
281 | m_Exceptions.insert(std::pair<ERlvBehaviour, RlvException>(eBhvr, RlvException(idObj, eBhvr, varOption))); | ||
282 | } | ||
283 | |||
284 | // Checked: 2009-07-09 (RLVa-1.0.0f) | Modified: RLVa-1.0.0f | ||
285 | inline bool RlvHandler::canShowHoverText(LLViewerObject *pObj) const | ||
286 | { | ||
287 | return ( (!pObj) || (LL_PCODE_VOLUME != pObj->getPCode()) || | ||
288 | !( (hasBehaviour(RLV_BHVR_SHOWHOVERTEXTALL)) || | ||
289 | ( (hasBehaviour(RLV_BHVR_SHOWHOVERTEXTWORLD)) && (!pObj->isHUDAttachment()) ) || | ||
290 | ( (hasBehaviour(RLV_BHVR_SHOWHOVERTEXTHUD)) && (pObj->isHUDAttachment()) ) || | ||
291 | (isException(RLV_BHVR_SHOWHOVERTEXT, pObj->getID(), RLV_CHECK_PERMISSIVE)) ) ); | ||
292 | } | ||
293 | |||
294 | // Checked: 2009-05-23 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d | ||
295 | inline S32 RlvHandler::getAttachPointIndex(std::string strText, bool fExact) const | ||
296 | { | ||
297 | U16 nParam; RlvMultiStringSearchMatch match; | ||
298 | LLStringUtil::toLower(strText); | ||
299 | return (fExact) ? ((m_AttachLookup.getExactMatchParam(strText, nParam)) ? nParam : 0) | ||
300 | : ((m_AttachLookup.findLast(strText, match)) ? match.nParam : 0); | ||
301 | } | ||
302 | |||
303 | // Checked: 2009-05-23 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d | ||
304 | inline S32 RlvHandler::getAttachPointIndex(LLViewerObject* pObj) const | ||
305 | { | ||
306 | return (pObj) ? ATTACHMENT_ID_FROM_STATE(pObj->getState()) : 0; | ||
307 | } | ||
308 | |||
309 | // Checked: 2009-06-02 (RLVa-0.2.0g) | ||
310 | inline std::string RlvHandler::getSharedPath(const LLUUID& idFolder) const | ||
311 | { | ||
312 | return getSharedPath(gInventory.getCategory(idFolder)); // getSharedPath() has a NULL pointer check so this is safe | ||
313 | } | ||
314 | |||
315 | // Checked: 2009-06-07 (RLVa-0.2.1c) | ||
316 | inline std::string RlvHandler::getVersionString() const | ||
317 | { | ||
318 | return llformat("RestrainedLife viewer v%d.%d.%d (%s %d.%d.%d.%d - RLVa %d.%d.%d)", | ||
319 | RLV_VERSION_MAJOR, RLV_VERSION_MINOR, RLV_VERSION_PATCH, | ||
320 | LLAppViewer::instance()->getSecondLifeTitle().c_str(), LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VERSION_BUILD, | ||
321 | RLVa_VERSION_MAJOR, RLVa_VERSION_MINOR, RLVa_VERSION_PATCH); | ||
322 | } | ||
323 | |||
324 | // Checked: 2009-10-04 (RLVa-1.0.4b) | Added: RLVa-1.0.4b | ||
325 | inline std::string RlvHandler::getVersionNumString() const | ||
326 | { | ||
327 | return llformat("%d%02d%02d%02d", RLV_VERSION_MAJOR, RLV_VERSION_MINOR, RLV_VERSION_PATCH, RLV_VERSION_BUILD); | ||
328 | } | ||
329 | |||
330 | // Checked: 2009-05-23 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d | ||
331 | inline bool RlvHandler::hasAttachPointName(const LLInventoryItem *pItem, bool fStrict) const | ||
332 | { | ||
333 | return (getAttachPoint(pItem, fStrict) != NULL); // getAttachPoint() has a NULL pointer check so this is safe | ||
334 | } | ||
335 | |||
336 | // Checked: | ||
337 | inline bool RlvHandler::hasBehaviour(ERlvBehaviour eBehaviour, const std::string& strOption) const | ||
338 | { | ||
339 | return hasBehaviourExcept(eBehaviour, strOption, LLUUID::null); | ||
340 | } | ||
341 | |||
342 | // Checked: | ||
343 | inline bool RlvHandler::hasBehaviourExcept(ERlvBehaviour eBehaviour, const LLUUID& idObj) const | ||
344 | { | ||
345 | return hasBehaviourExcept(eBehaviour, std::string(), idObj); | ||
346 | } | ||
347 | |||
348 | #ifdef RLV_EXPERIMENTAL_COMPOSITES | ||
349 | // Checked: | ||
350 | inline bool RlvHandler::isCompositeFolder(const LLInventoryCategory* pFolder) const | ||
351 | { | ||
352 | return getCompositeInfo(pFolder, NULL); | ||
353 | } | ||
354 | |||
355 | // Checked: | ||
356 | inline bool RlvHandler::isCompositeDescendent(const LLUUID& idItem) const | ||
357 | { | ||
358 | return getCompositeInfo(idItem, NULL, NULL); | ||
359 | } | ||
360 | #endif // RLV_EXPERIMENTAL_COMPOSITES | ||
361 | |||
362 | // Checked: 2009-09-08 (RLVa-1.0.2c) | Added: RLVa-1.0.2c | ||
363 | inline bool RlvHandler::isDetachable(LLViewerJointAttachment *pAttachPt) const | ||
364 | { | ||
365 | // If there's an attached object it's faster to just use that; otherwise look up the attachment index because it might be locked empty | ||
366 | return (pAttachPt == NULL) || | ||
367 | ( (pAttachPt->getObject() != NULL) && isDetachable(pAttachPt->getObject()) ) || (isDetachable(getAttachPointIndex(pAttachPt))); | ||
368 | } | ||
369 | |||
370 | // Checked: 2009-05-23 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d | ||
371 | inline bool RlvHandler::isDetachable(LLViewerObject* pObj) const | ||
372 | { | ||
373 | return (pObj == NULL) || (!pObj->isAttachment()) || (isDetachable(getAttachPointIndex(pObj))); | ||
374 | } | ||
375 | |||
376 | inline bool RlvHandler::isPermissive(ERlvBehaviour eBhvr) const | ||
377 | { | ||
378 | return (RlvCommand::hasStrictVariant(eBhvr)) | ||
379 | ? !((hasBehaviour(RLV_BHVR_PERMISSIVE)) || (isException(RLV_BHVR_PERMISSIVE, eBhvr, RLV_CHECK_PERMISSIVE))) | ||
380 | : true; | ||
381 | } | ||
382 | |||
383 | // Checked: 2009-07-29 (RLVa-1.0.1b) | Added: RLVa-1.0.1b | ||
384 | inline bool RlvHandler::isFoldedFolder(const LLInventoryCategory* pFolder, bool fAttach) const | ||
385 | { | ||
386 | return | ||
387 | ( | ||
388 | // .(<attachpt>) type folder (on detach we don't care about its children, but on attach there can only be 1 attachment) | ||
389 | ( (gRlvHandler.getAttachPoint(pFolder, true)) && | ||
390 | ( (!fAttach) || (1 == rlvGetDirectDescendentsCount(pFolder, LLAssetType::AT_OBJECT))) ) | ||
391 | #ifdef RLV_EXTENSION_FLAG_NOSTRIP | ||
392 | // .(nostrip) folder | ||
393 | || ( (pFolder) && (".("RLV_FOLDER_FLAG_NOSTRIP")" == pFolder->getName()) ) | ||
394 | #endif // RLV_EXTENSION_FLAG_NOSTRIP | ||
395 | ); | ||
396 | } | ||
397 | |||
398 | // Checked: 2009-05-23 (RLVa-0.2.0d) | Added: RLVa-0.2.0d | ||
399 | inline bool RlvHandler::isRemovableExcept(EWearableType type, const LLUUID& idObj) const | ||
400 | { | ||
401 | // NOTE: mind the bitwise OR rather than the logical OR!! | ||
402 | return (isRemovable(type)) || !( (hasBehaviourExcept(RLV_BHVR_REMOUTFIT, idObj)) | | ||
403 | (hasBehaviourExcept(RLV_BHVR_REMOUTFIT, LLWearable::typeToTypeName(type), idObj)) ); | ||
404 | } | ||
405 | |||
406 | #ifndef RLV_EXTENSION_FLAG_NOSTRIP | ||
407 | // Checked: 2009-05-23 (RLVa-0.2.0d) | Added: RLVa-0.2.0d | ||
408 | bool RlvHandler::isStrippable(const LLUUID& idItem) const | ||
409 | { | ||
410 | return true; | ||
411 | } | ||
412 | #endif // RLV_EXTENSION_FLAG_NOSTRIP | ||
413 | |||
414 | // Checked: 2009-10-04 (RLVa-1.0.4a) | Modified: RLVa-1.0.4a | ||
415 | inline void RlvHandler::removeException(const LLUUID& idObj, ERlvBehaviour eBhvr, const RlvExceptionOption& varOption) | ||
416 | { | ||
417 | for (rlv_exception_map_t::iterator itException = m_Exceptions.lower_bound(eBhvr), | ||
418 | endException = m_Exceptions.upper_bound(eBhvr); itException != endException; ++itException) | ||
419 | { | ||
420 | if ( (itException->second.idObject == idObj) && (itException->second.varOption == varOption) ) | ||
421 | { | ||
422 | m_Exceptions.erase(itException); | ||
423 | break; | ||
424 | } | ||
425 | } | ||
426 | } | ||
427 | |||
428 | // Checked: 2009-08-05 (RLVa-1.0.1e) | Modified: RLVa-1.0.1e | ||
429 | inline void RlvHandler::retainCommand(const std::string& strObj, const LLUUID& idObj, const std::string& strCmd) | ||
430 | { | ||
431 | #ifdef RLV_DEBUG | ||
432 | RLV_INFOS << "[" << idObj << "]: " << strCmd << " (retaining)" << LL_ENDL; | ||
433 | #endif // RLV_DEBUG | ||
434 | m_Retained.push_back(RlvRetainedCommand(strObj, idObj, strCmd)); | ||
435 | } | ||
436 | |||
437 | // Checked: 2009-05-23 (RLVa-0.2.0d) | Modified: RLVa-0.2.0d | ||
438 | inline bool RlvHandler::setDetachable(LLViewerObject* pObj, const LLUUID& idRlvObj, bool fDetachable) | ||
439 | { | ||
440 | return setDetachable(getAttachPointIndex(pObj), idRlvObj, fDetachable); // getAttachPointIndex() has a NULL pointer check | ||
441 | } | ||
442 | |||
443 | // ============================================================================ | ||
444 | |||
445 | #endif // RLV_HANDLER_H | ||