Changeset 6853 for code/trunk
- Timestamp:
- May 3, 2010, 11:52:07 PM (15 years ago)
- Location:
- code/trunk/src/modules/objects/triggers
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk/src/modules/objects/triggers/MultiTrigger.cc
r6851 r6853 36 36 namespace orxonox 37 37 { 38 38 39 // Initialization of some static (magic) variables. 39 40 /*static*/ const int MultiTrigger::INF_s = -1; 40 41 /*static*/ const std::string MultiTrigger::or_s = "or"; … … 43 44 44 45 CreateFactory(MultiTrigger); 45 46 47 /** 48 @brief 49 Constructor. Registers the objects and initializes default values. 50 @param creator 51 The creator. 52 */ 46 53 //TODO: Clean up. 47 54 MultiTrigger::MultiTrigger(BaseObject* creator) : StaticEntity(creator) 48 55 { 49 56 RegisterObject(MultiTrigger); 57 58 this->bFirstTick_ = true; 50 59 51 60 this->mode_ = MultiTriggerMode::EventTriggerAND; 52 53 this->bFirstTick_ = true;54 61 55 62 this->bInvertMode_ = false; … … 66 73 } 67 74 68 //TODO: Document 75 /** 76 @brief 77 Destructor. Cleans up the state queue. 78 */ 69 79 MultiTrigger::~MultiTrigger() 70 80 { … … 76 86 delete state; 77 87 } 78 } 79 80 //TODO: Document. 88 89 // Destroying the appended triggers 90 for(std::set<MultiTrigger*>::iterator it = this->children_.begin(); it != this->children_.end(); it++) 91 { 92 (*it)->destroy(); 93 } 94 this->children_.clear(); 95 96 // Telling everyone, that this trigger is gone. 97 for(std::set<BaseObject*>::iterator it = this->active_.begin(); it != this->active_.end(); it++) 98 { 99 this->fire(false, *it); 100 } 101 this->active_.clear(); 102 } 103 104 /** 105 @brief 106 Method for creating a MultiTrigger object through XML. 107 For a detailed description of the parameters please see the class description in the header file. 108 */ 81 109 void MultiTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode) 82 110 { … … 92 120 XMLPortParamLoadOnly(MultiTrigger, "target", addTargets, xmlelement, mode).defaultValues("ControllableEntity"); //TODO: Remove load only 93 121 122 //TODO: Maybe nicer with explicit subgroup, e.g. triggers 94 123 XMLPortObject(MultiTrigger, MultiTrigger, "", addTrigger, getTrigger, xmlelement, mode); 95 124 … … 97 126 } 98 127 99 //TODO: Document 128 129 /** 130 @brief 131 A method that is executed each tick. 132 @param dt 133 The duration of the last tick. 134 */ 100 135 void MultiTrigger::tick(float dt) 101 136 { 102 if(this->bFirstTick_) // If this is the first tick. 137 // If this is the first tick. 138 //TODO: Determine need for this, else kick it out. 139 if(this->bFirstTick_) 103 140 { 104 141 this->bFirstTick_ = false; 105 this->fire(false); //TODO: Does this work? Resp. Is it correct?106 } 107 108 // Check if the object is active (this is NOT Trigger::isActive()!)142 this->fire(false); 143 } 144 145 // Check if the object is active (this is NOT MultiTrigger::isActive()!) 109 146 if (!this->BaseObject::isActive()) 110 147 return; 111 148 112 149 SUPER(MultiTrigger, tick, dt); 113 150 151 // Let the MultiTrigger return the states that trigger and process the new states if there are any. 114 152 std::queue<MultiTriggerState*>* queue = this->letTrigger(); 115 116 153 if(queue != NULL) 117 154 { … … 120 157 //TODO: Be more efficient, Don't delete a state and create a new one immediately after that. Reuse! 121 158 MultiTriggerState* state = queue->front(); 159 // If the state is NULL. (This really shouldn't happen) 122 160 if(state == NULL) 123 break; 124 161 { 162 COUT(1) << "In MultiTrigger '" << this->getName() << "' (&" << this << "), Error: State of new states queue was NULL." << std::endl; 163 queue->pop(); 164 continue; 165 } 166 167 // The new triggered state dependent on the requested state, the mode and the invert-mode. 125 168 bool bTriggered = (state->bTriggered & this->isModeTriggered(state->originator)) ^ this->bInvertMode_; 126 if(bTriggered ^ this->isTriggered(state->originator)) 169 170 // If the 'triggered' state has changed a new state is added to the state queue. 171 //TODO: Do something against flooding, when there is delay. 172 if(this->delay_ != 0.0f || bTriggered ^ this->isTriggered(state->originator)) 127 173 this->addState(bTriggered, state->originator); 174 128 175 queue->pop(); 129 176 delete state; 130 177 } 131 178 delete queue; 132 } 133 179 } 180 181 // Go through the state queue. 134 182 if (this->stateQueue_.size() > 0) 135 183 { 136 184 MultiTriggerState* state; 137 185 float timeRemaining; 186 187 // Go through all pending states. 138 188 for(int size = this->stateQueue_.size(); size >= 1; size--) 139 189 { 140 190 timeRemaining = this->stateQueue_.front().first; 141 191 state = this->stateQueue_.front().second; 192 193 // If the remaining time has expired, the state has to be set as the state of the MultiTrigger. 142 194 if(timeRemaining <= dt) 143 195 { 196 // If the maximum number of objects simultaniously triggering this MultiTrigger is not exceeded. 144 197 if(this->maxNumSimultaniousTriggerers_ == INF_s || this->triggered_.size() < (unsigned int)this->maxNumSimultaniousTriggerers_) 145 198 { 146 // Add the originator to the objects triggering this MultiTrigger. 147 if(state->bTriggered == true) 199 bool bStateChanged = false; 200 // If the 'triggered' state is different form what it is now, change it. 201 if(state->bTriggered ^ this->isTriggered(state->originator)) 148 202 { 149 this->triggered_.insert(state->originator); 203 // Add the originator to the objects triggering this MultiTrigger. 204 if(state->bTriggered == true) 205 { 206 this->triggered_.insert(state->originator); 207 } 208 // Remove the originator from the objects triggering this MultiTrigger. 209 else 210 { 211 this->triggered_.erase(state->originator); 212 } 213 214 bStateChanged = true; 150 215 } 151 // Remove the originator from the objects triggering this MultiTrigger. 152 else 216 217 // If the activity is different from what it is now, change it and fire an Event. 218 if(state->bActive ^ this->isActive(state->originator)) 153 219 { 154 this->triggered_.erase(state->originator); 220 221 bool bFire = true; 222 223 // Add the originator to the objects activating this MultiTrigger. 224 if(state->bActive == true) 225 { 226 if(this->remainingActivations_ != 0) 227 { 228 this->active_.insert(state->originator); 229 if(this->remainingActivations_ != INF_s) 230 this->remainingActivations_--; // Decrement the remaining activations. 231 } 232 else 233 { 234 bFire = false; 235 } 236 } 237 // Remove the originator from the objects activating this MultiTrigger. 238 else 239 { 240 if(!this->bStayActive_ || this->remainingActivations_ != 0) 241 { 242 this->active_.erase(state->originator); 243 } 244 else 245 { 246 bFire = false; 247 } 248 } 249 250 // Fire the Event if the activity has changed. 251 if(bFire) 252 { 253 this->fire(state->bActive, state->originator); 254 bStateChanged = true; 255 } 155 256 } 156 157 // Add the originator to the objects activating this MultiTrigger. 158 if(state->bActive == true) 257 258 // Print some debug output if the state has changed. 259 if(bStateChanged) 260 COUT(4) << "MultiTrigger '" << this->getName() << "' (&" << this << ") changed state. originator: " << state->originator->getIdentifier()->getName() << " (&" << state->originator << "), active: " << state->bActive << ", triggered: " << state->bTriggered << "." << std::endl; 261 262 // If the MultiTrigger has exceeded its amount of activations and it desn't stay active, it has to be destroyed, 263 if(this->remainingActivations_ == 0 && bStateChanged && !state->bActive && !this->bStayActive_) 159 264 { 160 this-> active_.insert(state->originator);265 this->destroy(); 161 266 } 162 // Remove the originator from the objects activating this MultiTrigger.163 else164 {165 this->active_.erase(state->originator);166 }167 168 // Fire the event.169 this->fire(state->bActive, state->originator);170 267 } 171 268 172 269 // Remove the state from the state queue. 173 270 this->stateQueue_.pop_front(); 174 COUT(4) << "MultiTrigger '" << this->getName() << "' &" << this << ": State processed, removing from state queue. originator: " << state->originator->getIdentifier()->getName() << " (&" << state->originator << "), active: " << state->bActive << "|" << this->isActive(state->originator) << ", triggered: " << state->bTriggered << "|" << this->isTriggered(state->originator) << "." << std::endl;175 271 delete state; 176 272 size -= 1; 177 273 } 274 // If the remaining time has not yet expired. Decrement the remainig time. 178 275 else 179 276 { 180 277 this->stateQueue_.push_back(std::pair<float, MultiTriggerState*>(timeRemaining-dt, state)); 181 278 this->stateQueue_.pop_front(); 182 COUT(4) << "MultiTrigger '" << this->getName() << "' &" << this << ": State processed, decreasing time remaining. originator: " << state->originator->getIdentifier()->getName() << " (&" << state->originator << "), active: " << state->bActive << ", triggered: " << state->bTriggered << ", time remaining: " << timeRemaining-dt << "." << std::endl;183 279 } 184 280 } … … 318 414 bActive = this->isActive(originator); 319 415 } 320 // If the state changes to active.321 else if(this->remainingActivations_ != INF_s && bActive)322 {323 if(this->remainingActivations_ == 0)324 return false;325 this->remainingActivations_--;326 }327 else328 {329 // If the MultiTrigger should stay active if there are no more remaining activations.330 //TODO: Find out how this applies to infinitely many activations.331 if(this->bStayActive_ && this->remainingActivations_ == 0)332 return false;333 }334 335 COUT(4) << "MultiTrigger &" << this << ": State added to state queue. originator: " << originator->getIdentifier()->getName() << " (&" << originator << "), active: " << bActive << "|" << this->isActive(originator) << ", triggered: " << bTriggered << "|" << this->isTriggered(originator) << ", remaining activations: " << this->remainingActivations_ << "." << std::endl;336 416 337 417 // Create state. -
code/trunk/src/modules/objects/triggers/MultiTrigger.h
r6851 r6853 43 43 namespace orxonox 44 44 { 45 45 46 //! The different modes the MultiTrigger can be in. 46 47 namespace MultiTriggerMode 47 48 { … … 53 54 }; 54 55 } 55 56 57 //! Struct to handle MultiTrigger states internally. 56 58 struct MultiTriggerState 57 59 { … … 64 66 @brief 65 67 The MultiTrigger class implements a trigger that has a distinct state for each object triggering it. 68 In more detail: A Trigger is an object that can either be active or inactive, whith a specified behaviour how to switch between the two. A MultiTrigger generalizes that behaviour for multiple objects trigggering the trigger. A MultiTrigger can be active or inactive for any object triggering it, with the state for each object being completely independent of the state for other objects. Each time a switch occurs an Event is fired with as the originator a MultiTriggerContainer, containig a pointer to the pointer that caused the Event and a pointer to the object that caused the trigger to change it's activity. 69 70 MultiTriggers also allow for additional complexity which can be added trough the choice of the parameters explained (briefly) below: 71 But first you must understand a small implementational detail. There is a distinction between the MultiTrigger being triggered (there is the state 'triggered' for that) and the MultiTrigger being active (for that is the state 'activity'). From the outside only the activity is visible. The state 'triggered' tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be triggered (or to the outside, active), while it in fact isn't. The standard behaviour is, that the cativity changes, when the MultiTrigger transits from being triggered to not being triggered or the other way around. 72 The parameters are: 73 'delay': The delay is the time that the trigger waits until it reacts (i.e. changes it's state) to the triggering condition being fulfilled. 74 'switch': Switch is a bool, if true the MultiTrigger is in switch-mode, meaning, that the activity changes only when the trigger is triggered , this means, that now the activity only changes, when the trigger changes from not being triggered to being triggered but not the other way around. The default is false. 75 'stayactive': Stay active is also a bool, if true the MultiTrigger stays active after it has been activated as many times as specified by the parameter activations. The default is -1, which is infinity. 76 'activations': The number of activations until the trigger can't be triggered anymore. The default is -1, which is infinity. 77 'invert': Invert is a bool, if true the trigger is in invert-mode, meaning, that if the triggering condition is fulfilled the MultiTrigger will have the state not triggered and and if the condition is not fulfilled it will have the state triggered. In short it just inverts the behaviour of the MultiTrigger. The default is false. 78 'simultaniousTriggerers': The number of simultanious triggerers limits the number of object that are allowed to trigger the MultiTrigger at the same time. Or a little more precisely, the number of distinct objects the MultiTrigger has 'triggered' states for, at each point in time. 79 'mode': The mode describes how the MultiTrigger acts in relation to all the MultiTriggers, that are appended to it. There are 3 modes: 'and', meaning that the MultiTrigger can only be triggered if all the appended MultiTriggers are active. 'or', meaning that the MultiTrigger can only triggered if at least one of the appendend MultiTriggers is active. And 'xor', meaning that the MultiTrigger can only be triggered if one and only one appended MultiTrigger is active. Notice, that I wrote 'can only be active', that implies, that there is an addtitional condition to the activity of the MultiTrigger and that is the fulfillment of the triggering condition (the MultiTrigger itself doesn't have one, but all derived classes should). Also bear in mind, that the activity of a MultiTrigger is still coupled to the object that triggered it. The default is 'and'. 80 'target': The target describes the kind of objects that are allowed to trigger this MultiTrigger. The default is 'ControllableEntity'. 81 Also there is the possibility of appending MultiTriggers to the MultiTrigger just by adding them as subobjects in the XML description of your MultiTrigger. 82 83 @author 84 Damian 'Mozork' Frick 66 85 */ 67 86 class _ObjectsExport MultiTrigger : public StaticEntity, public Tickable 68 87 { 69 88 public: 70 MultiTrigger(BaseObject* creator); 71 ~MultiTrigger(); 89 MultiTrigger(BaseObject* creator); //!< Constructor. Registers the objects and initializes default values. 90 ~MultiTrigger(); //!< Destructor. 72 91 73 virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode); 74 virtual void tick(float dt); 92 virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode); //!< Method for creating a MultiTrigger object through XML. 93 virtual void tick(float dt); //!< A method that is executed each tick. 75 94 76 95 bool isActive(BaseObject* triggerer = NULL);
Note: See TracChangeset
for help on using the changeset viewer.