• 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.

MSFS20 Windscreen wipers

Messages
236
Country
australia
Hi folks,

Just wondering if anyone can help. I am modeling the wipers to my aircraft currently and I like the Asobo template for it. However I have come up against a problem, My wipers need 50 Keyframes to go the distance but the ASOBO wiper template uses only one. Now the problem is that my windscreen has a little curve in it hence the requirement to have more than one KF in order to set a central position in order to mount this curve. For the life of me, I cant find the actual XML code that drives ASOBO's animation. All I get to in the handling templates and sub templates is XML code without any reference to animation. Can anyone tell me where I can find the actual XML code that drives the animation. Any help would be greatly appreciated. Many thanks in advance.

Regards, TJ
 
If it is a two keyframe animation, then it is essentially a "switch," in that we only "animate" the two end positions and the engine does the tweening. However we're not constrained to the Asobo templates, we can write our own.

 
Thanks for replying RK. I actually need a 50 key animation which is why I wanted to use the ASOBO XML, but I can't find it anywhere. Might you know where I have to look? Thanks
 
If it is a two keyframe animation, then it is essentially a "switch," in that we only "animate" the two end positions and the engine does the tweening. However we're not constrained to the Asobo templates, we can write our own.

Thanks for replying RK. I actually need a 50 key animation which is why I wanted to use the ASOBO XML, but I can't find it anywhere. Might you know where I have to look? Thanks
 
We do not have access to that code, which is why we have to create custom templates. It is something I'll likely have to do as well, as I have an aircraft with a rotor speed of 270 RPM, which is much lower than allowed for maximum power for a rotorcraft. If you scan the custom template XML, you can see the term "override," which I believe indicates it is replacing a default template.

One more idea you could try the animation using default template keyframes. I am animating instruments currently and one of my animations was a two key rotation. If I rotate the proper direction, the mesh animates perfectly, but if I rotate reverse, the mesh animates backwards. Presumably, keyframes have only positional information, but this proves direction, or history, is also recorded. Doubt this idea will work, but it might to simply trace your intended wiper path, setting only the start and end keys.
 
We do not have access to that code, which is why we have to create custom templates. It is something I'll likely have to do as well, as I have an aircraft with a rotor speed of 270 RPM, which is much lower than allowed for maximum power for a rotorcraft. If you scan the custom template XML, you can see the term "override," which I believe indicates it is replacing a default template.

One more idea you could try the animation using default template keyframes. I am animating instruments currently and one of my animations was a two key rotation. If I rotate the proper direction, the mesh animates perfectly, but if I rotate reverse, the mesh animates backwards. Presumably, keyframes have only positional information, but this proves direction, or history, is also recorded. Doubt this idea will work, but it might to simply trace your intended wiper path, setting only the start and end keys.
I was afraid of that. Anyway yours sounds like a great idea. Will try that. Thank you for your help. TJ
 
The wiper blades (at least the ones for the A320 Neo) are in ASOBO_HANDLING_Wipers_Template. It looks like it uses 100 keyframes animated in one direction (the code then reverses the direction to go backwards)

Code:
<Template Name="ASOBO_HANDLING_Wipers_Template">
    <DefaultTemplateParameters>
        <ANIM_NAME>HANDLING_Wipers</ANIM_NAME>
        <CIRCUIT_ID_WIPERS>1</CIRCUIT_ID_WIPERS>
        <MIN_SPEED_PERCENT>0.1</MIN_SPEED_PERCENT>
        <MAX_SPEED>600</MAX_SPEED>
        <Condition Valid="CIRCUIT_ID_PARK">
            <PARK_SPEED>600</PARK_SPEED>
        </Condition>
        <WWISE_EVENT_1>wipers_forward</WWISE_EVENT_1>
        <NORMALIZED_TIME_1>0.2</NORMALIZED_TIME_1>
        <WWISE_EVENT_2>wipers_backward</WWISE_EVENT_2>
        <NORMALIZED_TIME_2>0.8</NORMALIZED_TIME_2>
        <AIRSPEED_DISABLED>230</AIRSPEED_DISABLED>
    </DefaultTemplateParameters>
    <OverrideTemplateParameters>
        <ONE_MINUS_MIN_SPEED Process="Float">1 #MIN_SPEED_PERCENT# -</ONE_MINUS_MIN_SPEED>
        <Condition Valid="CIRCUIT_ID_PARK">
            <True>
                <FAILURE_CODE>
                        (O:AnimCode) 0 &gt; if{
                            (A:CIRCUIT ON:#CIRCUIT_ID_PARK#, Bool) if{
                                #PARK_SPEED# (&gt;O:_AnimSpeed)
                                -1 (O:_AnimSpeed) * (A:ANIMATION DELTA TIME, seconds) * (O:AnimCode) + (&gt;O:NewAnimCode)
                                (O:NewAnimCode) 0 &lt; if{ 0 (&gt;O:NewAnimCode) }
                                (O:NewAnimCode) (&gt;O:AnimCode)
                            }
                        }
                        (O:AnimCode)
                    </FAILURE_CODE>
            </True>
            <False>
                <FAILURE_CODE>
                        (O:AnimCode) 0 &gt; if{
                            (A:CIRCUIT POWER SETTING:#CIRCUIT_ID_WIPERS#, percent over 100) 1 #MIN_SPEED_PERCENT# - * #MIN_SPEED_PERCENT# + #MAX_SPEED# * (&gt;O:_AnimSpeed)
                            (O:_GoForward) if{ 1 (&gt;O:_AnimDirection) } els{ -1 (&gt;O:_AnimDirection) }
                            (O:_AnimDirection) (O:_AnimSpeed) * (A:ANIMATION DELTA TIME, seconds) * (O:AnimCode) + (&gt;O:NewAnimCode)
                            (O:NewAnimCode) 100 &gt; if{
                                100 (O:NewAnimCode) 100 % - (&gt;O:NewAnimCode)
                                1 (&gt;O:_ChangedDirection)
                            }
                            (O:NewAnimCode) 0 &lt; if{
                                0 (&gt;O:NewAnimCode)
                            }
                            (O:_ChangedDirection) if{
                                (O:_GoForward) ! (&gt;O:_GoForward)
                                0 (&gt;O:_ChangedDirection)
                            }
                            (O:NewAnimCode) (&gt;O:AnimCode)
                        }
                        (O:AnimCode)
                    </FAILURE_CODE>
            </False>
        </Condition>
    </OverrideTemplateParameters>
    <Update Once="True">
            0 (&gt;O:AnimCode)
        </Update>
    <UseTemplate Name="ASOBO_GT_Anim_Code">
        <ANIM_CODE>
                (A:CIRCUIT POWER SETTING:#CIRCUIT_ID_WIPERS#, percent over 100) #ONE_MINUS_MIN_SPEED# * #MIN_SPEED_PERCENT# + #MAX_SPEED# * (&gt;O:_AnimSpeed)
                (O:_GoForward) if{ 1 (&gt;O:_AnimDirection) } els{ -1 (&gt;O:_AnimDirection) }
                (O:_AnimDirection) (O:_AnimSpeed) * (A:ANIMATION DELTA TIME, seconds) * (O:AnimCode) + (&gt;O:NewAnimCode)
                (O:NewAnimCode) 100 &gt; if{
                    100 (O:NewAnimCode) 100 % - (&gt;O:NewAnimCode)
                    1 (&gt;O:_ChangedDirection)
                }
                (O:NewAnimCode) 0 &lt; if{
                    (O:NewAnimCode) abs 100 % (&gt;O:NewAnimCode)
                    1 (&gt;O:_ChangedDirection)
                }
                (O:_ChangedDirection) if{
                    (O:_GoForward) ! (&gt;O:_GoForward)
                    0 (&gt;O:_ChangedDirection)
                }
                (O:NewAnimCode)
            </ANIM_CODE>
        <FAILURE>(A:CIRCUIT ON:#CIRCUIT_ID_WIPERS#, Bool) (A:AIRSPEED INDICATED, Knots) #AIRSPEED_DISABLED# &lt; and</FAILURE>
    </UseTemplate>
    <UseTemplate Name="ASOBO_GT_AnimTriggers_2SoundEvents"/>
</Template>

Note that you will need to create a circuit to power the wipers.

Personally I use my own code below but this is a bit complicated as it accelerates and decelerates the wipers when you turn them off (which looks so much more pro). And it also controls triggers for the sound. I use 200 keyframes and animate forward and back in the keyframes. Note my wipers are powered by Circuit 39.

But the basic principle is the same. You use delta time to read each frame time and then move the wipers the appropriate number of keyframes.

Code:
        <UseTemplate Name="ASOBO_GT_Anim_Code">
            <ANIM_NAME>Winjeel_wipers_anim</ANIM_NAME>
            <ANIM_CODE>
            (A:IS USER SIM,bool)
            if{
                (A:CIRCUIT ON:39,Bool)
                if{
                    (L:sound_wipers,number) 0 == if{ 1 (&gt;L:sound_wipers,number) }
                    (L:winjeel_wipers_accel,number) 50 &lt; if{ (L:winjeel_wipers_accel,number) 5 + 50 min (&gt;L:winjeel_wipers_accel,number) }
                    (L:winjeel_wipers_position,number) (E:SIMULATION DELTA TIME,seconds) (L:winjeel_wipers_accel,number) * + (&gt;L:winjeel_wipers_position,number)
                    (L:winjeel_wipers_position,number) 200 &gt; if{ 0 (&gt;L:winjeel_wipers_position,number) 0 (&gt;L:sound_wipers,number) }
                }
                els{
                    0 (&gt;L:sound_wipers,number)
                    (L:winjeel_wipers_accel,number) 0 &gt;
                    if{
                    (L:winjeel_wipers_accel,number) 5 - 0 max (&gt;L:winjeel_wipers_accel,number)
                    (L:winjeel_wipers_position,number) (E:SIMULATION DELTA TIME,seconds) (L:winjeel_wipers_accel,number) * + (&gt;L:winjeel_wipers_position,number)
                    (L:winjeel_wipers_position,number) 200 &gt; if{ 0 (&gt;L:winjeel_wipers_position,number) }
                    (L:winjeel_wipers_accel,number)
                    }
                }
                (L:winjeel_wipers_position,number)
            }
            els{ 0 }
            </ANIM_CODE>
            <ANIM_LAG>0</ANIM_LAG>
            <ANIM_LENGTH>200</ANIM_LENGTH>
        </UseTemplate>
 
G
The wiper blades (at least the ones for the A320 Neo) are in ASOBO_HANDLING_Wipers_Template. It looks like it uses 100 keyframes animated in one direction (the code then reverses the direction to go backwards)

Code:
<Template Name="ASOBO_HANDLING_Wipers_Template">
    <DefaultTemplateParameters>
        <ANIM_NAME>HANDLING_Wipers</ANIM_NAME>
        <CIRCUIT_ID_WIPERS>1</CIRCUIT_ID_WIPERS>
        <MIN_SPEED_PERCENT>0.1</MIN_SPEED_PERCENT>
        <MAX_SPEED>600</MAX_SPEED>
        <Condition Valid="CIRCUIT_ID_PARK">
            <PARK_SPEED>600</PARK_SPEED>
        </Condition>
        <WWISE_EVENT_1>wipers_forward</WWISE_EVENT_1>
        <NORMALIZED_TIME_1>0.2</NORMALIZED_TIME_1>
        <WWISE_EVENT_2>wipers_backward</WWISE_EVENT_2>
        <NORMALIZED_TIME_2>0.8</NORMALIZED_TIME_2>
        <AIRSPEED_DISABLED>230</AIRSPEED_DISABLED>
    </DefaultTemplateParameters>
    <OverrideTemplateParameters>
        <ONE_MINUS_MIN_SPEED Process="Float">1 #MIN_SPEED_PERCENT# -</ONE_MINUS_MIN_SPEED>
        <Condition Valid="CIRCUIT_ID_PARK">
            <True>
                <FAILURE_CODE>
                        (O:AnimCode) 0 &gt; if{
                            (A:CIRCUIT ON:#CIRCUIT_ID_PARK#, Bool) if{
                                #PARK_SPEED# (&gt;O:_AnimSpeed)
                                -1 (O:_AnimSpeed) * (A:ANIMATION DELTA TIME, seconds) * (O:AnimCode) + (&gt;O:NewAnimCode)
                                (O:NewAnimCode) 0 &lt; if{ 0 (&gt;O:NewAnimCode) }
                                (O:NewAnimCode) (&gt;O:AnimCode)
                            }
                        }
                        (O:AnimCode)
                    </FAILURE_CODE>
            </True>
            <False>
                <FAILURE_CODE>
                        (O:AnimCode) 0 &gt; if{
                            (A:CIRCUIT POWER SETTING:#CIRCUIT_ID_WIPERS#, percent over 100) 1 #MIN_SPEED_PERCENT# - * #MIN_SPEED_PERCENT# + #MAX_SPEED# * (&gt;O:_AnimSpeed)
                            (O:_GoForward) if{ 1 (&gt;O:_AnimDirection) } els{ -1 (&gt;O:_AnimDirection) }
                            (O:_AnimDirection) (O:_AnimSpeed) * (A:ANIMATION DELTA TIME, seconds) * (O:AnimCode) + (&gt;O:NewAnimCode)
                            (O:NewAnimCode) 100 &gt; if{
                                100 (O:NewAnimCode) 100 % - (&gt;O:NewAnimCode)
                                1 (&gt;O:_ChangedDirection)
                            }
                            (O:NewAnimCode) 0 &lt; if{
                                0 (&gt;O:NewAnimCode)
                            }
                            (O:_ChangedDirection) if{
                                (O:_GoForward) ! (&gt;O:_GoForward)
                                0 (&gt;O:_ChangedDirection)
                            }
                            (O:NewAnimCode) (&gt;O:AnimCode)
                        }
                        (O:AnimCode)
                    </FAILURE_CODE>
            </False>
        </Condition>
    </OverrideTemplateParameters>
    <Update Once="True">
            0 (&gt;O:AnimCode)
        </Update>
    <UseTemplate Name="ASOBO_GT_Anim_Code">
        <ANIM_CODE>
                (A:CIRCUIT POWER SETTING:#CIRCUIT_ID_WIPERS#, percent over 100) #ONE_MINUS_MIN_SPEED# * #MIN_SPEED_PERCENT# + #MAX_SPEED# * (&gt;O:_AnimSpeed)
                (O:_GoForward) if{ 1 (&gt;O:_AnimDirection) } els{ -1 (&gt;O:_AnimDirection) }
                (O:_AnimDirection) (O:_AnimSpeed) * (A:ANIMATION DELTA TIME, seconds) * (O:AnimCode) + (&gt;O:NewAnimCode)
                (O:NewAnimCode) 100 &gt; if{
                    100 (O:NewAnimCode) 100 % - (&gt;O:NewAnimCode)
                    1 (&gt;O:_ChangedDirection)
                }
                (O:NewAnimCode) 0 &lt; if{
                    (O:NewAnimCode) abs 100 % (&gt;O:NewAnimCode)
                    1 (&gt;O:_ChangedDirection)
                }
                (O:_ChangedDirection) if{
                    (O:_GoForward) ! (&gt;O:_GoForward)
                    0 (&gt;O:_ChangedDirection)
                }
                (O:NewAnimCode)
            </ANIM_CODE>
        <FAILURE>(A:CIRCUIT ON:#CIRCUIT_ID_WIPERS#, Bool) (A:AIRSPEED INDICATED, Knots) #AIRSPEED_DISABLED# &lt; and</FAILURE>
    </UseTemplate>
    <UseTemplate Name="ASOBO_GT_AnimTriggers_2SoundEvents"/>
</Template>

Note that you will need to create a circuit to power the wipers.

Personally I use my own code below but this is a bit complicated as it accelerates and decelerates the wipers when you turn them off (which looks so much more pro). And it also controls triggers for the sound. I use 200 keyframes and animate forward and back in the keyframes. Note my wipers are powered by Circuit 39.

But the basic principle is the same. You use delta time to read each frame time and then move the wipers the appropriate number of keyframes.

Code:
        <UseTemplate Name="ASOBO_GT_Anim_Code">
            <ANIM_NAME>Winjeel_wipers_anim</ANIM_NAME>
            <ANIM_CODE>
            (A:IS USER SIM,bool)
            if{
                (A:CIRCUIT ON:39,Bool)
                if{
                    (L:sound_wipers,number) 0 == if{ 1 (&gt;L:sound_wipers,number) }
                    (L:winjeel_wipers_accel,number) 50 &lt; if{ (L:winjeel_wipers_accel,number) 5 + 50 min (&gt;L:winjeel_wipers_accel,number) }
                    (L:winjeel_wipers_position,number) (E:SIMULATION DELTA TIME,seconds) (L:winjeel_wipers_accel,number) * + (&gt;L:winjeel_wipers_position,number)
                    (L:winjeel_wipers_position,number) 200 &gt; if{ 0 (&gt;L:winjeel_wipers_position,number) 0 (&gt;L:sound_wipers,number) }
                }
                els{
                    0 (&gt;L:sound_wipers,number)
                    (L:winjeel_wipers_accel,number) 0 &gt;
                    if{
                    (L:winjeel_wipers_accel,number) 5 - 0 max (&gt;L:winjeel_wipers_accel,number)
                    (L:winjeel_wipers_position,number) (E:SIMULATION DELTA TIME,seconds) (L:winjeel_wipers_accel,number) * + (&gt;L:winjeel_wipers_position,number)
                    (L:winjeel_wipers_position,number) 200 &gt; if{ 0 (&gt;L:winjeel_wipers_position,number) }
                    (L:winjeel_wipers_accel,number)
                    }
                }
                (L:winjeel_wipers_position,number)
            }
            els{ 0 }
            </ANIM_CODE>
            <ANIM_LAG>0</ANIM_LAG>
            <ANIM_LENGTH>200</ANIM_LENGTH>
        </UseTemplate>
Great find Anthony, thank you. I didn't look in the A320 XML file. Will give it a try when I get back to my computer and thanks for sharing your version. Cheers
 
Back
Top