Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 6853


Ignore:
Timestamp:
May 3, 2010, 11:52:07 PM (14 years ago)
Author:
dafrick
Message:

Started documenting, also changed some of the implementation to avoid possible bugs.

Location:
code/trunk/src/modules/objects/triggers
Files:
2 edited

Legend:

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

    r6851 r6853  
    3636namespace orxonox
    3737{
    38    
     38
     39    // Initialization of some static (magic) variables.
    3940    /*static*/ const int MultiTrigger::INF_s = -1;
    4041    /*static*/ const std::string MultiTrigger::or_s = "or";
     
    4344   
    4445    CreateFactory(MultiTrigger);
    45    
     46
     47    /**
     48    @brief
     49        Constructor. Registers the objects and initializes default values.
     50    @param creator
     51        The creator.
     52    */
    4653    //TODO: Clean up.
    4754    MultiTrigger::MultiTrigger(BaseObject* creator) : StaticEntity(creator)
    4855    {
    4956        RegisterObject(MultiTrigger);
     57
     58        this->bFirstTick_ = true;
    5059       
    5160        this->mode_ = MultiTriggerMode::EventTriggerAND;
    52 
    53         this->bFirstTick_ = true;
    5461
    5562        this->bInvertMode_ = false;
     
    6673    }
    6774   
    68     //TODO: Document
     75    /**
     76    @brief
     77        Destructor. Cleans up the state queue.
     78    */
    6979    MultiTrigger::~MultiTrigger()
    7080    {
     
    7686            delete state;
    7787        }
    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    */
    81109    void MultiTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
    82110    {
     
    92120        XMLPortParamLoadOnly(MultiTrigger, "target", addTargets, xmlelement, mode).defaultValues("ControllableEntity"); //TODO: Remove load only
    93121
     122        //TODO: Maybe nicer with explicit subgroup, e.g. triggers
    94123        XMLPortObject(MultiTrigger, MultiTrigger, "", addTrigger, getTrigger, xmlelement, mode);
    95124       
     
    97126    }
    98127   
    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    */
    100135    void MultiTrigger::tick(float dt)
    101136    {
    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_)
    103140        {
    104141            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()!)
    109146        if (!this->BaseObject::isActive())
    110147            return;
    111148
    112149        SUPER(MultiTrigger, tick, dt);
    113        
     150
     151        // Let the MultiTrigger return the states that trigger and process the new states if there are any.
    114152        std::queue<MultiTriggerState*>* queue  = this->letTrigger();
    115        
    116153        if(queue != NULL)
    117154        {
     
    120157                //TODO: Be more efficient, Don't delete a state and create a new one immediately after that. Reuse!
    121158                MultiTriggerState* state = queue->front();
     159                // If the state is NULL. (This really shouldn't happen)
    122160                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.
    125168                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))
    127173                    this->addState(bTriggered, state->originator);
     174               
    128175                queue->pop();
    129176                delete state;
    130177            }
    131178            delete queue;
    132         }       
    133 
     179        }
     180
     181        // Go through the state queue.
    134182        if (this->stateQueue_.size() > 0)
    135183        {
    136184            MultiTriggerState* state;
    137185            float timeRemaining;
     186           
     187            // Go through all pending states.
    138188            for(int size = this->stateQueue_.size(); size >= 1; size--)
    139189            {
    140190                timeRemaining = this->stateQueue_.front().first;
    141191                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.
    142194                if(timeRemaining <= dt)
    143195                {
     196                    // If the maximum number of objects simultaniously triggering this MultiTrigger is not exceeded.
    144197                    if(this->maxNumSimultaniousTriggerers_ == INF_s || this->triggered_.size() < (unsigned int)this->maxNumSimultaniousTriggerers_)
    145198                    {
    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))
    148202                        {
    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;
    150215                        }
    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))
    153219                        {
    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                            }
    155256                        }
    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_)
    159264                        {
    160                             this->active_.insert(state->originator);
     265                            this->destroy();
    161266                        }
    162                         // Remove the originator from the objects activating this MultiTrigger.
    163                         else
    164                         {
    165                             this->active_.erase(state->originator);
    166                         }
    167                        
    168                         // Fire the event.
    169                         this->fire(state->bActive, state->originator);
    170267                    }
    171268                   
    172269                    // Remove the state from the state queue.
    173270                    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;
    175271                    delete state;
    176272                    size -= 1;
    177273                }
     274                // If the remaining time has not yet expired. Decrement the remainig time.
    178275                else
    179276                {
    180277                    this->stateQueue_.push_back(std::pair<float, MultiTriggerState*>(timeRemaining-dt, state));
    181278                    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;
    183279                }
    184280            }
     
    318414            bActive = this->isActive(originator);
    319415        }
    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         else
    328         {
    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;
    336416       
    337417        // Create state.
  • code/trunk/src/modules/objects/triggers/MultiTrigger.h

    r6851 r6853  
    4343namespace orxonox
    4444{
    45    
     45
     46    //! The different modes the MultiTrigger can be in.
    4647    namespace MultiTriggerMode
    4748    {
     
    5354        };
    5455    }
    55    
     56
     57    //! Struct to handle MultiTrigger states internally.
    5658    struct MultiTriggerState
    5759    {
     
    6466    @brief
    6567        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
    6685    */
    6786    class _ObjectsExport MultiTrigger : public StaticEntity, public Tickable
    6887    {
    6988        public:
    70             MultiTrigger(BaseObject* creator);
    71             ~MultiTrigger();
     89            MultiTrigger(BaseObject* creator); //!< Constructor. Registers the objects and initializes default values.
     90            ~MultiTrigger(); //!< Destructor.
    7291           
    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.
    7594           
    7695            bool isActive(BaseObject* triggerer = NULL);
Note: See TracChangeset for help on using the changeset viewer.