Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.cc @ 11897

Last change on this file since 11897 was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

  • Property svn:eol-style set to native
File size: 10.0 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 DistanceMultiTrigger.cc
31    @brief Implementation of the DistanceMultiTrigger class.
32    @ingroup MultiTrigger
33*/
34
35#include "DistanceMultiTrigger.h"
36
37#include "core/CoreIncludes.h"
38#include "core/XMLPort.h"
39
40#include "DistanceTriggerBeacon.h"
41
42namespace orxonox
43{
44
45    /*static*/ const std::string DistanceMultiTrigger::beaconModeOff_s = "off";
46    /*static*/ const std::string DistanceMultiTrigger::beaconModeIdentify_s = "identify";
47    /*static*/ const std::string DistanceMultiTrigger::beaconModeExlcude_s = "exclude";
48   
49    RegisterClass(DistanceMultiTrigger);
50
51    /**
52    @brief
53        Default Constructor. Registers the object and initializes default values.
54    */
55    DistanceMultiTrigger::DistanceMultiTrigger(Context* context) : MultiTrigger(context)
56    {
57        RegisterObject(DistanceMultiTrigger);
58
59        this->distance_ = 100.0f;
60        this->setBeaconModeDirect(DistanceMultiTriggerBeaconMode::off);
61        this->targetName_ = "";
62        this->beaconMask_.exclude(Class(BaseObject));
63        this->beaconMask_.include(Class(DistanceTriggerBeacon));
64    }
65
66    /**
67    @brief
68        Destructor.
69    */
70    DistanceMultiTrigger::~DistanceMultiTrigger()
71    {
72
73    }
74
75    /**
76    @brief
77        Method for creating a DistanceMultiTrigger object through XML.
78    */
79    void DistanceMultiTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
80    {
81        SUPER(DistanceMultiTrigger, XMLPort, xmlelement, mode);
82
83        XMLPortParam(DistanceMultiTrigger, "distance", setDistance, getDistance, xmlelement, mode);
84        XMLPortParam(DistanceMultiTrigger, "beaconMode", setBeaconMode, getBeaconMode, xmlelement, mode);
85        XMLPortParam(DistanceMultiTrigger, "targetname", setTargetName, getTargetName, xmlelement, mode);
86    }
87
88    /**
89    @brief
90        This method is called by the MultiTrigger to get information about new trigger events that need to be looked at.
91
92        In this implementation we iterate through all possible objects and check whether the fact that they are in range or not has changed and fire and hand a state ofer to the MultiTrigger if so.
93    @return
94        Returns a pointer to a queue of MultiTriggerState pointers, containing all the necessary information to decide whether these states should indeed become new states of the MultiTrigger.
95    */
96    std::queue<MultiTriggerState*>* DistanceMultiTrigger::letTrigger(void)
97    {
98
99        std::queue<MultiTriggerState*>* queue = nullptr;
100
101        // Check for objects that were in range but no longer are. Iterate through all objects, that are in range.
102        for(std::set<WeakPtr<WorldEntity>>::iterator it = this->range_.begin(); it != this->range_.end(); )
103        {
104            WorldEntity* entity = *it;
105
106            // If the entity no longer exists.
107            if(entity == nullptr)
108            {
109                this->range_.erase(it++);
110                continue;
111            }
112
113            Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
114            // If the object is no longer in range.
115            if (distanceVec.length() > this->distance_)
116            {
117                this->range_.erase(it++);
118
119                // If no queue has been created, yet.
120                if(queue == nullptr)
121                    queue = new std::queue<MultiTriggerState*>();
122
123                // Create a state and append it to the queue.
124                MultiTriggerState* state = new MultiTriggerState;
125                state->bTriggered = false; // Because the entity went out of range.
126                state->originator = entity;
127                queue->push(state);
128            }
129            else
130            {
131                ++it;
132            }
133        }
134
135        // Check for new objects that are in range
136        ClassTreeMask targetMask = this->getTargetMask();
137        // If we are in identify-mode another target mask has to be applies to find the DistanceTriggerBeacons.
138        if(this->beaconMode_ == DistanceMultiTriggerBeaconMode::identify)
139            targetMask = this->beaconMask_;
140
141        // Iterate through all objects that are targets of the DistanceMultiTrigger.
142        for(ClassTreeMaskObjectIterator it = targetMask.begin(); it != targetMask.end(); ++it)
143        {
144            WorldEntity* entity = static_cast<WorldEntity*>(*it);
145
146            // If the DistanceMultiTrigger is in identify-mode and the DistanceTriggerBeacon attached to the object has the wrong name we ignore it.
147            if(this->beaconMode_ == DistanceMultiTriggerBeaconMode::identify)
148            {
149                if(entity->getName() != this->targetName_)
150                    continue;
151                // If the object, the DistanceTriggerBeacon is attached to, is not a target of this DistanceMultiTrigger.
152                else if(this->getTargetMask().isExcluded(entity->getParent()->getIdentifier()))
153                    continue;
154            }
155           
156            // If the DistanceMultiTrigger is in exclude mode and the DistanceTriggerBeacon attached to the object has the right name, we ignore it.
157            if(this->beaconMode_ == DistanceMultiTriggerBeaconMode::exclude)
158            {
159               
160                const std::set<WorldEntity*> attachedObjects = entity->getAttachedObjects();
161                bool found = false;
162                for(WorldEntity* attachedObject : attachedObjects)
163                {
164                    if(attachedObject->isA(ClassIdentifier<DistanceTriggerBeacon>::getIdentifier()) && static_cast<DistanceTriggerBeacon*>(attachedObject)->getName() == this->targetName_)
165                    {
166                        found = true;
167                        break;
168                    }
169                }
170                if(found)
171                    continue;
172            }
173
174            Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
175            // If the object is in range.
176            if (distanceVec.length() <= this->distance_)
177            {
178                // Add the object to the objects that are in range.
179                // Objects that already are in range are not added twice, because in a map (this->range_) each key can only exist once and thus addToRange() will reject all attempts of duplicate entries.
180                if(!this->addToRange(entity))
181                    continue;
182
183                // Change the entity to the parent of the DistanceTriggerBeacon (if in identify-mode), which is the entity to which the beacon is attached.
184                if(this->beaconMode_ == DistanceMultiTriggerBeaconMode::identify)
185                    entity = entity->getParent();
186
187                // If no queue has been created, yet.
188                if(queue == nullptr)
189                    queue = new std::queue<MultiTriggerState*>();
190
191                // Create a state and append it to the queue.
192                MultiTriggerState* state = new MultiTriggerState;
193                state->bTriggered = true; // Because the entity came into range.
194                state->originator = entity;
195                queue->push(state);
196            }
197        }
198
199        return queue;
200    }
201   
202    /**
203    @brief
204        Set the beacon mode.
205    @param mode
206        The mode as an enum.
207    */
208    void DistanceMultiTrigger::setBeaconModeDirect(DistanceMultiTriggerBeaconMode mode)
209    {
210        this->beaconMode_ = mode;
211    }
212   
213    /**
214    @brief
215        Get the beacon mode.
216    @return
217        Returns the mode as a string.
218    */
219    const std::string& DistanceMultiTrigger::getBeaconMode(void) const
220    {
221        switch(this->getBeaconModeDirect())
222        {
223            case DistanceMultiTriggerBeaconMode::off :
224                return DistanceMultiTrigger::beaconModeOff_s;
225            case DistanceMultiTriggerBeaconMode::identify:
226                return DistanceMultiTrigger::beaconModeIdentify_s;
227            case DistanceMultiTriggerBeaconMode::exclude:
228                return DistanceMultiTrigger::beaconModeExlcude_s;
229            default :
230                assert(0); // This is impossible.
231                return BLANKSTRING;
232        }
233    }
234   
235    /**
236    @brief
237        Set the beacon mode.
238    @param mode
239        The mode as a string.
240    */
241    void DistanceMultiTrigger::setBeaconMode(const std::string& mode)
242    {
243        if(mode == DistanceMultiTrigger::beaconModeOff_s)
244            this->setBeaconModeDirect(DistanceMultiTriggerBeaconMode::off);
245        else if(mode == DistanceMultiTrigger::beaconModeIdentify_s)
246            this->setBeaconModeDirect(DistanceMultiTriggerBeaconMode::identify);
247        else if(mode == DistanceMultiTrigger::beaconModeExlcude_s)
248            this->setBeaconModeDirect(DistanceMultiTriggerBeaconMode::exclude);
249        else
250            orxout(internal_error, context::triggers) << "Invalid beacon mode in DistanceMultiTrigger." << endl;
251    }
252
253    /**
254    @brief
255        Add a given entity to the entities, that currently are in range of the DistanceMultiTrigger.
256    @param entity
257        A pointer to the entity.
258    @return
259        Returns true if successful, false if not.
260    */
261    bool DistanceMultiTrigger::addToRange(WorldEntity* entity)
262    {
263        std::pair<std::set<WeakPtr<WorldEntity>>::iterator, bool> pair = this->range_.insert(entity);
264        return pair.second;
265    }
266}
Note: See TracBrowser for help on using the repository browser.