Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Fixed a small bug in the clean-function of ClassTreeMask (I made it recursively and forgot the recursion-call :D). From what I see now the ClassTreeMask works fine. And yes, I know it's overkill, no one will ever use more than 10% of the features, but I like it. ;)

File size: 14.3 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*>::iterator it = this->rootlist_.insert(this->rootlist_.end(), node);
91        this->nodes_.push(std::pair<std::list<ClassTreeMaskNode*>::iterator, std::list<ClassTreeMaskNode*>::iterator>(it, this->rootlist_.end()));
92    }
93
94    ClassTreeMaskIterator::~ClassTreeMaskIterator()
95    {
96    }
97
98    ClassTreeMaskIterator& ClassTreeMaskIterator::operator++()
99    {
100        if ((*this->nodes_.top().first)->subnodes_.begin() != (*this->nodes_.top().first)->subnodes_.end())
101            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()));
102        else
103        {
104            do
105            {
106                ++this->nodes_.top().first;
107                if (this->nodes_.top().first == this->nodes_.top().second)
108                {
109                    this->nodes_.pop();
110                    continue;
111                }
112
113                break;
114            } while (!this->nodes_.empty());
115        }
116
117        return *this;
118    }
119
120    ClassTreeMaskNode* ClassTreeMaskIterator::operator*() const
121    {
122        return (*this->nodes_.top().first);
123    }
124
125    ClassTreeMaskNode* ClassTreeMaskIterator::operator->() const
126    {
127        return (*this->nodes_.top().first);
128    }
129
130    ClassTreeMaskIterator::operator bool()
131    {
132        return (!this->nodes_.empty());
133    }
134
135    bool ClassTreeMaskIterator::operator==(ClassTreeMaskNode* compare)
136    {
137        if (!this->nodes_.empty())
138            return ((*this->nodes_.top().first) == compare);
139        else
140            return (compare == 0);
141    }
142
143    bool ClassTreeMaskIterator::operator!=(ClassTreeMaskNode* compare)
144    {
145        if (!this->nodes_.empty())
146            return ((*this->nodes_.top().first) != compare);
147        else
148            return (compare != 0);
149    }
150
151
152    // ###############################
153    // ###      ClassTreeMask      ###
154    // ###############################
155    ClassTreeMask::ClassTreeMask()
156    {
157        this->root_ = new ClassTreeMaskNode(ClassManager<BaseObject>::getIdentifier("BaseObject"), true);
158    }
159
160    ClassTreeMask::ClassTreeMask(const ClassTreeMask& other)
161    {
162        this->root_ = new ClassTreeMaskNode(ClassManager<BaseObject>::getIdentifier("BaseObject"), true);
163        for (ClassTreeMaskIterator it = other.root_; it; ++it)
164            this->add(it->getClass(), it->isIncluded());
165    }
166
167    ClassTreeMask::~ClassTreeMask()
168    {
169        delete this->root_;
170    }
171
172    void ClassTreeMask::include(const Identifier* subclass)
173    {
174        this->add(subclass, true);
175    }
176
177    void ClassTreeMask::exclude(const Identifier* subclass)
178    {
179        this->add(subclass, false);
180    }
181
182    void ClassTreeMask::add(const Identifier* subclass, bool bInclude)
183    {
184        this->add(this->root_, subclass, bInclude);
185    }
186
187    void ClassTreeMask::add(ClassTreeMaskNode* node, const Identifier* subclass, bool bInclude)
188    {
189        // Check if the current node contains exactly the subclass we want to add
190        if (subclass == node->getClass())
191        {
192            // We're at the right place, just change the mask and return
193            node->setIncluded(bInclude);
194            return;
195        }
196        else
197        {
198            // Search for an already existing node, containing the subclass we want to add
199            for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); ++it)
200            {
201                if (subclass->isA((*it)->getClass()))
202                {
203                    // We've found an existing node -> delegate the work and return
204                    this->add(*it, subclass, bInclude);
205                    return;
206                }
207            }
208
209            // There is no existing node satisfying our needs -> we create a new node
210            ClassTreeMaskNode* newnode = new ClassTreeMaskNode(subclass, bInclude);
211
212            // Search for nodes that should actually be subnodes of our new node
213            for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); )
214            {
215                if ((*it)->getClass()->isChildOf(subclass))
216                {
217                    // We've found a subnode: add it to the new node an erase it from the current node
218                    newnode->addSubnode(*it);
219                    node->subnodes_.erase(it++);
220                }
221                else
222                {
223                    ++it;
224                }
225            }
226
227            // Finally add the new node as a subnode to the current node
228            node->addSubnode(newnode);
229        }
230    }
231
232    void ClassTreeMask::reset()
233    {
234        delete this->root_;
235        this->root_ = new ClassTreeMaskNode(ClassManager<BaseObject>::getIdentifier("BaseObject"), true);
236    }
237
238    bool ClassTreeMask::isIncluded(const Identifier* subclass) const
239    {
240        return this->isIncluded(this->root_, subclass);
241    }
242
243    bool ClassTreeMask::isIncluded(ClassTreeMaskNode* node, const Identifier* subclass) const
244    {
245//std::cout << "1_1: " << subclass->getName() << " (" << subclass << ") / " << node->getClass()->getName() << " (" << node->getClass() << ")" << std::endl;
246        // Check if the searched subclass is of the same type as the class in the current node or a derivative
247        if (subclass->isA(node->getClass()))
248        {
249            // Check for the special case
250            if (subclass == node->getClass())
251                return node->isIncluded();
252
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
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            // The class is not included in the mask: return false
264            return false;
265        }
266    }
267
268    bool ClassTreeMask::isExcluded(const Identifier* subclass) const
269    {
270        return (!this->isIncluded(subclass));
271    }
272
273    void ClassTreeMask::clean()
274    {
275        this->clean(this->root_);
276    }
277
278    void ClassTreeMask::clean(ClassTreeMaskNode* node)
279    {
280//std::cout << "4_1: " << node->getClass()->getName() << ": " << node->isIncluded() << "\n";
281        for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); )
282        {
283//std::cout << "4_2: " << (*it)->getClass()->getName() << ": " << (*it)->isIncluded() << "\n";
284            this->clean(*it);
285//std::cout << "4_3\n";
286            if ((*it)->isIncluded() == node->isIncluded())
287            {
288//std::cout << "4_4\n";
289                node->subnodes_.insert(node->subnodes_.end(), (*it)->subnodes_.begin(), (*it)->subnodes_.end());
290                (*it)->subnodes_.clear();
291                node->subnodes_.erase(it);
292                it = node->subnodes_.begin();
293//std::cout << "4_5\n";
294            }
295            else
296            {
297//std::cout << "4_6\n";
298                ++it;
299            }
300        }
301//std::cout << "4_7\n";
302    }
303
304    ClassTreeMask& ClassTreeMask::operator=(const ClassTreeMask& other)
305    {
306        ClassTreeMask temp(other);
307
308        this->reset();
309
310        for (ClassTreeMaskIterator it = temp.root_; it; ++it)
311            this->add(it->getClass(), it->isIncluded());
312
313        return (*this);
314    }
315
316    ClassTreeMask& ClassTreeMask::operator+()
317    {
318        return (*this);
319    }
320
321    ClassTreeMask ClassTreeMask::operator-() const
322    {
323        return (!(*this));
324    }
325
326    ClassTreeMask ClassTreeMask::operator+(const ClassTreeMask& other) const
327    {
328        ClassTreeMask newmask;
329        for (ClassTreeMaskIterator it = this->root_; it; ++it)
330        {
331            const Identifier* subclass = it->getClass();
332            newmask.add(subclass, this->isIncluded(subclass) or other.isIncluded(subclass));
333        }
334        for (ClassTreeMaskIterator it = other.root_; it; ++it)
335        {
336            const Identifier* subclass = it->getClass();
337            newmask.add(subclass, this->isIncluded(subclass) or other.isIncluded(subclass));
338        }
339        newmask.clean();
340
341        return newmask;
342    }
343
344    ClassTreeMask ClassTreeMask::operator*(const ClassTreeMask& other) const
345    {
346        ClassTreeMask newmask;
347        for (ClassTreeMaskIterator it = this->root_; it; ++it)
348        {
349            const Identifier* subclass = it->getClass();
350            newmask.add(subclass, this->isIncluded(subclass) and other.isIncluded(subclass));
351        }
352        for (ClassTreeMaskIterator it = other.root_; it; ++it)
353        {
354            const Identifier* subclass = it->getClass();
355            newmask.add(subclass, this->isIncluded(subclass) and other.isIncluded(subclass));
356        }
357        newmask.clean();
358
359        return newmask;
360    }
361
362    ClassTreeMask ClassTreeMask::operator-(const ClassTreeMask& other) const
363    {
364        return ((*this) * (!other));
365    }
366
367    ClassTreeMask ClassTreeMask::operator!() const
368    {
369        ClassTreeMask newmask;
370        for (ClassTreeMaskIterator it = this->root_; it; ++it)
371        {
372            const Identifier* subclass = it->getClass();
373            newmask.add(subclass, !this->isIncluded(subclass));
374        }
375        return newmask;
376    }
377
378    ClassTreeMask& ClassTreeMask::operator+=(const ClassTreeMask& other)
379    {
380        (*this) = (*this) + other;
381        return (*this);
382    }
383
384    ClassTreeMask& ClassTreeMask::operator*=(const ClassTreeMask& other)
385    {
386        (*this) = (*this) * other;
387        return (*this);
388    }
389
390    ClassTreeMask& ClassTreeMask::operator-=(const ClassTreeMask& other)
391    {
392        (*this) = (*this) - other;
393        return (*this);
394    }
395
396    ClassTreeMask ClassTreeMask::operator&(const ClassTreeMask& other) const
397    {
398        return ((*this) * other);
399    }
400
401    ClassTreeMask ClassTreeMask::operator|(const ClassTreeMask& other) const
402    {
403        return ((*this) + other);
404    }
405
406    ClassTreeMask ClassTreeMask::operator^(const ClassTreeMask& other) const
407    {
408        ClassTreeMask newmask;
409        for (ClassTreeMaskIterator it = this->root_; it; ++it)
410        {
411            const Identifier* subclass = it->getClass();
412            newmask.add(subclass, this->isIncluded(subclass) xor other.isIncluded(subclass));
413        }
414        for (ClassTreeMaskIterator it = other.root_; it; ++it)
415        {
416            const Identifier* subclass = it->getClass();
417            newmask.add(subclass, this->isIncluded(subclass) xor other.isIncluded(subclass));
418        }
419        newmask.clean();
420
421        return newmask;
422    }
423
424    ClassTreeMask ClassTreeMask::operator~() const
425    {
426        return (!(*this));
427    }
428
429    ClassTreeMask& ClassTreeMask::operator&=(const ClassTreeMask& other)
430    {
431        (*this) = (*this) & other;
432        return (*this);
433    }
434
435    ClassTreeMask& ClassTreeMask::operator|=(const ClassTreeMask& other)
436    {
437        (*this) = (*this) | other;
438        return (*this);
439    }
440
441    ClassTreeMask& ClassTreeMask::operator^=(const ClassTreeMask& other)
442    {
443        (*this) = (*this) ^ other;
444        return (*this);
445    }
446
447    std::ostream& operator<<(std::ostream& out, const ClassTreeMask& mask)
448    {
449        for (ClassTreeMaskIterator it = mask.root_; it; ++it)
450        {
451            if (it->isIncluded())
452                out << "+";
453            else
454                out << "-";
455
456            out << it->getClass()->getName() << " ";
457        }
458
459        return out;
460    }
461}
Note: See TracBrowser for help on using the repository browser.