| [1505] | 1 | /* | 
|---|
 | 2 |  *   ORXONOX - the hottest 3D action shooter ever to exist | 
|---|
 | 3 |  *                    > www.orxonox.net < | 
|---|
 | 4 |  * | 
|---|
 | 5 |  * | 
|---|
 | 6 |  *   License notice: | 
|---|
 | 7 |  * | 
|---|
 | 8 |  *   This program is free software; you can redistribute it and/or | 
|---|
 | 9 |  *   modify it under the terms of the GNU General Public License | 
|---|
 | 10 |  *   as published by the Free Software Foundation; either version 2 | 
|---|
 | 11 |  *   of the License, or (at your option) any later version. | 
|---|
 | 12 |  * | 
|---|
 | 13 |  *   This program is distributed in the hope that it will be useful, | 
|---|
 | 14 |  *   but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
 | 15 |  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
 | 16 |  *   GNU General Public License for more details. | 
|---|
 | 17 |  * | 
|---|
 | 18 |  *   You should have received a copy of the GNU General Public License | 
|---|
 | 19 |  *   along with this program; if not, write to the Free Software | 
|---|
 | 20 |  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. | 
|---|
 | 21 |  * | 
|---|
 | 22 |  *   Author: | 
|---|
 | 23 |  *      Fabian 'x3n' Landau | 
|---|
 | 24 |  *   Co-authors: | 
|---|
 | 25 |  *      ... | 
|---|
 | 26 |  * | 
|---|
 | 27 |  */ | 
|---|
 | 28 |  | 
|---|
 | 29 | /** | 
|---|
| [2171] | 30 |     @file | 
|---|
| [7401] | 31 |     @ingroup Class | 
|---|
 | 32 |     @brief Declaration of the ClassTreeMask, ClassTreeMaskNode, and ClassTreeMaskIterator classes. | 
|---|
| [1505] | 33 |  | 
|---|
| [7401] | 34 |     ClassTreeMask is a class to define a mask of the class-tree beginning with orxonox::BaseObject. | 
|---|
| [1505] | 35 |     You can include or exclude classes by calling the corresponding functions with the | 
|---|
| [7401] | 36 |     orxonox::Identifier of the class. This mask can then be used to filter out objects that | 
|---|
 | 37 |     are instances of classes which aren't included in the tree, for example when Loading a | 
|---|
 | 38 |     level file or if a Trigger should be triggered by only a few classes. | 
|---|
| [1505] | 39 |  | 
|---|
| [7401] | 40 |     See the description of orxonox::ClassTreeMask for a short example. | 
|---|
 | 41 |  | 
|---|
| [1505] | 42 |     You can work with a ClassTreeMask in the sense of the set-theory, meaning that you can create | 
|---|
 | 43 |     unions, intersections, complements and differences by using overloaded operators. | 
|---|
 | 44 |  | 
|---|
| [7401] | 45 |     @par Tree structure | 
|---|
| [1505] | 46 |  | 
|---|
 | 47 |     The ClassTreeMask is internally represented by a tree. The nodes in the tree are | 
|---|
 | 48 |     ClassTreeMaskNodes, containing the rule (included or excluded) for this class and all | 
|---|
 | 49 |     subclasses and a list of all subnodes. To minimize the size, the tree contains only | 
|---|
 | 50 |     nodes changing the mask. By adding new rules, the tree gets reordered dynamically. | 
|---|
 | 51 |  | 
|---|
| [7401] | 52 |     Adding a new rule overwrites all rules assigned to inherited classes. Use <tt>overwrite = false</tt> | 
|---|
| [1505] | 53 |     if you don't like this feature. Useless rules that don't change the information of the mask | 
|---|
| [7401] | 54 |     aren't saved in the internal tree. Use <tt>clean = false</tt> if you still want to save them. | 
|---|
| [1505] | 55 |  | 
|---|
| [7401] | 56 |     With <tt>overwrite = false</tt> and <tt>clean = false</tt> it doesn't matter in which order | 
|---|
 | 57 |     you create the mask. You can manually drop useless rules from the tree by calling | 
|---|
 | 58 |     @ref orxonox::ClassTreeMask::clean() "clean()". | 
|---|
| [1505] | 59 |  | 
|---|
| [7401] | 60 |     @par Objects | 
|---|
| [1505] | 61 |  | 
|---|
| [7401] | 62 |     To iterate through all objects of the classes that were included by a ClassTreeMask, | 
|---|
 | 63 |     use orxonox::ClassTreeMaskObjectIterator. The description of this class also contains | 
|---|
 | 64 |     a short example of how to use it. | 
|---|
| [1505] | 65 | */ | 
|---|
 | 66 |  | 
|---|
 | 67 | #ifndef _ClassTreeMask_H__ | 
|---|
 | 68 | #define _ClassTreeMask_H__ | 
|---|
 | 69 |  | 
|---|
 | 70 | #include "CorePrereqs.h" | 
|---|
 | 71 |  | 
|---|
 | 72 | #include <list> | 
|---|
 | 73 | #include <stack> | 
|---|
| [3196] | 74 | #include "BaseObject.h" | 
|---|
| [1757] | 75 | #include "Iterator.h" | 
|---|
 | 76 |  | 
|---|
| [1505] | 77 | namespace orxonox | 
|---|
 | 78 | { | 
|---|
| [1747] | 79 |     // ################################### | 
|---|
 | 80 |     // ###      ClassTreeMaskNode      ### | 
|---|
 | 81 |     // ################################### | 
|---|
| [1505] | 82 |     /** | 
|---|
| [7401] | 83 |         @brief The ClassTreeMaskNode is a node in the internal tree of the ClassTreeMask, containing the rules of the mask. | 
|---|
 | 84 |  | 
|---|
| [1505] | 85 |         The ClassTreeMaskNode is used to store the rule (included or excluded) for a given | 
|---|
 | 86 |         class (described by the corresponding Identifier). The nodes are used in the internal | 
|---|
 | 87 |         tree of ClassTreeMask. To build a tree, they store a list of all subnodes. | 
|---|
 | 88 |     */ | 
|---|
 | 89 |     class _CoreExport ClassTreeMaskNode | 
|---|
 | 90 |     { | 
|---|
 | 91 |         friend class ClassTreeMask; | 
|---|
 | 92 |         friend class ClassTreeMaskIterator; | 
|---|
| [1757] | 93 |         friend class ClassTreeMaskObjectIterator; | 
|---|
| [1505] | 94 |  | 
|---|
 | 95 |         public: | 
|---|
 | 96 |             ClassTreeMaskNode(const Identifier* subclass, bool bIncluded = true); | 
|---|
 | 97 |             ~ClassTreeMaskNode(); | 
|---|
 | 98 |  | 
|---|
 | 99 |             void include(bool overwrite = true); | 
|---|
 | 100 |             void exclude(bool overwrite = true); | 
|---|
 | 101 |             void setIncluded(bool bIncluded, bool overwrite = true); | 
|---|
 | 102 |  | 
|---|
 | 103 |             void addSubnode(ClassTreeMaskNode* subnode); | 
|---|
 | 104 |  | 
|---|
| [7401] | 105 |             /// Tells if the rule is "included" or not. | 
|---|
| [1757] | 106 |             inline bool isIncluded() const { return this->bIncluded_; } | 
|---|
| [7401] | 107 |             /// Tells if the rule is "excluded" or not. | 
|---|
| [1757] | 108 |             inline bool isExcluded() const { return (!this->bIncluded_); } | 
|---|
| [1505] | 109 |  | 
|---|
| [7401] | 110 |             /// Returns the Identifier of the class the rule refers to. | 
|---|
| [1757] | 111 |             inline const Identifier* getClass() const { return this->subclass_; } | 
|---|
| [1505] | 112 |  | 
|---|
| [7401] | 113 |             /// Returns true if the node has some subnodes. | 
|---|
| [1757] | 114 |             inline bool hasSubnodes() const { return !this->subnodes_.empty(); } | 
|---|
 | 115 |  | 
|---|
| [1505] | 116 |         private: | 
|---|
 | 117 |             void deleteAllSubnodes(); | 
|---|
 | 118 |  | 
|---|
| [7401] | 119 |             const Identifier* subclass_;                ///< The Identifier of the subclass the rule refers to | 
|---|
 | 120 |             bool bIncluded_;                            ///< The rule: included or excluded | 
|---|
 | 121 |             std::list<ClassTreeMaskNode*> subnodes_;    ///< A list containing all subnodes of this node | 
|---|
| [1505] | 122 |     }; | 
|---|
 | 123 |  | 
|---|
 | 124 |  | 
|---|
| [1747] | 125 |     // ################################### | 
|---|
 | 126 |     // ###    ClassTreeMaskIterator    ### | 
|---|
 | 127 |     // ################################### | 
|---|
| [1505] | 128 |     /** | 
|---|
| [7401] | 129 |         @brief The ClassTreeMaskIterator moves through all ClassTreeMaskNodes of the internal tree of a ClassTreeMask which contains the rules. | 
|---|
 | 130 |  | 
|---|
| [1505] | 131 |         Because of the complicated shape of the internal rule-tree of ClassTreeMask, an | 
|---|
 | 132 |         iterator is used to move through all nodes of the tree. It starts with the BaseObject | 
|---|
 | 133 |         and moves on to the first subclass until it reaches a leaf of the tree. Then the | 
|---|
 | 134 |         iterator moves one step back and iterates to the second subclass. If there are no more | 
|---|
 | 135 |         subclasses, it steps another step back, and so on. | 
|---|
| [7401] | 136 |  | 
|---|
 | 137 |         Example: A and B are children of BaseObject, A1 and A2 are children of A, B1 and B2 are children of B. | 
|---|
 | 138 |         The ClassTreeMaskIterator would move trough the tree in the following order: | 
|---|
 | 139 |         BaseObject, A, A1, A2, B, B1, B2. | 
|---|
 | 140 |  | 
|---|
 | 141 |         Note that the iterator doesn't move trough the whole class-tree, but only through the | 
|---|
 | 142 |         internal tree of the mask, containing the minimal needed set of nodes to describe the mask. | 
|---|
| [1505] | 143 |     */ | 
|---|
 | 144 |     class _CoreExport ClassTreeMaskIterator | 
|---|
 | 145 |     { | 
|---|
 | 146 |         public: | 
|---|
 | 147 |             ClassTreeMaskIterator(ClassTreeMaskNode* node); | 
|---|
 | 148 |             ~ClassTreeMaskIterator(); | 
|---|
 | 149 |  | 
|---|
| [1757] | 150 |             const ClassTreeMaskIterator& operator++(); | 
|---|
| [1505] | 151 |             ClassTreeMaskNode* operator*() const; | 
|---|
 | 152 |             ClassTreeMaskNode* operator->() const; | 
|---|
| [1757] | 153 |             operator bool() const; | 
|---|
 | 154 |             bool operator==(ClassTreeMaskNode* compare) const; | 
|---|
 | 155 |             bool operator!=(ClassTreeMaskNode* compare) const; | 
|---|
| [1505] | 156 |  | 
|---|
 | 157 |         private: | 
|---|
| [7401] | 158 |             std::stack<std::pair<std::list<ClassTreeMaskNode*>::iterator, std::list<ClassTreeMaskNode*>::iterator> > nodes_;    ///< A stack to store list-iterators | 
|---|
 | 159 |             std::list<ClassTreeMaskNode*> rootlist_;                                                                            ///< A list for internal use (it only stores the root-node) | 
|---|
| [1505] | 160 |     }; | 
|---|
 | 161 |  | 
|---|
 | 162 |  | 
|---|
| [1747] | 163 |     // ################################### | 
|---|
 | 164 |     // ###        ClassTreeMask        ### | 
|---|
 | 165 |     // ################################### | 
|---|
| [1505] | 166 |     /** | 
|---|
| [7401] | 167 |         @brief The ClassTreeMask is a set of rules, containing the information for each class whether it's included or not. | 
|---|
 | 168 |  | 
|---|
| [1505] | 169 |         With a ClassTreeMask, you can include or exclude subtrees of the class-tree, starting | 
|---|
 | 170 |         with a given subclass, described by the corresponding Identifier. To minimize the size | 
|---|
 | 171 |         of the mask, the mask saves only relevant rules. But you can manually add rules that | 
|---|
| [7401] | 172 |         don't change the information of the mask by using <tt>clean = false</tt>. If you want to drop | 
|---|
| [1505] | 173 |         useless rules, call the clean() function. | 
|---|
| [7401] | 174 |  | 
|---|
 | 175 |         Example: | 
|---|
 | 176 |         @code | 
|---|
 | 177 |         ClassTreeMask mymask; | 
|---|
 | 178 |         mymask.exclude(Class(A)); | 
|---|
 | 179 |         mymask.exclude(Class(B)); | 
|---|
 | 180 |         mymask.include(Class(ChildOfA)); | 
|---|
 | 181 |         @endcode | 
|---|
 | 182 |  | 
|---|
 | 183 |         In this example, the classes A and B are excluded from the mask, but one of the child | 
|---|
 | 184 |         classes of A is included again. | 
|---|
| [1505] | 185 |     */ | 
|---|
 | 186 |     class _CoreExport ClassTreeMask | 
|---|
 | 187 |     { | 
|---|
| [1757] | 188 |         friend class ClassTreeMaskObjectIterator; | 
|---|
 | 189 |  | 
|---|
| [1505] | 190 |         public: | 
|---|
 | 191 |             ClassTreeMask(); | 
|---|
 | 192 |             ClassTreeMask(const ClassTreeMask& other); | 
|---|
 | 193 |             ~ClassTreeMask(); | 
|---|
 | 194 |  | 
|---|
 | 195 |             void include(const Identifier* subclass, bool overwrite = true, bool clean = true); | 
|---|
 | 196 |             void exclude(const Identifier* subclass, bool overwrite = true, bool clean = true); | 
|---|
 | 197 |             void add(const Identifier* subclass, bool bInclude, bool overwrite = true, bool clean = true); | 
|---|
 | 198 |  | 
|---|
 | 199 |             void includeSingle(const Identifier* subclass, bool clean = true); | 
|---|
 | 200 |             void excludeSingle(const Identifier* subclass, bool clean = true); | 
|---|
 | 201 |             void addSingle(const Identifier* subclass, bool bInclude, bool clean = true); | 
|---|
 | 202 |  | 
|---|
 | 203 |             void reset(); | 
|---|
 | 204 |             void clean(); | 
|---|
 | 205 |  | 
|---|
 | 206 |             bool isIncluded(const Identifier* subclass) const; | 
|---|
 | 207 |             bool isExcluded(const Identifier* subclass) const; | 
|---|
 | 208 |  | 
|---|
| [7401] | 209 |             /// Begin of the ClassTreeMaskObjectIterator. | 
|---|
| [1757] | 210 |             inline const ClassTreeMask& begin() const { return (*this); } | 
|---|
| [7401] | 211 |             /// End of the ClassTreeMaskObjectIterator. | 
|---|
| [1757] | 212 |             inline BaseObject*          end()   const { return 0; } | 
|---|
| [1505] | 213 |  | 
|---|
| [7268] | 214 |             ClassTreeMask& operator=(const ClassTreeMask& other); | 
|---|
| [1757] | 215 |  | 
|---|
| [1505] | 216 |             bool operator==(const ClassTreeMask& other) const; | 
|---|
 | 217 |             bool operator!=(const ClassTreeMask& other) const; | 
|---|
 | 218 |  | 
|---|
| [1757] | 219 |             const ClassTreeMask& operator+() const; | 
|---|
| [1505] | 220 |             ClassTreeMask operator-() const; | 
|---|
 | 221 |  | 
|---|
 | 222 |             ClassTreeMask operator+(const ClassTreeMask& other) const; | 
|---|
 | 223 |             ClassTreeMask operator*(const ClassTreeMask& other) const; | 
|---|
 | 224 |             ClassTreeMask operator-(const ClassTreeMask& other) const; | 
|---|
 | 225 |             ClassTreeMask operator!() const; | 
|---|
 | 226 |  | 
|---|
| [1757] | 227 |             const ClassTreeMask& operator+=(const ClassTreeMask& other); | 
|---|
 | 228 |             const ClassTreeMask& operator*=(const ClassTreeMask& other); | 
|---|
 | 229 |             const ClassTreeMask& operator-=(const ClassTreeMask& other); | 
|---|
| [1505] | 230 |  | 
|---|
 | 231 |             ClassTreeMask operator&(const ClassTreeMask& other) const; | 
|---|
 | 232 |             ClassTreeMask operator|(const ClassTreeMask& other) const; | 
|---|
 | 233 |             ClassTreeMask operator^(const ClassTreeMask& other) const; | 
|---|
 | 234 |             ClassTreeMask operator~() const; | 
|---|
 | 235 |  | 
|---|
| [1757] | 236 |             const ClassTreeMask& operator&=(const ClassTreeMask& other); | 
|---|
 | 237 |             const ClassTreeMask& operator|=(const ClassTreeMask& other); | 
|---|
 | 238 |             const ClassTreeMask& operator^=(const ClassTreeMask& other); | 
|---|
| [1505] | 239 |  | 
|---|
 | 240 |             friend std::ostream& operator<<(std::ostream& out, const ClassTreeMask& mask); | 
|---|
 | 241 |  | 
|---|
 | 242 |         private: | 
|---|
 | 243 |             void add(ClassTreeMaskNode* node, const Identifier* subclass, bool bInclude, bool overwrite = true); | 
|---|
 | 244 |             bool isIncluded(ClassTreeMaskNode* node, const Identifier* subclass) const; | 
|---|
 | 245 |             void clean(ClassTreeMaskNode* node); | 
|---|
 | 246 |             bool nodeExists(const Identifier* subclass); | 
|---|
 | 247 |  | 
|---|
| [7401] | 248 |             ClassTreeMaskNode* root_;   ///< The root-node of the internal rule-tree, usually BaseObject | 
|---|
| [1505] | 249 |     }; | 
|---|
| [1747] | 250 |  | 
|---|
 | 251 |  | 
|---|
 | 252 |     // ################################### | 
|---|
 | 253 |     // ### ClassTreeMaskObjectIterator ### | 
|---|
 | 254 |     // ################################### | 
|---|
 | 255 |     /** | 
|---|
| [7401] | 256 |         @brief The ClassTreeMaskObjectIterator iterates through all objects of the classes that were included by a ClassTreeMask. | 
|---|
| [1757] | 257 |  | 
|---|
| [7401] | 258 |         This is done the following way: | 
|---|
 | 259 |         @code | 
|---|
| [1757] | 260 |         ClassTreeMask mask; | 
|---|
 | 261 |         for (ClassTreeMaskObjectIterator it = mask.begin(); it != mask.end(); ++it) | 
|---|
 | 262 |             it->doSomething(); | 
|---|
| [7401] | 263 |         @endcode | 
|---|
| [1757] | 264 |  | 
|---|
| [7401] | 265 |         @note The ClassTreeMaskObjectIterator handles all objects as BaseObjects. If | 
|---|
| [1757] | 266 |               you want to use another class, you should use a dynamic_cast. | 
|---|
 | 267 |  | 
|---|
| [7401] | 268 |         The performance of ClassTreeMaskObjectIterator is good as long as you don't exclude | 
|---|
| [1757] | 269 |         subclasses of included classes. Of course you can still exlucde subclasses, but | 
|---|
 | 270 |         if this is done more often, we need a new implementation using a second ObjectList | 
|---|
 | 271 |         in the Identifier, containing all objects of exactly one class. | 
|---|
| [1747] | 272 |     */ | 
|---|
 | 273 |     class _CoreExport ClassTreeMaskObjectIterator | 
|---|
 | 274 |     { | 
|---|
| [1757] | 275 |         public: | 
|---|
| [7401] | 276 |             /// Default-constructor: Does nothing. | 
|---|
| [1757] | 277 |             inline ClassTreeMaskObjectIterator() {} | 
|---|
| [7401] | 278 |             /// Copy-Constructor: Initializes the iterator from another ClassTreeMask. | 
|---|
| [1757] | 279 |             inline ClassTreeMaskObjectIterator(const ClassTreeMask& mask) { (*this) = mask; } | 
|---|
 | 280 |  | 
|---|
| [7268] | 281 |             ClassTreeMaskObjectIterator& operator=(const ClassTreeMask& mask); | 
|---|
| [1757] | 282 |  | 
|---|
 | 283 |             const ClassTreeMaskObjectIterator& operator++(); | 
|---|
 | 284 |  | 
|---|
| [7401] | 285 |             /// Returns true if the ClassTreeMaskObjectIterator points at the given object. | 
|---|
| [5929] | 286 |             inline bool operator==(BaseObject* pointer) const { return (this->objectIterator_ && (*this->objectIterator_) == pointer) || (!this->objectIterator_ && pointer == 0); } | 
|---|
| [7401] | 287 |             /// Returns true if the ClassTreeMaskObjectIterator doesn't point at the given object. | 
|---|
| [5929] | 288 |             inline bool operator!=(BaseObject* pointer) const { return (this->objectIterator_ && (*this->objectIterator_) != pointer) || (!this->objectIterator_ && pointer != 0); } | 
|---|
| [7401] | 289 |             /// Returns true if the ClassTreeMaskObjectIterator hasn't already reached the end. | 
|---|
| [1757] | 290 |             inline operator bool() const { return (this->objectIterator_); } | 
|---|
| [7401] | 291 |             /// Returns the object the ClassTreeMaskObjectIterator currently points at. | 
|---|
| [1757] | 292 |             inline BaseObject* operator*() const { return (*this->objectIterator_); } | 
|---|
| [7401] | 293 |             /// Returns the object the ClassTreeMaskObjectIterator currently points at. | 
|---|
| [1757] | 294 |             inline BaseObject* operator->() const { return (*this->objectIterator_); } | 
|---|
 | 295 |  | 
|---|
 | 296 |         private: | 
|---|
 | 297 |             void create(ClassTreeMaskNode* node); | 
|---|
 | 298 |  | 
|---|
| [7401] | 299 |             std::list<std::pair<const Identifier*, bool> >           subclasses_;       ///< A list of all Identifiers through which objects the iterator should iterate | 
|---|
 | 300 |             std::list<std::pair<const Identifier*, bool> >::iterator subclassIterator_; ///< The current class of the iterator | 
|---|
 | 301 |             Iterator<BaseObject>                                     objectIterator_;   ///< The current object of the iterator | 
|---|
| [1747] | 302 |     }; | 
|---|
| [1505] | 303 | } | 
|---|
 | 304 |  | 
|---|
 | 305 | #endif /* _ClassTreeMask_H__ */ | 
|---|