• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

MSFS Here's how to write you own ModelBehavior code.

Messages
1,049
Country
australia
Code:
<UseTemplate Name="ASOBO_GT_Anim_Code">
    <ANIM_NAME>a582_TailWheel</ANIM_NAME>
    <ANIM_CODE>(A:RUDDER DEFLECTION PCT,percent) 110 +</ANIM_CODE>
    <ANIM_LENGTH>210</ANIM_LENGTH>
</UseTemplate>

ANIM_NAME is the name of your animation part in your modeling program.

ANIM_CODE is any XML code you like.

ANIM_LENGTH is ... do I really need to explain this one?

ASOBO_GT_Anim_Code is at the core of just about every template. It creates the header information such as anim name, GUID. This template itselfs calls other subtemplates but it eventually boils down to just this:

Code:
        <Animation Name = "#ANIM_NAME#" Guid = "#ANIM_GUID#" Length = "#ANIM_LENGTH#" Type = "Sim" TypeParam = "AutoPlay">
            <Parameter>
                <Code>#ANIM_CODE#</Code>
                <Lag>#ANIM_LAG#</Lag>
                <Wrap>#ANIM_WRAP#</Wrap>
                <Delta>#ANIM_DELTA#</Delta>
                <BlendWeight>#ANIM_BLENDWEIGHT#</BlendWeight>
            </Parameter>
        </Animation>

I don't know how the sim generates the GUID but it does. Some sort of magic going on there so you shouldn't need to add any GUIDs yourself.

Anything else you can just add an element to overwrite the default. ANIM_CODE and ANIM_LENGTH in my example show how to do this.

I think Wrap is TRUE or FALSE and probably smoothly wraps the animation around if you use Lag. No idea what Delta and BlendWeight do.

Note how the core code is very similar to the code we used in PartInfo. There are variations (for example, the emissive code is different) and this doesn't include mouse code.
 
Messages
10,088
Country
us-arizona
Many thanks, Anthony31!

I am hoping we can put these in a folder system with our planes instead of mixing up code in the 'Official' folder system. Example, what if we could place these in the panel folder? Or perhaps duplicate a folder name of the Asobo Behaviors folder(s) and have that in our aircrafts folder structure in 'Community'.
 
Messages
1,049
Country
australia
As a continuation from my original post here is some more details on ModelBehavior.

ModelBehavior code is very similar to PartInfo code (the code used in FSX and P3D) but it is not exactly the same. You can write ModelBehavior code directly into your model xml (I will show an example later where the template is no more efficient than writing the code directly). The templates are essentially macros. The problem with the templates is they are not documented. To understand which parameters they take you need to search through multiple templates in multiple files and piece it all together. Most of the templates boil down to the simple ASOBO_GT_Anim_Sim and ASOBO_GT_Anim_Code subtemplates. In a lot of circumstances it would be easier to call this directly yourself rather than deciphering the various templates.


INCLUDE FILES

In these examples you need to include in your model xml the common.xml for the ASOBO_GT_Anim_Sim or ASOBO_GT_Anim_Code templates and Generic.xml for Visibility and Emissive

<Include ModelBehaviorFile="Asobo\Common.xml"/>
<Include ModelBehaviorFile="Asobo\Generic.xml"/>

In this guide I list the required parameters and optional parameters. Required parameters must be entered to make it work. Optional parameters have default values in (parentheses). (F/T) indicates FALSE/TRUE with FALSE the default. (T/F) indicates TRUE is default.


CREATING AN ANIMATION

Select either ASOBO_GT_Anim_Sim or ASOBO_GT_Anim_Code template to create your code. Ensure you include the common.xml. Most of the ASOBO templates will call these subtemplates as they are at the heart of every animation.

ASOBO_GT_Anim_Sim
Base template that provides animation using the Simvar format. ANIM_NAME is the name of the NLA animation track in your 3D model. Note that it is NOT the part name (the reason will become clearer later). As you can see in the example this is very easy to implement. You don't need to think about it too much and no need to decipher the ASOBO templates. Simply supply a handful of parameters and the template handles the rest.


Required parameters:
ANIM_NAME
ANIM_SIMVAR
ANIM_SIMVAR_UNITS

Optional parameters:
ANIM_LENGTH (100)
ANIM_SIMVAR_SCALE (1)
ANIM_SIMVAR_BIAS (0)
ANIM_LAG (0)
ANIM_WRAP (F/T)

DISABLE_ANIMATION (T/F)
INVERT_ANIM (T/F)
FAILURE (?)

Example:
Code:
<UseTemplate Name="ASOBO_GT_Anim_Sim">
    <ANIM_NAME>a582_Wheel_Centre</ANIM_NAME>
    <ANIM_SIMVAR>CENTER WHEEL ROTATION ANGLE</ANIM_SIMVAR>
    <ANIM_SIMVAR_UNITS>radians</ANIM_SIMVAR_UNITS>
    <ANIM_SIMVAR_SCALE>15.91</ANIM_SIMVAR_SCALE>
    <ANIM_SIMVAR_BIAS>0</ANIM_SIMVAR_BIAS>
    <ANIM_LENGTH>100</ANIM_LENGTH> <!-- This is unnecessary as the default length is 100 -->
</UseTemplate>



ASOBO_GT_Anim_Code
Base template that provides animation driven by code.

Required parameters:
ANIM_NAME
ANIM_CODE

Optional parameters:
ANIM_LENGTH (100)
ANIM_LAG (0)
ANIM_WRAP (F/T)
ANIM_DELTA (F/T)
ANIM_BLENDWEIGHT (1.0)

Example:
Code:
<UseTemplate Name="ASOBO_GT_Anim_Code">
    <ANIM_NAME>a582_Elevator</ANIM_NAME>
    <ANIM_CODE>(A:ELEVATOR POSITION,percent) + 110 + 10 max 210 min</ANIM_CODE>
    <ANIM_LENGTH>210</ANIM_LENGTH>
</UseTemplate>
 
Last edited:
Messages
1,049
Country
australia
ADDING A VISIBILITY CONDITION:

Now, here is a very important distinction between ModelBehavior code and PartInfo code. With PartInfo you could either use an Attachpoint (no longer supported in MSFS) or add it to an animated. With ModelBehavior the visibility condition is completely separate to any animation. You can easily make non-animated parts visible or not visible. While the ASOBO_GT_Anim templates refer to the name of the animation in your 3D model visibility refers to the name of your part.

To attach a visibility condition to any part you use the Component element.

Example:
Code:
<Component ID="ELEVATOR" Node="ELEVATOR">
    <UseTemplate Name="ASOBO_GT_Visibility">
        <VISIBILITY_CODE>(A:ELEVATOR POSITION,percent) 0 &gt;</VISIBILITY_CODE>
    </UseTemplate>
</Component>

Component ID probably needs to be unique. The Node is the name of the part (not the animation) in your 3D model. Any children of the part will be affected. In the ASOBO code the ID and Node are always the same so it is probably wise to follow the same convention. If you wish to attach multiple conditions to a single part you should probably put them all inside the same Component element.

For example, this code snippet the GT_Anim_Code template animates the elevator. The component ID that calls ASOBO_GT_Visibility makes the ELEVATOR part in the 3D model invisible. They are completely independent processes. Note how this is different to <PartInfo> coding where you need to have the Animation and Visibility elements all within the <PartInfo> element.

Code:
<UseTemplate Name="ASOBO_GT_Anim_Code">
    <ANIM_NAME>a582_Elevator</ANIM_NAME>
    <ANIM_CODE>(A:ELEVATOR TRIM PCT,percent) 50 / (A:Dynamic pressure,number) sqrt * (A:ELEVATOR POSITION,percent) + 110 + 10 max 210 min</ANIM_CODE>
    <ANIM_LENGTH>210</ANIM_LENGTH>
</UseTemplate>
<Component ID="ELEVATOR" Node="ELEVATOR">
    <UseTemplate Name="ASOBO_GT_Visibility">
        <VISIBILITY_CODE>(A:ELEVATOR POSITION,percent) 0 &gt;</VISIBILITY_CODE>
    </UseTemplate>
</Component>



ASOBO_GT_Visibility
Additional template to provide control of visibility

If using VISIBILITY_CODE:
Required parameters:
VISIBILITY_CODE

If using VISIBILITY_SIMVAR:
Required parameters:
VISIBILITY_SIMVAR
VISIBILITY_SIMVAR_UNITS

Optional parameters:
VISIBILITY_SIMVAR_SCALE (1)
VISIBILITY_SIMVAR_BIAS (0)

If you enter a VISIBILITY_SIMVAR parameter then the template will use the simvar format otherwise it will expect to use the VISIBILITY_CODE.


You can write the code directly if you wish. Using the template only saves a couple of lines. For example, this code does exactly the same thing as the code above that is using the ASOBO_GT_Visibility template:

Code:
<Component ID="ELEVATOR" Node="ELEVATOR">
    <Visibility>
        <Parameter>
            <Code>(A:ELEVATOR POSITION,percent) 0 &gt;</Code>
        </Parameter>
    </Visibility>
</Component>
 
Messages
1,049
Country
australia
ADDING AN EMISSIVE

Adding an emissive is the same theory as visibility. Again, it is completely separate from the animation code so you can add emissive to any part. Simply use the Component element and assign the Node name to the part in your 3D model. I don't know how emissive works if the part has multiple textures or if it only supports one texture per part.

I haven't quite interpreted the templates that ASOBO uses for emissive as there are a few in the generic/emissive.xml so I will only docuement ASOBO_GT_Material_Emissive_Sim and ASOBO_GT_Material_Emissive_Code.

ASOBO_GT_Material_Emissive_Sim

Required parameters:
EMISSIVE_SIMVAR
EMISSIVE_SIMVAR_UNITS

Optional parameters:
EMISSIVE_SIMVAR_SCALE (1)
EMISSIVE_SIMVAR_BIAS (0)
DONT_OVERRIDE_BASE_EMISSIVE (T/F)
ASOBO_GT_Part_ID (not sure what this does)


ASOBO_GT_Material_Emissive_Code

Required parameters:
EMISSIVE_CODE

Optional parameters:
FAILURE (1) (0 is a complete failure, 1 is working)
EMISSIVE_CODE_FACTOR (F/T)
ASOBO_GT_Part_ID (not sure what this does)

Example:
Code:
<Component ID="Horizontal_stab_left" Node="Horizontal_stab_left">
    <UseTemplate Name="ASOBO_GT_Material_Emissive_Code">
        <EMISSIVE_CODE>(A:ELEVATOR POSITION,percent)</EMISSIVE_CODE>
    </UseTemplate>
</Component>

An alternative to using the templates is to write the code directly into the component element.

Code:
<Component ID="Horizontal_stab_left" Node="Horizontal_stab_left">
    <Material>
        <EmissiveFactor>
            <Parameter>
                <Code>0 is no emissive, 1 is fully emissive</Code>
            </Parameter>
            <OverrideBaseEmissive>TRUE</OverrideBaseEmissive>
        </EmissiveFactor>
    </Material>
</Component>

Yes, I made my horizontal stabilizer change brightness by moving the elevator. It works and it's hilarious.
 
Messages
1,049
Country
australia
CREATING YOUR OWN TEMPLATE

I won't go into detail here. If you are smart enough to want to create your own templates then you're smart enough to read the ASOBO examples and use them as a basis. You can create your own templates in your model xml or using the virtual file system create a separate XML which you would need to include in your model xml.

Here is a generic template that combines the Animation code and the Visibility coding. To use this simply copy the code into the xml file, just below the Includes would be a good place.

Code:
<Template Name = "Change_this_to_your_own_unique_template_name">
    <DefaultTemplateParameters>
        <ANIM_GUID/>
        <ANIM_WRAP>FALSE</ANIM_WRAP>
        <ANIM_DELTA>FALSE</ANIM_DELTA>
        <ANIM_BLENDWEIGHT>1.0</ANIM_BLENDWEIGHT>
    </DefaultTemplateParameters>
    <EditableTemplateParameters>
        <AddParams>
            <ANIM_NAME/>
        </AddParams>
    </EditableTemplateParameters>

    <UseTemplate Name="ASOBO_GT_Anim_Code">
    </UseTemplate>
    
    <Component ID="#NODE_ID#" Node="#NODE_ID#">
        <UseTemplate Name="ASOBO_GT_Visibility">
        </UseTemplate>
    </Component>
</Template>

To call this template use:
Code:
<UseTemplate Name="Change_this_to_your_own_unique_template_name">
    <ANIM_NAME>a582_Elevator</ANIM_NAME>
    <ANIM_CODE>(A:ELEVATOR POSITION,percent) + 110 + 10 max 210 min</ANIM_CODE>
    <ANIM_LENGTH>210</ANIM_LENGTH>
    <NODE_ID>ELEVATOR<NODE_ID>
    <VISIBILITY_CODE>(A:ELEVATOR POSITION,percent) 0 &gt;</VISIBILITY_CODE>
</UseTemplate>
 
Messages
1,049
Country
australia
CREATING MOUSE ZONES

Mouse zones are similar to emissive and visibility in that they are attached to a <Component> element. Therefore, your mouse zone does not need to be the part it is animating so you can use a larger mouse square if you have a tiny switch.

Asobo has provided a number of templates in Generic/Complex that covers things such as knobs, levers, pushbuttons and switches. These templates also include code to control animations. But this post is about writing your own code and not re-using Asobo templates.

All Asobo templates lead to ASOBO_GT_MouseRect and that template leads to ASOBO_GT_MouseRect_Impl which is where the actual mouse rectangle code is written. ASOBO_GT_MouseRect_Impl is a complex template with nearly 200 lines of code most of which I don't understand. There are a lot of new parameters such as <IMCursorsInstances>. I don't know what the IM stands for but there are a lot of parameters that are called IM.

I highly recommend that you take a look at ASOBO_GT_MouseRect_Impl in OneStore/fs-base-aircraft-common/ModelBehaviourDefs/Asobo/Generic/Interactions.xml. This is the base code for mouse rectangles and contains everything, far more than I will explain in this brief introduction. We will use just a subset of the possible code.

One point I will make is that if you have used the right mouse button for interactions in the past then you probably shouldn't use it in MSFS. By default holding the right mouse button down allows the user to move the view with the mouse. The middle click does the same but it toggles mouse view on/off. I'd therefore recommend against using middle or right mouse actions and just limit yourself to left mouse click.

So, I think I will start with some simple code as an example. The examples I have created are based on the Asobo interactions templates. I have stripped them down to the core elements that do what I need and passed those elements to ASOBO_GT_MouseRect (which passes them on to ASOBO_GT_MouseRect_Impl). This example provides a mouse zone for a switch. I wanted to use the mouse wheel to toggle the switch as well as the standard left click to toggle on/off.

Code:
<Component ID="MouseZone_FuelPump" Node="MouseZone_FuelPump">       
    <UseTemplate Name="ASOBO_GT_MouseRect">
        <TOOLTIPID>Fuel Pump:%((A:GENERAL ENG FUEL PUMP SWITCH:1, Bool))%{if}ON%{else}OFF%{end}</TOOLTIPID>
        <CURSOR>Hand</CURSOR>
        <MOUSEFLAGS_DEFAULT_IM>LeftSingle+WheelUp+WheelDown</MOUSEFLAGS_DEFAULT_IM>
        <CALLBACKCODE_DEFAULT_IM>
            (M:Event) 'LeftSingle' scmi 0 == if{ (&gt;K:FUEL_PUMP) }
            (M:Event) 'WheelUp'    scmi 0 == if{ (A:GENERAL ENG FUEL PUMP SWITCH:1,bool) 0 == if{ (&gt;K:FUEL_PUMP) } }
            (M:Event) 'WheelDown'  scmi 0 == if{ (A:GENERAL ENG FUEL PUMP SWITCH:1,bool) 0 != if{ (&gt;K:FUEL_PUMP) } }           
        </CALLBACKCODE_DEFAULT_IM>
    </UseTemplate>   
</Component>

TOOLTIPID - This is equivalent to ToolTipText in the old FSX code. You can enter simple text here or complex text scripts. Preset tooltips can be called using the TT: code. The majority of ASOBO templates use the preset tooltips (which I presume are translated automatically) to display information. For example:

<TOOLTIPID>TT:COCKPIT.TOOLTIPS.FUEL_PUMP_SWITCH_ON</TOOLTIPID>

Asobo has not listed the tooltip codes (still TO DO I guess) but I have attached a list of the codes that I have pulled from the XML code in the Asobo model behaviors files. The first part is a list of used mouse Cursors. The second part is mostly text scripts that give you an idea how to do the complex scripts. Below that is an alphabetical listing of the tooltips. NOTE: These were pulled from the XML code so you may get some odd ordering and it is also no guarantee that these are all the tooltips.

Personally, I don't like the way Asobo has created tooltips. For example, if you are going through a checklist and it says FUEL PUMP ON then that is what I want the tooltip to say. It shouldn't say "Turn off fuel pump". That is too confusing in the cockpit, you end up having to figure out whether it means the fuel pump is already on or off.

CURSOR - These are the cursors I have been able to find in the templates and that work: TurnRight, TurnLeft, TurnRightSmall, TurnLeftSmall, TurnRightUpSideDown, TurnLeftUpSideDown, Hand, UpArrow, DownArrow, LeftArrow, RightArrow, Grab. The following names appear in the code but they do not appear to work with normal cursors: Animtip, Center_Cursor, Cursor, Center_Radius.

MOUSEFLAGS_DEFAULT_IM - LeftSingle, LeftDrag, LeftRelease, WheelUp, WheelDown seem to be the most common. As I said before Right and Middle mouse buttons are used to control the mouse view so unless you have a good reason I would advise against using them.

CALLBACKCODE_DEFAULT_IM - Some nice XML code. The mouse code supports CallbackJumpDragging and CallbackDragging although I refer you back to ASOBO_GT_MouseRect_Impl to see exactly which parameters are required as there are some new ones in all the callback elements.



Let's look at a more complex example. In this case the altimeter knob is partially obscured in my aircraft so I wanted click spots above and below the knob. Holding down the mouse button will repeatedly adjust the altimeter. Using the mouse wheel will also adjust the altimeter.

Code:
<Component ID="MouseZone_Altimeter_Inc" Node="MouseZone_Altimeter_Inc">       
    <Update Frequency = "10" InteractionModel="Default">
        (O:XMLVAR_FirstUpdateTime) 0 !=
        if{
            (O:XMLVAR_FirstUpdateTime) (E:SIMULATION TIME, seconds) &lt; if{ (&gt;K:KOHLSMAN_INC) }
        }
    </Update>
    <UseTemplate Name="ASOBO_GT_MouseRect">
        <TOOLTIPID>%((P:Units of measure, enum) 2 == )%{if}%((A:KOHLSMAN SETTING HG, mbar))%!d!TT:COCKPIT.TOOLTIPS.MBAR%{else}TT:COCKPIT.TOOLTIPS.ALTIMETER_CALIBRATION_KNOB_INHG</TOOLTIPID>
        <CURSOR>TurnLeft</CURSOR>
        <MOUSEFLAGS_DEFAULT_IM>LeftSingle+LeftRelease+WheelUp+WheelDown</MOUSEFLAGS_DEFAULT_IM>
        <CALLBACKCODE_DEFAULT_IM>
            (M:Event) 'LeftSingle' scmi 0 == if{
                (&gt;K:KOHLSMAN_INC)
                (E:SIMULATION TIME, seconds) 0.4 (&gt;O:XMLVAR_FirstUpdateTime)
                }
            (M:Event) 'WheelUp'    scmi 0 == if{ (&gt;K:KOHLSMAN_INC) }
            (M:Event) 'WheelDown'  scmi 0 == if{ (&gt;K:KOHLSMAN_DEC) }
            (M:Event) 'LeftRelease'   scmi 0 == if{ 0 (&gt;O:XMLVAR_FirstUpdateTime) }
        </CALLBACKCODE_DEFAULT_IM>
    </UseTemplate>   
</Component>
<Component ID="MouseZone_Altimeter_Dec" Node="MouseZone_Altimeter_Dec">       
    <Update Frequency = "10" InteractionModel="Default">
        (O:XMLVAR_FirstUpdateTime) 0 !=
        if{
            (O:XMLVAR_FirstUpdateTime) (E:SIMULATION TIME, seconds) &lt; if{ (&gt;K:KOHLSMAN_DEC) }
        }
    </Update>
    <UseTemplate Name="ASOBO_GT_MouseRect">
        <TOOLTIPID>%((P:Units of measure, enum) 2 == )%{if}%((A:KOHLSMAN SETTING HG, mbar))%!d!TT:COCKPIT.TOOLTIPS.MBAR%{else}TT:COCKPIT.TOOLTIPS.ALTIMETER_CALIBRATION_KNOB_INHG</TOOLTIPID>
        <CURSOR>TurnRight</CURSOR>
        <MOUSEFLAGS_DEFAULT_IM>LeftSingle+LeftRelease+WheelUp+WheelDown</MOUSEFLAGS_DEFAULT_IM>
        <CALLBACKCODE_DEFAULT_IM>
            (M:Event) 'LeftSingle' scmi 0 == if{
                (&gt;K:KOHLSMAN_DEC)
                (E:SIMULATION TIME, seconds) 0.4 (&gt;O:XMLVAR_FirstUpdateTime)
                }
            (M:Event) 'WheelUp'    scmi 0 == if{ (&gt;K:KOHLSMAN_INC) }
            (M:Event) 'WheelDown'  scmi 0 == if{ (&gt;K:KOHLSMAN_DEC) }           
            (M:Event) 'LeftRelease'   scmi 0 == if{ 0 (&gt;O:XMLVAR_FirstUpdateTime) }
        </CALLBACKCODE_DEFAULT_IM>
    </UseTemplate>   
</Component>

The interesting thing about this code is the <Update> element. It is not related at all to the mouse zone but it is used here to repeat an action while the mouse button is held down. The mouse code is used to turn on and off the update by writing into (O:XMLVAR_FirstUpdateTime). I assume Frequency is times per second, no idea what InteractionModel does. I don't see any reason why you couldn't use the update element to do just about any sort of XML code that you like.

When we call the ASOBO_GT_MouseRect you can see we use a script for the Tooltip to display either mbar or inHG depending on the user settings. This code is just copied from the Asobo altimeter template. Different cursors for the two zones so the user knows what to expect. Mouseflags includes LeftRelease so we can stop the Update code.

In the CallbackCode itself the LeftSingle will only occur once so we add 0.4 seconds to the sim time and write that into (O:XMLVAR_FirstUpdateTime). Now the update code will become active after a small pause (0.4 seconds) and then continue at the Frequency rate thus providing the continuous adjustment while the mouse button is held down. The LeftRelease will reset the (O:XMLVAR_FirstUpdateTime) to zero to stop the update otherwise it would go on forever. O: variables (as used in (O:XMLVAR_FirstUpdateTime)) seem to be Component dependent. The (O:XMLVAR_FirstUpdateTime) in "MouseZone_Altimeter_Inc" is not affected by the one in "MouseZone_Altimeter_Dec". I found this out in testing when I didn't have a LeftRelease for one of the zones. If the O: variable was global then clicking on the other zone should have stopped the update but it didn't.

Another example:

This is the code for a radio unit with a 12 key pad for user input. Hold the button down and then lift it when the mouse is released. No coding beyond the animation is done in this mouse interaction. I will process the inputs within the radio gauge itself. This is the perfect opportunity to create my own template and then I can simply call it 12 times for each key.

Here is the template where I combine our previous examples, animation, emissive and mouse rectangle, all into one template. This template takes in one parameter #KEY# which is used in the anim name, tooltip and L:var

Code:
<Template Name = "ANTS_a582_radio_button">
    <UseTemplate Name="ASOBO_GT_Anim_Code">
        <ANIM_NAME>a582_radio_button_#KEY#</ANIM_NAME>
        <ANIM_CODE>(L:radio_button_#KEY#,number)</ANIM_CODE>
        <ANIM_LAG>200</ANIM_LAG>
        <ANIM_LENGTH>20</ANIM_LENGTH>
    </UseTemplate>
    <Material>
        <EmissiveFactor>
            <Parameter>
                <Code>put some XML code in here to control the self illumination of the buttons</Code>
            </Parameter>
            <OverrideBaseEmissive>TRUE</OverrideBaseEmissive>
        </EmissiveFactor>
    </Material>
    <UseTemplate Name="ASOBO_GT_MouseRect">
        <TOOLTIPID>#KEY#</TOOLTIPID>
        <CURSOR>Hand</CURSOR>
        <MOUSEFLAGS_DEFAULT_IM>LeftSingle+LeftRelease</MOUSEFLAGS_DEFAULT_IM>
        <CALLBACKCODE_DEFAULT_IM>                   
            (M:Event) 'LeftSingle' scmi 0 == if{ 20 (&gt;L:radio_button_#KEY#,number) }
            (M:Event) 'LeftRelease' scmi 0 == if{ 0 (&gt;L:radio_button_#KEY#,number) }
        </CALLBACKCODE_DEFAULT_IM>   
    </UseTemplate>
</Template>

To call this template I simply use this code where KEY is the name/number of the key on the key pad. Repeat 12 times changing the component ID and Node and <KEY> to build the keypad.

Code:
<Component ID="Radio_Button_000" Node="Radio_Button_000">
    <UseTemplate Name="ANTS_a582_radio_button">
        <KEY>0</KEY>
    </UseTemplate>
</Component>

And so ends the lesson. This is just a brief introduction and I hope it gives you an idea of the underlying core at work here. The examples are very simple but they all use the core templates without the confusing plethora of templates and subtemplates that Asobo uses. Hopefully this will allow you to better understand how the Asobo templates work and if there isn't a template that works for you then you should be able to create your own for your needs.
 

Attachments

  • TooltipID.txt
    40.6 KB · Views: 370
Last edited:
Messages
407
Country
ca-britishcolumbia
Great thread. I'm going to test "wrap" right now. I've always been frustrated by the inability to use lag on anything that rotates through 360'.
 
Messages
244
Country
england
Great information Anthony. Thanks for taking the time to figure these out and post your results in an easy to understand format.
 
Messages
10,088
Country
us-arizona
Awesome awesome, Anthony! Many thanks for sharing your findings, 'Teacher'.

I can say that Mouse Wheel works fine on code, so long as the Cursor stays on the knob. Example, Altimeter knob. Unfortunately, on my code, I cannot mouse-drag it. And havent found a right mouse key that works either, sadly. Perhaps in the future in an update.
Heading knob code I am using is from FSX ModelDef, 'knob_heading'. It animates 'slow'... big time, and mouse dragging it a distance has no effect. Right clicking has no effect. I do not think left clicking works either. But mouse wheel does.

Bill
 
Last edited:
Messages
10,088
Country
us-arizona
What if.... we just had a list of the part animation codes that would go in our Model XML's? Then we wouldnt have to fill out Behavior codes (continuously) for every airplane construction... I have this idea of just making a master Notepad document that has a collection of most used animations I would use/need, like landing gear, heading knob, yoke, etc, and paste them into the 'master animation document' and just use things from there... Perhaps I would need to attach 'template call' blocks to the animation name sections so that we know what to paste in for the code to work, (UseTemplate.....) Its just an idea. Similar to how we have the ModelDef. Creating a giant master list with all our animations in one file and only need copy/pasting into our ModelXMLS's.
 
Messages
1,243
Country
canada
Creating a giant master list with all our animations in one file and only need copy/pasting into our ModelXMLS's.
See my thread on the SDK . It has a spreadsheet with all the animation names. Unofficial SDK update. I will be updating the SDK soon with info on collision objects that can replace mouse react example 172 altimeter knob.
 
Messages
1,049
Country
australia
What if.... we just had a list of the part animation codes that would go in our Model XML's?
That's pretty much what the templates are for. You could create your own set of templates and include them in your models then just call them with a couple of lines:


Code:
<Template Name = "ANTS_throttle">
        <DRAG_DELTA>0.002</DRAG_DELTA>
        <DRAG_SPEED>0.5</DRAG_SPEED>
        <UseTemplate Name="ASOBO_GT_MouseRect">
            <TOOLTIPID>TT:COCKPIT.TOOLTIPS.THROTTLE_CONTROL</TOOLTIPID>
            <CURSOR>Hand</CURSOR>
            <MOUSEFLAGS_DEFAULT_IM>LeftSingle+LeftRelease+LeftDrag+WheelUp+WheelDown</MOUSEFLAGS_DEFAULT_IM>
            <MouseFlags>LeftAll+WheelUp+WheelDown</MouseFlags>
            <CALLBACKCODE>
                (M:Event) 'WheelDown'    scmi 0 == if{ g1 } els{
                (M:Event) 'WheelUp'  scmi 0 == if{ g2 } els{
                (M:Event) 'LeftSingle' scmi 0 == if{ (M:RelativeY) (&gt;O:_LastY) } els{
                (M:Event) 'LeftDrag'   scmi 0 == if{
                    (O:_LastY) (M:RelativeY) -  #DRAG_DELTA# / abs (&gt;O:DragFactor)
                    (O:_LastY) (M:RelativeY) -  -#DRAG_DELTA# &lt;
                    if{
                        (M:RelativeY) (&gt;O:_LastY)
                        g1
                    }
                    els{
                        (O:_LastY) (M:RelativeY) -  #DRAG_DELTA# &gt;
                        if{
                        (M:RelativeY) (&gt;O:_LastY)
                        g2
                        }
                        els{
                        }
                    }
                } } } }
                quit
                
                :1 (&gt;K:THROTTLE_DECR_SMALL)
                quit
                
                :2 (&gt;K:THROTTLE_INCR_SMALL)
                quit
            </CALLBACKCODE>
        </UseTemplate>
    </Template>       

        <Component ID="a582_throttle" Node="a582_throttle">
            <UseTemplate Name="ANTS_throttle">
            </UseTemplate>
        </Component>
        <UseTemplate Name="ASOBO_GT_Anim_Sim">
            <ANIM_NAME>a582_ThrottleFront</ANIM_NAME>
            <ANIM_SIMVAR>GENERAL ENG THROTTLE LEVER POSITION:1</ANIM_SIMVAR>
            <ANIM_SIMVAR_UNITS>percent</ANIM_SIMVAR_UNITS>
        </UseTemplate>

I could move the call to ASOBO_GT_Anim_Sim into my throttle template to make it even cleaner.

The default aircraft are similar but as the Asobo templates are more complex you might need to set some more parameters. For example, the Asobo throttle template includes support for reverse thrust and a bunch of other stuff. That's why I made my own, it was too hard to decipher the Asobo template.
 
Messages
244
Country
england
Thanks for the continual updates. This info has certainly made things easier.
Do you mind if I use your throttle code in my project?
 
Messages
1,049
Country
australia
Thanks for the continual updates. This info has certainly made things easier.
Do you mind if I use your throttle code in my project?
Well, I took it from the Asobo throttle code (and removed all the extra stuff that they have in there) so feel free to copy. It's a very early example though, it may need some tweaking of DRAG_DELTA
 
Messages
255
Country
germany
Hi Anthony, I've gone through this threat and wondering if it would be useful for my problem to animate a hangar door by any kind of user event inside or outside the currently used aircraft. So I'd like to open a hangar that the aircraft is currently parked in front of or inside the hangar. Used the <visibility> and it hided my animated door when used inside <partinfo> but I haven't managed to close the door or open it.
In case of type=static the door is closing and opening in a loop but when I use type=sim inside the <animation> nothing happens at all. I tried to use L:XMLVAR_YokeHidden1 and A:AIRCRAFT LIGHT (ON) and other variables but nothing. Regards Guido
 
Top