USING MODEL BEHAVIOURS

This section explains how to use the Model Behavior system and the Input Events to connect the nodes and animations that have been created by artists so that the plane reacts correctly to the various user inputs. This is done by building XML files that describe the different properties of each instrument. Using this system enables you to create templates that can be used to reduce greatly the amount of duplicated code and build up a library of functions that can be reused as you build more planes.

 

Before continuing, it is worth noting that using and creating Model Behaviors is a big task and requires a certain amount of work. As such, we strongly suggest that you revise the following pages of the main documentation to get a greater understanding of the information given in this section:

 

The rest of this page gives some general information about the basics of the model behavior system, after which you should progress and read through the following pages:

 

 

Setup

In the section on the Model CFG and Aircraft XML, you should have created some XML files that are meant to contain the Model Behavior code. In most cases, you will have created one file for the interior of the plane and one for the exterior. Their names should correspond to the names that are defined inside of the model.cfg file next to the parameters interior (for the interior) and exterior (for the exterior, which can also be normal).

 

While the standard structure would be to have both XML files inside of the model folder along with the model.cfg file, it is possible for them to be located elsewhere. This can be useful for variations, where the variation has exactly the same nodes and animations and doesn't require it's own XML file. Basically this lets you use the base aircraft XML file rather than having to write a custom one each time.

NOTE: The XML files that you have created can be opened with any text editor, though text editors that are designed for coding such as Notepad++ or Visual Studio are advised.

 

It is very important to note that there have been a great number of model behavior templates created for the default aircraft available in Microsoft Flight Simulator 2024. These templates can be used for your own aircraft, and we strongly recommend that whenever you want to implement an instrument or behavior, it is advised to search through the templates folder for anything that may be appropriate. This task is made simpler by using the SDK documentation, where all the templates are listed and can be explored:

NOTE: All the core behaviour files for Microsoft Flight Simulator 2024 are in the Asobo_EX1 folder. The core files for Microsoft Flight Simulator 2020 are in the Asobo folder. You should not mix and match templates from both folders. They may work together, but future updates may break this and in general all aircraft for MSFS 2024 should use the Asobo_EX1 templates.

 

As an Example, if you go to that page and then search "Anim", you will see highlighted a number of templates that can be of use to you, and these can be used to setup different animations without having to reinvent the wheel:

Example Image Of The Different Templates Using The Search Function

 

 

File Structure

The model XML files are standard XML files which should contain a single <ModelInfo> element at their root. That element will contain a <LODS> sub-element that is used by the artists to setup when LODs should change, and a <CompileBehaviors> sub-element which will contain all the model behavior implementation. Note that if you have issues with the compiled XML then you may instead use the <Behaviors> element here instead (but not the <ModelBehaviors> element, this is specific to additional XML as explained in the Additional XML Files section, below).

 

Once you have setup these initial elements, you can then move on and add in any <Include> and <Macro> elements that you need, inside of the <CompileBehaviors> top element. <Include> will be used to include any additional files containing the <Template> or <ParametersFn> that you wish to use, while <Macro> lets you add global scope parameters to the behaviors. If at any point you decide you need to use a template from a new file, then a new <Include> will need to be added:

<?xml version="1.0" encoding="utf-8"?>
<ModelInfo>
    <LODS>
        <LOD minSize="0" ModelFile="..\..\Part_Interior_Cockpit\model\Cockpit_LOD00.gltf"/>
        <LOD minSize="0" ModelFile="..\..\Part_Interior_Cockpit\model\Cockpit_LOD01.gltf"/>
        <LOD minSize="0" ModelFile="..\..\Part_Interior_Cockpit\model\Cockpit_LOD02.gltf"/>
        <LOD minSize="0" ModelFile="..\..\Part_Interior_Cockpit\model\Cockpit_LOD03.gltf"/>
    </LODS>
    <CompileBehaviors version="2">
        <Include ModelBehaviorFile="Asobo_EX1\Index.xml" />
        <Include ModelBehaviorFile="Asobo_EX1\DefaultConfig.xml" />
        ...
        <Macro Name="MY_MACRO_1">1</Macro>
        <Macro Name="MY_MACRO_2">2</Macro>
        ...
    </CompileBehaviors>
</ModelInfo>

 

Once you've added the files to be included, you should add the <IncludeBase> tags, if required. This is used when creating presets for aircraft variations and it lets you take a "base" file from a different location (for example the common folder), and then override the components that are not applicable to the current preset including the file. For example, using it on a preset that has skis instead of wheels allows you to use all the other airframe behaviours but overwrite the landing gear components with new components specific to the skis, rather than having to duplicate the whole XML file.

 

Finally, to complete the initial setup, you should also have one or more <Component> elements, along with and . These will be used to separate the different sections of the aircraft, and - since they can be imbricated - you can use them to describe broad sections, and then define panels, and then define individual instruments or switches. Here is an example of the overall basic structure:

<?xml version="1.0" encoding="utf-8"?>
<ModelInfo>
    <LODS>
        <LOD minSize="0" ModelFile="..\..\Part_Interior_Cockpit\model\Cockpit_LOD00.gltf"/>
        <LOD minSize="0" ModelFile="..\..\Part_Interior_Cockpit\model\Cockpit_LOD01.gltf"/>
        <LOD minSize="0" ModelFile="..\..\Part_Interior_Cockpit\model\Cockpit_LOD02.gltf"/>
        <LOD minSize="0" ModelFile="..\..\Part_Interior_Cockpit\model\Cockpit_LOD03.gltf"/>
    </LODS>
    <CompileBehaviors version="2">
        <IncludeBase RelativeFile="aircraft_common.xml"/>
        <Include ModelBehaviorFile="ASOBO_EX1\InteriorDefs.xml"/>
        ...
        <Macro Name="MY_MACRO_1">1</Macro>
        <Macro Name="MY_MACRO_2">2</Macro>
        ...
        <!-- Further includes and macros here -->
        <Component ID="Left_Panel">
            <Component ID="Throttle_Section"></Component>
            <Component ID="Lights_Section">
                <Component ID="Exterior_Lights"></Component>
                <Component ID="Interior_Lights"></Component>
                ...
            </Component>
        </Component>
        ...
        <!-- Further components here -->
        <ParametersFn Name="function_1">
            <ReturnParameters>
                <UseParametersFn Name="ASOBO_function_1">
                    <POS_0>OFF</POS_0>
                    <POS_1>ON</POS_1>
                </UseParametersFn>
            </ReturnParameters>
        </ParametersFn>
        ...
        <!-- Further ParametersFn here -->
    </CompileBehaviors>
</ModelInfo>

 

Writing a clear and logical structure can be very important in making sure that the XML code is maintainable and that debugging is simpler. It is worth taking the extra time to setup and prepare things properly before diving into implementing the different interactions.

 

 

Additional XML Files

If you are expecting to create a number of templates specific to the aircraft you are working on, it can be a good idea to create one or more extra XML files to store those templates, and these will also need to be included in the model XML using either the <Include> element (if you just wish to reference the behaviors) or the <IncludeBase> element (if you wish to both reference and potentially overwrite the behaviors). Having extra files can be a good way to separate out logical elements - making debugging and maintaining the code easier - and also create re-useable XML.

 

When creating these additional XML files, you should not use the <CompileBehaviors> element at the top level, since the <Include> elements from the main <model>.xml should already be inside this element. Instead these should have <ModelBehaviors> element at the top (and no <ModelInfo>):

<ModelBehaviors>
    <!-- INCLUDES -->
    <Include ModelBehaviorFile="ASOBO_EX1\InteriorDefs.xml"/>
    <Include RelativeFile="Cockpit_Behavior_Config.xml"/>
    ...
    <!-- MACROS -->
    <Macro Name="LIGHTING_Light_Cabin_Overhead_Pilot">1</Macro>
    <Macro Name="LIGHTING_Light_Cabin_Overhead_Copilot">2</Macro>
    ...
    <!-- COMPONENTS -->
    <Component ID="first">
        ...
    </Component>
    <Component ID="second">
        ...
    </Component>
    <!-- further components as required -->
</ModelBehaviors>

 

 

Components Hierarchy

Behaviors are defined using <Component> nodes, and a hierarchy of these nodes can be defined. In general, when defining a component hierarchy, you'll be using the following elements:

  1. <PartId>
  2. <CameraTitle>
  3. <FX>
  4. <AnimationTriggers>
  5. <Visibility>
  6. <EmissiveFactor>
  7. <Update>
  8. <Animation>
  9. <MouseRect>
  10. <UseInputEvent>

 

These elements are the main content you'll want to create, since they can take care of animation, interactions, visual effects, emissive textures and so on. Everything that has to be dynamic can be defined using a concrete component.

 

Each component is has to be given an "ID" and optionally a "Node" which will correspond to a node in the 3D model. For some elements such as <MouseRect> or <EmissiveFactor>, these can only be defined inside components with a Node. This node will be the one used to generate the clickable area in the case of a <MouseRect> and the emissive mesh for an <EmissiveFactor>. Generally, components will be structured as so:

<Component ID="A_Component">
    <!-- Elements definition here -->
    <!-- Only elements that don't require a node as target -->
    <!-- list: Animation, Triggers, Update, FX, InputEvent -->
</Component>
<Component ID="An_Other_Component" Node="A_GLTF_Node">
    <!-- Elements definition here -->
    <!-- Any element can be created here as there is a node defined -->
</Component>

 

 

Syntax

A component can be defined within a template definition or within a <CompileBehaviors>, <Behaviors>, or <ModelBehaviors> element (see the File Structure section for the differences between these top level elements). A component "ID" must be unique within the same scope.

<Component ID="Invalid_Declaration">
    <Component ID="A_Component"/>
    <Component ID="A_Component"/><!-- "A_Component" already exists! -->
</Component>
<Component ID="Valid_Declaration">
    <Component ID="A_Component"/>
    <Component ID="B_Component"/>
</Component>

 

 

Override

A component UID is defined by it's place in the hierarchy.

<!-- in some behavior file some_behavior.xml -->
<Component ID="Root_Component">
    <Component ID="Child_Comp"/><!-- UID is Root_Component:Child_Comp -->
</Component>

 

The component content can be overridden when it is included using <IncludeBase>. You would redefine the component content to target a specific base component using its UID with the attribute "OverrideID".

<!-- in an other behavior file -->
<IncludeBase RelativeFile="some_behavior.xml"/>
    <!-- Any content defined originally by the component in some_behavior.xml -->
    <!-- will be replaced by this definition instead -->
<Component ID="A_Component" OverrideID="Root_Component:Child_Comp"/>

 

 

Parameters

A parameter is used to store a value that you will want to use later in some function or element. They are created within some specific scopes defined by the following nodes:

  1. <Parameters>
  2. <UseParametersFn>
  3. <UseTemplate>
  4. <UseInputEvent>
  5. <ReturnParameters>
  6. <SaveParameters>
  7. <macro>

 

Parameters are the lynch-pin to using the model behavior XML and templates, and there is a full page dedicated to explaining how they work here:

 

 

Input Events

As part of the Model Behaviors, you can use Input Events. While this is a complex system to use, and interactions can be implemented without them, it is recommended to use this system and add an Input Event for each interaction. This is because they provide the following powerful features:

 

  • Input Events allow you to create Increase/Decrease operations for your interaction, which enables gamepad interactions, using the lock/unlock system.

 

  • Input Events allow you to intercept key Event IDs in order to force them to go through the Input Event's code rather than the normal C++ code.
    NOTE: This also means that you can disable some key events, or add some XML code to keys (By intercepting them, running your XML code, then calling that Key again

 

  • Input Events allow you to abstract a number of events into a single shorthand. As an example, to make the Copilot press a button in the checklist, you would normally have to set both the variable (and/or possible key) driving the button itself, but also for momentary buttons an extra LocalVar to make the button stay down for a second. Using input events, you can create a shorthand which holds down the button for a limited time, which can then be called Checklist side in a single instruction.

 

The following page provides more in-depth information about inputs:

 

You can find a full and detailed tutorial on input events within the SDK documentation:

 

 

Animation Conventions

There are a number of conventions that the Model Behavior templates use which you should be aware of. Unless you are writing your templates by hand, you will want to have your artists follow these conventions to ensure that the templates behave properly:

 

  • When an interaction (switch/lever/etc...) has a normal On/Off logic, frame 0 of the animation should correspond to Off, and the maximum frame should correspond to On.

 

  • When a knob can do a full 360° rotation, it should have at least 3, equidistant, frames in its animation to ensure that it rotates in the right direction.

 

  • When a knob can do a full 360° rotation, it should have its first and last frame at the same position, and the XML should set the <WRAP> parameter to true to ensure it properly wraps from 360° to 0°.

 

  • When a switch has more than 2 positions, it should have frame 0 at the bottom position - for vertical switches - or the left position - for horizontal switches.

 

  • Whenever possible, animations should have the same name as the nodes they are animating.

 

  • For creating levers, try to match the lever values (and note that levers all usually work the same way). Levers that lay on a pedestal go from the back to the front of the cockpit when animated. Levers that lay against a wall in front of the pilot go from the pushed to the pulled position. Gates (ie: idle) don’t need to be accounted for with keyframes.

 

  • Animations should be linear to be accurate, especially for needles.

 

  • When the gauge of a needle does not have linear intervals (say if an RPM gauge has the same angle between 0° and 40° than between 40° and 60°), the artist can separate the animation in linear intervals, to facilitate its XML implementation. If that artist adds frames at 0, 20, 40 and 60, the default needle template will be able to properly animate the needle without having to account for the non-linear gauge.