Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/usability/src/libraries/core/ClassTreeMask.h @ 9215

Last change on this file since 9215 was 7401, checked in by landauf, 14 years ago

merged doc branch back to trunk

  • Property svn:eol-style set to native
File size: 13.9 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 "Iterator.h"
76
77namespace orxonox
78{
79    // ###################################
80    // ###      ClassTreeMaskNode      ###
81    // ###################################
82    /**
83        @brief The ClassTreeMaskNode is a node in the internal tree of the ClassTreeMask, containing the rules of the mask.
84
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;
93        friend class ClassTreeMaskObjectIterator;
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
105            /// Tells if the rule is "included" or not.
106            inline bool isIncluded() const { return this->bIncluded_; }
107            /// Tells if the rule is "excluded" or not.
108            inline bool isExcluded() const { return (!this->bIncluded_); }
109
110            /// Returns the Identifier of the class the rule refers to.
111            inline const Identifier* getClass() const { return this->subclass_; }
112
113            /// Returns true if the node has some subnodes.
114            inline bool hasSubnodes() const { return !this->subnodes_.empty(); }
115
116        private:
117            void deleteAllSubnodes();
118
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
122    };
123
124
125    // ###################################
126    // ###    ClassTreeMaskIterator    ###
127    // ###################################
128    /**
129        @brief The ClassTreeMaskIterator moves through all ClassTreeMaskNodes of the internal tree of a ClassTreeMask which contains the rules.
130
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.
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.
143    */
144    class _CoreExport ClassTreeMaskIterator
145    {
146        public:
147            ClassTreeMaskIterator(ClassTreeMaskNode* node);
148            ~ClassTreeMaskIterator();
149
150            const ClassTreeMaskIterator& operator++();
151            ClassTreeMaskNode* operator*() const;
152            ClassTreeMaskNode* operator->() const;
153            operator bool() const;
154            bool operator==(ClassTreeMaskNode* compare) const;
155            bool operator!=(ClassTreeMaskNode* compare) const;
156
157        private:
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)
160    };
161
162
163    // ###################################
164    // ###        ClassTreeMask        ###
165    // ###################################
166    /**
167        @brief The ClassTreeMask is a set of rules, containing the information for each class whether it's included or not.
168
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
172        don't change the information of the mask by using <tt>clean = false</tt>. If you want to drop
173        useless rules, call the clean() function.
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.
185    */
186    class _CoreExport ClassTreeMask
187    {
188        friend class ClassTreeMaskObjectIterator;
189
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
209            /// Begin of the ClassTreeMaskObjectIterator.
210            inline const ClassTreeMask& begin() const { return (*this); }
211            /// End of the ClassTreeMaskObjectIterator.
212            inline BaseObject*          end()   const { return 0; }
213
214            ClassTreeMask& operator=(const ClassTreeMask& other);
215
216            bool operator==(const ClassTreeMask& other) const;
217            bool operator!=(const ClassTreeMask& other) const;
218
219            const ClassTreeMask& operator+() const;
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
227            const ClassTreeMask& operator+=(const ClassTreeMask& other);
228            const ClassTreeMask& operator*=(const ClassTreeMask& other);
229            const ClassTreeMask& operator-=(const ClassTreeMask& other);
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
236            const ClassTreeMask& operator&=(const ClassTreeMask& other);
237            const ClassTreeMask& operator|=(const ClassTreeMask& other);
238            const ClassTreeMask& operator^=(const ClassTreeMask& other);
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
248            ClassTreeMaskNode* root_;   ///< The root-node of the internal rule-tree, usually BaseObject
249    };
250
251
252    // ###################################
253    // ### ClassTreeMaskObjectIterator ###
254    // ###################################
255    /**
256        @brief The ClassTreeMaskObjectIterator iterates through all objects of the classes that were included by a ClassTreeMask.
257
258        This is done the following way:
259        @code
260        ClassTreeMask mask;
261        for (ClassTreeMaskObjectIterator it = mask.begin(); it != mask.end(); ++it)
262            it->doSomething();
263        @endcode
264
265        @note The ClassTreeMaskObjectIterator handles all objects as BaseObjects. If
266              you want to use another class, you should use a dynamic_cast.
267
268        The performance of ClassTreeMaskObjectIterator is good as long as you don't exclude
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.
272    */
273    class _CoreExport ClassTreeMaskObjectIterator
274    {
275        public:
276            /// Default-constructor: Does nothing.
277            inline ClassTreeMaskObjectIterator() {}
278            /// Copy-Constructor: Initializes the iterator from another ClassTreeMask.
279            inline ClassTreeMaskObjectIterator(const ClassTreeMask& mask) { (*this) = mask; }
280
281            ClassTreeMaskObjectIterator& operator=(const ClassTreeMask& mask);
282
283            const ClassTreeMaskObjectIterator& operator++();
284
285            /// Returns true if the ClassTreeMaskObjectIterator points at the given object.
286            inline bool operator==(BaseObject* pointer) const { return (this->objectIterator_ && (*this->objectIterator_) == pointer) || (!this->objectIterator_ && pointer == 0); }
287            /// Returns true if the ClassTreeMaskObjectIterator doesn't point at the given object.
288            inline bool operator!=(BaseObject* pointer) const { return (this->objectIterator_ && (*this->objectIterator_) != pointer) || (!this->objectIterator_ && pointer != 0); }
289            /// Returns true if the ClassTreeMaskObjectIterator hasn't already reached the end.
290            inline operator bool() const { return (this->objectIterator_); }
291            /// Returns the object the ClassTreeMaskObjectIterator currently points at.
292            inline BaseObject* operator*() const { return (*this->objectIterator_); }
293            /// Returns the object the ClassTreeMaskObjectIterator currently points at.
294            inline BaseObject* operator->() const { return (*this->objectIterator_); }
295
296        private:
297            void create(ClassTreeMaskNode* node);
298
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
302    };
303}
304
305#endif /* _ClassTreeMask_H__ */
Note: See TracBrowser for help on using the repository browser.