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

P3D v4 Switch cover animation

Messages
153
Country
us-california
Hello all, im just dipping my feet into the world of coding animations. Im looking for a bit of help. Im trying to animate a rocker switch cover to open when clicked and when clicked to close it would also shut off the switch under it? Any help or point to a direction where I can read up on it? Thank you
 
Hi,
I think the reason why you still don't have a response is that your question is quite broad. What you're asking is not that difficult to code, but I don't know how much of an understanding you have of animating parts in the sim, or the quirky XML-scheme used by P3D/FSX.
Generally speaking, you can add new animations and mouserects to the list by making new entries in the modeldef.xml file of the SDK. I'd suggest that you backup the original file before doing so though. Every animation entry in the file has a header and a body, which are usually at different locations in the xml file. Let's take the fasten seatbelt switch as an example. Here's the header:
Code:
    <Animation name="switch_fasten_belts" guid="624F6916-78A9-4ae7-87DA-604F4B75FD95" length="50" type="Sim" typeParam2="switch_fasten_belts" typeParam="AutoPlay" />

The animation header has a name, a guid you have to generate yourself, and an animation length. Don't forget to pass the animation name as a typeParam2 as well.

The body of the animation looks like this:
Code:
    <PartInfo>
    <Name>switch_fasten_belts</Name>
    <AnimLength>50</AnimLength>
    <Animation>
      <Parameter>
       <Code>
          (A:CABIN SEATBELTS ALERT SWITCH,bool) 50 *
      </Code>
      <Lag>50</Lag>
      </Parameter>
    </Animation>
    <MouseRect>
      <Cursor>Hand</Cursor>
      <TooltipID>TOOLTIPTEXT_SEATBELTS_SWITCH</TooltipID>
      <EventID>CABIN_SEATBELTS_ALERT_SWITCH_TOGGLE</EventID>
    </MouseRect>
  </PartInfo>

There's a code segment that tells the sim which keyframe of the animation should be played at any time in the simulation. The MouseRect section contains the information on how the part interacts with the mouse. In this case, it's using a pre-defined code, but in your case you should replace it with your own code block, using a CallbackCode section instead. Here's an example:
Code:
    <MouseRect>
      <Cursor>Hand</Cursor>
      <MouseFlags>LeftSingle</MouseFlags>
      <CallbackCode>
          (L:SWITCH,bool) ! (&gt;L:SWITCH,bool)
      </CallbackCode>
    </MouseRect>

I hope this helps!
 
To add to the above from Vitus, your cover will use the same format with its own unique L:variable. In the CallbackCode for the cover, you will need to reset the switch's L:var back to zero (which will turn it off of course.
 
Thank you Vitus and Bill

Sorry for my vague description, I have a decent knowledge of modeling and animating but this is my first attempt to mess with modeldef, write my own code, and animate gauges. I have done a considerable amount of research on here about xml and such but not quite able to understand the language of xml yet.

This was my attempt at your guys post above. I wasnt sure on Bill's reply about resetting the switch L:var back to zero? I appreciate you guys taking the time to reply.


Code:
  <Animation name="s2t_switch_tank_arm_cover" guid="d7a62935-5bc4-452d-b24e-fd1418dca918" length="50" type="Sim" typeParam2="s2t_switch_tank_arm_cover" typeParam="AutoPlay" />

   <PartInfo>
    <Name>s2t_switch_tank_arm_cover</Name>
    <AnimLength>50</AnimLength>
    <Animation>
      <Parameter>
       <Code>
          (A:s2t_switch_tank_arm_cover,bool) 50 *
      </Code>
      <Lag>50</Lag>
      </Parameter>
    </Animation>
    <MouseRect>
      <Cursor>Hand</Cursor>
      <TooltipID>TOOLTIPTEXT_SWITCH_COVER</TooltipID>
      <MouseFlags>LeftSingle</MouseFlags>
      <CallbackCode>
          (L:s2t_switch_tank_arm_cover,bool) ! (&gt;L:s2t_switch_tank_arm_cover,bool)
      </CallbackCode>
    </MouseRect>
  </PartInfo>
 
All variables in P3D have a prefix. E:<variable name> is for all environmental values, A:<variable name> is for aircraft variables, L:<variable name> is for local, custom variables. The thing is that the only variables you can customize are the L-Vars.
(A:s2t_switch_tank_arm_cover,bool) does not exist for the sim (because you cannot define A: variables), so the code will always result in "0". Fix this by changing the Animation code to:
(L:s2t_switch_tank_arm_cover,bool) 50 *
 
Thanks Vitus! I made the change and it worked like a dream. If you have time I was wondering if its possible, I want to make it where I click the cover to open the it, then click the switch underneath on, then when I close the cover it also flips the switch underneath off. Would that be possible?
 
Something like this would be your switch code:
Code:
    <MouseRect>
      <Cursor>Hand</Cursor>
      <TooltipText>
        Important switch%((L:s2t_switch_tank_arm_cover,bool) 0 ==)%{if} - open cover first%{else}%{end}
      </TooltipText>
      <MouseFlags>LeftSingle</MouseFlags>
      <CallbackCode>
          (L:s2t_switch_tank_arm_cover,bool) 0 !=
        if{
               (L:s2t_switch_tank_arm,bool) ! (&gt;L:s2t_switch_tank_arm,bool)
        }
      </CallbackCode>
    </MouseRect>
Notice the use of a custom tooltip with additional code.


Something like this would be your cover code:
Code:
    <MouseRect>
      <Cursor>Hand</Cursor>
      <TooltipID>TOOLTIPTEXT_SWITCH_COVER</TooltipID>
      <MouseFlags>LeftSingle</MouseFlags>
      <CallbackCode>
        (L:s2t_switch_tank_arm_cover,bool) 0 ==
        if{
          1 (&gt;L:s2t_switch_tank_arm_cover,bool)
        }
        els{
          0 (&gt;L:s2t_switch_tank_arm,bool)
          1 (&gt;L:s2t_switch_tank_arm_cover,bool)
        }
      </CallbackCode>
    </MouseRect>
 
Shouldn't this be zero as well?
Code:
          0 (&gt;L:s2t_switch_tank_arm,bool)            // This will close the switch
          0 (&gt;L:s2t_switch_tank_arm_cover,bool)      // This will close the cover!
 
I have another question. I am trying to animate a pitot cover that rotates up about 30 degrees to allow air into the pitot tube when above 10 knots. Does this code make sense for that?

Code:
  <Animation name="s2t_pitot_cover" guid="4d09eab8-0422-4823-9ae5-0e71bec8f8b7" length="100" type="Sim" typeparam2="s2t_pitot_cover" typeparam="AutoPlay" />

  <PartInfo>
    <Name>s2t_pitot_cover</Name>
    <AnimLength>100</AnimLength>
    <Animation>
      <Parameter>
        <Code>
          (A:AIRSPEED TRUE, Knots) >= 10; if{ 1 } els{ 0 }
        </Code>
      </Parameter>
    </Animation>
  </PartInfo>
 
I think if the animation keyframes are 0-100 then it should be if{ 100 } els{ 0 }

but this will move instantaneously - if you want it to move more slowly add a Lag statement after the Code statement:

<Lag>5</Lag>

Change the number to alter the speed of the movement. Five moves somewhat slowly. Also, I think that wind speed would be more closely related to Indicated airspeed, rather than True?

The other way to do this would be to use a formula that bases the keyframe number on the speed of the plane, say from 10 KIAS = keyframe 0 to 15 KIAS = keyframe 100.
 
Nah, xml goes "reverse Polish", which means to express x >= 10 you have to write x 10 >=. No semi-colons, as Vitus says, and 0 and 100 and Lag as Tom says. I normally also replace comparison ops like >= by the &gt;= notation, just to be on the safe side, so that the parser doesn't take this for a closing bracket. To be perfectly pedantic, a simple greater-than would do just as well given the purpose. So, my suggestion:

Code:
<Code>
   (A:AIRSPEED TRUE, Knots) 10 &gt; if{ 100 } els{ 0 }
</Code>
<Lag>25</Lag>
 
Last edited by a moderator:
Hi I need some help again. I found this code on here for a spring switch L-M-R to test the low fuel lights. I am trying to adapt it my model but it says unable to display visual model after I implement this code. If I remove it everything is ok. Can anyone see an issue with it?
Code:
    <Animation name="s2t_fuel_test_switch" guid="9d16a6aa-5dac-452c-8408-c57fd504e58a" length="100" type="Sim" typeParam2="s2t_fuel_test_switch" typeParam="AutoPlay" />

    <PartInfo>
        <Name>s2t_fuel_test_switch</Name>
        <AnimLength>100</AnimLength>
        <Animation>
            <Parameter>
                <Code>50 (L:s2t_fuel_test_switch, bool) 50 * + </Code>
                <Lag>400</Lag>
            </Parameter>
        </Animation>
        <MouseRect>
            <Cursor>Hand</Cursor>
            <TooltipText>Fuel Gauge Test</TooltipText>
          <MouseFlags>LeftSingle+RightSingle+Release</MouseFlags>
        <CallbackCode>
          (M:Event) 'LeftSingle' scmp  0 ==
          if{ -1 (>L:s2t_fuel_test_switch, bool) -310 (>L:tank_gauge_test, gallons) }
          (M:Event) 'RightSingle' scmp  0 ==
          if{ 1 (>L:s2t_fuel_test_switch, bool) 310 (>L:tank_gauge_test, gallons) }
          (M:Event) 'Release' scmp  0 ==
           if{ 0 (>L:s2t_fuel_test_switch, bool) 0 (>L:tank_gauge_test, gallons) }
         </CallbackCode>
        </MouseRect>
    </PartInfo>
 
Last edited:
Hi,
Try to use the Lvar "(L:s2t_fuel_test_switch, bool)" in the "code" section!
 
And use "enum" instead of "bool" for this Lvar! But Its not the reason for the crash, i guess!
 
Back
Top