Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/ClassTreeMask.h @ 12249

Last change on this file since 12249 was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

  • Property svn:eol-style set to native
File size: 14.0 KB
Line 
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/**
30    @file
31    @ingroup Class
32    @brief Declaration of the ClassTreeMask, ClassTreeMaskNode, and ClassTreeMaskIterator classes.
33
34    ClassTreeMask is a class to define a mask of the class-tree beginning with orxonox::BaseObject.
35    You can include or exclude classes by calling the corresponding functions with the
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.
39
40    See the description of orxonox::ClassTreeMask for a short example.
41
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
45    @par Tree structure
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
52    Adding a new rule overwrites all rules assigned to inherited classes. Use <tt>overwrite = false</tt>
53    if you don't like this feature. Useless rules that don't change the information of the mask
54    aren't saved in the internal tree. Use <tt>clean = false</tt> if you still want to save them.
55
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()".
59
60    @par Objects
61
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.
65*/
66
67#ifndef _ClassTreeMask_H__
68#define _ClassTreeMask_H__
69
70#include "CorePrereqs.h"
71
72#include <list>
73#include <stack>
74#include "BaseObject.h"
75#include "object/Iterator.h"
76#include "class/Identifier.h"
77
78namespace orxonox
79{
80    // ###################################
81    // ###      ClassTreeMaskNode      ###
82    // ###################################
83    /**
84        @brief The ClassTreeMaskNode is a node in the internal tree of the ClassTreeMask, containing the rules of the mask.
85
86        The ClassTreeMaskNode is used to store the rule (included or excluded) for a given
87        class (described by the corresponding Identifier). The nodes are used in the internal
88        tree of ClassTreeMask. To build a tree, they store a list of all subnodes.
89    */
90    class _CoreExport ClassTreeMaskNode
91    {
92        friend class ClassTreeMask;
93        friend class ClassTreeMaskIterator;
94        friend class ClassTreeMaskObjectIterator;
95
96        public:
97            ClassTreeMaskNode(const Identifier* subclass, bool bIncluded = true);
98            ~ClassTreeMaskNode();
99
100            void include(bool overwrite = true);
101            void exclude(bool overwrite = true);
102            void setIncluded(bool bIncluded, bool overwrite = true);
103
104            void addSubnode(ClassTreeMaskNode* subnode);
105
106            /// Tells if the rule is "included" or not.
107            inline bool isIncluded() const { return this->bIncluded_; }
108            /// Tells if the rule is "excluded" or not.
109            inline bool isExcluded() const { return (!this->bIncluded_); }
110
111            /// Returns the Identifier of the class the rule refers to.
112            inline const Identifier* getClass() const { return this->subclass_; }
113
114            /// Returns true if the node has some subnodes.
115            inline bool hasSubnodes() const { return !this->subnodes_.empty(); }
116
117        private:
118            void deleteAllSubnodes();
119
120            const Identifier* subclass_;                ///< The Identifier of the subclass the rule refers to
121            bool bIncluded_;                            ///< The rule: included or excluded
122            std::list<ClassTreeMaskNode*> subnodes_;    ///< A list containing all subnodes of this node
123    };
124
125
126    // ###################################
127    // ###    ClassTreeMaskIterator    ###
128    // ###################################
129    /**
130        @brief The ClassTreeMaskIterator moves through all ClassTreeMaskNodes of the internal tree of a ClassTreeMask which contains the rules.
131
132        Because of the complicated shape of the internal rule-tree of ClassTreeMask, an
133        iterator is used to move through all nodes of the tree. It starts with the BaseObject
134        and moves on to the first subclass until it reaches a leaf of the tree. Then the
135        iterator moves one step back and iterates to the second subclass. If there are no more
136        subclasses, it steps another step back, and so on.
137
138        Example: A and B are children of BaseObject, A1 and A2 are children of A, B1 and B2 are children of B.
139        The ClassTreeMaskIterator would move trough the tree in the following order:
140        BaseObject, A, A1, A2, B, B1, B2.
141
142        Note that the iterator doesn't move trough the whole class-tree, but only through the
143        internal tree of the mask, containing the minimal needed set of nodes to describe the mask.
144    */
145    class _CoreExport ClassTreeMaskIterator
146    {
147        public:
148            ClassTreeMaskIterator(ClassTreeMaskNode* node);
149            ~ClassTreeMaskIterator();
150
151            const ClassTreeMaskIterator& operator++();
152            ClassTreeMaskNode* operator*() const;
153            ClassTreeMaskNode* operator->() const;
154            explicit operator bool() const;
155            bool operator==(ClassTreeMaskNode* compare) const;
156            bool operator!=(ClassTreeMaskNode* compare) const;
157
158        private:
159            std::stack<std::pair<std::list<ClassTreeMaskNode*>::iterator, std::list<ClassTreeMaskNode*>::iterator>> nodes_;    ///< A stack to store list-iterators
160            std::list<ClassTreeMaskNode*> rootlist_;                                                                            ///< A list for internal use (it only stores the root-node)
161    };
162
163
164    // ###################################
165    // ###        ClassTreeMask        ###
166    // ###################################
167    /**
168        @brief The ClassTreeMask is a set of rules, containing the information for each class whether it's included or not.
169
170        With a ClassTreeMask, you can include or exclude subtrees of the class-tree, starting
171        with a given subclass, described by the corresponding Identifier. To minimize the size
172        of the mask, the mask saves only relevant rules. But you can manually add rules that
173        don't change the information of the mask by using <tt>clean = false</tt>. If you want to drop
174        useless rules, call the clean() function.
175
176        Example:
177        @code
178        ClassTreeMask mymask;
179        mymask.exclude(Class(A));
180        mymask.exclude(Class(B));
181        mymask.include(Class(ChildOfA));
182        @endcode
183
184        In this example, the classes A and B are excluded from the mask, but one of the child
185        classes of A is included again.
186    */
187    class _CoreExport ClassTreeMask
188    {
189        friend class ClassTreeMaskObjectIterator;
190
191        public:
192            ClassTreeMask();
193            ClassTreeMask(const ClassTreeMask& other);
194            ~ClassTreeMask();
195
196            void include(const Identifier* subclass, bool overwrite = true, bool clean = true);
197            void exclude(const Identifier* subclass, bool overwrite = true, bool clean = true);
198            void add(const Identifier* subclass, bool bInclude, bool overwrite = true, bool clean = true);
199
200            void includeSingle(const Identifier* subclass, bool clean = true);
201            void excludeSingle(const Identifier* subclass, bool clean = true);
202            void addSingle(const Identifier* subclass, bool bInclude, bool clean = true);
203
204            void reset();
205            void clean();
206
207            bool isIncluded(const Identifier* subclass) const;
208            bool isExcluded(const Identifier* subclass) const;
209
210            /// Begin of the ClassTreeMaskObjectIterator.
211            inline const ClassTreeMask& begin() const { return (*this); }
212            /// End of the ClassTreeMaskObjectIterator.
213            inline BaseObject*          end()   const { return nullptr; }
214
215            ClassTreeMask& operator=(const ClassTreeMask& other);
216
217            bool operator==(const ClassTreeMask& other) const;
218            bool operator!=(const ClassTreeMask& other) const;
219
220            const ClassTreeMask& operator+() const;
221            ClassTreeMask operator-() const;
222
223            ClassTreeMask operator+(const ClassTreeMask& other) const;
224            ClassTreeMask operator*(const ClassTreeMask& other) const;
225            ClassTreeMask operator-(const ClassTreeMask& other) const;
226            ClassTreeMask operator!() const;
227
228            const ClassTreeMask& operator+=(const ClassTreeMask& other);
229            const ClassTreeMask& operator*=(const ClassTreeMask& other);
230            const ClassTreeMask& operator-=(const ClassTreeMask& other);
231
232            ClassTreeMask operator&(const ClassTreeMask& other) const;
233            ClassTreeMask operator|(const ClassTreeMask& other) const;
234            ClassTreeMask operator^(const ClassTreeMask& other) const;
235            ClassTreeMask operator~() const;
236
237            const ClassTreeMask& operator&=(const ClassTreeMask& other);
238            const ClassTreeMask& operator|=(const ClassTreeMask& other);
239            const ClassTreeMask& operator^=(const ClassTreeMask& other);
240
241            friend std::ostream& operator<<(std::ostream& out, const ClassTreeMask& mask);
242
243        private:
244            void add(ClassTreeMaskNode* node, const Identifier* subclass, bool bInclude, bool overwrite = true);
245            bool isIncluded(ClassTreeMaskNode* node, const Identifier* subclass) const;
246            void clean(ClassTreeMaskNode* node);
247            bool nodeExists(const Identifier* subclass);
248
249            ClassTreeMaskNode* root_;   ///< The root-node of the internal rule-tree, usually BaseObject
250    };
251
252
253    // ###################################
254    // ### ClassTreeMaskObjectIterator ###
255    // ###################################
256    /**
257        @brief The ClassTreeMaskObjectIterator iterates through all objects of the classes that were included by a ClassTreeMask.
258
259        This is done the following way:
260        @code
261        ClassTreeMask mask;
262        for (ClassTreeMaskObjectIterator it = mask.begin(); it != mask.end(); ++it)
263            it->doSomething();
264        @endcode
265
266        @note The ClassTreeMaskObjectIterator handles all objects as BaseObjects. If
267              you want to use another class, you should use a dynamic_cast.
268
269        The performance of ClassTreeMaskObjectIterator is good as long as you don't exclude
270        subclasses of included classes. Of course you can still exlucde subclasses, but
271        if this is done more often, we need a new implementation using a second ObjectList
272        in the Identifier, containing all objects of exactly one class.
273    */
274    class _CoreExport ClassTreeMaskObjectIterator
275    {
276        public:
277            /// Default-constructor: Does nothing.
278            inline ClassTreeMaskObjectIterator() = default;
279            /// Copy-Constructor: Initializes the iterator from another ClassTreeMask.
280            inline ClassTreeMaskObjectIterator(const ClassTreeMask& mask) { (*this) = mask; }
281
282            ClassTreeMaskObjectIterator& operator=(const ClassTreeMask& mask);
283
284            const ClassTreeMaskObjectIterator& operator++();
285
286            /// Returns true if the ClassTreeMaskObjectIterator points at the given object.
287            inline bool operator==(BaseObject* pointer) const { return (this->objectIterator_ && (*this->objectIterator_) == pointer) || (!this->objectIterator_ && pointer == nullptr); }
288            /// Returns true if the ClassTreeMaskObjectIterator doesn't point at the given object.
289            inline bool operator!=(BaseObject* pointer) const { return (this->objectIterator_ && (*this->objectIterator_) != pointer) || (!this->objectIterator_ && pointer != nullptr); }
290            /// Returns true if the ClassTreeMaskObjectIterator hasn't already reached the end.
291            inline explicit operator bool() const { return this->objectIterator_.operator bool(); }
292            /// Returns the object the ClassTreeMaskObjectIterator currently points at.
293            inline BaseObject* operator*() const { return (*this->objectIterator_); }
294            /// Returns the object the ClassTreeMaskObjectIterator currently points at.
295            inline BaseObject* operator->() const { return (*this->objectIterator_); }
296
297        private:
298            void create(ClassTreeMaskNode* node);
299
300            std::list<std::pair<const Identifier*, bool>>           subclasses_;       ///< A list of all Identifiers through which objects the iterator should iterate
301            std::list<std::pair<const Identifier*, bool>>::iterator subclassIterator_; ///< The current class of the iterator
302            Iterator<BaseObject>                                    objectIterator_;   ///< The current object of the iterator
303    };
304}
305
306#endif /* _ClassTreeMask_H__ */
Note: See TracBrowser for help on using the repository browser.