Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

added code for testing

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