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

FSXA Endless Knob Rotation

Messages
683
Country
us-california
I have a knob that adjusts the autopilot heading. Currently it works thru 360*, but it needs to be able to keep rotating in either direction. Here's the current code...

Code:
<PartInfo>
    <Name>XLS+_FGS_HEADING_ROTARY</Name>
     <AnimLength>360</AnimLength>
      <Animation>
       <Parameter>
        <Code>
          (L:XLS+_FGC_HEADING_ROTARY, enum)
        </Code>
       </Parameter>
     </Animation>
    <MouseRect>
     <Cursor>Hand</Cursor>
      <TooltipText>Heading Adjust</TooltipText>
       <MouseFlags>LeftSingle+RightSingle+DownRepeat</MouseFlags>
        <CallbackCode>
            (M:Event) 'LeftSingle' scmp 0 == 
                if{    (L:XLS+_FGC_HEADING_ROTARY, enum) -- (&gt;L:XLS+_FGC_HEADING_ROTARY, enum) 0x18304 (>L:C560_VC_EVENT,enum) }
            (M:Event) 'RightSingle' scmp 0 == 
                if{ (L:XLS+_FGC_HEADING_ROTARY, enum) ++ (&gt;L:XLS+_FGC_HEADING_ROTARY, enum) 0x18303 (>L:C560_VC_EVENT,enum) }
        </CallbackCode>
    </MouseRect>
</PartInfo>
 
<PartInfo>
<Name>XLS+_FGS_HEADING_ROTARY</Name>
<AnimLength>360</AnimLength>
<Animation>
<Parameter>
<Code>
(L:XLS+_FGC_HEADING_ROTARY, enum)
</Code>
</Parameter>
</Animation>
<MouseRect>
<Cursor>Hand</Cursor>
<TooltipText>Heading Adjust</TooltipText>
<MouseFlags>LeftSingle+RightSingle+DownRepeat</MouseFlags>
<CallbackCode>
(M:Event) 'LeftSingle' scmp 0 ==
if{ (L:XLS+_FGC_HEADING_ROTARY, enum) -- 360 % d (&gt;L:XLS+_FGC_HEADING_ROTARY, enum) 0x18304 (>L:C560_VC_EVENT,enum) }
(M:Event) 'RightSingle' scmp 0 ==
if{ (L:XLS+_FGC_HEADING_ROTARY, enum) ++ 360 % d (&gt;L:XLS+_FGC_HEADING_ROTARY, enum) 0x18303 (>L:C560_VC_EVENT,enum) }
</CallbackCode>
</MouseRect>
</PartInfo>

I'm not sure if the modulo thingy works when decreasing a variable, but it definitely works for an increase.
If not, you might need to sneak a "(L:XLS+_FGC_HEADING_ROTARY, enum) 360 == if{ 0 (>L:XLS+_FGC_HEADING_ROTARY, enum) }" in there.
 
(L:XLS+_FGC_HEADING_ROTARY, enum) 100 % works fine for increasing values (note that I changed my animation length to 100). I still lose the animation when the value goes negative. The other idea did not work at all. It seems like there should be a way to set (L:XLS+_FGC_HEADING_ROTARY, enum) equal to 0 when the value is greater than 100 and set it to 100 when the value is less than zero.
 
You can make use of a controller poly* in your model to reset your knob control variable.

Code:
<PartInfo>
<Name>XLS_Controller</Name>
<Visibility>
<Parameter>
<Code>
(L:XLS+_FGC_HEADING_ROTARY, enum) 0 == if{ 99 (>L:XLS+_FGC_HEADING_ROTARY, enum) }
</Code>
</Parameter>
</Visibility>
</PartInfo>


*See the bottom part of this post for an explanation:
http://fsdeveloper.com/forum/threads/case-in-eventid.436185/#post-732688
 
I've used that method for certain things in the past, and was something I was thinking of doing if there was no way to do it in the existing part code. I'll give it a go as soon as Max gets done baking a part.
Thanks Bjoern!
 
Here is how I achieve continuous rotation of a control:

Code:
  <CallbackCode>
        (L:XLS+_FGC_HEADING_ROTARY,enum) 0 &lt; if{ 100 (>L:XLS+_FGC_HEADING_ROTARY,enum) }
        (L:XLS+_FGC_HEADING_ROTARY,enum) 100 &gt; if{ 0 (>L:XLS+_FGC_HEADING_ROTARY,enum) }
        (M:Event) 'LeftSingle' scmp 0 ==
           if{  (L:XLS+_FGC_HEADING_ROTARY, enum) -- (&gt;L:XLS+_FGC_HEADING_ROTARY, enum) 0x18304 (>L:C560_VC_EVENT,enum) }
        (M:Event) 'RightSingle' scmp 0 ==
           if{ (L:XLS+_FGC_HEADING_ROTARY, enum) ++ (&gt;L:XLS+_FGC_HEADING_ROTARY, enum) 0x18303 (>L:C560_VC_EVENT,enum) }
  </CallbackCode>
 
WINNER!

Thanks Bill. That code works well. Now I can start animating a whole bunch of rotary knobs. :D
 
Although your problem is solved, I'll just throw in my two cents :D

Should work like the ones above, but a bit less code...

Code:
(M:Event) 'LeftSingle' scmi 0 == if{ (L:XLS+_FGC_HEADING_ROTARY, enum) ++ 101 % (>L:XLS+_FGC_HEADING_ROTARY, enum) }
(M:Event) 'RightSingle' scmi 0 == if{ (L:XLS+_FGC_HEADING_ROTARY, enum) d 0 == if{ 100 } els{ -- } (>L:XLS+_FGC_HEADING_ROTARY, enum) }
 
Instead of the extra if statements, you can do something like this as well:

Code:
(M:Event) 'LeftSingle' scmp 0 ==
           if{  (L:XLS+_FGC_HEADING_ROTARY, enum) -- 100 (L:XLS+_FGC_HEADING_ROTARY, enum) 0 > ? (&gt;L:XLS+_FGC_HEADING_ROTARY, enum) 0x18304 (>L:C560_VC_EVENT,enum) }

if > 0, the first operation (the --) will be sent to the variable. else, 100 will be sent.
 
Hello dear friends

First of all, I hope everyone is doing ok during this troubled times. Due this, I have been working in one of my "abandoned projects".
I know this thread is a little bit old but I have some questions for you. I have written an HSI with rotating knobs and they work like a charm as 2D panel... however, I am trying to implement my dictionary part including for the first time
rotating knobs. My first attempt wil be the heading knob and the code in my 2d gauge is:

As a side note, all code is intended to be used in a model for FS2004.:duck:

HTML:
 <Gauge Name="Heading_Knob" Version="1.0">
     <Image Name="HSI_Heading_Knob.bmp"/>

      <Element>
          <Position X="63" Y="63"/>
          <Image Name="HSI_Heading_Knob.bmp">
              <Axis X="63" Y="63"/>
          </Image>
          <Rotate>
              <Value>(A:Autopilot heading lock dir,radians) 3 *</Value>
          </Rotate>
      </Element>
           <!--                                                                                                       M O U S E   E V E N T    L O G I C                                                                                                            -->
      <Mouse>
      <!-- Heading Knob -->
          <Area Left="0" Top="0" Width="127" Height="127">
          <ToolTip>HDG: %((A:Autopilot heading lock dir,degrees))%!03.0f!°</ToolTip>
              <Cursor Type="hand"/>
              <Click Kind="LeftSingle+RightSingle+WheelUp+WheelDown" Repeat="Yes">
                  (M:Event) 'LeftSingle' scmp 0 == (M:Event) 'WheelUp' scmp 0 == or
                      if{
                         (A:AUTOPILOT HEADING LOCK DIR, degrees) ++ dnor (>K:HEADING_BUG_SET)
                         1 (>MD_900_Rotary_Click, number)
                        }
                  (M:Event) 'RightSingle' scmp 0 == (M:Event) 'WheelDown' scmp 0 == or
                      if{
                         (A:AUTOPILOT HEADING LOCK DIR, degrees) -- dnor (>K:HEADING_BUG_SET)
                         1 (>MD_900_Rotary_Click, number)
                        }
                  </Click>
              </Area>
      </Mouse>
</Gauge>

And if I understood all explanations given in this post, my version for the 3D part would be:
HTML:
<part>
    <name>MD900_HDG_Knob</name>
    <visible_in_range>
        <animation>
            <parameter>
                <code>
                    (L:HDG_Knob_Animation,number)
                </code>
            </parameter>
        </animation>
        <mouserect>
            <cursor>Hand</cursor>
            <tooltip_text>HDG: %((A:Autopilot heading lock dir,degrees))%!03.0f!°</tooltip_text>
            <mouse_flags>LeftSingle+RightSingle+WheelUp+WheelDown</mouse_flags>
            <callback_code>
                (L:HDG_Knob_Anim_Control,number) 0 &lt;
                    if{ 100 (>L:HDG_Knob_Anim_Control,number) }
                (L:HDG_Knob_Anim_Control,number) 100 &gt;
                    if{ 0 (>L:HDG_Knob_Anim_Control,number) }
                (M:Event) 'LeftSingle' scmp 0 == (M:Event) 'WheelUp' scmp 0 == or
                    if{
                        (L:HDG_Knob_Anim_Control,number) -- (>L:HDG_Knob_Anim_Control,number) 0x18304 (>L:HDG_Knob_Animation,number)
                        (A:AUTOPILOT HEADING LOCK DIR, degrees) ++ dnor (>K:HEADING_BUG_SET)
                        1 (>L:MD_900_Rotary_Click, number)
                      }
                (M:Event) 'RightSingle' scmp 0 == (M:Event) 'WheelDown' scmp 0 == or
                    if{
                        (L:HDG_Knob_Anim_Control,number) ++ (>L:HDG_Knob_Anim_Control,number) 0x18303 (>L:HDG_Knob_Animation,number)
                        (A:AUTOPILOT HEADING LOCK DIR, degrees) -- dnor (>K:HEADING_BUG_SET)
                        1 (>L:MD_900_Rotary_Click, number)
                      }
            </callback_code>
        </mouserect>
    </visible_in_range>
</part>

So... here we go to the query part:
  1. I will have at least four rotating knobs distributed in the VC. I am shaking right now... Each and every animation will require 360 rotation keys??? :yikes: :yikes: :yikes:
  2. I can't remember how to change the number of keyframes in Gmax, the default is only for 100 keys; how should I change the settings to have 360 keyframes?
  3. About the the purpose of the hexadecimal numbers included in the callback section by Fr. Leaming; what are they for?
  4. I can't test the 3d part because... (GOTO 2, LOL).
The code above, was made possible with the help of all of you guys! As always, I am very thankful.
All the best,
Sergio.
 
Last edited:
So... here we go to the query part:
  1. I will have at least four rotating knobs distributed in the VC. I am shaking right now... Each and every animation will require 360 keys??? :yikes: :yikes: :yikes:
  2. I can't remember how to change the number of keyframes in Gmax, the default is only for 100 keys; how should I change the settings to have 360 keyframes?
  3. About the the purpose of the hexadecimal numbers included in the callback section by Fr. Leaming; what are they for?
  4. I can't test the 3d part because... (GOTO 2, LOL).
How to explain this without getting too deep into the weeds...

In Robert's original post, if you look closely you will see that his mouse script only "animates" the knob in the VC. No actual commands to adjust the sim's 'heading' is actually made! That is the purpose of the hex numbers! The XLS project he was working on had all of the actual logic in a C++ module.

In that module, an "Event Handler" would "decode" the hex numbers and execute the actual commands each unique hex number requested: 0x18304 = left click, 0x18303 = right click.

So, for your purposes you can simply ignore those pesky hex numbers since they won't actually serve any purpose at all!
0x18304 (>L:HDG_Knob_Animation,number) 0x18303 (>L:HDG_Knob_Animation,number)
 
WOW!

That was fast! So.. the only thing to do is to remove them from the code; dear Fr. Leaming, I really appreciate your simple and complete explanations.
Just a moment ago, I was looking how Bill was being helped with the same topic! (just in case anyone else need to tackle the same questions as me: https://www.fsdeveloper.com/forum/threads/knob-rotation-lh-rh-modeldefxml-code.447708/#post-845161).
Now I think I have all information required to test the code into the model :D

May God bless you and your lovely family.
Thank you kindly.
Sergio.
 
Last edited:
It should work even with the unused script present, since it will be ignored anyway...

...but does clutter up the nice script with unnecessary junk. :rotfl:

Nota Bene: I appreciate the blessings my friend. May God bless you and your lovely family as well!
 
I am going to honor Robert, Roman and you for this. Thank you :)

Just to resume and "stitch" all ideas going from a 2d gauge code to a 3d part.

Given a 2d gauge code:
HTML:
 <Gauge Name="Heading_Knob" Version="1.0">
     <Image Name="HSI_Heading_Knob.bmp"/>

      <Element>
          <Position X="63" Y="63"/>
          <Image Name="HSI_Heading_Knob.bmp">
              <Axis X="63" Y="63"/>
          </Image>
          <Rotate>
              <Value>(A:Autopilot heading lock dir,radians) 3 *</Value>
          </Rotate>
      </Element>
           <!--                                                                                                       M O U S E   E V E N T    L O G I C                                                                                                            -->
      <Mouse>
      <!-- Heading Knob -->
          <Area Left="0" Top="0" Width="127" Height="127">
          <ToolTip>HDG: %((A:Autopilot heading lock dir,degrees))%!03.0f!°</ToolTip>
              <Cursor Type="hand"/>
              <Click Kind="LeftSingle+RightSingle+WheelUp+WheelDown" Repeat="Yes">
                  (M:Event) 'LeftSingle' scmp 0 == (M:Event) 'WheelUp' scmp 0 == or
                      if{
                         (A:AUTOPILOT HEADING LOCK DIR, degrees) ++ dnor (>K:HEADING_BUG_SET)
                         1 (>MD_900_Rotary_Click, number)
                        }
                  (M:Event) 'RightSingle' scmp 0 == (M:Event) 'WheelDown' scmp 0 == or
                      if{
                         (A:AUTOPILOT HEADING LOCK DIR, degrees) -- dnor (>K:HEADING_BUG_SET)
                         1 (>MD_900_Rotary_Click, number)
                        }
                  </Click>
              </Area>
      </Mouse>
</Gauge>

EDIT 1
A tested 3d part code is:
HTML:
    <part>
        <name>MD900_HDG_Knob</name>
            <animation>
                <parameter>
                    <code>
                        (L:HDG_Knob_Anim_Control,number)
                    </code>
                </parameter>
            </animation>
            <mouserect>
                <cursor>Hand</cursor>
                <tooltip_text>HDG: %((A:Autopilot heading lock dir,degrees))%!03.0f!°</tooltip_text>
                <mouse_flags>LeftSingle+RightSingle+WheelUp+WheelDown</mouse_flags>
                <callback_code>
                    <!-- Test Values -->
                    (L:HDG_Knob_Anim_Control,number) 0 &lt;
                        if{ 100 (>L:HDG_Knob_Anim_Control,number) }
                    (L:HDG_Knob_Anim_Control,number) 100 &gt;
                        if{ 0 (>L:HDG_Knob_Anim_Control,number) }

                    <!-- Animation trigger controls -->
                    (M:Event) 'LeftSingle' scmp 0 == (M:Event) 'WheelUp' scmp 0 == or
                        if{
                            (L:HDG_Knob_Anim_Control,number) ++ (>L:HDG_Knob_Anim_Control,number)
                            (A:AUTOPILOT HEADING LOCK DIR, degrees) ++ dnor (>K:HEADING_BUG_SET)
                            1 (>L:MD_900_Rotary_Click, number)
                          }
                    (M:Event) 'RightSingle' scmp 0 == (M:Event) 'WheelDown' scmp 0 == or
                        if{
                            (L:HDG_Knob_Anim_Control,number) -- (>L:HDG_Knob_Anim_Control,number)
                            (A:AUTOPILOT HEADING LOCK DIR, degrees) -- dnor (>K:HEADING_BUG_SET)
                            1 (>L:MD_900_Rotary_Click, number)
                          }
                </callback_code>
            </mouserect>
    </part>

For the 3ds Max / Gmax animation stuff, I will quote Roman;
"Increase the AnimLength in the declaration header to 360, animate as such at: 0,1,90,180,270,359 Dealing with a circular rotation now. Remove the <Lag>, rotations don't like it.
You can adjust the speed per click etc.. by changing the now given values: (5 +) and (5 -)
The problem you were having is that you were toggling booleans ( 0 -> 1, 1 -> 0 ), multiplying them by 100 for animation.
The only animation you would ever get is 0 and 100, nothing in between. "


Translation:
For this code in particular, the rotation keys I tested are:
Key 0 = 0° ----------> Animation begin at
Key 1 = 1° ----------->
Key 40 = 89° ----------> 1°+ 89° = 90°
Key 60 = 90° ----------> 90° + 90° = 180°
Key 80 = 90° ----------> 180° + 90° = 270°
Key 100= 89° ----------> 270° + 89° = 359°

Animate the rotation steps clockwise or counter clockwise!!! Your choice.

NOTE:
This guarantees a full rotation from 0° to 359° using only 100 keys. The variable (L:HDG_Knob_Anim_Control,number) which drives the animation, is incremented from 0 to 100; and the test values are included in the callback code.

Again... all code is intended to be used in a model for FS2004. Now, I hope everyone would benefit and connect the dots between a 2d gauge to a 3d part and share more code ideas!
Should be simple enough to follow and make all pertinent changes to use this with P3D/FSX.

Thank you all,
Sergio.
:)

P.S.1 Robert, please forgive me to kidnap your post. But if I am not mistaken, you are very kind and you always support all help provided for this great comunity. My actions were made only in the spirit to help just a bit more.
P.S.2 Dear Fr. Leaming, the code you teached us works like a charm; thanks a million!
P.S.3 Roman, thanks again for teachimg me how to prevent code flooding; the 2d gauge was written with your help.
 
Last edited:
Back
Top