Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 8213


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.

Location:
code/trunk
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • code/trunk/data/levels/fightInOurBack.oxw

    r8079 r8213  
    135135            </events>
    136136            <attached>
    137                 <DistanceTrigger name="FightInOurBack_MainStart_FollowStart" position="0,0,0" distance="50" target="DistanceTriggerBeacon" targetname="PlayerDistanceTrigger" />
     137                <DistanceTrigger name="FightInOurBack_MainStart_FollowStart" position="0,0,0" distance="50" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" />
    138138                <!--<Billboard position="0,0,0" colour="1.0,1.0,1.0" material="Examples/Flare" />-->
    139139            </attached>
     
    153153            <attached>
    154154                <!--<Billboard position="0,0,0" colour="1,1,1" material="Examples/Flare" />-->
    155                 <DistanceTrigger name="FightInOurBack_FollowEnd_DTranspStart_AssisStart" position="0,0,0" distance="1000" target="DistanceTriggerBeacon" targetname="PlayerDistanceTrigger" stayactive=1 activations=1 />
     155                <DistanceTrigger name="FightInOurBack_FollowEnd_DTranspStart_AssisStart" position="0,0,0" distance="1000" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" stayactive=1 activations=1 />
    156156            </attached>
    157157        </QuestEffectBeacon>
     
    316316<!---->
    317317<!--Trigger to activate this Team (TEAM NO 1)-->
    318     <DistanceTrigger name="activateTeam0No1" position="8000,0,3100" distance="1000" target="DistanceTriggerBeacon" targetname="PlayerDistanceTrigger" activations="1" stayactive="true" />
     318    <DistanceTrigger name="activateTeam0No1" position="8000,0,3100" distance="1000" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" activations="1" stayactive="true" />
    319319
    320320<!--TEAM NO 1 (activationType : distance || killing a spaceship what belongs to TEAM 0 NO 0)-->
     
    476476
    477477<Trigger invert=true name="activateFirstSpawnpoint">
    478     <DistanceTrigger name="activateSecondSpawnpoint" position="10000,0,3000" distance="1000" target="DistanceTriggerBeacon" targetname="PlayerDistanceTrigger" activations="1" stayactive="true" />
     478    <DistanceTrigger name="activateSecondSpawnpoint" position="10000,0,3000" distance="1000" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" activations="1" stayactive="true" />
    479479</Trigger>
    480480
  • code/trunk/data/levels/pirateAttack.oxw

    r7679 r8213  
    142142            </events>
    143143            <attached>
    144                 <DistanceTrigger name=questbeacon1 position="0,0,0" distance=100 target=DistanceTriggerBeacon targetname=Me/>
     144                <DistanceTrigger name=questbeacon1 position="0,0,0" distance=100 target="Pawn" beaconMode="identify" targetname=Me/>
    145145            </attached>
    146146            </QuestEffectBeacon>
     
    156156                    <attached>
    157157                        <Billboard position="0,0,0" scale=3 colour="1.0,1.0,0" material="Examples/Flare" />
    158                         <DistanceTrigger name=questbeacon2 targetname=Me position="0,0,0" target=DistanceTriggerBeacon distance=400 />
     158                        <DistanceTrigger name=questbeacon2 targetname=Me position="0,0,0" target="Pawn" beaconMode="identify" distance=400 />
    159159                    </attached>
    160160                    <effects>
     
    171171        <QuestEffectBeacon position="0,0,0" times=1>
    172172                    <attached>
    173                         <DistanceTrigger name=questbeacon3  position="0,0,0" distance=300 target=DistanceTriggerBeacon targetname=Me delay="5" />
     173                        <DistanceTrigger name=questbeacon3  position="0,0,0" distance=300 target="Pawn" beaconMode="identify" targetname=Me delay="5" />
    174174                    </attached>
    175175                    <effects>
     
    188188                    <attached>
    189189                        <Billboard position="0,0,0" scale=3 colour="0,1.0,0" material="Examples/Flare" />
    190                         <DistanceTrigger name=questbeacon4  position="0,0,0" distance=200 target=DistanceTriggerBeacon targetname=Me />
     190                        <DistanceTrigger name=questbeacon4  position="0,0,0" distance=200 target="Pawn" beaconMode="identify" targetname=Me />
    191191                    </attached>
    192192   
     
    207207        <QuestEffectBeacon position="7600,300,-8000" times=1>
    208208                    <attached>
    209                         <DistanceTrigger name=questbeacon5  position="0,0,0" distance=300 target=DistanceTriggerBeacon targetname=Me />
     209                        <DistanceTrigger name=questbeacon5  position="0,0,0" distance=300 target="Pawn" beaconMode="identify" targetname=Me />
    210210                    </attached>
    211211                    <effects>
     
    222222        <QuestEffectBeacon position="1600,2300,-10000" times=1>
    223223                    <attached>
    224                         <DistanceTrigger name=questbeacon8  position="0,0,0" distance=300 target=DistanceTriggerBeacon targetname=Me />
     224                        <DistanceTrigger name=questbeacon8  position="0,0,0" distance=300 target="Pawn" beaconMode="identify" targetname=Me />
    225225                    </attached>
    226226                    <effects>
     
    237237        <QuestEffectBeacon position="4600,5300,-11000" times=1>
    238238                    <attached>
    239                         <DistanceTrigger name=questbeacon6  position="0,0,0" distance=600 target=DistanceTriggerBeacon targetname=Me />
     239                        <DistanceTrigger name=questbeacon6  position="0,0,0" distance=600 target="Pawn" beaconMode="identify" targetname=Me />
    240240                    </attached>
    241241                    <effects>
     
    255255        <QuestEffectBeacon position="4800,5785,-10725" times=1>
    256256                    <attached>
    257                         <DistanceTrigger name=questbeacon7  position="0,0,0" distance=30 target=DistanceTriggerBeacon targetname=Me />
     257                        <DistanceTrigger name=questbeacon7  position="0,0,0" distance=30 target="Pawn" beaconMode="identify" targetname=Me />
    258258                    </attached>
    259259                    <effects>
     
    274274                    <attached>
    275275                        <Billboard position="0,0,0" scale=3 colour="0,0,1.0" material="Examples/Flare" />
    276                         <DistanceTrigger name=questbeacon9 position="0,0,0" distance=500 target=DistanceTriggerBeacon targetname=Me />
     276                        <DistanceTrigger name=questbeacon9 position="0,0,0" distance=500 target="Pawn" beaconMode="identify" targetname=Me />
    277277                    </attached>
    278278                    <effects>
  • code/trunk/data/levels/theTimeMachine.oxw

    r7845 r8213  
    9494   
    9595        <!--TRIGGERS IF THE PLAYERS REACHES THE "TIME MACHINE"-->
    96         <DistanceTrigger name="EnterTimeMachine" position="0,0,0" distance="100" target="DistanceTriggerBeacon" targetname="PlayerDistanceTrigger" >
     96        <DistanceTrigger name="EnterTimeMachine" position="0,0,0" distance="100" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" >
    9797            <attached>
    9898                <Billboard position="0,0,0" material="Examples/Flare" colour="0, 0, 1" scale=1/>
  • code/trunk/doc/api/groups/Triggers.dox

    r8108 r8213  
    77    @defgroup NormalTrigger Trigger
    88    @ingroup Triggers
     9   
     10    @ref orxonox::Trigger "Triggers" are objects which react to certain events by changing their boolean state. That state is the trigger's activity @ref orxonox::Trigger can be either <em>active</em> or <em>not active</em>.
     11   
     12    @section TriggerTechnicalDetails Technical Details
     13    A common @ref orxonox::Trigger "Trigger" is an object that can either be <em>active</em> or <em>inactive</em>, with a specified behavior how to switch between the two. Each time a switch occurs an @ref orxonox::Event "Event" is fired (see the @ref Eventsystem "Eventsystem" for more information about how that works exactly), with th @ref orxonox::Trigger "Trigger" as the originator. This way the entity that reacts to the @ref orxonox::Trigger "Trigger" triggering receives information about the @ref orxonox::Trigger "Trigger" that created the @ref orxonox::Event "Event". If the @ref orxonox::Trigger "Trigger" is also a @ref orxonox::PlayerTrigger "PlayerTrigger", under some conditions, the entity that caused the @ref orxonox::Trigger "Trigger" to trigger can be accessed.
     14
     15    Also, just as with all triggers, @ref orxonox::Trigger "Triggers" can be nested (even with e.g. @ref orxonox::MultiTrigger "MultiTriggers").
     16    @code
     17    <Trigger switch="true" delay="2">
     18        <DistanceTrigger position="100,0,0" distance="80" />
     19        <EventMultiTrigger ... />
     20    </Trigger>
     21    @endcode
     22
     23    @ref orxonox::Trigger "Triggers" also allow for additional complexity which can be added through the choice of the parameters explained below.
     24    But first it is important to understand a small implementation detail. There is a distinction between the @ref orxonox::Trigger "Trigger" being triggered (there is the state <em>triggered</em> for that) and the @ref orxonox::Trigger "Trigger" being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible. The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be <em>active</em> to the outside, while it in fact isn't. The standard behavior is, that the <em>activity</em> changes, when the @ref orxonox::Trigger "Trigger" transits from being <em>triggered</em> to being <em>not triggered</em> or the other way around.
     25
     26    The parameters of the @ref orxonox::Trigger "Trigger" are:
     27    - @b delay The delay is the time in seconds, that the trigger waits until it reacts (i.e. changes it's state) to the triggering condition being fulfilled. Internally this is handled by a state queue coupled with a counter, for each state that is delayed. The state becomes <em>active</em> when the counter runs out. This allows the @ref orxonox::Trigger "Trigger" to work even if the delay changes at runtime. However if the delay changes it only affects newly arriving states not the ones already in the queue. The default is <code>0.0</code>.
     28    - @b switch Switch is a boolean, if <code>true</code> the @ref orxonox::Trigger "Trigger" is in <em>switch-mode</em>, meaning, that the <em>activity</em> changes only when the trigger is <em>triggered</em>, not when it is <em>not triggered</em> (Just like a light switch does). This means, that in <em>switch-mode</em> the <em>activity</em> only changes, when the trigger changes from being <em>not triggered</em> to being <em>triggered</em> but not the other way around. The default is <code>false</code>.
     29    - @b stayActive Stay active is also a boolean, if <code>true</code> the @ref orxonox::Trigger "Trigger" stays active after it has been activated as many times as specified by the parameter <em>activations</em>. In essence this means, that after the last time it is activated it cannot be deactivated. The default is <code>false</code>.
     30    - @b activations Activations is the number of times the @ref orxonox::Trigger "Trigger" can be activated until the trigger can't be triggered anymore. The default is <code>-1</code>, which denotes infinity.
     31    - @b invert Invert is a boolean, if <code>true</code> the @ref orxonox::Trigger "Trigger" is in <em>invert-mode</em>, meaning, that if the triggering condition is fulfilled the @ref orxonox::Trigger "Trigger" will have the state <em>not triggered</em> and and if the condition is not fulfilled it will have the state <em>triggered</em>. In short it inverts the behavior of the @ref orxonox::Trigger "Trigger". The default is <code>false</code>.
     32    - @b mode The mode describes how the @ref orxonox::Trigger "Trigger" acts in relation to all the triggers (its children), that are appended to it. There are 3 modes: <em>and</em>, meaning that the @ref orxonox::Trigger "Trigger" can only be triggered if all the appended triggers are active. <em>or</em>, meaning that the @ref orxonox::Trigger "Trigger" can only be triggered if at least one of the appended triggers is active. And <em>xor</em>, meaning that the @ref orxonox::Trigger "Trigger" can only be triggered if one and only one appended trigger is active. Note, that I wrote 'can only be active', that implies, that there is an additional condition to the <em>activity</em> of the @ref orxonox::Trigger "Trigger" and that is the fulfillment of the triggering condition (the @ref orxonox::Trigger "Trigger" class itself doesn't have one, but all derived classes should). Also bear in mind, that the <em>activity</em> of a @ref orxonox::Trigger "Trigger" is still coupled to the object that triggered it. The default is <em>and</em>.
     33
     34    @subsection Sub-typesOfTriggers Sub-types of Triggers
     35
     36    @subsubsection EventTrigger EventTrigger
     37    An @ref orxonox::EventTrigger "EventTrigger" can either be used to be triggered when an @ref orxonox::Event "Event", that itself is triggering, arrives at its event port.
     38
     39    A common usage could look like this:
     40    @code
     41    <EventTrigger invert="true" delay="1">
     42        <events>
     43            <trigger>
     44                <Trigger ... />
     45                <Trigger ... />
     46            </trigger>
     47        </events>
     48    </EventTrigger>
     49    @endcode
     50
     51    @subsubsection DistanceTrigger DistanceTrigger
     52    The @ref orxonox::DistanceTrigger "DistanceTrigger" is a Trigger that triggers whenever an object (that is of the specified target type) is in a specified range of the @ref orxonox::DistanceTrigger "DistanceTrigger". The object can be specified further by setting the <em>beaconMode</em> and attaching a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" to the object.
     53    Parameters are (additional to the ones of Trigger):
     54    - @b distance Which specifies the maximum distance at which the @ref orxonox::DistanceTrigger "DistanceTrigger" still triggers, i.e. its range. Default is <code>100</code>.
     55    - @b target Which specifies the class of objects that can trigger the @ref orxonox::DistanceTrigger "DistanceTrigger". Default is <code>"Pawn"</code>.
     56    - @b beaconMode Which specifies, whether the @ref orxonox::DistanceTrigger "DistanceTrigger" operates on @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" or not. If <em>off</em> the DistanceMultiTrigger works as usual. If set to <em>identify</em> the @ref orxonox::DistanceTrigger "DistanceTrigger" is only triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. If set to <em>exclude</em> the @ref orxonox::DistanceTrigger "DistanceTrigger" is only triggered by objects that don't have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. Default is <em>off</em>.
     57    - @b targetname Which specifies the name @ref oroxnox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the @ref orxonox::DistanceTrigger "DistanceTrigger" react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
     58
     59    A simple @ref orxonox::DistanceTrigger "DistanceTrigger" could look like this:
     60    @code
     61    <DistanceTrigger position="0,0,0" switch="true" target="Pawn" distance="20" />
     62    @endcode
     63
     64    An implementation that only reacts to objects with a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" attached would look like this:
     65    @code
     66    <DistanceTrigger position="0,0,0" target="Pawn" beaconMode="identify" targetname="beacon1" distance="30" />
     67    @endcode
     68    This particular @ref orxonox::DistanceTrigger "DistanceTrigger" would only react if an object was in range, that had a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the name <em>beacon1</em> attached.
    969
    1070    @defgroup MultiTrigger MultiTrigger
    1171    @ingroup Triggers
    1272
    13     @ref orxonox::MultiTrigger "MultiTriggers" are (as they are @ref orxonox::TriggerBase "Triggers") objects which react to certain events. They offer all the functionality that the common @ref orxonox::Trigger "Triggers" do with one significant difference. The common @ref orxonox::Trigger "Trigger" has just one state, it can either be <em>triggered</em> or <em>not triggered</em>, it doesn't discriminate between who's triggering (or not triggering) it. A @ref orxonox::MultiTrigger "MultiTrigger", on the other hand, has a distinct state (<em>triggered</em> or <em>not triggered</em>) for each entity that is defined as being able to trigger said @ref orxonox::MultiTrigger "MultiTrigger".
     73    @ref orxonox::MultiTrigger "MultiTriggers" are (as they are @ref orxonox::TriggerBase "Triggers") objects which react to certain events. They offer all the functionality that the common @ref orxonox::Trigger "Triggers" do with one significant difference. The common @ref orxonox::Trigger "Trigger" has just one state, it can either be <em>active</em> or <em>not acive</em>, it doesn't discriminate between who's triggering (or not triggering) it. A @ref orxonox::MultiTrigger "MultiTrigger", on the other hand, has a distinct state (<em>active</em> or <em>not actve</em>) for each entity that is defined as being able to trigger said @ref orxonox::MultiTrigger "MultiTrigger".
    1474
    15     This difference becomes significant, when, for example, you want a @ref orxonox::DistanceTrigger "DistanceTrigger" to trigger a @ref orxonox::QuestEffectBeacon "QuestEffectBeacon" to hand out a @ref orxonox::Quest "Quest" to any @ref orxonox::Pawn "Pawn" that enters its range. With a simple @ref orxonox::DistanceTrigger "DistanceTrigger" (as opposed to the more complex @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger") the first @ref orxonox::Pawn "Pawn" to be in range would trigger it an receive the @ref orxonox::Quest "Quest", however if a second @ref orxonox::Pawn "Pawn" would enter the range, while the first @ref orxonox::Pawn "Pawn" still is in the range nothing would happen and even after the first @ref orxonox::Pawn "Pawn" left nothing would happen, since the whole time the @ref orxonox::DistanceTrigger "DistanceTrigger" would just be triggered. In contrast with a @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" the first @ref orxonox::Pawn "Pawn" would enter the range and the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" would have the state <em>triggered</em> for this exact @ref orxonox::Pawn "Pawn" (but for none else) and thus the @ref orxonox::Pawn "Pawn" would receive the @ref orxonox::Quest "Quest" and when the second @ref orxonox::Pawn "Pawn" enters the range the state of the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" for that second @ref orxonox::Pawn "Pawn" would change to <em>triggered</em> and it would receive the @ref orxonox::Quest "Quest" as well.
     75    This difference becomes significant, when, for example, you want a @ref orxonox::DistanceTrigger "DistanceTrigger" to trigger a @ref orxonox::QuestEffectBeacon "QuestEffectBeacon" to hand out a @ref orxonox::Quest "Quest" to any @ref orxonox::Pawn "Pawn" that enters its range. With a simple @ref orxonox::DistanceTrigger "DistanceTrigger" (as opposed to the more complex @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger") the first @ref orxonox::Pawn "Pawn" to be in range would trigger it an receive the @ref orxonox::Quest "Quest", however if a second @ref orxonox::Pawn "Pawn" would enter the range, while the first @ref orxonox::Pawn "Pawn" still is in the range nothing would happen and even after the first @ref orxonox::Pawn "Pawn" left nothing would happen, since the whole time the @ref orxonox::DistanceTrigger "DistanceTrigger" would just be <em>active</em>. In contrast with a @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" the first @ref orxonox::Pawn "Pawn" would enter the range and the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" would have the state <em>active</em> for this exact @ref orxonox::Pawn "Pawn" (but for none else) and thus the @ref orxonox::Pawn "Pawn" would receive the @ref orxonox::Quest "Quest" and when the second @ref orxonox::Pawn "Pawn" enters the range the state of the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" for that second @ref orxonox::Pawn "Pawn" would change to <em>active</em> and it would receive the @ref orxonox::Quest "Quest" as well.
    1676
    1777    @section WhenToUseMultiTriggers When to use MultiTriggers
     
    2080    @section HowToUseMultiTriggers How to use MultiTriggers
    2181    ...
     82   
     83    @section HowToCreateANewMultiTrigger How to create a new MultiTrigger.
     84    ...
    2285
    2386    @section MultiTriggerTechnicalDetails Technical Details
    24     A common @ref orxonox::Trigger "Trigger" is an object that can either be <em>active</em> or <em>inactive</em>, with a specified behavior how to switch between the two. A @ref orxonox::MultiTrigger "MultiTrigger" generalizes that behavior for multiple objects triggering the trigger. A @ref orxonox::MultiTrigger "MultiTrigger" can be <em>active</em> or <em>inactive</em> for any object triggering it, with the state for each object being completely independent of the state for all other objects. Each time a switch occurs an @ref orxonox::Event "Event" is fired, with a @ref orxonox::MultiTriggerContainer "MultiTriggerContainer" as the originator, containing a pointer to the @ref orxonox::MultiTrigger "MultiTrigger" that caused the @ref orxonox::Event "Event" and a pointer to the object that caused the trigger to change it's activity. This way the entity that reacts to the @ref orxonox::MultiTrigger "MultiTrigger" triggering receives the information it needs about the entity that triggered the @ref orxonox::MultiTrigger "MultiTrigger".
     87    A common @ref orxonox::Trigger "Trigger" is an object that can either be <em>active</em> or <em>inactive</em>, with a specified behavior how to switch between the two. A @ref orxonox::MultiTrigger "MultiTrigger" generalizes that behavior for multiple objects triggering the trigger. A @ref orxonox::MultiTrigger "MultiTrigger" can be <em>active</em> or <em>inactive</em> for any object triggering it, with the state for each object being completely independent of the state for all other objects. Each time a switch occurs an @ref orxonox::Event "Event" is fired (see the @ref Eventsystem "Eventsystem" for more information about how that works exactly), with a @ref orxonox::MultiTriggerContainer "MultiTriggerContainer" as the originator, containing a pointer to the @ref orxonox::MultiTrigger "MultiTrigger" that caused the @ref orxonox::Event "Event" and a pointer to the object that caused the trigger to change it's activity. This way the entity that reacts to the @ref orxonox::MultiTrigger "MultiTrigger" triggering receives the information it needs about the entity that triggered the @ref orxonox::MultiTrigger "MultiTrigger".
    2588
    26     Also, just as with all triggers, @ref orxonox::MultiTrigger "MultiTriggers" can be nested (event with triggers other than @ref orxonox::MultiTrigger "MultiTriggers").
     89    Also, just as with all triggers, @ref orxonox::MultiTrigger "MultiTriggers" can be nested (even with triggers other than @ref orxonox::MultiTrigger "MultiTriggers").
    2790    @code
    2891    <MultiTrigger switch="true" delay="2">
     
    3396
    3497    @ref orxonox::MultiTrigger "MultiTriggers" also allow for additional complexity which can be added through the choice of the parameters (some of which are also present in the common @ref orxonox::Trigger "Trigger") explained (briefly) below.
    35     But first it is important to understand a small implementational detail. There is a distinction between the @ref orxonox::MultiTrigger "MultiTrigger" being triggered (there is the state <em>triggered</em> for that) and the @ref orxonox::MultiTrigger "MultiTrigger" being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible (and has above been referred to as <em>triggered</em> for the sake of comprehensibility). The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be <em>triggered</em> to the outside, while it in fact isn't (but it would then be <em>active</em>). The standard behavior is, that the <em>activity</em> changes, when the @ref orxonox::MultiTrigger "MultiTrigger" transits from being triggered to not being triggered or the other way around. So to the inside a @ref orxonox::MultiTrigger "MultiTrigger" being <em>active</em> is synonymous to the @ref orxonox::MultiTrigger "MultiTrigger" being <em>triggered</em> to the outside.
     98    But first it is important to understand a small implementation detail. There is a distinction between the @ref orxonox::MultiTrigger "MultiTrigger" being triggered (there is the state <em>triggered</em> for that) and the @ref orxonox::MultiTrigger "MultiTrigger" being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible. The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be <em>active</em> to the outside, while it in fact isn't. The standard behavior is, that the <em>activity</em> changes, when the @ref orxonox::MultiTrigger "MultiTrigger" transits from being <em>triggered</em> to being <em>not triggered</em> or the other way around.
    3699
    37100    The parameters of the @ref orxonox::MultiTrigger "MultiTrigger" are:
    38     - @b delay The delay is the time in seconds, that the trigger waits until it reacts (i.e. changes it's state) to the triggering condition being fulfilled. Internally this is handled by a state queue coupled with a counter, for each state that is delayed. The state becomes <em>active</em> when the counter runs out. This allows the @ref orxonox::MultiTrigger "MultiTrigger" to work even if the delay changes at runtime. However if the delay changes it only affects newly arriving states not the ones already in the queue. The default is <code>0</code>.
     101    - @b delay The delay is the time in seconds, that the trigger waits until it reacts (i.e. changes it's state) to the triggering condition being fulfilled. Internally this is handled by a state queue coupled with a counter, for each state that is delayed. The state becomes <em>active</em> when the counter runs out. This allows the @ref orxonox::MultiTrigger "MultiTrigger" to work even if the delay changes at runtime. However if the delay changes it only affects newly arriving states not the ones already in the queue. The default is <code>0.0</code>.
    39102    - @b switch Switch is a boolean, if <code>true</code> the @ref orxonox::MultiTrigger "MultiTrigger" is in <em>switch-mode</em>, meaning, that the <em>activity</em> changes only when the trigger is triggered, not when it is un-triggered (Just like a light switch does). This means, that in <em>switch-mode</em> the <em>activity</em> only changes, when the trigger changes from not being triggered to being triggered but not the other way around. The default is <code>false</code>.
    40103    - @b stayActive Stay active is also a boolean, if <code>true</code> the @ref orxonox::MultiTrigger "MultiTrigger" stays active after it has been activated as many times as specified by the parameter <em>activations</em>. In essence this means, that after the last time it is activated it cannot be deactivated. The default is <code>false</code>.
     
    64127
    65128    @subsubsection DistanceMultiTrigger DistanceMultiTrigger
    66     A @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is the MultiTrigger equivalent of the @ref orxonox::DistanceTrigger "DistanceTrigger" and works just the same way. It triggers (now separately for each object triggering it, since it's a @ref orxonox::MultiTrigger "MultiTrigger") whenever an object that is a target of the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is in the specified range.
     129    A @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is the @ref orxonox::MultiTrigger "MultiTrigger" equivalent of the @ref orxonox::DistanceTrigger "DistanceTrigger" and works just the same way. It triggers (now separately for each object triggering it, since it's a @ref orxonox::MultiTrigger "MultiTrigger") whenever an object that is a target of the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is in the specified range.
    67130
    68     Two additional parameters can be specified for the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" are the <em>distance</em>, which defines the maximum distance at which an object still triggers the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger", and the <em>targetname</em>. Setting the <em>targename</em> puts the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" in <em>single-target mode</em>. In this mode the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger"  can only be triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the name specified by <em>targetname</em> directly attached. For the <em>single-target mode</em> to work the target of the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" has to be set to <code>DistanceTriggerBeacon</code>.
     131    The target object can be specified further by setting the <em>beaconMode</em> and attaching a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" to the object.
     132    Parameters are (additional to the ones of @ref orxonox::MultiTrigger "MultiTrigger"):
     133    - @b distance Which specifies the maximum distance at which the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" still triggers. Default is <code>100</code>.
     134    - @b beaconMode Which specifies, whether the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" operates on @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" or not. If <em>off</em> the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" works as usual. If set to <em>identify</em> the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is only triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. If set to <em>exclude</em> the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is only triggered by objects that don't have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. Default is <em>off</em>.
     135    - @b targetname Which specifies the name @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
    69136
    70     A common usage (without @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon") would look like this:
     137    A simple @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" could look like this:
    71138    @code
    72     <DistanceMultiTrigger position="0,0,0" switch="true" target="Pawn" distance="20" />
     139    <@ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" position="0,0,0" switch="true" target="Pawn" distance="20" />
    73140    @endcode
    74141
    75     With @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" it would look like this:
     142    An implementation that only reacts to objects with a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" attached would look like this:
    76143    @code
    77     <DistanceMultiTrigger position="0,0,0" target="DistanceMultiTrigger" targetname="beacon1" distance="30" />
     144    <@ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" position="0,0,0" target="Pawn" beaconMode="identify" targetname="beacon1" distance="30" />
    78145    @endcode
     146    This particular @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" would only react if an object was in range, that had a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the name <em>beacon1</em> attached.
    79147*/
  • code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.cc

    r8079 r8213  
    4343{
    4444
     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   
    4549    CreateFactory(DistanceMultiTrigger);
    4650
     
    4953        Default Constructor. Registers the object and initializes default values.
    5054    */
    51     DistanceMultiTrigger::DistanceMultiTrigger(BaseObject* creator) : MultiTrigger(creator)
     55    DistanceMultiTrigger::DistanceMultiTrigger(BaseObject* creator) : MultiTrigger(creator), beaconMask_(NULL)
    5256    {
    5357        RegisterObject(DistanceMultiTrigger);
    5458
    5559        this->distance_ = 100.0f;
     60        this->setBeaconModeDirect(distanceMultiTriggerBeaconMode::off);
    5661        this->targetName_ = "";
    57         this->singleTargetMode_ = false;
    5862    }
    5963
     
    6468    DistanceMultiTrigger::~DistanceMultiTrigger()
    6569    {
    66 
     70        if(this->beaconMask_ != NULL)
     71            delete this->beaconMask_;
    6772    }
    6873
     
    7681
    7782        XMLPortParam(DistanceMultiTrigger, "distance", setDistance, getDistance, xmlelement, mode);
     83        XMLPortParam(DistanceMultiTrigger, "beaconMode", setBeaconMode, getBeaconMode, xmlelement, mode);
    7884        XMLPortParam(DistanceMultiTrigger, "targetname", setTargetName, getTargetName, xmlelement, mode);
    7985    }
     
    126132
    127133        // Check for new objects that are in range
    128         for(ClassTreeMaskObjectIterator it = this->getTargetMask().begin(); it != this->getTargetMask().end(); ++it)
     134        ClassTreeMask targetMask = this->getTargetMask();
     135        // If we are in identify-mode another target mask has to be applies to find the DistanceTriggerBeacons.
     136        if(this->beaconMode_ == distanceMultiTriggerBeaconMode::identify)
     137            targetMask = *this->beaconMask_;
     138
     139        // Iterate through all objects that are targets of the DistanceMultiTrigger.
     140        for(ClassTreeMaskObjectIterator it = targetMask.begin(); it != targetMask.end(); ++it)
    129141        {
    130142            WorldEntity* entity = static_cast<WorldEntity*>(*it);
    131143
    132             // If the DistanceMultiTrigger is in single-target mode.
    133             if(this->singleTargetMode_)
    134             {
    135                 // If the object that is a target is no DistanceTriggerBeacon, then the DistanceMultiTrigger can't be in single-target mode.
    136                 if(!entity->isA(ClassIdentifier<DistanceTriggerBeacon>::getIdentifier()))
     144            // If the DistanceMultiTrigger is in identify-mode and the DistanceTriggerBeacon attached to the object has the wrong name we ignore it.
     145            if(this->beaconMode_ == distanceMultiTriggerBeaconMode::identify)
     146            {
     147                if(entity->getName() != this->targetName_)
     148                    continue;
     149                // If the object, the DistanceTriggerBeacon is attached to, is not a target of this DistanceMultiTrigger.
     150                else if(this->getTargetMask().isExcluded(entity->getParent()->getIdentifier()))
     151                    continue;
     152            }
     153           
     154            // If the DistanceMultiTrigger is in exclude mode and the DistanceTriggerBeacon attached to the object has the right name, we ignore it.
     155            if(this->beaconMode_ == distanceMultiTriggerBeaconMode::exclude)
     156            {
     157               
     158                const std::set<WorldEntity*> attached = entity->getAttachedObjects();
     159                bool found = false;
     160                for(std::set<WorldEntity*>::const_iterator it = attached.begin(); it != attached.end(); it++)
    137161                {
    138                     this->singleTargetMode_ = false;
    139                     COUT(2) << "DistanceMultiTrigger " << this->getName() << " (&" << this <<  ")" << "is in single-target mode but the target is '" << entity->getIdentifier()->getName() << "' instead of DistanceTriggerBeacon. Setting single-target mode to false." << std::endl;
     162                    if((*it)->isA(ClassIdentifier<DistanceTriggerBeacon>::getIdentifier()) && static_cast<DistanceTriggerBeacon*>(*it)->getName() == this->targetName_)
     163                    {
     164                        found = true;
     165                        break;
     166                    }
    140167                }
    141                 // If the target name and the name of the DistancTriggerBeacon don't match.
    142                 else if(entity->getName().compare(this->targetName_) != 0)
     168                if(found)
    143169                    continue;
    144170            }
     
    153179                    continue;
    154180
    155                 // Change the entity to the parent of the DistanceTriggerBeacon (if in single-target-mode), which is the entity to which the beacon is attached.
    156                 if(this->singleTargetMode_)
     181                // Change the entity to the parent of the DistanceTriggerBeacon (if in identify-mode), which is the entity to which the beacon is attached.
     182                if(this->beaconMode_ == distanceMultiTriggerBeaconMode::identify)
    157183                    entity = entity->getParent();
    158184
     
    171197        return queue;
    172198    }
    173 
    174     /**
    175     @brief
    176         Set the target name of DistanceTriggerBeacons that triggers this DistanceMultiTrigger.
    177     @param targetname
    178         The name of the DistanceTriggerBeacon as a string.
    179     */
    180     void DistanceMultiTrigger::setTargetName(const std::string& targetname)
    181     {
    182         // If the targetname is no blank string single-target mode is enabled.
    183         if(targetname != "")
    184             this->singleTargetMode_ = true;
     199   
     200    /**
     201    @brief
     202        Set the beacon mode.
     203    @param mode
     204        The mode as an enum.
     205    */
     206    void DistanceMultiTrigger::setBeaconModeDirect(distanceMultiTriggerBeaconMode::Value mode)
     207    {
     208        this->beaconMode_ = mode;
     209        if(this->beaconMode_ == distanceMultiTriggerBeaconMode::identify && this->beaconMask_ == NULL)
     210        {
     211            this->beaconMask_ = new ClassTreeMask();
     212            this->beaconMask_->exclude(Class(BaseObject));
     213            this->beaconMask_->include(Class(DistanceTriggerBeacon));
     214        }
     215    }
     216   
     217    /**
     218    @brief
     219        Get the beacon mode.
     220    @return
     221        Returns the mode as a string.
     222    */
     223    const std::string& DistanceMultiTrigger::getBeaconMode(void) const
     224    {
     225        switch(this->getBeaconModeDirect())
     226        {
     227            case distanceMultiTriggerBeaconMode::off :
     228                return DistanceMultiTrigger::beaconModeOff_s;
     229            case distanceMultiTriggerBeaconMode::identify:
     230                return DistanceMultiTrigger::beaconModeIdentify_s;
     231            case distanceMultiTriggerBeaconMode::exclude:
     232                return DistanceMultiTrigger::beaconModeExlcude_s;
     233            default :
     234                assert(0); // This is impossible.
     235                return BLANKSTRING;
     236        }
     237    }
     238   
     239    /**
     240    @brief
     241        Set the beacon mode.
     242    @param mode
     243        The mode as a string.
     244    */
     245    void DistanceMultiTrigger::setBeaconMode(const std::string& mode)
     246    {
     247        if(mode == DistanceMultiTrigger::beaconModeOff_s)
     248            this->setBeaconModeDirect(distanceMultiTriggerBeaconMode::off);
     249        else if(mode == DistanceMultiTrigger::beaconModeIdentify_s)
     250            this->setBeaconModeDirect(distanceMultiTriggerBeaconMode::identify);
     251        else if(mode == DistanceMultiTrigger::beaconModeExlcude_s)
     252            this->setBeaconModeDirect(distanceMultiTriggerBeaconMode::exclude);
    185253        else
    186             this->singleTargetMode_ = false;
    187 
    188         this->targetName_ = targetname;
     254            COUT(1) << "Invalid beacon mode in DistanceMultiTrigger." << endl;
    189255    }
    190256
  • code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.h

    r7601 r8213  
    5151    /**
    5252    @brief
    53         The DistanceMultiTrigger is a MultiTrigger that triggers whenever an object (that is of the specified target type) is in a specified range of the DistanceMultiTrigger. The object can be specified further by adding a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" (by just attaching it) to the objects that can trigger this DistanceMultiTrigger and specify the name of the @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the parameter <em>targetname</em> and only objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with that name will trigger the DistanceMultiTrigger.
     53        Enum for the beacon mode of the DistanceMultiTrigger.
     54       
     55    @ingroup MultiTrigger
     56    */
     57    namespace distanceMultiTriggerBeaconMode
     58    {
     59        enum Value {
     60            off, //!< The DistanceMultiTrigger is not in <em>beacon-mode</em>.
     61            identify, //!< The DistanceTrigger is in <em>identify-mode</em>.
     62            exclude //!< The DistanceTrigger is in <em>exclude-mode</em>.
     63        };
     64    }
     65
     66    /**
     67    @brief
     68        The DistanceMultiTrigger is a MultiTrigger that triggers whenever an object (that is of the specified target type) is in a specified range of the DistanceMultiTrigger. The object can be specified further by setting the <em>beaconMode</em> and attaching a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" to the object.
    5469        Parameters are (additional to the ones of MultiTrigger):
    55         - @b distance Which specifies the maximum distance at which the DistanceMultiTrigger still triggers. Default is 100.
    56         - @b targetname Which, if not left blank, causes the DistancMultiTrigger to be in <em>single-target</em> mode, meaning, that it only reacts to objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" (therefore the target has to be set to @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" for it to work), with the name specified by <em>targetname</em>, attached.
     70        - @b distance Which specifies the maximum distance at which the DistanceMultiTrigger still triggers. Default is <code>100</code>.
     71        - @b beaconMode Which specifies, whether the DistanceMultiTrigger operates on @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" or not. If <em>off</em> the DistanceMultiTrigger works as usual. If set to <em>identify</em> the DistanceMultiTrigger is only triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. If set to <em>exclude</em> the DistanceMultiTrigger is only triggered by objects that don't have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. Default is <em>off</em>.
     72        - @b targetname Which specifies the name @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the DistanceMultiTrigger react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
    5773
    58         A simple DistanceMultiTrigger would look like this:
     74        A simple DistanceMultiTrigger could look like this:
    5975        @code
    6076        <DistanceMultiTrigger position="0,0,0" switch="true" target="Pawn" distance="20" />
     
    6379        An implementation that only reacts to objects with a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" attached would look like this:
    6480        @code
    65         <DistanceMultiTrigger position="0,0,0" target="DistanceMultiTrigger" targetname="beacon1" distance="30" />
     81        <DistanceMultiTrigger position="0,0,0" target="Pawn" beaconMode="identify" targetname="beacon1" distance="30" />
    6682        @endcode
    6783        This particular DistanceMultiTrigger would only react if an object was in range, that had a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the name <em>beacon1</em> attached.
    6884
    6985    @see MultiTrigger
    70         For more information on MultiTriggers.
     86        For more information on @ref orxonox::MultiTrigger "MultiTriggers".
    7187
    7288    @author
     
    7995
    8096        public:
    81             DistanceMultiTrigger(BaseObject* creator); //!< Default Constructor. Registers the object and initializes default values.
    82             virtual ~DistanceMultiTrigger(); //!< Destructor.
     97            DistanceMultiTrigger(BaseObject* creator); // Default Constructor. Registers the object and initializes default values.
     98            virtual ~DistanceMultiTrigger(); // Destructor.
    8399
    84             void XMLPort(Element& xmlelement, XMLPort::Mode mode); //!< Method for creating a DistanceMultiTrigger object through XML.
    85 
    86             void setTargetName(const std::string& targetname); //!< Set the target name of DistanceTriggerBeacons that triggers this DistanceMultiTrigger.
    87             /**
    88             @brief Get the target name of the DistanceTriggerbeacon, that triggers this DistanceMultiTrigger.
    89             @return Returns the target name as a string.
    90             */
    91             inline const std::string& getTargetName(void)
    92                 { return this->targetName_; }
    93 
     100            void XMLPort(Element& xmlelement, XMLPort::Mode mode); // Method for creating a DistanceMultiTrigger object through XML.
     101           
    94102            /**
    95103            @brief Set the distance at which the DistanceMultiTrigger triggers.
     
    104112            inline float getDistance() const
    105113                { return this->distance_; }
     114           
     115            void setBeaconModeDirect(distanceMultiTriggerBeaconMode::Value mode); // Set the beacon mode.
     116            /**
     117            @brief Get the beacon mode.
     118            @return Returns the mode as an enum.
     119            */
     120            inline distanceMultiTriggerBeaconMode::Value getBeaconModeDirect(void) const
     121                { return this->beaconMode_; }
     122            void setBeaconMode(const std::string& mode); // Set the beacon mode.
     123            const std::string& getBeaconMode(void) const; // Get the beacon mode.
     124
     125            /**
     126            @brief Set the target name of DistanceTriggerBeacons that triggers this DistanceMultiTrigger.
     127            @param targetname The name of the DistanceTriggerBeacon as a string.
     128            */
     129            inline void setTargetName(const std::string& targetname)
     130                { this->targetName_ = targetname; }
     131            /**
     132            @brief Get the target name of the DistanceTriggerbeacon, that triggers this DistanceMultiTrigger.
     133            @return Returns the target name as a string.
     134            */
     135            inline const std::string& getTargetName(void) const
     136                { return this->targetName_; }
    106137
    107138        protected:
    108             virtual std::queue<MultiTriggerState*>* letTrigger(void); //!< This method is called by the MultiTrigger to get information about new trigger events that need to be looked at.
     139            virtual std::queue<MultiTriggerState*>* letTrigger(void); // This method is called by the MultiTrigger to get information about new trigger events that need to be looked at.
    109140
    110             bool addToRange(WorldEntity* entity); //!< Add a given entity to the entities, that currently are in range of the DistanceMultiTrigger.
    111             bool removeFromRange(WorldEntity* entity); //!< Remove a given entity from the set of entities, that currently are in range of the DistanceMultiTrigger.
     141            bool addToRange(WorldEntity* entity); // Add a given entity to the entities, that currently are in range of the DistanceMultiTrigger.
     142            bool removeFromRange(WorldEntity* entity); // Remove a given entity from the set of entities, that currently are in range of the DistanceMultiTrigger.
    112143
    113144        private:
     145            //! Strings for the beacon modes.
     146            static const std::string beaconModeOff_s;
     147            static const std::string beaconModeIdentify_s;
     148            static const std::string beaconModeExlcude_s;
     149           
    114150            float distance_; //!< The distance at which the DistanceMultiTrigger triggers.
     151
     152            distanceMultiTriggerBeaconMode::Value beaconMode_; //!< The beacon mode, the DistanceMultiTrigger is in.
    115153            std::string targetName_; //!< The target name, used in <em>single-target</em> mode.
    116             bool singleTargetMode_; //!< To indicate whe the MultiDistanceTrigger is in <em>single-target</em> mode.
     154            ClassTreeMask* beaconMask_; //!< A mask, that only accepts DistanceTriggerBeacons.
    117155
    118156            std::map<WorldEntity*, WeakPtr<WorldEntity>* > range_; //!< The set of entities that currently are in range of the DistanceMultiTrigger.
  • code/trunk/src/modules/objects/triggers/DistanceTrigger.cc

    r8079 r8213  
    3737#include "core/CoreIncludes.h"
    3838#include "core/XMLPort.h"
     39
    3940#include "worldentities/pawns/Pawn.h"
     41
    4042#include "DistanceTriggerBeacon.h"
    4143
    4244namespace orxonox
    4345{
    44   CreateFactory(DistanceTrigger);
    45 
    46   DistanceTrigger::DistanceTrigger(BaseObject* creator) : Trigger(creator)
    47   {
    48     RegisterObject(DistanceTrigger);
    49 
    50     this->distance_ = 100;
    51     this->targetMask_.exclude(Class(BaseObject));
    52     this->targetName_ = "";
    53     this->singleTargetMode_ = false;
    54   }
    55 
    56   DistanceTrigger::~DistanceTrigger()
    57   {
    58   }
    59 
    60   void DistanceTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
    61   {
    62     SUPER(DistanceTrigger, XMLPort, xmlelement, mode);
    63 
    64     XMLPortParam(DistanceTrigger, "distance", setDistance, getDistance, xmlelement, mode).defaultValues(100.0f);
    65     XMLPortParamLoadOnly(DistanceTrigger, "target", addTargets, xmlelement, mode).defaultValues("Pawn");
    66     XMLPortParam(DistanceTrigger, "targetname", setTargetName, getTargetName, xmlelement, mode);
    67   }
    68 
    69   void DistanceTrigger::addTarget(Ogre::Node* targetNode)
    70   {
    71     this->targetSet_.insert(targetNode);
    72   }
    73 
    74   void DistanceTrigger::removeTarget(Ogre::Node* targetNode)
    75   {
    76     int returnval = this->targetSet_.erase(targetNode);
    77     if (returnval == 0)
    78     {
    79       COUT(2) << "Warning: Node " << targetNode << " did not exist in targetSet of trigger " << this << " !" << std::endl;
    80       COUT(4) << "Content of targetSet of trigger " << this << " :" << std::endl;
    81       std::set<Ogre::Node*>::iterator it;
    82       for (it = this->targetSet_.begin(); it != this->targetSet_.end(); ++it)
    83       {
    84         COUT(4) << *it << std::endl;
    85       }
    86       COUT(4) << "End of targetSet of trigger " << this << std::endl;
    87     }
    88   }
    89 
    90   void DistanceTrigger::addTargets(const std::string& targets)
    91   {
    92     Identifier* targetId = ClassByString(targets);
    93 
    94     //! Checks whether the target is (or is derived from) a ControllableEntity.
    95     Identifier* pawnId = Class(Pawn);
    96     Identifier* distanceTriggerBeaconId = Class(DistanceTriggerBeacon);
    97     if(targetId->isA(pawnId) || targetId->isA(distanceTriggerBeaconId))
    98     {
    99       this->setForPlayer(true);
    100     }
    101 
    102     if (!targetId)
    103     {
    104         COUT(1) << "Error: \"" << targets << "\" is not a valid class name to include in ClassTreeMask (in " << this->getName() << ", class " << this->getIdentifier()->getName() << ')' << std::endl;
    105         return;
    106     }
    107 
    108     this->targetMask_.include(targetId);
    109 
    110     // trigger shouldn't react on itself or other triggers
    111     this->targetMask_.exclude(Class(Trigger), true);
    112 
    113     // we only want WorldEntities
    114     ClassTreeMask WEMask;
    115     WEMask.include(Class(WorldEntity));
    116     this->targetMask_ *= WEMask;
    117 
    118     this->notifyMaskUpdate();
    119   }
    120 
    121   void DistanceTrigger::removeTargets(const std::string& targets)
    122   {
    123     Identifier* targetId = ClassByString(targets);
    124     this->targetMask_.exclude(targetId);
    125   }
    126 
    127   bool DistanceTrigger::checkDistance()
    128   {
    129     // Iterate through all objects
    130     for (ClassTreeMaskObjectIterator it = this->targetMask_.begin(); it != this->targetMask_.end(); ++it)
    131     {
    132       WorldEntity* entity = orxonox_cast<WorldEntity*>(*it);
    133       if (!entity)
    134         continue;
    135 
    136       // If the DistanceTrigger is in single-target mode.
    137       if(this->singleTargetMode_)
    138       {
    139         // If the object that is a target is no DistanceTriggerBeacon, then the DistanceTrigger can't be in single-target-mode.
    140         if(!(*it)->isA(ClassIdentifier<DistanceTriggerBeacon>::getIdentifier()))
    141         {
    142           this->singleTargetMode_ = false;
    143           COUT(2) << "DistanceTrigger " << this->getName() << " (&" << this <<  ")" << "is in single-target mode but the target is '" << entity->getIdentifier()->getName() << "' instead of DistanceTriggerBeacon. Setting single-target mode to false." << std::endl;
    144         }
    145         // If the target name and the name of the DistancTriggerBeacon don't match.
    146         else if(entity->getName().compare(this->targetName_) != 0)
    147           continue;
    148       }
    149 
    150       Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
    151       if (distanceVec.length() < this->distance_)
    152       {
    153 
    154         // If the target is a player (resp. is a, or is derived from a, ControllableEntity) the triggeringPlayer is set to the target entity.
    155         if(this->isForPlayer())
    156         {
    157 
    158           // Change the entity to the parent of the DistanceTriggerBeacon (if in single-target-mode), which is the entity to which the beacon is attached.
    159           if(this->singleTargetMode_)
    160             entity = entity->getParent();
    161 
    162           Pawn* player = orxonox_cast<Pawn*>(entity);
    163           this->setTriggeringPlayer(player);
    164         }
    165 
    166         return true;
    167       }
    168     }
    169 
    170     return false;
    171   }
    172 
    173   bool DistanceTrigger::isTriggered(TriggerMode::Value mode)
    174   {
    175     if (Trigger::isTriggered(mode))
    176     {
    177       return checkDistance();
    178     }
    179     else
    180       return false;
    181   }
     46
     47    /*static*/ const std::string DistanceTrigger::beaconModeOff_s = "off";
     48    /*static*/ const std::string DistanceTrigger::beaconModeIdentify_s = "identify";
     49    /*static*/ const std::string DistanceTrigger::beaconModeExlcude_s = "exclude";
     50
     51    CreateFactory(DistanceTrigger);
     52
     53    /**
     54    @brief
     55        Constructor. Registers and initializes the object.
     56    @param creator
     57        The creator of this trigger.
     58    */
     59    DistanceTrigger::DistanceTrigger(BaseObject* creator) : Trigger(creator), beaconMask_(NULL)
     60    {
     61        RegisterObject(DistanceTrigger);
     62
     63        this->distance_ = 100;
     64        this->targetMask_.exclude(Class(BaseObject));
     65        this->targetName_ = "";
     66    }
     67
     68    /**
     69    @brief
     70        Destructor.
     71    */
     72    DistanceTrigger::~DistanceTrigger()
     73    {
     74        // Delete the beacon mask if it exists.
     75        if(this->beaconMask_ != NULL)
     76            delete this->beaconMask_;
     77    }
     78
     79    /**
     80    @brief
     81        Method for creating a DistanceTrigger object through XML.
     82    */
     83    void DistanceTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
     84    {
     85        SUPER(DistanceTrigger, XMLPort, xmlelement, mode);
     86
     87        XMLPortParam(DistanceTrigger, "distance", setDistance, getDistance, xmlelement, mode).defaultValues(100.0f);
     88        XMLPortParamLoadOnly(DistanceTrigger, "target", addTarget, xmlelement, mode).defaultValues("Pawn");
     89        XMLPortParam(DistanceTrigger, "beaconMode", setBeaconMode, getBeaconMode, xmlelement, mode);
     90        XMLPortParam(DistanceTrigger, "targetname", setTargetName, getTargetName, xmlelement, mode);
     91    }
     92
     93    /**
     94    @brief
     95        Add some target to the DistanceTrigger.
     96    @param targetStr
     97        The target class name as a string.
     98    */
     99    void DistanceTrigger::addTarget(const std::string& targetStr)
     100    {
     101        Identifier* targetId = ClassByString(targetStr);
     102
     103        // Checks whether the target is (or is derived from) a Pawn and if so set the PlayerTrigger aspect of this trigger to be for the player, meaning, that from this Trigger one can derive the Pawn that caused it to trigger.
     104        Identifier* pawnId = Class(Pawn);
     105        if(targetId->isA(pawnId))
     106            this->setForPlayer(true);
     107
     108        if (targetId == NULL)
     109        {
     110            COUT(1) << "Error: \"" << targetStr << "\" is not a valid class name to include in ClassTreeMask (in " << this->getName() << ", class " << this->getIdentifier()->getName() << ')' << std::endl;
     111            return;
     112        }
     113
     114        // Add the target to the target mask.
     115        this->targetMask_.include(targetId);
     116
     117        // The DistanceTrigger shouldn't react to itself or other triggers.
     118        this->targetMask_.exclude(Class(TriggerBase), true);
     119
     120        // We only want WorldEntities (since only they have a position)
     121        ClassTreeMask WEMask;
     122        WEMask.include(Class(WorldEntity));
     123        this->targetMask_ *= WEMask;
     124
     125        this->notifyMaskUpdate(); // Inform interested parties that the target mask has been updated.
     126    }
     127
     128    /**
     129    @brief
     130        Remove some target from the DistanceTrigger.
     131    @param targetStr
     132        The target class name as a string.
     133    */
     134    void DistanceTrigger::removeTarget(const std::string& targetStr)
     135    {
     136        Identifier* targetId = ClassByString(targetStr);
     137        this->targetMask_.exclude(targetId);
     138    }
     139
     140    /**
     141    @brief
     142        Check, whether there are entities that are targets of this DistanceTrigger in its range.
     143    @return
     144        Returns true if there are valid entities in its range.
     145    */
     146    bool DistanceTrigger::checkDistance()
     147    {
     148        // Check whether there is a cached object, it still exists and whether it is still in range, if so nothing further needs to be done.
     149        if(this->cache_.get() != NULL)
     150        {
     151            if((this->cache_.get()->getWorldPosition() - this->getWorldPosition()).length() < this->distance_)
     152                return true;
     153            else
     154                this->cache_.reset();
     155        }
     156       
     157        // Check for new objects that are in range
     158        ClassTreeMask targetMask = this->targetMask_;
     159        // If we are in identify-mode another target mask has to be applies to find the DistanceTriggerBeacons.
     160        if(this->beaconMode_ == distanceTriggerBeaconMode::identify)
     161            targetMask = *this->beaconMask_;
     162
     163        // Iterate through all objects that are targets of the DistanceTrigger.
     164        for (ClassTreeMaskObjectIterator it = targetMask.begin(); it != targetMask.end(); ++it)
     165        {
     166            WorldEntity* entity = static_cast<WorldEntity*>(*it);
     167
     168            // If the DistanceTrigger is in identify-mode and the DistanceTriggerBeacon attached to the object has the wrong name we ignore it.
     169            if(this->beaconMode_ == distanceTriggerBeaconMode::identify)
     170            {
     171                if(entity->getName() != this->targetName_)
     172                    continue;
     173                // If the object, the DistanceTriggerBeacon is attached to, is not a target of this DistanceMultiTrigger.
     174                else if(this->targetMask_.isExcluded(entity->getParent()->getIdentifier()))
     175                    continue;
     176            }
     177
     178            // If the DistanceTrigger is in exclude mode and the DistanceTriggerBeacon attached to the object has the right name, we ignore it.
     179            if(this->beaconMode_ == distanceTriggerBeaconMode::exclude)
     180            {
     181
     182                const std::set<WorldEntity*> attached = entity->getAttachedObjects();
     183                bool found = false;
     184                for(std::set<WorldEntity*>::const_iterator it = attached.begin(); it != attached.end(); it++)
     185                {
     186                    if((*it)->isA(ClassIdentifier<DistanceTriggerBeacon>::getIdentifier()) && static_cast<DistanceTriggerBeacon*>(*it)->getName() == this->targetName_)
     187                    {
     188                        found = true;
     189                        break;
     190                    }
     191                }
     192                if(found)
     193                    continue;
     194            }
     195
     196            // Check if the entity is in range.
     197            Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
     198            if (distanceVec.length() < this->distance_)
     199            {
     200                // If the target is a player (resp. is a, or is derived from a, Pawn) the triggeringPlayer is set to the target entity.
     201                if(this->isForPlayer())
     202                {
     203                    // Change the entity to the parent of the DistanceTriggerBeacon (if in identify-mode), which is the entity to which the beacon is attached.
     204                    if(this->beaconMode_ == distanceTriggerBeaconMode::identify)
     205                        entity = entity->getParent();
     206
     207                    Pawn* player = orxonox_cast<Pawn*>(entity);
     208                    this->setTriggeringPlayer(player);
     209                }
     210               
     211                // Add the entity to the cache.
     212                this->cache_ = WeakPtr<WorldEntity>(entity);
     213
     214                return true;
     215            }
     216        }
     217
     218        return false;
     219    }
     220
     221    /**
     222    @brief
     223        Set the beacon mode.
     224    @param mode
     225        The mode as an enum.
     226    */
     227    void DistanceTrigger::setBeaconModeDirect(distanceTriggerBeaconMode::Value mode)
     228    {
     229        this->beaconMode_ = mode;
     230        if(this->beaconMode_ == distanceTriggerBeaconMode::identify && this->beaconMask_ == NULL)
     231        {
     232            this->beaconMask_ = new ClassTreeMask();
     233            this->beaconMask_->exclude(Class(BaseObject));
     234            this->beaconMask_->include(Class(DistanceTriggerBeacon));
     235        }
     236    }
     237
     238    /**
     239    @brief
     240        Get the beacon mode.
     241    @return
     242        Returns the mode as a string.
     243    */
     244    const std::string& DistanceTrigger::getBeaconMode(void) const
     245    {
     246        switch(this->getBeaconModeDirect())
     247        {
     248            case distanceTriggerBeaconMode::off :
     249                return DistanceTrigger::beaconModeOff_s;
     250            case distanceTriggerBeaconMode::identify:
     251                return DistanceTrigger::beaconModeIdentify_s;
     252            case distanceTriggerBeaconMode::exclude:
     253                return DistanceTrigger::beaconModeExlcude_s;
     254            default :
     255                assert(0); // This is impossible.
     256                return BLANKSTRING;
     257        }
     258    }
     259
     260    /**
     261    @brief
     262        Set the beacon mode.
     263    @param mode
     264        The mode as a string.
     265    */
     266    void DistanceTrigger::setBeaconMode(const std::string& mode)
     267    {
     268        if(mode == DistanceTrigger::beaconModeOff_s)
     269            this->setBeaconModeDirect(distanceTriggerBeaconMode::off);
     270        else if(mode == DistanceTrigger::beaconModeIdentify_s)
     271            this->setBeaconModeDirect(distanceTriggerBeaconMode::identify);
     272        else if(mode == DistanceTrigger::beaconModeExlcude_s)
     273            this->setBeaconModeDirect(distanceTriggerBeaconMode::exclude);
     274        else
     275            COUT(1) << "Invalid beacon mode in DistanceTrigger." << endl;
     276    }
     277
     278    /**
     279    @brief
     280        Check whether the DistanceTrigger is triggered.
     281        It is triggered if it is triggered according only to its mode (i.e. its sub-triggers) and if a target is in range.
     282    @param
     283        Returns true if it is triggered ,false if not.
     284    */
     285    bool DistanceTrigger::isTriggered(TriggerMode::Value mode)
     286    {
     287        if (Trigger::isTriggered(mode))
     288            return checkDistance();
     289        else
     290            return false;
     291    }
    182292}
  • code/trunk/src/modules/objects/triggers/DistanceTrigger.h

    r8079 r8213  
    3939
    4040#include <set>
     41
    4142#include "core/ClassTreeMask.h"
     43
     44#include "interfaces/PlayerTrigger.h"
     45
    4246#include "Trigger.h"
    43 #include "interfaces/PlayerTrigger.h"
    4447
    4548namespace orxonox
    4649{
    47 
     50   
    4851  /**
    4952  @brief
    50 
    51   @author
    52     Benjamin Knecht
    53   @author
    54     Damian 'Mozork' Frick
    55 
     53      Enum for the beacon mode of the DistanceTrigger.
     54     
    5655  @ingroup NormalTrigger
    5756  */
    58   class _ObjectsExport DistanceTrigger : public Trigger, public PlayerTrigger
     57  namespace distanceTriggerBeaconMode
    5958  {
    60     public:
    61       DistanceTrigger(BaseObject* creator);
    62       virtual ~DistanceTrigger();
     59      enum Value {
     60          off,
     61          identify,
     62          exclude
     63      };
     64  }
    6365
    64       virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
     66    /**
     67    @brief
     68        The DistanceTrigger is a Trigger that triggers whenever an object (that is of the specified target type) is in a specified range of the DistanceTrigger. The object can be specified further by setting the <em>beaconMode</em> and attaching a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" to the object.
     69        Parameters are (additional to the ones of Trigger):
     70        - @b distance Which specifies the maximum distance at which the DistanceTrigger still triggers, i.e. its range. Default is <code>100</code>.
     71        - @b target Which specifies the class of objects that can trigger the DistanceTrigger. Default is <code>"Pawn"</code>.
     72        - @b beaconMode Which specifies, whether the DistanceTrigger operates on @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" or not. If <em>off</em> the DistanceMultiTrigger works as usual. If set to <em>identify</em> the DistanceTrigger is only triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. If set to <em>exclude</em> the DistanceTrigger is only triggered by objects that don't have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. Default is <em>off</em>.
     73        - @b targetname Which specifies the name @ref oroxnox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the DistanceTrigger react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
    6574
    66       void addTarget(Ogre::Node* targetNode);
    67       void addTargets(const std::string& targets);
    68       void removeTarget(Ogre::Node* targetNode);
    69       void removeTargets(const std::string& targets);
     75        A simple DistanceTrigger could look like this:
     76        @code
     77        <DistanceTrigger position="0,0,0" switch="true" target="Pawn" distance="20" />
     78        @endcode
    7079
    71       inline void setTargetName(const std::string& targetname)
    72         { if(targetname != "") this->singleTargetMode_ = true; else this->singleTargetMode_ = false; this->targetName_ = targetname; }
    73       inline const std::string& getTargetName(void)
    74         { return this->targetName_; }
     80        An implementation that only reacts to objects with a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" attached would look like this:
     81        @code
     82        <DistanceTrigger position="0,0,0" target="Pawn" beaconMode="identify" targetname="beacon1" distance="30" />
     83        @endcode
     84        This particular DistanceTrigger would only react if an object was in range, that had a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the name <em>beacon1</em> attached.
    7585
    76       inline void setDistance(float distance)
    77         { this->distance_ = distance; }
    78       inline float getDistance() const
    79         { return this->distance_; }
     86    @see Trigger
     87        For more information on @ref orxonox::Trigger "Triggers".
    8088
    81       bool checkDistance();
     89    @author
     90        Benjamin Knecht
     91    @author
     92        Damian 'Mozork' Frick
    8293
    83     protected:
    84       virtual bool isTriggered(TriggerMode::Value mode);
    85       virtual void notifyMaskUpdate() {}
     94    @ingroup NormalTrigger
     95    */
     96    class _ObjectsExport DistanceTrigger : public Trigger, public PlayerTrigger
     97    {
     98        public:
     99            DistanceTrigger(BaseObject* creator); // Constructor. Registers and initializes the object.
     100            virtual ~DistanceTrigger();
    86101
    87       ClassTreeMask targetMask_;
     102            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode); // Method for creating a DistanceTrigger object through XML.
    88103
    89     private:
    90       std::set<Ogre::Node*> targetSet_;
    91       std::string targetName_;
    92       float distance_;
    93       bool singleTargetMode_;
     104            void addTarget(const std::string& targets); // Add some target to the DistanceTrigger.
     105            void removeTarget(const std::string& targets); // Remove some target from the DistanceTrigger.
    94106
    95   };
     107            /**
     108            @brief Set the range of the DistanceTrigger.
     109            @param distance The range to be set.
     110            */
     111            inline void setDistance(float distance)
     112                { this->distance_ = distance; }
     113            /**
     114            @brief Get the range of the DistanceTrigger.
     115            @return Returns the range of the distance trigger.
     116            */
     117            inline float getDistance() const
     118                { return this->distance_; }
     119
     120            void setBeaconModeDirect(distanceTriggerBeaconMode::Value mode); // Set the beacon mode.
     121            /**
     122            @brief Get the beacon mode.
     123            @return Returns the mode as an enum.
     124            */
     125            inline distanceTriggerBeaconMode::Value getBeaconModeDirect(void) const
     126            { return this->beaconMode_; }
     127            void setBeaconMode(const std::string& mode); // Set the beacon mode.
     128            const std::string& getBeaconMode(void) const; // Get the beacon mode.
     129
     130            /**
     131            @brief Set the name a DistanceTriggerBeacon needs to have to make the DistanceTrigger react to it if in beacon-mode.
     132            @param targetname The name as a string.
     133            */
     134            inline void setTargetName(const std::string& targetname)
     135                { this->targetName_ = targetname; }
     136            /**
     137            @brief Get the target name.
     138            @return Returns the target name as a string.
     139            */
     140            inline const std::string& getTargetName(void)
     141                { return this->targetName_; }
     142
     143            bool checkDistance(); // Check, whether there are entities that are targets of this DistanceTrigger in its range.
     144
     145        protected:
     146            virtual bool isTriggered(TriggerMode::Value mode); // Check whether the DistanceTrigger is triggered.
     147            /**
     148            @brief Notifies interested parties about a change of the DistanceTrigger's target mask.
     149            */
     150            virtual void notifyMaskUpdate() {}
     151
     152            ClassTreeMask targetMask_; //!< The target mask, specifies by which types of objects the DistanceTrigger can be triggered.
     153
     154        private:
     155            //! Strings for the beacon modes.
     156            static const std::string beaconModeOff_s;
     157            static const std::string beaconModeIdentify_s;
     158            static const std::string beaconModeExlcude_s;
     159
     160            float distance_; //!< The range of the DistanceTrigger.
     161           
     162            distanceTriggerBeaconMode::Value beaconMode_; //!< The beacon mode.
     163            std::string targetName_; //!< The name a DistanceTriggerBeacon needs to have to make the DistanceTrigger react to it if in beacon-mode.
     164            ClassTreeMask* beaconMask_; //!< A mask, that only accepts DistanceTriggerBeacons.
     165           
     166            WeakPtr<WorldEntity> cache_; //!< Caches the entity that triggered the DistanceTrigger last.
     167    };
    96168}
    97169
  • code/trunk/src/modules/objects/triggers/EventMultiTrigger.h

    r7601 r8213  
    6262
    6363    @see MultiTrigger
    64         For more information on MultiTriggers.
     64        For more information on @ref orxonox::MultiTrigger "MultiTriggers".
    6565
    6666    @author
  • code/trunk/src/modules/objects/triggers/EventTrigger.cc

    r7601 r8213  
    4242    CreateFactory(EventTrigger);
    4343
     44    /**
     45    @brief
     46        Constructor. Registers and initializes the object.
     47    @param creator
     48        The creator of the EventTrigger.
     49    */
    4450    EventTrigger::EventTrigger(BaseObject* creator) : Trigger(creator)
    4551    {
     
    4955    }
    5056
     57    /**
     58    @brief
     59        Destructor.
     60    */
    5161    EventTrigger::~EventTrigger()
    5262    {
    5363    }
    5464
     65    /**
     66    @brief
     67        Creates an event port.
     68    */
    5569    void EventTrigger::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
    5670    {
     
    6074    }
    6175
     76    /**
     77    @brief
     78        Check whether the EventTrigger should be triggered.
     79        It should be triggered if it is triggered according just to its sub-triggers and if the last event that came in was an event that changed from not triggered to triggered.
     80    */
    6281    bool EventTrigger::isTriggered(TriggerMode::Value mode)
    6382    {
  • code/trunk/src/modules/objects/triggers/EventTrigger.h

    r7601 r8213  
    3737
    3838#include "objects/ObjectsPrereqs.h"
     39
    3940#include "Trigger.h"
    4041
     
    4445    /**
    4546    @brief
     47        The EventTrigger class provides a way to have a Trigger triggered by any kinds of @ref orxonox::Event "Events".
     48
     49        Example:
     50        @code
     51        <EventTrigger invert="true">
     52            <events>
     53                <trigger>
     54                    <TriggerBase ... />
     55                    <EventListener ... />
     56                </trigger>
     57            </events>
     58        </EventTrigger>
     59        @endcode
     60
     61    @see Trigger
     62        For more information on @ref oroxnox::Trigger "Triggers".
    4663
    4764    @author
     
    5370    {
    5471        public:
    55             EventTrigger(BaseObject* creator);
     72            EventTrigger(BaseObject* creator); // Constructor. Registers and initializes the object.
    5673            virtual ~EventTrigger();
    5774
    58             virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode);
     75            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode); // Creates an event port.
    5976
     77            /**
     78            @brief Method that is called when a new event comes in.
     79                   The tick call makes sure the state change takes effect immediately.
     80            @param bTriggered The state of the incoming event.
     81            */
    6082            inline void trigger(bool bTriggered)
    6183                { this->bEventTriggered_ = bTriggered; this->tick(0); }
    6284
    6385        protected:
    64             virtual bool isTriggered(TriggerMode::Value mode);
     86            virtual bool isTriggered(TriggerMode::Value mode); // Check whether the EventTrigger should be triggered.
    6587
    6688        private:
    67             bool bEventTriggered_;
     89            bool bEventTriggered_; //!< Boolean to keep track of what the state of the last event was.
    6890    };
    6991}
  • code/trunk/src/modules/objects/triggers/MultiTrigger.cc

    r8193 r8213  
    9292        XMLPortParam(MultiTrigger, "simultaneousTriggerers", setSimultaneousTriggerers, getSimultaneousTriggerers, xmlelement, mode);
    9393        XMLPortParam(MultiTrigger, "broadcast", setBroadcast, getBroadcast, xmlelement, mode);
    94         XMLPortParamLoadOnly(MultiTrigger, "target", addTargets, xmlelement, mode).defaultValues("Pawn"); //TODO: Remove load only
     94        XMLPortParamLoadOnly(MultiTrigger, "target", addTarget, xmlelement, mode).defaultValues("Pawn"); //TODO: Remove load only
    9595
    9696        COUT(4) << "MultiTrigger '" << this->getName() << "' (&" << this << ") created." << std::endl;
     
    275275    /**
    276276    @brief
    277         Get whether the MultiTrigger is active for a given object.
     277        Check whether the MultiTrigger is active for a given object.
    278278    @param triggerer
    279279        A pointer to the object.
     
    293293        Add some target to the MultiTrigger.
    294294    @param targetStr
    295         The target as a string.
    296     */
    297     void MultiTrigger::addTargets(const std::string& targetStr)
     295        The target class name as a string.
     296    */
     297    void MultiTrigger::addTarget(const std::string& targetStr)
    298298    {
    299299        Identifier* target = ClassByString(targetStr);
     
    308308        this->targetMask_.include(target);
    309309
    310         // A MultiTrigger shouldn't react to itself or other MultiTriggers.
    311         this->targetMask_.exclude(Class(MultiTrigger), true);
     310        // A MultiTrigger shouldn't react to itself or other triggers.
     311        this->targetMask_.exclude(Class(TriggerBase), true);
    312312
    313313        // We only want WorldEntities
     
    324324        The target to be removed as a string.
    325325    */
    326     void MultiTrigger::removeTargets(const std::string& targetStr)
     326    void MultiTrigger::removeTarget(const std::string& targetStr)
    327327    {
    328328        Identifier* target = ClassByString(targetStr);
  • code/trunk/src/modules/objects/triggers/MultiTrigger.h

    r7601 r8213  
    6767
    6868        MultiTriggers also allow for additional complexity which can be added through the choice of the parameters explained (briefly) below:
    69         But first you must understand a small implementational detail. There is a distinction between the MultiTrigger being triggered (there is the state <em>triggered</em> for that) and the MultiTrigger being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible. The state <em>triggered</em> 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 behavior is, that the <em>activity</em> changes, when the MultiTrigger transits from being triggered to not being triggered or the other way around.
     69        But first you must understand a small implementation detail. There is a distinction between the MultiTrigger being triggered (there is the state <em>triggered</em> for that) and the MultiTrigger being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible. The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be <em>active</em>, while it in fact isn't. The standard behavior is, that the <em>activity</em> changes, when the MultiTrigger transits from being <em>triggered</em> to being <em>not triggered</em> or the other way around.
    7070        The parameters are:
    7171        - @b 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.
    72         - @b switch Switch is a boolean, if true the MultiTrigger is in switch-mode, meaning, that the <em>activity</em> changes only when the trigger is triggered, this means, that now the <em>activity</em> only changes, when the trigger changes from not being triggered to being triggered but not the other way around. The default is false.
    73         - @b stayactive Stay active is also a boolean, if true the MultiTrigger stays active after it has been activated as many times as specified by the parameter activations. The default is false.
    74         - @b activations The number of activations until the trigger can't be triggered anymore. The default is -1, which is infinity.
    75         - @b invert Invert is a boolean, if true the trigger is in <em>invert-mode</em>, 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 behavior of the MultiTrigger. The default is false.
    76         - @b simultaneousTriggerers The number of simultaneous triggerers limits the number of objects that are allowed to trigger the MultiTrigger at the same time. Or more precisely, the number of distinct objects the MultiTrigger has <em>triggered</em> states for, at each point in time. The default is -1, which denotes infinity.
    77         - @b mode The mode describes how the MultiTrigger acts in relation to all the triggers, that are appended to it. There are 3 modes: <em>and</em>, meaning that the MultiTrigger can only be triggered if all the appended triggers are active. <em>or</em>, meaning that the MultiTrigger can only triggered if at least one of the appended triggers is active. And <em>xor</em>, meaning that the MultiTrigger can only be triggered if one and only one appended trigger is active. Note, that I wrote <em>can only be active</em>, that implies, that there is an additional 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 <em>and</em>.
     72        - @b switch Switch is a boolean, if true the MultiTrigger is in <em>switch-mode</em>, meaning, that the <em>activity</em> changes only when the trigger is triggered, this means, that now the <em>activity</em> only changes, when the trigger changes from not being triggered to being triggered but not the other way around. The default is <code>false</code>.
     73        - @b stayactive Stay active is also a boolean, if true the MultiTrigger stays active after it has been activated as many times as specified by the parameter <em>activations</em>. The default is <code>false</code>.
     74        - @b activations The number of times the MultiTrigger can be activated until the trigger can't be triggered anymore. The default is <code>-1</code>, which denotes infinity.
     75        - @b invert Invert is a boolean, if true the MultiTrigger is in <em>invert-mode</em>, meaning, that if the triggering condition is fulfilled the MultiTrigger will have the state <em>not triggered</em> and and if the condition is not fulfilled it will have the state <em>triggered</em>. In short it just inverts the behavior of the MultiTrigger. The default is <code>false</code>.
     76        - @b simultaneousTriggerers The number of simultaneous triggerers limits the number of objects that are allowed to trigger the MultiTrigger at the same time. Or more precisely, the number of distinct objects the MultiTrigger has <em>triggered</em> states for, at each point in time. The default is <code>-1</code>, which denotes infinity.
     77        - @b mode The mode describes how the MultiTrigger acts in relation to all the triggers, that are appended to it. There are 3 modes: <em>and</em>, meaning that the MultiTrigger can only be triggered if all the appended triggers are active. <em>or</em>, meaning that the MultiTrigger can only triggered if at least one of the appended triggers is active. And <em>xor</em>, meaning that the MultiTrigger can only be triggered if one and only one appended trigger is active. Note, that I wrote <em>can only be active</em>, that implies, that there is an additional condition to the <em>activity</em> 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 <em>activity</em> of a MultiTrigger is still coupled to the object that triggered it. The default is <em>and</em>.
    7878        - @b broadcast Broadcast is a boolean, if true the MutliTrigger is in <em>broadcast-mode</em>, meaning, that all trigger events that are caused by no originator (originator is NULL) are broadcast as having come from every possible originator, or more precisely as having come from all objects that are specified targets of this MultiTrigger. The default is false.
    7979        - @b target The target describes the kind of objects that are allowed to trigger this MultiTrigger. The default is @ref orxonox::Pawn "Pawn".
     
    111111            inline bool isActive(void) const
    112112                { return this->isActive(NULL); }
    113             bool isActive(BaseObject* triggerer = NULL) const; //!< Get whether the MultiTrigger is active for a given object.
     113            bool isActive(BaseObject* triggerer = NULL) const; //!< Check whether the MultiTrigger is active for a given object.
    114114
    115115            /**
     
    158158            void broadcast(bool status); //!< Helper method. Broadcasts an Event for every object that is a target.
    159159
    160             void addTargets(const std::string& targets); //!< Add some target to the MultiTrigger.
    161             void removeTargets(const std::string& targets); //!< Remove some target from the MultiTrigger.
     160            void addTarget(const std::string& targets); //!< Add some target to the MultiTrigger.
     161            void removeTarget(const std::string& targets); //!< Remove some target from the MultiTrigger.
    162162
    163163            /**
  • 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}
  • code/trunk/src/modules/objects/triggers/Trigger.h

    r7601 r8213  
    4848{
    4949
    50   /**
    51   @brief
    52    
    53   @author
    54     Benjamin Knecht
     50    /**
     51    @brief
     52         A Trigger is an object that can either be <em>active</em> or <em>inactive</em>, with a specified behavior how to switch between the two. Each time a switch occurs an @ref orxonox::Event "Event" is fired with as the originator the Trigger that caused the @ref orxonox::Event "Event".
     53         
     54        Triggers also allow for additional complexity which can be added through the choice of the parameters explained below:
     55        But first it is imperative to understand a small implementation detail. There is a distinction between the Trigger being triggered (there is the state <em>triggered</em> for that) and the Trigger being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible. The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be <em>active</em>, while it in fact isn't. The standard behavior is, that the <em>activity</em> changes, when the Trigger transits from being <em>triggered</em> to being <em>not triggered</em> or the other way around.
     56        The parameters are:
     57        - @b 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.
     58        - @b switch Switch is a boolean, if true the Trigger is in <em>switch-mode</em>, meaning, that the <em>activity</em> changes only when the trigger is triggered, this means, that now the <em>activity</em> only changes, when the trigger changes from not being triggered to being triggered but not the other way around. The default is <code>false</code>.
     59        - @b stayactive Stay active is also a boolean, if true the Trigger stays active after it has been activated as many times as specified by the parameter <em>activations</em>. The default is <code>false</code>.
     60        - @b activations The number of times the Trigger can be activated until the trigger can't be triggered anymore. The default is <code>-1</code>, which denotes infinity.
     61        - @b invert Invert is a boolean, if true the Trigger is in <em>invert-mode</em>, meaning, that if the triggering condition is fulfilled the Trigger will have the state <em>not triggered</em> and and if the condition is not fulfilled it will have the state <em>triggered</em>. In short it just inverts the behavior of the Trigger. The default is <code>false</code>.
     62        - @b mode The mode describes how the Trigger acts in relation to all the triggers, that are appended to it. There are 3 modes: <em>and</em>, meaning that the Trigger can only be triggered if all the appended triggers are active. <em>or</em>, meaning that the Trigger can only triggered if at least one of the appended triggers is active. And <em>xor</em>, meaning that the Trigger can only be triggered if one and only one appended trigger is active. Note, that I wrote <em>can only be active</em>, that implies, that there is an additional condition to the <em>activity</em> of the Trigger and that is the fulfillment of the triggering condition (the Trigger itself doesn't have one, but all derived classes should). Also bear in mind, that the <em>activity</em> of a Trigger is still coupled to the object that triggered it. The default is <em>and</em>.
     63        - Also there is the possibility of appending triggers (as long as they inherit from TriggerBase) to the Trigger just by adding them as children in the XML description of your Trigger.
    5564
    56   @ingroup NormalTrigger
    57   */
    58   class _ObjectsExport Trigger : public TriggerBase
    59   {
    60     public:
    61       Trigger(BaseObject* creator);
    62       virtual ~Trigger();
     65        An example of a Trigger created through XML would look like this:
     66        @code
     67        <Trigger position="0,0,0" delay="1.3" switch="true" stayactive="true" activations="7" invert="true" mode="xor" broadcast="false" target="Pawn">
     68            <TriggerBase />
     69            ...
     70            <TriggerBase />
     71        </Trigger>
     72        @endcode
    6373
    64       virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
    65       virtual void tick(float dt);
     74    @author
     75        Benjamin Knecht
    6676
    67       inline bool isActive(void) const
    68         { return this->bActive_; }
     77    @ingroup NormalTrigger
     78    */
     79    class _ObjectsExport Trigger : public TriggerBase
     80    {
     81        public:
     82            Trigger(BaseObject* creator); // Constructor. Registers and initializes the object.
     83            virtual ~Trigger();
    6984
    70       inline void setVisible(bool visibility)
    71         { this->debugBillboard_.setVisible(visibility); }
     85            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode); // Method for creating a Trigger object through XML.
     86            virtual void tick(float dt);
    7287
    73       void delayChanged(void);
     88            /**
     89            @brief Check whether the Trigger is active.
     90            @return Returns if the Trigger is active.
     91            */
     92            inline bool isActive(void) const
     93                { return this->bActive_; }
    7494
    75       bool switchState();
     95            void delayChanged(void); // React to a change in delay.
    7696
    77       static void debugFlares(bool bVisible);
    78       virtual void changedVisibility();
     97            static void debugFlares(bool bVisible); // Set the visibility of all debug billboards of all Triggers.
     98            virtual void changedVisibility(); // React to a change of visibility of the trigger by adjusting the visibility of the debug billboards.
    7999
    80     protected:
    81       inline bool isTriggered() { return this->isTriggered(this->mode_); }
    82       virtual bool isTriggered(TriggerMode::Value mode);
    83       virtual void triggered(bool bIsTriggered);
     100        protected:
     101            /**
     102            @brief Check whether the Trigger is triggered according to its mode.
     103            @return Returns true if the Trigger is triggered, false if not.
     104            */
     105            inline bool isTriggered()
     106                { return this->isTriggered(this->mode_); }
     107            virtual bool isTriggered(TriggerMode::Value mode); // Check whether the Trigger should be triggered, given only its sub-triggers, given a specific mode.
     108            virtual void triggered(bool bIsTriggered); // Fires an event with the input triggered state.
    84109
    85     private:
    86       bool checkAnd();
    87       bool checkOr();
    88       bool checkXor();
    89       void setBillboardColour(const ColourValue& colour);
    90       void storeState();
     110        private:
     111            bool switchState(); // Switch (toggle) the activity (to the outside the triggered state) of the trigger.
     112            void storeState(); // Stores the state in the queue.
     113           
     114            bool checkAnd(); // Check whether all the sub-triggers of this Trigger are active.
     115            bool checkOr(); // Check whether at least one of the sub-triggers of this Trigger is active.
     116            bool checkXor(); // Check whether exactly one of the sub-triggers of this Trigger is active.
     117           
     118            void setBillboardColour(const ColourValue& colour); // Set the colour of the debug billboard.
    91119
    92       bool bActive_;
    93       bool bTriggered_;
     120            bool bActive_; //!< Whether the trigger is active (to the outside triggered).
     121            bool bTriggered_; //!< Whether the trigger is triggered (to the inside).
    94122
    95       char latestState_;
    96       float remainingTime_;
    97       float timeSinceLastEvent_;
     123            char latestState_; //!< Temporarily stores a state consisting of whether the trigger is triggeres at the first bit (least significant bit) and its activity at the second bit.
     124            float remainingTime_; //!< The time until the next state (in the queue) takes effect.
     125            float timeSinceLastEvent_; //!< The time since the last event came in.
    98126
    99 //      bool bUpdating_;
    100       BillboardSet debugBillboard_;
     127            BillboardSet debugBillboard_; //!< A set of debug billboards to visualize the state of the trigger.
    101128
    102       std::queue<std::pair<float, char> > stateChanges_;
    103   };
     129            std::queue<std::pair<float, char> > stateChanges_; //!< A queue of state changes (in the same format as latestState_) paired with the time they will take effect since the last state change took effect.
     130    };
    104131
    105132}
  • code/trunk/src/modules/objects/triggers/TriggerBase.h

    r8193 r8213  
    6464    /**
    6565    @brief
    66         The TriggerBase class is a base class for the two types of triggers, the (normal) @ref orxonox::Trigger "Triggers" and the @ref orxonox::MultiTrigger "MultiTriggers", it encompasses the shared data and functionality between these two types of triggers, but is in itself not a trigger that has any meaningful behaviour and thus should not be instantiated.
     66        The TriggerBase class is a base class for the two types of triggers, the (normal) @ref orxonox::Trigger "Triggers" and the @ref orxonox::MultiTrigger "MultiTriggers", it encompasses the shared data and functionality between these two types of triggers, but is in itself not a trigger that has any meaningful behavior and thus should not be instantiated.
    6767
    6868    @author
     
    8181
    8282            /**
    83             @brief Check whether the trigger is active.
     83            @brief Check whether the trigger is active. (i.e. triggered to the outside)
    8484            @return Returns if the trigger is active.
    8585            */
Note: See TracChangeset for help on using the changeset viewer.