Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Apr 9, 2011, 3:33:06 PM (13 years ago)
Author:
dafrick
Message:

Adding changes made to DistanceTrigger also in trunk.
Also documenting trigger.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/trunk/src/modules/objects/triggers/Trigger.cc

    r7601 r8213  
    3939#include "core/XMLPort.h"
    4040#include "core/command/ConsoleCommand.h"
     41
    4142#include "Scene.h"
    4243
     
    4445{
    4546
    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    {
    136336        this->timeSinceLastEvent_ = this->getDelay();
    137337    }
    138338
    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    }
    274373}
Note: See TracChangeset for help on using the changeset viewer.