Changeset 8213 for code/trunk/src/modules/objects/triggers/Trigger.cc
- Timestamp:
- Apr 9, 2011, 3:33:06 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk/src/modules/objects/triggers/Trigger.cc
r7601 r8213 39 39 #include "core/XMLPort.h" 40 40 #include "core/command/ConsoleCommand.h" 41 41 42 #include "Scene.h" 42 43 … … 44 45 { 45 46 46 SetConsoleCommand("Trigger", "debugFlares", &Trigger::debugFlares).defaultValues(false); 47 48 CreateFactory(Trigger); 49 50 Trigger::Trigger(BaseObject* creator) : TriggerBase(creator) 51 { 52 RegisterObject(Trigger); 53 54 this->bActive_ = false; 55 this->bTriggered_ = false; 56 this->latestState_ = 0x0; 57 58 this->remainingTime_ = 0.0f; 59 this->timeSinceLastEvent_ = 0.0f; 60 61 // this->bUpdating_ = false; 62 63 if (this->getScene() && GameMode::showsGraphics()) 64 { 65 this->debugBillboard_.setBillboardSet(this->getScene()->getSceneManager(), "Examples/Flare", ColourValue(1.0, 0.0, 0.0), 1); 66 this->debugBillboard_.setVisible(false); 67 68 if (this->debugBillboard_.getBillboardSet()) 69 this->attachOgreObject(this->debugBillboard_.getBillboardSet()); 70 } 71 72 this->setSyncMode(0x0); 73 } 74 75 Trigger::~Trigger() 76 { 77 } 78 79 void Trigger::XMLPort(Element& xmlelement, XMLPort::Mode mode) 80 { 81 SUPER(Trigger, XMLPort, xmlelement, mode); 82 } 83 84 void Trigger::tick(float dt) 85 { 86 if(this->bFirstTick_) 87 { 88 this->bFirstTick_ = false; 89 this->triggered(false); 90 } 91 92 // Check if the object is active (this is NOT Trigger::isActive()!) 93 if (!this->BaseObject::isActive()) 94 return; 95 96 SUPER(Trigger, tick, dt); 97 98 bool newTriggered = this->isTriggered() ^ this->getInvert(); 99 100 // check if new triggering event is really new 101 if ((this->latestState_ & 0x1) != newTriggered) 102 { 103 // create new state 104 if (newTriggered) 105 { 106 this->latestState_ |= 1; // set trigger bit to 1 107 this->switchState(); 108 } 109 else 110 { 111 this->latestState_ &= 0xFE; // set trigger bit to 0 112 if (!this->getSwitch()) 113 this->switchState(); 114 } 115 } 116 117 if (this->remainingTime_ > 0.0) 118 { 119 this->remainingTime_ -= dt; 120 // only increase when acctually waiting for a state in the queue 121 if (this->timeSinceLastEvent_ >= 0.0) 122 this->timeSinceLastEvent_ += dt; 123 } 124 125 while (this->remainingTime_ <= 0.0 && this->stateChanges_.size() > 0) 126 { 127 // time ran out, change state to new one 128 char newState = this->stateChanges_.front().second; 129 this->bTriggered_ = (newState & 0x1); 130 this->bActive_ = newState & 2; 131 this->triggered(this->bActive_); 132 this->stateChanges_.pop(); 133 if (this->stateChanges_.size() != 0) 134 this->remainingTime_ = this->stateChanges_.front().first; 135 else 47 SetConsoleCommand("Trigger", "debugFlares", &Trigger::debugFlares).defaultValues(false); 48 49 CreateFactory(Trigger); 50 51 /** 52 @brief 53 Constructor. Registers and initializes the object. 54 @param creator 55 The creator of the Trigger. 56 */ 57 Trigger::Trigger(BaseObject* creator) : TriggerBase(creator) 58 { 59 RegisterObject(Trigger); 60 61 this->bActive_ = false; 62 this->bTriggered_ = false; 63 this->latestState_ = 0x0; 64 65 this->remainingTime_ = 0.0f; 66 this->timeSinceLastEvent_ = 0.0f; 67 68 // Set the debug billboard. 69 if (this->getScene() && GameMode::showsGraphics()) 70 { 71 this->debugBillboard_.setBillboardSet(this->getScene()->getSceneManager(), "Examples/Flare", ColourValue(1.0, 0.0, 0.0), 1); 72 this->debugBillboard_.setVisible(false); 73 74 if (this->debugBillboard_.getBillboardSet()) 75 this->attachOgreObject(this->debugBillboard_.getBillboardSet()); 76 } 77 78 this->setSyncMode(0x0); 79 } 80 81 /** 82 @brief 83 Destructor. 84 */ 85 Trigger::~Trigger() 86 { 87 88 } 89 90 /** 91 @brief 92 Method for creating a Trigger object through XML. 93 */ 94 void Trigger::XMLPort(Element& xmlelement, XMLPort::Mode mode) 95 { 96 SUPER(Trigger, XMLPort, xmlelement, mode); 97 } 98 99 /** 100 @brief 101 102 @param dt 103 The time elapsed since last tick. 104 */ 105 void Trigger::tick(float dt) 106 { 107 // If this is the first tick, announce, that the trigger is not triggered. 108 // This is needed, e.g. for an inverted trigger, that needs to announce at the beginning, that it is active. 109 if (this->bFirstTick_) 110 { 111 this->bFirstTick_ = false; 112 this->triggered(false); 113 } 114 115 // Check if the object is active (this is NOT Trigger::isActive()!) 116 // If the object is not active we do nothing. 117 if (!this->BaseObject::isActive()) 118 return; 119 120 SUPER(Trigger, tick, dt); 121 122 // Apply the invert operation. 123 bool newTriggered = this->isTriggered() ^ this->getInvert(); 124 125 // Check if new triggering event is really new. (i.e. if the previous triggering state is not the same as the current) 126 if ((this->latestState_ & 0x1) != newTriggered) 127 { 128 // Create new state 129 if (newTriggered) 130 { 131 this->latestState_ |= 1; // Set triggered bit to 1. 132 this->switchState(); // Toggle the activity of the trigger. 133 } 134 else 135 { 136 this->latestState_ &= 0xFE; // Set triggered bit to 0. 137 // If this trigger is not in switched-mode (i.e. it switches its activity only if it changes from not triggered to triggered and not the other way around), the activity of the trigger is toggled. 138 if (!this->getSwitch()) 139 this->switchState(); 140 } 141 } 142 143 // If there is time remaining, i.e. there are states in the queue waiting to take effect. 144 if (this->remainingTime_ > 0.0) 145 { 146 // Discount the last tick time from the time remaining. 147 this->remainingTime_ -= dt; 148 // Increase the time since the last event (the time since the last state took effect), but only when actually waiting for a state in the queue 149 if (this->timeSinceLastEvent_ >= 0.0) 150 this->timeSinceLastEvent_ += dt; 151 } 152 153 // If the remaining time has run out and there are states in the queue waiting to take effect. 154 while (this->remainingTime_ <= 0.0 && this->stateChanges_.size() > 0) 155 { 156 // Get the state to take effect and apply it. 157 char newState = this->stateChanges_.front().second; 158 this->bTriggered_ = (newState & 0x1); 159 this->bActive_ = newState & 0x2; 160 161 // Fire a triggered (or un-triggered, depending on the activity) event. 162 this->triggered(this->bActive_); 163 164 // Remove the state that was just applied from the queue. 165 this->stateChanges_.pop(); 166 167 // If there are still states in the queue, set the remaining time to the time of the next state to take effect. 168 if (this->stateChanges_.size() != 0) 169 this->remainingTime_ = this->stateChanges_.front().first; 170 // Else the time since the last event is set to the delay. 171 else 172 this->timeSinceLastEvent_ = this->getDelay(); 173 } 174 175 // Set the color of the debug billboard according to the current state of the trigger. 176 if (this->bTriggered_ && this->bActive_) 177 this->setBillboardColour(ColourValue(0.5, 1.0, 0.0)); 178 else if (!this->bTriggered_ && this->bActive_) 179 this->setBillboardColour(ColourValue(0.0, 1.0, 0.0)); 180 else if (this->bTriggered_ && !this->bActive_) 181 this->setBillboardColour(ColourValue(1.0, 0.5, 0.0)); 182 else 183 this->setBillboardColour(ColourValue(1.0, 0.0, 0.0)); 184 } 185 186 /** 187 @brief 188 Fires an event with the input triggered state. 189 @param bIsTriggered 190 The triggered state. 191 */ 192 void Trigger::triggered(bool bIsTriggered) 193 { 194 this->fireEvent(bIsTriggered); 195 } 196 197 /** 198 @brief 199 Check whether the Trigger should be triggered, given only its sub-triggers, given a specific mode. 200 @param mode 201 The Trigger mode. Specifies how the sub-triggers are combined and how they affect the Trigger. 202 @return 203 Returns true if the Trigger should be triggered and false if not. 204 */ 205 bool Trigger::isTriggered(TriggerMode::Value mode) 206 { 207 // If the trigger has sub-triggers. 208 if (this->children_.size() > 0) 209 { 210 switch (mode) 211 { 212 case TriggerMode::EventTriggerAND: 213 return checkAnd(); 214 case TriggerMode::EventTriggerOR: 215 return checkOr(); 216 case TriggerMode::EventTriggerXOR: 217 return checkXor(); 218 default: 219 return false; 220 } 221 } 222 // If the trigger has no sub-triggers, whether it is triggered should only depend on itself and nothing else, thus this returns true. 223 return true; 224 } 225 226 /** 227 @brief 228 Check whether all the sub-triggers of this Trigger are active. 229 This is in fact the conjunction (logical AND) of the activity of all its sub-triggers. 230 @return 231 Returns true if all the sub-triggers of this Trigger are active, false if at least one of them is not active. 232 */ 233 bool Trigger::checkAnd() 234 { 235 // Iterate over all sub-triggers. 236 for (std::set<TriggerBase*>::iterator it = this->children_.begin(); it != this->children_.end(); ++it) 237 { 238 if (!(*it)->isActive()) 239 return false; 240 } 241 return true; 242 } 243 244 /** 245 @brief 246 Check whether at least one of the sub-triggers of this Trigger is active. 247 This is in fact the disjunction (logical OR) of the activity of all its sub-triggers. 248 @return 249 Returns true if at least one of the sub-triggers of this Trigger is active, false if none of them is active. 250 */ 251 bool Trigger::checkOr() 252 { 253 // Iterate over all sub-triggers. 254 for (std::set<TriggerBase*>::iterator it = this->children_.begin(); it != this->children_.end(); ++it) 255 { 256 if ((*it)->isActive()) 257 return true; 258 } 259 return false; 260 } 261 262 /** 263 @brief 264 Check whether exactly one of the sub-triggers of this Trigger is active. 265 This is in fact the logical XOR of the activity of all its sub-triggers. 266 @return 267 Returns true if exactly one of the sub-triggers of this Trigger is active, false if none of them or two or more of them are active. 268 */ 269 bool Trigger::checkXor() 270 { 271 bool test = false; 272 for (std::set<TriggerBase*>::iterator it = this->children_.begin(); it != this->children_.end(); ++it) 273 { 274 if (test && (*it)->isActive()) 275 return false; 276 if ((*it)->isActive()) 277 test = true; 278 } 279 return test; 280 } 281 282 /** 283 @brief 284 Switch (toggle) the activity of the Trigger. 285 @return 286 Returns true if the activity of the Trigger has changed. False if not. 287 */ 288 bool Trigger::switchState() 289 { 290 // If the previous state was active and there are no remaining activations, but the trigger stays active. 291 // or if the previous state was inactive and there are no remaining activations. 292 // the activity is not switched. 293 if (( (this->latestState_ & 0x2) && this->getStayActive() && (this->remainingActivations_ <= 0)) 294 || (!(this->latestState_ & 0x2) && (this->remainingActivations_ == 0))) 295 return false; 296 // Else the activity is switched. 297 else 298 { 299 this->latestState_ ^= 0x2; // Toggle activity bit. 300 301 // If the activity has switched to active, decrease the remaining activations. 302 if (this->latestState_ & 0x2 && this->remainingActivations_ > 0) 303 this->remainingActivations_--; 304 305 // Store the new state in the queue. 306 this->storeState(); 307 308 return true; 309 } 310 } 311 312 /** 313 @brief 314 Stores the state in the queue. 315 The queue is a list of states that are waiting to take effect paired with the time it has to wait after its preceding state takes effect. 316 */ 317 void Trigger::storeState() 318 { 319 // Put the state change into the queue. 320 this->stateChanges_.push(std::pair<float, char>(this->timeSinceLastEvent_, this->latestState_)); 321 // Reset time since last event 322 this->timeSinceLastEvent_ = 0.0; 323 324 // If there is just one state in the queue. (i.e. the one that we just added), The remaining time is set to the time it takes for the next state to take effect. 325 if (this->stateChanges_.size() == 1) 326 this->remainingTime_ = this->stateChanges_.front().first; 327 } 328 329 /** 330 @brief 331 React to a change in delay. 332 Only newly arriving states are affected by a change in delay. 333 */ 334 void Trigger::delayChanged(void) 335 { 136 336 this->timeSinceLastEvent_ = this->getDelay(); 137 337 } 138 338 139 if (this->bTriggered_ && this->bActive_) 140 this->setBillboardColour(ColourValue(0.5, 1.0, 0.0)); 141 else if (!this->bTriggered_ && this->bActive_) 142 this->setBillboardColour(ColourValue(0.0, 1.0, 0.0)); 143 else if (this->bTriggered_ && !this->bActive_) 144 this->setBillboardColour(ColourValue(1.0, 0.5, 0.0)); 145 else 146 this->setBillboardColour(ColourValue(1.0, 0.0, 0.0)); 147 } 148 149 void Trigger::triggered(bool bIsTriggered) 150 { 151 this->fireEvent(bIsTriggered); 152 } 153 154 bool Trigger::isTriggered(TriggerMode::Value mode) 155 { 156 // if (this->bUpdating_) 157 // return this->bTriggered_; 158 159 // this->bUpdating_ = true; 160 if (this->children_.size() != 0) 161 { 162 bool returnval = false; 163 164 switch (mode) 165 { 166 case TriggerMode::EventTriggerAND: 167 returnval = checkAnd(); 168 break; 169 case TriggerMode::EventTriggerOR: 170 returnval = checkOr(); 171 break; 172 case TriggerMode::EventTriggerXOR: 173 returnval = checkXor(); 174 break; 175 default: 176 returnval = false; 177 break; 178 } 179 // this->bUpdating_ = false; 180 181 return returnval; 182 } 183 return true; 184 } 185 186 bool Trigger::checkAnd() 187 { 188 std::set<TriggerBase*>::iterator it; 189 for(it = this->children_.begin(); it != this->children_.end(); ++it) 190 { 191 if (!(*it)->isActive()) 192 return false; 193 } 194 return true; 195 } 196 197 bool Trigger::checkOr() 198 { 199 std::set<TriggerBase*>::iterator it; 200 for(it = this->children_.begin(); it != this->children_.end(); ++it) 201 { 202 if ((*it)->isActive()) 203 return true; 204 } 205 return false; 206 } 207 208 bool Trigger::checkXor() 209 { 210 std::set<TriggerBase*>::iterator it; 211 bool test = false; 212 for(it = this->children_.begin(); it != this->children_.end(); ++it) 213 { 214 if (test && (*it)->isActive()) 215 return false; 216 if ((*it)->isActive()) 217 test = true; 218 } 219 return test; 220 } 221 222 bool Trigger::switchState() 223 { 224 if (( (this->latestState_ & 2) && this->getStayActive() && (this->remainingActivations_ <= 0)) 225 || (!(this->latestState_ & 2) && (this->remainingActivations_ == 0))) 226 return false; 227 else 228 { 229 this->latestState_ ^= 2; // toggle state bit 230 231 // increase activation count 232 if (this->latestState_ & 2 && this->remainingActivations_ > 0) 233 this->remainingActivations_--; 234 235 this->storeState(); 236 237 return true; 238 } 239 } 240 241 void Trigger::storeState() 242 { 243 // put state change into queue 244 this->stateChanges_.push(std::pair<float, char>(this->timeSinceLastEvent_, this->latestState_)); 245 // reset time since last event 246 this->timeSinceLastEvent_ = 0.0; 247 248 if (this->stateChanges_.size() == 1) 249 this->remainingTime_ = this->stateChanges_.front().first; 250 } 251 252 void Trigger::delayChanged(void) 253 { 254 this->timeSinceLastEvent_ = this->getDelay(); 255 } 256 257 void Trigger::debugFlares(bool bVisible) 258 { 259 for (ObjectList<Trigger>::iterator it = ObjectList<Trigger>::begin(); it != ObjectList<Trigger>::end(); ++it) 260 it->setVisible(bVisible); 261 } 262 263 void Trigger::setBillboardColour(const ColourValue& colour) 264 { 265 this->debugBillboard_.setColour(colour); 266 } 267 268 void Trigger::changedVisibility() 269 { 270 SUPER(Trigger, changedVisibility); 271 272 this->debugBillboard_.setVisible(this->isVisible()); 273 } 339 /** 340 @brief 341 Set the visibility of all debug billboards of all Triggers. 342 @param bVisible 343 The visibility the billboards are set to. 344 */ 345 void Trigger::debugFlares(bool bVisible) 346 { 347 // Iterate over all Triggers. 348 for (ObjectList<Trigger>::iterator it = ObjectList<Trigger>::begin(); it != ObjectList<Trigger>::end(); ++it) 349 it->setVisible(bVisible); 350 } 351 352 /** 353 @brief 354 Set the colour of the debug billboard. 355 @param colour 356 The colour the billboard is set to. 357 */ 358 void Trigger::setBillboardColour(const ColourValue& colour) 359 { 360 this->debugBillboard_.setColour(colour); 361 } 362 363 /** 364 @brief 365 React to a change of visibility of the trigger by adjusting the visibility of the debug billboards. 366 */ 367 void Trigger::changedVisibility() 368 { 369 SUPER(Trigger, changedVisibility); 370 371 this->debugBillboard_.setVisible(this->isVisible()); 372 } 274 373 }
Note: See TracChangeset
for help on using the changeset viewer.