Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

I'm doing strange things… expanded the ClassTreeMask with scary operators and an iterator. it's not yet tested, it's probably doing bullshit right now, but it looks much better than the last approach with the Level class.

File size: 11.7 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(ClassIdentifier<BaseObject>::getIdentifier(), 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(ClassIdentifier<BaseObject>::getIdentifier(), 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        // Check if the searched subclass is of the same type as the class in the current node or a derivative
240        if (subclass->isA(node->getClass()))
241        {
242            // Check for the special case
243            if (subclass == node->getClass())
244                return node->isIncluded();
245
246            // Go through the list of subnodes and look for a node containing the searched subclass
247            for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); ++it)
248                if (subclass->isA((*it)->getClass()))
249                    return isIncluded(*it, subclass);
250
251            // There is no subnode containing our class -> the rule of the current node takes in effect
252            return node->isIncluded();
253        }
254        else
255        {
256            // The class is not included in the mask: return false
257            return false;
258        }
259    }
260
261    bool ClassTreeMask::isExcluded(const Identifier* subclass) const
262    {
263        return (!this->isIncluded(subclass));
264    }
265
266    void ClassTreeMask::clean()
267    {
268        this->clean(this->root_);
269    }
270
271    void ClassTreeMask::clean(ClassTreeMaskNode* node)
272    {
273        for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); )
274        {
275            if ((*it)->isIncluded() == node->isIncluded())
276            {
277                node->subnodes_.insert(node->subnodes_.end(), (*it)->subnodes_.begin(), (*it)->subnodes_.end());
278                (*it)->subnodes_.clear();
279                node->subnodes_.erase(it++);
280            }
281            else
282            {
283                ++it;
284            }
285        }
286    }
287
288    ClassTreeMask ClassTreeMask::operator+(const ClassTreeMask& other) const
289    {
290        ClassTreeMask newmask;
291        for (ClassTreeMaskIterator it = this->root_; it; ++it)
292        {
293            const Identifier* subclass = it->getClass();
294            newmask.add(subclass, this->isIncluded(subclass) or other.isIncluded(subclass));
295        }
296        for (ClassTreeMaskIterator it = other.root_; it; ++it)
297        {
298            const Identifier* subclass = it->getClass();
299            newmask.add(subclass, this->isIncluded(subclass) or other.isIncluded(subclass));
300        }
301        newmask.clean();
302
303        return newmask;
304    }
305
306    ClassTreeMask ClassTreeMask::operator*(const ClassTreeMask& other) const
307    {
308        ClassTreeMask newmask;
309        for (ClassTreeMaskIterator it = this->root_; it; ++it)
310        {
311            const Identifier* subclass = it->getClass();
312            newmask.add(subclass, this->isIncluded(subclass) and other.isIncluded(subclass));
313        }
314        for (ClassTreeMaskIterator it = other.root_; it; ++it)
315        {
316            const Identifier* subclass = it->getClass();
317            newmask.add(subclass, this->isIncluded(subclass) and other.isIncluded(subclass));
318        }
319        newmask.clean();
320
321        return newmask;
322    }
323
324    ClassTreeMask ClassTreeMask::operator!() const
325    {
326        ClassTreeMask newmask;
327        for (ClassTreeMaskIterator it = this->root_; it; ++it)
328        {
329            const Identifier* subclass = it->getClass();
330            newmask.add(subclass, !this->isIncluded(subclass));
331        }
332
333        return newmask;
334    }
335
336    ClassTreeMask ClassTreeMask::operator-(const ClassTreeMask& other) const
337    {
338        return ((*this) * (!other));
339    }
340
341    ClassTreeMask ClassTreeMask::operator&(const ClassTreeMask& other) const
342    {
343        return ((*this) * other);
344    }
345
346    ClassTreeMask ClassTreeMask::operator|(const ClassTreeMask& other) const
347    {
348        return ((*this) + other);
349    }
350
351    ClassTreeMask ClassTreeMask::operator^(const ClassTreeMask& other) const
352    {
353        ClassTreeMask newmask;
354        for (ClassTreeMaskIterator it = this->root_; it; ++it)
355        {
356            const Identifier* subclass = it->getClass();
357            newmask.add(subclass, this->isIncluded(subclass) xor other.isIncluded(subclass));
358        }
359        for (ClassTreeMaskIterator it = other.root_; it; ++it)
360        {
361            const Identifier* subclass = it->getClass();
362            newmask.add(subclass, this->isIncluded(subclass) xor other.isIncluded(subclass));
363        }
364        newmask.clean();
365
366        return newmask;
367    }
368
369    ClassTreeMask ClassTreeMask::operator~() const
370    {
371        return (!(*this));
372    }
373}
Note: See TracBrowser for help on using the repository browser.