Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/environment2/src/modules/pickup/PickupCollection.cc @ 9241

Last change on this file since 9241 was 8305, checked in by dafrick, 14 years ago

Fixing another potential memory leak.

  • Property svn:eol-style set to native
File size: 11.4 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 *      Damian 'Mozork' Frick
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file PickupCollection.cc
31    @brief Implementation of PickupCollection.
32*/
33
34#include "core/CoreIncludes.h"
35#include "core/XMLPort.h"
36
37#include "interfaces/PickupCarrier.h"
38
39#include "CollectiblePickup.h"
40#include "DroppedPickup.h"
41#include "PickupCollectionIdentifier.h"
42
43#include "PickupCollection.h"
44
45namespace orxonox
46{
47
48    CreateFactory(PickupCollection);
49
50    /**
51    @brief
52        Default Constructor.
53    @param creator
54        The creator of the object.
55    */
56    PickupCollection::PickupCollection(BaseObject* creator) : BaseObject(creator), pickupCollectionIdentifier_(NULL)
57    {
58        RegisterObject(PickupCollection);
59
60        this->pickupCollectionIdentifier_ = new PickupCollectionIdentifier(this);
61        this->usedCounter_ = 0;
62        this->pickedUpCounter_ = 0;
63        this->disabledCounter_ = 0;
64        this->processingUsed_ = false;
65        this->processingPickedUp_ = false;
66    }
67
68    /**
69    @brief
70        Destructor. Iterates through all Pickupables this PickupCollection consists of and destroys them if they haven't been already.
71    */
72    PickupCollection::~ PickupCollection()
73    {
74        // Destroy all Pickupables constructing this PickupCollection.
75        for(std::vector<CollectiblePickup*>::iterator it = this->pickups_.begin(); it != this->pickups_.end(); it++)
76        {
77            (*it)->removeFromCollection();
78            (*it)->destroy();
79        }
80        this->pickups_.clear();
81       
82        if(this->pickupCollectionIdentifier_ != NULL)
83            delete this->pickupCollectionIdentifier_;
84    }
85
86    /**
87    @brief
88        Creates an instance of this Class through XML.
89    */
90    void PickupCollection::XMLPort(Element& xmlelement, XMLPort::Mode mode)
91    {
92        SUPER(PickupCollection, XMLPort, xmlelement, mode);
93
94        XMLPortObject(PickupCollection, CollectiblePickup, "pickupables", addPickupable, getPickupable, xmlelement, mode);
95
96        this->initializeIdentifier();
97    }
98
99    /**
100    @brief
101        Initializes the PickupIdentifier for this pickup.
102    */
103    void PickupCollection::initializeIdentifier(void)
104    {
105        for(std::vector<CollectiblePickup*>::iterator it = this->pickups_.begin(); it != this->pickups_.end(); it++)
106        {
107            this->pickupCollectionIdentifier_->addPickup((*it)->getPickupIdentifier());
108        }
109    }
110
111    /**
112    @brief
113        Is called when the pickup has transited from used to unused or the other way around.
114        Any Class overwriting this method must call its SUPER function by adding SUPER(Classname, changedUsed); to their changdeUsed method.
115    */
116    void PickupCollection::changedUsed(void)
117    {
118        SUPER(PickupCollection, changedUsed);
119
120        this->processingUsed_ = true;
121        // Change used for all Pickupables this PickupCollection consists of.
122        for(std::vector<CollectiblePickup*>::iterator it = this->pickups_.begin(); it != this->pickups_.end(); it++)
123            (*it)->setUsed(this->isUsed());
124
125        this->processingUsed_ = false;
126
127        this->changedUsedAction();
128    }
129
130    /**
131    @brief
132        Helper method.
133        Checks whether due to changes in the used status of the pickups of this PickupCollection the used status of this PickupCollection has to change as well.
134    */
135    void PickupCollection::changedUsedAction(void)
136    {
137        if(this->processingUsed_)
138            return;
139
140        // If all the pickups are not in use but the PickupCollection is.
141        if(this->usedCounter_ == 0 && this->isUsed())
142            this->setUsed(false);
143
144        // If all the enabled pickups are in use but the PickupCollection is not.
145        if(this->usedCounter_ != 0 && this->usedCounter_ == this->pickups_.size()-this->disabledCounter_ && !this->isUsed())
146            this->setUsed(true);
147    }
148
149    /**
150    @brief
151        Is called when the pickup has changed its PickupCarrier.
152        Any Class overwriting this method must call its SUPER function by adding SUPER(Classname, changedCarrier); to their changedCarrier method.
153    */
154    void PickupCollection::changedCarrier(void)
155    {
156        SUPER(PickupCollection, changedCarrier);
157
158        // Change the PickupCarrier for all Pickupables this PickupCollection consists of.
159        for(std::vector<CollectiblePickup*>::iterator it = this->pickups_.begin(); it != this->pickups_.end(); it++)
160        {
161            if(this->getCarrier() == NULL)
162                (*it)->setCarrier(NULL);
163            else
164                (*it)->setCarrier(this->getCarrier()->getTarget(*it));
165        }
166    }
167
168    /**
169    @brief
170        Is called when the pickup has transited from picked up to dropped or the other way around.
171        Any Class overwriting this method must call its SUPER function by adding SUPER(Classname, changedPickedUp); to their changedPickedUp method.
172    */
173    void PickupCollection::changedPickedUp()
174    {
175        SUPER(PickupCollection, changedPickedUp);
176
177        this->processingPickedUp_ = true;
178        // Change the pickedUp status for all Pickupables this PickupCollection consists of.
179        for(std::vector<CollectiblePickup*>::iterator it = this->pickups_.begin(); it != this->pickups_.end(); it++)
180            (*it)->setPickedUp(this->isPickedUp());
181
182        this->processingPickedUp_ = false;
183
184        this->changedPickedUpAction();
185    }
186
187    /**
188    @brief
189        Helper method.
190        Checks whether due to changes in the picked up status of the pickups of this PickupCollection the picked up status of this PickupCollection has to change as well.
191    */
192    void PickupCollection::changedPickedUpAction(void)
193    {
194        if(this->processingPickedUp_)
195            return;
196
197        // If at least all the enabled pickups of this PickupCollection are no longer picked up.
198        if(this->pickedUpCounter_ <= this->disabledCounter_ && this->isPickedUp())
199            this->Pickupable::destroy();
200
201        // If the PickupCollection is no longer picked up.
202        if(!this->isPickedUp())
203            this->pickedUpCounter_ = 0;
204    }
205
206    /**
207    @brief
208        Creates a duplicate of the input Pickupable.
209        This method needs to be implemented by any Class inheriting from Pickupable.
210    @param item
211        A reference to a pointer to the OrxonoxClass that is to be duplicated.
212    */
213    void PickupCollection::clone(OrxonoxClass*& item)
214    {
215        if(item == NULL)
216            item = new PickupCollection(this);
217
218        SUPER(PickupCollection, clone, item);
219
220        PickupCollection* pickup = dynamic_cast<PickupCollection*>(item);
221        // Clone all Pickupables this PickupCollection consist of.
222        for(std::vector<CollectiblePickup*>::iterator it = this->pickups_.begin(); it != this->pickups_.end(); it++)
223        {
224            Pickupable* newPickup = (*it)->clone();
225            CollectiblePickup* collectible = static_cast<CollectiblePickup*>(newPickup);
226            pickup->addPickupable(collectible);
227        }
228
229        pickup->initializeIdentifier();
230    }
231
232    /**
233    @brief
234        Get whether a given class, represented by the input Identifier, is a target of this PickupCollection.
235    @param carrier
236        A pointer to the PickupCarrier we want to know of, whether it is a target of this PickupCollection.
237    @return
238        Returns true if the PickupCarrier identified by the input PickupIdentififer it is a target of this PickupCollection, false if not.
239    */
240    bool PickupCollection::isTarget(const PickupCarrier* carrier) const
241    {
242        for(std::vector<CollectiblePickup*>::const_iterator it = this->pickups_.begin(); it != this->pickups_.end(); it++)
243        {
244            if(!carrier->isTarget(*it))
245                return false;
246        }
247
248        return true;
249    }
250
251    /**
252    @brief
253        Get the PickupIdentifier of this PickupCollection.
254        This is in fact the PickupCollectionIdentifier.
255    @return
256        Returns a pointer to the PickupIdentifier of this PickupCollection.
257    */
258    const PickupIdentifier* PickupCollection::getPickupIdentifier(void) const
259    {
260        return this->pickupCollectionIdentifier_;
261    }
262
263    /**
264    @brief
265        Add the input Pickupable to list of Pickupables combined by this PickupCollection.
266    @param pickup
267        The Pickupable to be added.
268    @return
269        Returns true if successful,
270    */
271    bool PickupCollection::addPickupable(CollectiblePickup* pickup)
272    {
273        if(pickup == NULL)
274            return false;
275
276        pickup->addToCollection(this);
277        this->pickups_.push_back(pickup);
278        return true;
279    }
280
281    /**
282    @brief
283        Get the Pickupable at the given index.
284    @param index
285        The index the Pickupable is fetched from.
286    @return
287        Returns a pointer to the Pickupable at the index given by index.
288    */
289    const Pickupable* PickupCollection::getPickupable(unsigned int index) const
290    {
291        return this->pickups_[index];
292    }
293
294    /**
295    @brief
296        Informs the PickupCollection, that one of its pickups has changed its used status to the input value.
297        This is used internally by the CollectiblePickup class.
298    @param changed
299        The value the used status has changed to.
300    */
301    void PickupCollection::pickupChangedUsed(bool changed)
302    {
303        if(changed)
304            this->usedCounter_++;
305        else
306            this->usedCounter_--;
307
308        this->changedUsedAction();
309    }
310
311    /**
312    @brief
313        Informs the PickupCollection, that one of its pickups has changed its picked up status to the input value.
314        This is used internally by the CollectiblePickup class.
315    @param changed
316        The value the picked up status has changed to.
317    */
318    void PickupCollection::pickupChangedPickedUp(bool changed)
319    {
320        if(changed)
321            this->pickedUpCounter_++;
322        else
323            this->pickedUpCounter_--;
324
325        this->changedPickedUpAction();
326    }
327
328    /**
329    @brief
330        Informs the PickupCollection, that one of its pickups has been disabled.
331        This is used internally by the CollectiblePickup class.
332    */
333    void PickupCollection::pickupDisabled(void)
334    {
335        this->disabledCounter_++;
336    }
337
338    /**
339    @brief
340        Facilitates the creation of a PickupSpawner upon dropping of the Pickupable.
341        This method must be implemented by any class directly inheriting from Pickupable. It is most easily done by just creating a new DroppedPickup, e.g.:
342        DroppedPickup(BaseObject* creator, Pickupable* pickup, const Vector3& position);
343    @return
344        Returns true if a spawner was created, false if not.
345    */
346    bool PickupCollection::createSpawner(void)
347    {
348        new DroppedPickup(this, this, this->getCarrier());
349        return true;
350    }
351
352}
Note: See TracBrowser for help on using the repository browser.