# Interaction Configurations Once the [cockpit interactions](creating-cockpit-interactions/) have been setup, you will want to properly configure the maximum amount of instruments before making use of [Interaction Procedures](interaction-procedures/) for more demanding or complex (interdependent) configurations.   The configuration of an instrument corresponds to the "behind the scenes" of what happens when you move switch, or push a button, etc... and configurations fall broadly into three categories: - the button (with a state) - the discrete state configuration - the event (without any state) All parameters set in an interaction can also be set in the return field of the configuration being created, allowing you to create custom mouserect code snippets easily (see [Advanced Interactions](advanced-interactions/) for more information).     ### Watching Variables An important part of configurations - and templates in general - is the ability to *watch* variables. A watched variable is one that is being polled constantly for data. To make use of watch vars for any given input event you can use some included [Parameter Function](../model-behaviors-component-overview/#Parameter_Functions) helpers to add one - or several - SimVars or LocalVars (XMLVars) to track:  
Template NameDescription
ASOBO_Watch_Simvar_HelperTake a single SIMVAR to watch, for example:
<UseParametersFn Name="ASOBO_Watch_Simvar_Helper">
    <SIMVAR>#SIMVAR_ADF_STANDBY_FREQUENCY#</SIMVAR>
</UseParametersFn>
ASOBO_Watch_Simvars_Helper

Take a list of SIMVARs to watch, for example:

<UseParametersFn Name="ASOBO_Watch_Simvars_Helper">
    <SaveParameters ID="Temp_Simvars_To_Watch">
        <LEFT_ENG_NH>TURB ENG CORRECTED N2:1</LEFT_ENG_NH>
        <RIGHT_ENG_NH>TURB ENG CORRECTED N2:2</RIGHT_ENG_NH>
    </SaveParameters>
</UseParametersFn>

Note that you must use the <SaveParameters> element with the ID "Temp_Simvars_To_Watch" when using this helper.

ASOBO_Watch_LocalVar_HelperTake a single LOCAL_VAR to watch, for example:
<UseParametersFn Name="ASOBO_Watch_LocalVar_Helper">
    <LOCAL_VAR>XMLVAR_ELECTRICAL_BATT_COVER</LOCAL_VAR>
</UseParametersFn>
ASOBO_Watch_LocalVars_Helper

Take a list of LOCAL_VARs to watch, for example:

<UseParametersFn Name="ASOBO_Watch_LocalVars_Helper">
    <SaveParameters ID="Temp_LocalVars_To_Watch">
        <VAR_LIGHT_MODE>XMLVAR_H125_LIGHT_MODE</VAR_LIGHT_MODE>
        <VAR_FORCE_MODE>XMLVAR_H125_LIGHT_FORCE_MODE</VAR_FORCE_MODE>
    </SaveParameters>
</UseParametersFn>

Note that you must use the <SaveParameters> element with the ID "Temp_LocalVars_To_Watch" when using this helper.

    ### Generic Helper Functions Here is an additional list of *generic* ParameterFN that can also be used to help you setup an input event:  
Template NameDescription
ASOBO_Append_Init_Code_HelperTake an <INIT_CODE> to append to <IE_VALUE_INIT_CODE>, for example:
<UseParametersFn Name="ASOBO_Append_Init_Code_Helper">
    <INIT_CODE>
        #GET_LIGHT_VALUE# 0.01  #MIN_LIGHT# #MAX_LIGHT# (F:Lerp) @IS_LIGHTMODE_NIGHT if{ @LIGHTMODE_NIGHT_COEF  } #SET_CIRCUIT_POWER_SETTING#
    </INIT_CODE>
</UseParametersFn>
ASOBO_Append_Value_Code_Helper

Take an <VALUE_CODE> to append to <IE_VALUE_CODE> and (optionally) <VALUE_UNITS> to append to <IE_VALUE_UNITS>, for example:

<UseParametersFn Name="ASOBO_Append_Value_Code_Helper">
    <VALUE_CODE>(L:1:XMLVAR_Brakes_Pressure)</VALUE_CODE>
    <VALUE_UNITS>psi</VALUE_UNITS>
</UseParametersFn>
ASOBO_Append_Inc_Code_HelperTake an <INC_CODE> to append to <IE_INC_CODE>, for example:
<UseParametersFn Name="ASOBO_Append_Inc_Code_Helper">
    <INC_CODE>p0 if{ #ON_EVENT_INC# }</INC_CODE>
</UseParametersFn>
ASOBO_Append_Dec_Code_Helper

Take an <DEC_CODE> to append to <IE_DEC_CODE>, for example:

<UseParametersFn Name="ASOBO_Append_Dec_Code_Helper">
    <DEC_CODE>p0 if{ #ON_EVENT_DEC# }</DEC_CODE>
</UseParametersFn>
ASOBO_Append_Set_Code_Helper

Take an <SET_CODE> to append to <IE_SET_CODE>, for example:

<UseParametersFn Name="ASOBO_Append_Set_Code_Helper">
    <SET_CODE>p0 if{ #ON_EVENT# }</SET_CODE>
</UseParametersFn>
  Note that all of these functions use the same base function and will also accept the following parameter: - `` - If "true", the provided content will appended *before* any already existing content.     ### Discrete State Configurations To give an example of a *simple* configuration, we'll look at a simple switch and see what we can do to configure the switch to toggle the autopilot yaw damper mode. Here is the basic switch XML: ``` xml OVHD_FLT_CONTROL_SWITCH_YAW_DAMPER_1 YAW_DAMPER ON_OFF_Settings 1 ON OFF ```   To create a configuration for this switch the first thing to do is create a new [Parameter Function](../model-behaviors-component-overview/#Parameter_Functions). Since we want to configure the switch to toggle the autopilot yaw damper mode, we'll call our function `YAW_DAMPER_Settings_Config`. The basics of this parameter function will be the following: ``` xml ``` {{< callout context="note" title="NOTE" icon="outline/bulb" >}} We make use of `ASOBO_Auto_Define_XStates_Variant_Helper` to ensure that the interaction parameters will be handled by the correct parser. {{< /callout >}}   Now we need to fill in the POS fields. To do so we can use another helper function provided by the [Model Behaviors Templates](../templates/templates/) giving a simple interface to all SimVars. In this case we'll be using the `ASOBO_Yaw_Damper_Parameters` helper, which is defined as follows: ``` xml AUTOPILOT YAW DAMPER (A:#SIMVAR_YAW_DAMPER#, Bool) (>K:YAW_DAMPER_SET) (>K:YAW_DAMPER_TOGGLE) #SIMVAR_YAW_DAMPER# #GET_YAW_DAMPER# #SET_YAW_DAMPER# #TOGGLE_YAW_DAMPER# ```   To make use of it, we add a [``](../../general-template-xml-properties/#Parameters) element with a [``](../../general-template-xml-properties/#UseParametersFn) sub-element where the yaw damper function is the target: ``` xml ```   Now we can use the interface to check and set the SimVar as needed: ``` xml #GET_YAW_DAMPER# ! #GET_YAW_DAMPER# 0 #SET_YAW_DAMPER# 1 #SET_YAW_DAMPER# ```   With that we're almost finished creating the switch configuration, with the final thing to do being synchronise the SimVar state to the switch state, ie: we want the switch to automatically move if the SimVar is changed externally (from a user keybind or any other source). To sync a SimVar to an input event we will use the `ASOBO_Watch_Simvar_Helper` function, along with the SimVar `AUTOPILOT YAW DAMPER` provided for us by the helper function in the `#SIMVAR_YAW_DAMPER#` parameter. The function ensures that our input event will be notified when the SimVar value changes so that the value field is recalculated. All we need to do now is add the following statement to our configuration to include this SimVar: ``` xml #SIMVAR_YAW_DAMPER# ```   The final step is to add the configuration "getter" to override the default interaction by adding the following statement in the initial [``](../../general-template-xml-properties/#UseTemplate) element: ``` xml YAW_DAMPER_Settings_Config ```   With that last statement the switch is done and is ready to be tested in the simulation. Here is the full code we have at this point: ``` xml OVHD_FLT_CONTROL_SWITCH_YAW_DAMPER_1 YAW_DAMPER ON_OFF_Settings YAW_DAMPER_Settings_Config 1 ON OFF #SIMVAR_YAW_DAMPER# #GET_YAW_DAMPER# ! #GET_YAW_DAMPER# 0 #SET_YAW_DAMPER# 1 #SET_YAW_DAMPER# ```     #### Additional Parameters By default when a discrete state configuration has only 2 possible states the interaction will be simplified to a simple toggle-on-click. However, if you wish to enforce a *drag* interaction you can use the following additional parameter: ``` xml False ``` For example: ``` xml BOX_SKI_SWITCH SKIS LandingGearOfSkis_Down_Up_Settings ASOBO_Gears_Settings_Config False 1 ```   When using a lever, by default the animation will show the in-between position when dragging with a mouse or controller. This may not be desirable if the lever can be locked by another source (for example some gears levers are mechanically locked). To prevent this behavior you can use the `SHOW_INTERMEDIARY_POS_CONDITION` parameter and specify an additional condition, for example: ``` xml (L:1:XMLVAR_Gears_lever_Locked) ! and ```     ### Enum Based Configurations Sometimes some switches are tied to several SimVars at a time. For example, if we have a light switch that can handle several light states depending on switch the position, we'll probably want to go this route. Let's look at an example and then we'll take it apart and examine the details: ``` xml 0 1 2 POSITION STROBE #IS_POS_BOTH# if{ 1 sp1 1 sp2 } #IS_POS_OFF# if{ 0 sp1 0 sp2 } #IS_POS_STEADY# if{ 1 sp1 0 sp2 } #GET_LIGHT_POSITION# l1 != if{ l1 #SET_LIGHT_POSITION# } #GET_LIGHT_STROBE# l2 != if{ l2 #SET_LIGHT_STROBE# } #SIMVAR_LIGHT_POSITION_SWITCH# #SIMVAR_LIGHT_STROBE_SWITCH# #IS_POS_BOTH# #IS_POS_OFF# #IS_POS_STEADY# #SET_POS_BOTH# #SET_POS_OFF# #SET_POS_STEADY# ```   The first thing to notice about this example is the enum declaration - it takes a set of enum values where each ID is given a number and saved in a [``](../../general-template-xml-properties/#saveparams) collection: ``` xml L 0 1 2 ``` This function will create an interface to *set* and *check* an enum value. For each position you'll get the following two parameters you can use: - `SET_POS_#` - Set the enum var to the \# value. - `IS_POS#` - Check if the enum var is equal to the \# value. We make use of these parameters to define the position to *check*, and also to *set* the position of our switch: ``` xml #IS_POS_BOTH# #IS_POS_OFF# #IS_POS_STEADY# #SET_POS_BOTH# #SET_POS_OFF# #SET_POS_STEADY# ```   To correctly set the SimVars we make use of the **init code**, which is an [RPN](../../../../../programming-apis/reverse-polish-notation/) sample executed at the start, and then again at any time a watched value changes (see [``](../../input-event-xml-properties/#Init) for more information): ``` xml #IS_POS_BOTH# if{ 1 sp1 1 sp2 } (* turn both lights on *) #IS_POS_OFF# if{ 0 sp1 0 sp2 } (* turn both lights off *) #IS_POS_STEADY# if{ 1 sp1 0 sp2 } (* turn position light on *) #GET_LIGHT_POSITION# l1 != if{ l1 #SET_LIGHT_POSITION# } #GET_LIGHT_STROBE# l2 != if{ l2 #SET_LIGHT_STROBE# } #SIMVAR_LIGHT_POSITION_SWITCH# #SIMVAR_LIGHT_STROBE_SWITCH# ```     ### Continuous State Configurations By default **all** input events are of the type *continuous state* which is why we don't need to do anything specific when we want to use this type of configuration (unlike for discrete state configurations). This type of configuration is fairly simple and takes very few parameters: - `IE_GET_STATE` - Return the current value - `IE_SET_STATE` - Set the current value - `VALUE_TYPE` - The type of value, can be any of the following:   {{< table-wrapper >}} | Name | Range | TT Format | Type | |-----------|------------|-----------|--------------| | `U16K` | 0 → 16K | %.1f%% | position 16k | | `S16K` | -16K → 16K | %.1f%% | position 16k | | `M16K` | -N → 16K | %.1f%% | position 16k | | `PERCENT` | 0 → 100% | %.1f%% | percent | | `NUMBER` | -A → B | %.1f | number | {{< /table-wrapper >}}   When in doubt use `NUMBER` and configure `MIN_VALUE` and `MAX_VALUE`.   As an example of how a continuous state configuration looks, we'll make one for a throttle lever, starting from this XML: ``` xml THROTTLE ENGINE_LEVER_THROTTLE ```   To create a configuration for this lever, the first thing to do is create a [Parameter Function](../model-behaviors-component-overview/#Parameter_Functions). Here we want to configure the lever to drive the throttle lever SimVar, so we'll simply call our function `THROTTLE_Settings_Config`. To make our life easier we can use a helper function provided with the model behaviors to get an interface to help configure our lever. In this case we'll be using `ASOBO_Throttle_Parameters` as defined below: ``` xml 1 (A:THROTTLE LOWER LIMIT, position 16k) @16K GENERAL ENG THROTTLE LEVER POSITION:#ENG_ID# position (A:#SIMVAR_THROTTLE#, #SIMVAR_THROTTLE_UNITS#) @16K / (>K:THROTTLE#ENG_ID#_SET) (A:#SIMVAR_THROTTLE#, position 16k) (>K:THROTTLE#ENG_ID#_SET) #SIMVAR_THROTTLE# #THROTTLE_MIN_VALUE_16K# #THROTTLE_MAX_VALUE_16K# #GET_THROTTLE# #SET_THROTTLE# #GET_THROTTLE_16K# #SET_THROTTLE_16K# ```   Here we are going to make this a simple throttle with no reverser capabilities, and for that we will need to override the `THROTTLE_MIN_VALUE_16K`, setting it to 0 to clamp the value. For that we can do this: ``` xml 0 ```   We can now define our `SET_STATE`, `GET_STATE`, and out `VALUE_TYPE`: ``` xml U16K #GET_THROTTLE_16K# #SET_THROTTLE_16K# ```   We then watch the `#SIMVAR_THROTTLE#` for changes: ``` xml #SIMVAR_THROTTLE# ```   Finally we need to add the configuration "getter" to override the default interaction by adding the following statement in the initial [``](../../general-template-xml-properties/#UseTemplate) element: ``` xml ASOBO_THROTTLE_Settings_Config ```   Putting all this together, we have the following lever code that can be tested in the simulation: ``` xml THROTTLE ENGINE_LEVER_THROTTLE THROTTLE_Settings_Config 0 U16K #GET_THROTTLE_16K# #SET_THROTTLE_16K# #SIMVAR_THROTTLE# ```     #### Curve (Trajectory drag only) A curve is a reinterpolation of the input event position for a given animation position. The configuration of the curve is stored in 2 different [``](../../general-template-xml-properties/#saveparams): - `PLOAD_AXIS_CURVE` - List of points (`POINT_#` starting a 0) defining the curve. Each point value will be it's identifier while evaluating the curve configuration. - `PLOAD_AXIS_CURVE_CONFIG` - Configuration of every point in the list.   Let's take the throttle example from above and remove the reverser limitation, as well as add a gate for the idle position. First we define the names of our saved parameters: ``` xml Throttle_Gates Throttle_Gates_Config ```   Then we define 1 point for the *Idle* gate: ``` xml Idle ```   And finally we configure this point so that when the animation is at 50% we set the value 0 into the input event *set* event: ``` xml 0 50 Both ```   Here is the final configuration of the throttle with an idle gate (notice that since we have an asymmetric 16K value we use M16K as the value type and not S16K): ``` xml 0 50 Both M16K #GET_THROTTLE_16K# #SET_THROTTLE_16K# #SIMVAR_THROTTLE# Throttle_Gates Throttle_Gates_Config Idle #IDLE_IE_PERCENT_SET# #IDLE_ANIM_PERCENT# #IDLE_GATE_DIRECTION# ```     #### Drag Sensitivity Drag sensitivity doesn't affect mouse use for trajectory drag, but it *will* affect every other kind of drag interaction. For this, a threshold is defined by 2 values: - `THRESHOLD_RELATIVE` - Threshold for devices using *relative* coordinates (controller) - `THRESHOLD_ASBOLUTE` - Threshold for devices using *absolute* coordinates (mouse)   Generally we rely on some presets for these values depending on how much/how fast the value needs to change. These presets are defined in [Parameter Functions](../model-behaviors-component-overview/#Parameter_Functions) and specified by the parameter `PFN_DELTA_THRESHOLD_VALUES`. By default every interaction uses the `ASOBO_Drag_Threshold_Small` parameter function. The table below shows a list of all the default threshold for the different drag presets you can use: {{< callout context="note" title="NOTE" icon="outline/bulb" >}} The smaller a threshold value is, the more reactive the input will feel. {{< /callout >}} {{< table-wrapper >}} | Function Name | Relative Threshold | Absolute Threshold | |----------------------------------------|--------------------|--------------------| | `ASOBO_Drag_Threshold_Extremely_Small` | 0.00025 | 0.0001 | | `ASOBO_Drag_Threshold_Very_Small` | 0.001 | 0.00025 | | `ASOBO_Drag_Threshold_Small` | 0.0025 | 0.001 | | `ASOBO_Drag_Threshold_Medium` | 0.00625 | 0.004 | | `ASOBO_Drag_Threshold_Large` | 0.015625 | 0.016 | | `ASOBO_Drag_Threshold_Very_Large` | 0.039 | 0.032 | | `ASOBO_Drag_Threshold_States` | 0.01 | 0.005 | | `ASOBO_Drag_Threshold_States_No_Gates` | 0.025 | 0.025 | {{< /table-wrapper >}}   Additionally you can set the parameter `THRESHOLD_TRANSFORM_VALUE`, which takes the number of times the threshold has been crossed, and - by default - returns it. Discrete states use the `ASOBO_Drag_Threshold_Statesand ``ASOBO_Drag_Threshold_States_No_Gates` depending of if there are any gates defined.     #### Value The displayed value can be formatted using the `TOOLTIP_VALUE_FORMAT` parameter: ``` xml '%d ft' ```   If you are using a NUMBER value type, the limits can also be specified either using of the following: - `MIN_VALUE` - Minimum reachable value - `MAX_VALUE` - Maximum reachable value - `CLAMP_VALUE` - User defined clamp (for example, using `dnor`)   The type of the value can be specified using the parameter `IE_VALUE_UNITS`. For example, to configure an input event to use degrees for the value we would use: ``` xml Degrees ```   Note that if `IE_VALUE_UNITS` is defined, the `TOOLTIP_VALUE_FORMAT` will be pre-filled for some units. See the `ASOBO_Format_Tooltip_Value_Units_Helper` parameter helper for a list of all units handled by default.   The way the value is incremented or decremented can be controlled using the following parameters: - `IE_INCREMENT` - Increment added (see ``) or removed (see ``) when using the Increment and Decrement keys - `INCREMENT_PER_THRESHOLD` - Increment added every time a threshold is crossed (see the section on [Drag Sensitivity](interaction-configurations/#DragSensitivity) to see how to configure the threshold sensitivity). - `INFINITE_ANIM_SCALE_FACTOR` - This is for Infinite interactions only and lets you configure how fast the rotation variable moves in comparison to the input event value.     ### Event Configuration For event configuration we will be using the `ASOBO_Auto_Define_Event_Param_Helper` parameter function to define what happens on 2 events (optional): - `ON_EVENT_SET` - Event triggered when entering the interaction (on click) - `ON_EVENT_RELEASE` - Event triggered when leaving the interaction (on release) To illustrate this, well make the barometric toggle button, so that it toggles the standard mode for the selected barometer when clicked: ``` xml BARO_STD GLSHD_EFIS_PUSH_BARO_STD 7 ```   To make our life easier we can use a helper function provided by the model behavior templates to get an interface to help configure our button. In this case we'll be using `ASOBO_Baro_Parameters`, and with that the only important thing we need to do is configure our `ON_EVENT_SET` to toggle the barometer standard mode: ``` xml #GET_BARO_STD# ! #SET_BARO_STD# ```   With this helper we'll also need to configure the tooltips as they are not included as part of the helper, using something like the following: ``` xml (R:1:@TT_Package.STATE.OFF) (R:1:@TT_Package.STATE.STANDARD) #GET_BARO_STD# if{ #TOOLTIP_STD# } els{ #TOOLTIP_NOT_STD# } ```   We also shouldn't forget to add the configuration getter to override the default interaction by adding the following statement in the initial [``](../../general-template-xml-properties/#UseTemplate) element: ``` xml ASOBO_Baro_STD_Settings_Config ```   With that last statement our button is done and can be tested in game. The full code looks something like that shown below: ``` xml BARO_STD GLSHD_EFIS_PUSH_BARO_STD 7 ASOBO_Baro_STD_Settings_Config (R:1:@TT_Package.STATE.OFF) (R:1:@TT_Package.STATE.STANDARD) #GET_BARO_STD# if{ #TOOLTIP_STD# } els{ #TOOLTIP_NOT_STD# } #GET_BARO_STD# ! #SET_BARO_STD# #SIMVAR_BARO_STD# ```   There are a couple of additional templates that can be useful for doing event configuration:   - `ASOBO_Add_Button_Long_Press_Event_Helper` - this is used to add a handler to the input event to trigger an [RPN](../../../../../programming-apis/reverse-polish-notation/) snippet `ON_LONG_PRESS_EVENT` when the button has been pressed for a given duration (defined using `LONG_PRESS_DURATION` - in seconds). A code snippet will also be added to the `ON_EVENT_SET` parameter. If you wish to change this target parameter you can override `OUT_EVENT_PARAM_NAME` with the desired parameter name: ``` xml ON_EVENT ``` Afterward you need to call `ASOBO_Auto_Define_Event_Param_Helper` to append your event trigger.   - `ASOBO_Add_Button_Down_Event_Helper` - this is used to add a handler to the input event to trigger an [RPN](../../../../../programming-apis/reverse-polish-notation/) snippet `ON_BUTTON_DOWN` every frame while the button is down. A code snippet will also be added to the `ON_EVENT_SET` parameter. If you wish to change this target parameter you can override `OUT_EVENT_PARAM_NAME` with the desired parameter name: ``` xml ON_EVENT ``` Afterward you need to call `ASOBO_Auto_Define_Event_Param_Helper` to append your event trigger.     ### Binding Configurations When it comes to using configurations, they can be exceptionally helpful when used along with input **bindings**. Bindings are explained in the detail on the [Input Bindings](../model-behaviors-inputs/#InputBindings) page, however that explains the *low-level* concept and creation of bindings directly within the input events, something that you generally don't have to do when using the model behavior templates and configurations. Instead it's usually done using one of the following helpers: - [ASOBO\_Add\_Inc\_Binding\_Helper](../../templateexplorer/asobo-ex1/generic/interior/templates/parametersfn/interaction-helpers/#ASOBO_Add_Inc_Binding_Helper) - Create a binding for the [``](../../input-event-xml-properties/#Inc) event. - [ASOBO\_Add\_Dec\_Binding\_Helper](../../templateexplorer/asobo-ex1/generic/interior/templates/parametersfn/interaction-helpers/#ASOBO_Add_Dec_Binding_Helper) - Create a binding for the [``](../../input-event-xml-properties/#Dec) event - [ASOBO\_Add\_Set\_Binding\_Helper](../../templateexplorer/asobo-ex1/generic/interior/templates/parametersfn/interaction-helpers/#ASOBO_Add_Set_Binding_Helper) - Create a binding for the [``](../../input-event-xml-properties/#Set) event   A binding is identified using and *alias* or an *event ID*: - `ALIAS_ID` - the name of the binding - `EVENT_ID` - name of the event ID (key event) The binding can then define what to do with each parameter by specifying a list of `PARAM_#` starting at 0. If a parameter does not need to be evaluated as [RPN](../../../../../programming-apis/reverse-polish-notation/) (ie: it's a literal value), you can set `PARAM_#_IS_DYNAMIC` to "False" to save on computation time. For example: ``` xml U16K 0 @16K #GET_LIQUID_DROPPING_DOOR_TARGET_POSITION_16K# #SET_LIQUID_DROPPING_DOOR_TARGET_POSITION_16K# #SIMVAR_LIQUID_DROPPING_DOOR_TARGET_POSITION# TOGGLE #GET_LIQUID_DROPPING_DOOR_TARGET_POSITION_16K# 0 > if{ 0 } els{ @16K } True ```