Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/ClassTreeMask.h @ 2981

Last change on this file since 2981 was 2171, checked in by landauf, 16 years ago

merged revisions 2111-2170 from objecthierarchy branch back to trunk.

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