Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core/src/orxonox/core/ClassTreeMask.cc @ 806

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

cleanup

File size: 12.1 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *
4 *
5 *   License notice:
6 *
7 *   This program is free software; you can redistribute it and/or
8 *   modify it under the terms of the GNU General Public License
9 *   as published by the Free Software Foundation; either version 2
10 *   of the License, or (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *   Author:
22 *      Fabian 'x3n' Landau
23 *   Co-authors:
24 *      ...
25 *
26 */
27
28#include "ClassTreeMask.h"
29#include "Identifier.h"
30#include "BaseObject.h"
31
32namespace orxonox
33{
34    // ###############################
35    // ###    ClassTreeMaskNode    ###
36    // ###############################
37    ClassTreeMaskNode::ClassTreeMaskNode(const Identifier* subclass, bool bIncluded)
38    {
39        this->subclass_ = subclass;
40        this->bIncluded_ = bIncluded;
41    }
42
43    ClassTreeMaskNode::~ClassTreeMaskNode()
44    {
45        for (std::list<ClassTreeMaskNode*>::iterator it = this->subnodes_.begin(); it != this->subnodes_.end(); )
46            delete (*(it++));
47    }
48
49    void ClassTreeMaskNode::include()
50    {
51        this->bIncluded_ = true;
52    }
53
54    void ClassTreeMaskNode::exclude()
55    {
56        this->bIncluded_ = false;
57    }
58
59    void ClassTreeMaskNode::setIncluded(bool bIncluded)
60    {
61        this->bIncluded_ = bIncluded;
62    }
63
64    void ClassTreeMaskNode::addSubnode(ClassTreeMaskNode* subnode)
65    {
66        this->subnodes_.insert(this->subnodes_.end(), subnode);
67    }
68
69    bool ClassTreeMaskNode::isIncluded() const
70    {
71        return this->bIncluded_;
72    }
73
74    bool ClassTreeMaskNode::isExcluded() const
75    {
76        return (!this->bIncluded_);
77    }
78
79    const Identifier* ClassTreeMaskNode::getClass() const
80    {
81        return this->subclass_;
82    }
83
84
85    // ###############################
86    // ###  ClassTreeMaskIterator  ###
87    // ###############################
88    ClassTreeMaskIterator::ClassTreeMaskIterator(ClassTreeMaskNode* node)
89    {
90        std::list<ClassTreeMaskNode*> templist;
91        std::list<ClassTreeMaskNode*>::iterator tempiterator = templist.insert(templist.end(), node);
92        this->nodes_.push(std::pair<std::list<ClassTreeMaskNode*>::iterator, std::list<ClassTreeMaskNode*>::iterator>(tempiterator, templist.end()));
93    }
94
95    ClassTreeMaskIterator::~ClassTreeMaskIterator()
96    {
97    }
98
99    ClassTreeMaskIterator& ClassTreeMaskIterator::operator++()
100    {
101        if ((*this->nodes_.top().first)->subnodes_.begin() != (*this->nodes_.top().first)->subnodes_.end())
102            this->nodes_.push(std::pair<std::list<ClassTreeMaskNode*>::iterator, std::list<ClassTreeMaskNode*>::iterator>((*this->nodes_.top().first)->subnodes_.begin(), (*this->nodes_.top().first)->subnodes_.end()));
103        else
104        {
105            do
106            {
107                ++this->nodes_.top().first;
108                if (this->nodes_.top().first == this->nodes_.top().second)
109                {
110                    this->nodes_.pop();
111                    continue;
112                }
113
114                break;
115            } while (!this->nodes_.empty());
116        }
117
118        return *this;
119    }
120
121    ClassTreeMaskNode* ClassTreeMaskIterator::operator*() const
122    {
123        return (*this->nodes_.top().first);
124    }
125
126    ClassTreeMaskNode* ClassTreeMaskIterator::operator->() const
127    {
128        return (*this->nodes_.top().first);
129    }
130
131    ClassTreeMaskIterator::operator bool()
132    {
133        return (!this->nodes_.empty());
134    }
135
136    bool ClassTreeMaskIterator::operator==(ClassTreeMaskNode* compare)
137    {
138        if (!this->nodes_.empty())
139            return ((*this->nodes_.top().first) == compare);
140        else
141            return (compare == 0);
142    }
143
144    bool ClassTreeMaskIterator::operator!=(ClassTreeMaskNode* compare)
145    {
146        if (!this->nodes_.empty())
147            return ((*this->nodes_.top().first) != compare);
148        else
149            return (compare != 0);
150    }
151
152
153    // ###############################
154    // ###      ClassTreeMask      ###
155    // ###############################
156    ClassTreeMask::ClassTreeMask()
157    {
158        this->root_ = new ClassTreeMaskNode(ClassManager<BaseObject>::getIdentifier("BaseObject"), true);
159    }
160
161    ClassTreeMask::~ClassTreeMask()
162    {
163        delete this->root_;
164    }
165
166    void ClassTreeMask::include(const Identifier* subclass)
167    {
168        this->add(subclass, true);
169    }
170
171    void ClassTreeMask::exclude(const Identifier* subclass)
172    {
173        this->add(subclass, false);
174    }
175
176    void ClassTreeMask::add(const Identifier* subclass, bool bInclude)
177    {
178        this->add(this->root_, subclass, bInclude);
179    }
180
181    void ClassTreeMask::add(ClassTreeMaskNode* node, const Identifier* subclass, bool bInclude)
182    {
183        // Check if the current node contains exactly the subclass we want to add
184        if (subclass == node->getClass())
185        {
186            // We're at the right place, just change the mask and return
187            node->setIncluded(bInclude);
188            return;
189        }
190        else
191        {
192            // Search for an already existing node, containing the subclass we want to add
193            for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); ++it)
194            {
195                if (subclass->isA((*it)->getClass()))
196                {
197                    // We've found an existing node -> delegate the work and return
198                    this->add(*it, subclass, bInclude);
199                    return;
200                }
201            }
202
203            // There is no existing node satisfying our needs -> we create a new node
204            ClassTreeMaskNode* newnode = new ClassTreeMaskNode(subclass, bInclude);
205
206            // Search for nodes that should actually be subnodes of our new node
207            for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); )
208            {
209                if ((*it)->getClass()->isChildOf(subclass))
210                {
211                    // We've found a subnode: add it to the new node an erase it from the current node
212                    newnode->addSubnode(*it);
213                    node->subnodes_.erase(it++);
214                }
215                else
216                {
217                    ++it;
218                }
219            }
220
221            // Finally add the new node as a subnode to the current node
222            node->addSubnode(newnode);
223        }
224    }
225
226    void ClassTreeMask::reset()
227    {
228        delete this->root_;
229        this->root_ = new ClassTreeMaskNode(ClassManager<BaseObject>::getIdentifier("BaseObject"), true);
230    }
231
232    bool ClassTreeMask::isIncluded(const Identifier* subclass) const
233    {
234        return this->isIncluded(this->root_, subclass);
235    }
236
237    bool ClassTreeMask::isIncluded(ClassTreeMaskNode* node, const Identifier* subclass) const
238    {
239//std::cout << "1_1: " << subclass->getName() << " (" << subclass << ") / " << node->getClass()->getName() << " (" << node->getClass() << ")" << std::endl;
240        // Check if the searched subclass is of the same type as the class in the current node or a derivative
241        if (subclass->isA(node->getClass()))
242        {
243//std::cout << "1_2\n";
244            // Check for the special case
245            if (subclass == node->getClass())
246            {
247//std::cout << "1_3\n";
248                return node->isIncluded();
249            }
250
251//std::cout << "1_4\n";
252            // Go through the list of subnodes and look for a node containing the searched subclass
253            for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); ++it)
254                if (subclass->isA((*it)->getClass()))
255                    return isIncluded(*it, subclass);
256
257//std::cout << "1_5\n";
258            // There is no subnode containing our class -> the rule of the current node takes in effect
259            return node->isIncluded();
260        }
261        else
262        {
263//std::cout << "1_6\n";
264            // The class is not included in the mask: return false
265            return false;
266        }
267    }
268
269    bool ClassTreeMask::isExcluded(const Identifier* subclass) const
270    {
271        return (!this->isIncluded(subclass));
272    }
273
274    void ClassTreeMask::clean()
275    {
276        this->clean(this->root_);
277    }
278
279    void ClassTreeMask::clean(ClassTreeMaskNode* node)
280    {
281        for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); )
282        {
283            if ((*it)->isIncluded() == node->isIncluded())
284            {
285                node->subnodes_.insert(node->subnodes_.end(), (*it)->subnodes_.begin(), (*it)->subnodes_.end());
286                (*it)->subnodes_.clear();
287                node->subnodes_.erase(it++);
288            }
289            else
290            {
291                ++it;
292            }
293        }
294    }
295
296    ClassTreeMask ClassTreeMask::operator+(const ClassTreeMask& other) const
297    {
298        ClassTreeMask newmask;
299        for (ClassTreeMaskIterator it = this->root_; it; ++it)
300        {
301            const Identifier* subclass = it->getClass();
302            newmask.add(subclass, this->isIncluded(subclass) or other.isIncluded(subclass));
303        }
304        for (ClassTreeMaskIterator it = other.root_; it; ++it)
305        {
306            const Identifier* subclass = it->getClass();
307            newmask.add(subclass, this->isIncluded(subclass) or other.isIncluded(subclass));
308        }
309        newmask.clean();
310
311        return newmask;
312    }
313
314    ClassTreeMask ClassTreeMask::operator*(const ClassTreeMask& other) const
315    {
316        ClassTreeMask newmask;
317        for (ClassTreeMaskIterator it = this->root_; it; ++it)
318        {
319            const Identifier* subclass = it->getClass();
320            newmask.add(subclass, this->isIncluded(subclass) and other.isIncluded(subclass));
321        }
322        for (ClassTreeMaskIterator it = other.root_; it; ++it)
323        {
324            const Identifier* subclass = it->getClass();
325            newmask.add(subclass, this->isIncluded(subclass) and other.isIncluded(subclass));
326        }
327        newmask.clean();
328
329        return newmask;
330    }
331
332    ClassTreeMask ClassTreeMask::operator!() const
333    {
334        ClassTreeMask newmask;
335        for (ClassTreeMaskIterator it = this->root_; it; ++it)
336        {
337            const Identifier* subclass = it->getClass();
338            newmask.add(subclass, !this->isIncluded(subclass));
339        }
340
341        return newmask;
342    }
343
344    ClassTreeMask ClassTreeMask::operator-(const ClassTreeMask& other) const
345    {
346        return ((*this) * (!other));
347    }
348
349    ClassTreeMask ClassTreeMask::operator&(const ClassTreeMask& other) const
350    {
351        return ((*this) * other);
352    }
353
354    ClassTreeMask ClassTreeMask::operator|(const ClassTreeMask& other) const
355    {
356        return ((*this) + other);
357    }
358
359    ClassTreeMask ClassTreeMask::operator^(const ClassTreeMask& other) const
360    {
361        ClassTreeMask newmask;
362        for (ClassTreeMaskIterator it = this->root_; it; ++it)
363        {
364            const Identifier* subclass = it->getClass();
365            newmask.add(subclass, this->isIncluded(subclass) xor other.isIncluded(subclass));
366        }
367        for (ClassTreeMaskIterator it = other.root_; it; ++it)
368        {
369            const Identifier* subclass = it->getClass();
370            newmask.add(subclass, this->isIncluded(subclass) xor other.isIncluded(subclass));
371        }
372        newmask.clean();
373
374        return newmask;
375    }
376
377    ClassTreeMask ClassTreeMask::operator~() const
378    {
379        return (!(*this));
380    }
381}
Note: See TracBrowser for help on using the repository browser.