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

XML Syntax Question

Messages
159
Country
us-colorado
In looking at some existing code, apparently the and operation in the code line below is not required. Why is that? I would think you would need to and the result of the string compare with the value of the Lvar, but it seems to work either way.
Thx,
Al

(M:Event) 'LeftSingle' scmp 0 == (L:Var1,bool) 1 == and if{ ... }
 
D

Deleted member 1281

Guest
What Edu says, and I personally prefer to have the mouse click test as a simple (non-boolean) if statement. In the following example, Var2 increments on a left click if Var1 is TRUE and decrements on a right click.

Code:
<Click Kind="LeftSingle+RightSingle">
  (M:Event) 'LeftSingle' scmp 0 == if{
    (L:Var1,bool) if{ (L:Var2,enum) ++ (>L:Var2,enum) }
  } els{
    (L:Var2,enum) -- (>L:Var2,enum)
  }
</Click>

As an alternative, clever use of the quit operator can do much to unscramble complex if-els architectures:

Code:
<Click Kind="LeftSingle+RightSingle">
  (M:Event) 'LeftSingle' scmp 0 == if{
    (L:Var1,bool) if{ (L:Var2,enum) ++ (>L:Var2,enum) }
    quit
  }
  (M:Event) 'RightSingle' scmp 0 == if{
    (L:Var2,enum) -- (>L:Var2,enum)
    quit
  }
 </Click>
 
Last edited by a moderator:
Messages
159
Country
us-colorado
Thanks for the replies.
The context of my original post is that the syntax of the code line is from an aircraft interior model file, and the actual code line in that model file does not include the and operator, which surprised me. However, the fact is the code does seem to work, and thus my question.

I guess the way to think about it is that a successful mouse click just means "do the following code" while ignoring that a mouse click is represented by a string compare.

Al
 
Last edited:
D

Deleted member 1281

Guest
Al, the code without the "and" doesn't make much sense, but strange things can happen on an RPN stack. We need some more context to test it fully, including the <Click> line. First question would be, does the code also "work" with a right or middle click? If so, the error is right there.
 
Messages
1,564
Country
thailand
Manfred mentioned the stack - that's the key. The if{ ... } condition will be executed if a non-zero value is at the top of the stack when the parser reads the "if{"

Take a look at the stack at each step of the script to see what's going on. If (L:Var1, bool) equals 1, then

1562692826814.png


and,

1562692836171.png


both yield a non-zero value at the top of the stack. Regardless of how <Click> is defined, look at the stack to see how the if{ will be handled.

Bob
 
Last edited:
Messages
159
Country
us-colorado
The code only works with a Left click as intended. As for the <Click> line, I don't know where to find that in the a/c interior model file. And of course, since the model file is compiled I can only see very limited parts of it with a text editor - I don't have the XML source code. Since the intent of the code line is the if{} should only be executed when there is a left click and
(L:Var1,bool) 1 == , I do prefer using the and operator. Makes things clearer, at least to me.
Thanks all,
Al
 
Last edited:
D

Deleted member 1281

Guest
Ah ... yes, you said it was in a model, we overlooked that and thought we were talking panel gauge code.

In this case, rather than look at the compiled code, push the mdl file through MCX and use the Modeldef.xml Editor button to give you a searchable text file. In that text file, search your var names and/or the tooltip string (if there is one). In the modeldef, the relevant sections are called <MouseRect>, <MouseFlags>, and <CallbackCode>, and the latter has the true xml code. This will surely get us closer to solving the riddle, and may also enable us to replicate the logic if necessary.
 
Messages
159
Country
us-colorado
I think I need to rephrase my original question a bit. What I'd like to know is what is the proper way to view the string compare operation associated with the detection of a mouse click? Do you treat it as a typical logical operation? For example, if I wanted to compare two strings and then do something if the strings compared and also Lvar var1 was true, I think it would be written as:
'string1' 'string2' scmp 0 == (L:var1,bool) 1 == and if{ do something }

If a string compare associated with detecting a mouse click is treated the same way then we should have:
(M:Event) 'LeftSingle' scmp 0 == (L:var1,bool) 1 == and if{ do something }

and the and operator should be used. Whether or not it just happens that you can get away with not using the and operator with the Mouse Event in a particular situation is another issue. I want to understand what is considered the proper coding technique in this situation.

Thanks for all the responses -- much appreciated.
Al
 

tgibson

Resource contributor
Messages
11,327
Country
us-california
Yes. In the FSX SDK's modeldef.xml file MS coded it that way:

XML:
            (M:Event) 'LeftSingle' scmp 0 == (L:CROSS FEED1, enum) 2 &lt; &amp;&amp;
            if{ (L:CROSS FEED1, enum) 1 + (&gt;L:CROSS FEED1, enum) }
            (M:Event) 'RightSingle' scmp 0 == (L:CROSS FEED1, enum) 0 &gt; &amp;&amp;
            if{ (L:CROSS FEED1, enum) 1 - (&gt;L:CROSS FEED1, enum) }

"&amp;&amp;" is the same as and.
 
Messages
542
Country
australia
It really is simple , if it is just one left click , then you have two options.
Option #1.
<Click>
(L:var1,bool) 1 == if{ do something }

Option #2.
<Click Kind="LeftSingle">
(M:Event) 'LeftSingle' scmp 0 == (L:var1,bool) 1 == and if{ do something }

This line " (M:Event) 'LeftSingle' scmp 0 == (L:var1,bool) 1 == and if{ do something } " represents two parts ;
* First ,
(M:Event) 'LeftSingle' scmp 0 == (L:var1,bool) 1 == and
it's a Visibility statement with two conditions , the " and " is essential as it ensures that both conditions are considered .

* Second ,
if{ do something }
this is the action that is enacted if all the conditions in the visibility are valid .

The main significance of the " and " useage in the Visibility statement becomes apparent when one Button hot spot can serve multiple functions .
For example you might have an MFD that has multiple pages , each page might have multiple functions , and
to further complicate it different click kinds (Left , Middle , Right click) are used .

The following example is one button in one of my MFD's ,
Code:
    <Macro Name="Button9">(M:Event) 'LeftSingle' scmp 0 == (L:DAT37 mode,enum) 2 == and
                                if{ (>K:NAV1_RADIO_SWAP) (>K:FREQUENCY_SWAP) }
                          (M:Event) 'LeftSingle' scmp 0 == (L:DAT37 mode,enum) 4 == (L:DAT37 MAP Zoom,enum) 24 &lt; and and
                                 if{ (L:DAT37 MAP Zoom,enum) 1 - (>L:DAT37 MAP Zoom,enum) }
                          (M:Event) 'LeftSingle' scmp 0 == (L:DAT37 mode,enum) 3 == (L:APT_Nrst_select, number) 3 == and and
                          (M:Event) 'LeftSingle' scmp 0 == (L:DAT37 mode,enum) 3 == (L:APT_Nrst_select, number) 4 == and and
                          or
                          (M:Event) 'LeftSingle' scmp 0 == (L:DAT37 mode,enum) 3 == (L:APT_Nrst_select, number) 9 == and and
                          or                    
                            if{ 9 (&gt;L:APT_Nrst_select, number) }
        (M:Event) 'LeftSingle' scmp 0 == (L:DAT37 mode,enum) 3 == (L:APT_Nrst_select, number) 6 == and and
                                        if{ 1 (&gt;L:Mark View,enum)
                                              (L:FarCalcLatitude,degrees) (&gt;L:MarkPositionLatitude,degrees)
                                              (L:FarCalcLongitude,degrees) (&gt;L:MarkPositionLongitude,degrees)
                                              (L:FarCalcAltitude, feet) (&gt;L:Saved Altitude, feet)
                                              (L:HEADINGFarCalc, degrees) 180 + dnor (&gt;L:HEADINGsavedMarkPos, degrees)
                                              (L:FarCalcGROUND ALTITUDE, feet) (&gt;L:MarkGROUND ALTITUDE, feet)
                                              (L:FarCalcRunwayLength, nmiles) 6076 * (&gt;L:RunwayLength, number) }
        (M:Event) 'MiddleSingle' scmp 0 == (L:DAT37 mode,enum) 3 == (L:APT_Nrst_select, number) 6 == and and
                                          if{ (L:FarCalcLatitude,degrees) (&gt;L:RequiredWaypointLatitude, degrees)
                                              (L:FarCalcLongitude,degrees) (&gt;L:RequiredWaypointLongitude, degrees) }
        (M:Event) 'RightSingle' scmp 0 == (L:DAT37 mode,enum) 3 == (L:APT_Nrst_select, number) 6 == and and
                                           if{ 1 (&gt;L:FarEndRunwayCalc,enum)
                                              (L:OrigMarkStoreLatitude,degrees) (&gt;L:FarCalcLatitude,degrees)
                                              (L:OrigMarkStoreLongitude,degrees) (&gt;L:FarCalcLongitude,degrees)
                                              (L:HEADINGOrigMarkStore, degrees) (&gt;L:HEADINGFarCalc, degrees)  
                                              (L:OrigMarkStoreGROUND ALTITUDE, feet) (&gt;L:FarCalcGROUND ALTITUDE, feet)
                                              (L:RunwayLength, number) 6076 / (&gt;L:FarCalcRunwayLength, nmiles)  
                                              (L:OrigMarkStoreAltitude, feet) (&gt;L:FarCalcAltitude, feet) }</Macro>
    <Area Left="200" Top="64" Width="20" Height="20">
      <Cursor Type="Hand"/>
      <Click Kind="LeftSingle+MiddleSingle+RightSingle">@Button9</Click>
    </Area>
You can see that there are 8 functions in this one button , but more importantly it is apparent how vital is the use of "and" .

In another MFD I have 21 functions in one button , all are left clicks only , in each case the Visibility statement determines
the " if{ do something } " function enacted by a click .
Code:
    <Macro Name="Button10">(L:DAT49 mode,enum) 2 == if{ (&gt;K:NAV2_RADIO_SWAP) }
           (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 0 == and
                if{ 0 (&gt;@c:FlightPlanWaypointIndex)
                    1 (&gt;@c:FlightPlanDirectToDestination)
                    1 (@c:FlightPlanWaypointIndex) (>@c:FlightPlanDeleteDirectTo)
                    0 (@c:FlightPlanWaypointIndex) (>@c:FlightPlanDeleteWaypoint) }
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 0 == (L:TypEntry, enum) 0 == and and and
               if{ (L:KoalaLatitude, degrees) (&gt;@c:FlightPlanNewWaypointLatitude, degrees)
                   (L:KoalaLongitude, degrees) (&gt;@c:FlightPlanNewWaypointLongitude, degrees)
                   'RDR' (L:F111_Wpt_Sum, number) near scat (&gt;@c:FlightPlanNewWaypointIdent)          
                   (L:F111_Wpt_Sum, number) (&gt;@c:FlightPlanAddWaypoint) }
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 0 == (L:TypEntry, enum) 1 == and and and
               if{ 0 (&gt;@c:FlightPlanWaypointIndex)
                   (L:KoalaLatitude, degrees) (&gt;@c:FlightPlanNewWaypointLatitude, degrees)
                   (L:KoalaLongitude, degrees) (&gt;@c:FlightPlanNewWaypointLongitude, degrees)
                   'RDR' (L:F111_Wpt_Sum, number) near scat (&gt;@c:FlightPlanNewWaypointIdent)
                    1 (&gt;@c:FlightPlanDirectToDestination) }
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 0 == (L:TypEntry, enum) 2 == and and and
               if{ (L:KoalaLatitude, degrees) (&gt;@c:FlightPlanNewWaypointLatitude, degrees)
                   (L:KoalaLongitude, degrees) (&gt;@c:FlightPlanNewWaypointLongitude, degrees)
                   'RDR' (L:F111_Wpt_Sum, number) near scat (&gt;@c:FlightPlanNewWaypointIdent)          
                   (L:F111_Wpt_Sum, number) (&gt;@c:FlightPlanAddWaypoint)
                   (L:F111_Wpt_Sum, number) 1 + (&gt;@c:FlightPlanDeleteWaypoint) }
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 1 == (L:TypEntry, enum) 0 == and and and
               if{ (@c:NearestAirportCurrentICAO) (&gt;@c:FlightPlanNewWaypointICAO)          
                   (L:F111_Wpt_Sum, number) (&gt;@c:FlightPlanAddWaypoint) }                  
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 1 == (L:TypEntry, enum) 1 == and and and                  
               if{ 0 (&gt;@c:FlightPlanWaypointIndex)
                  (@c:NearestAirportCurrentICAO) (&gt;@c:FlightPlanNewWaypointICAO)
                  1 (&gt;@c:FlightPlanDirectToDestination) }
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 1 == (L:TypEntry, enum) 2 == and and and            
               if{ (@c:NearestAirportCurrentICAO) (&gt;@c:FlightPlanNewWaypointICAO)          
                   (L:F111_Wpt_Sum, number) (&gt;@c:FlightPlanAddWaypoint)
                   (L:F111_Wpt_Sum, number) 1 + (&gt;@c:FlightPlanDeleteWaypoint) }
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 2 == (L:TypEntry, enum) 0 == and and and
               if{ (@c:NearestVorCurrentICAO) (&gt;@c:FlightPlanNewWaypointICAO)          
                   (L:F111_Wpt_Sum, number) (&gt;@c:FlightPlanAddWaypoint) }
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 2 == (L:TypEntry, enum) 1 == and and and                  
               if{ 0 (&gt;@c:FlightPlanWaypointIndex)
                  (@c:NearestVorCurrentICAO) (&gt;@c:FlightPlanNewWaypointICAO)
                  1 (&gt;@c:FlightPlanDirectToDestination) }
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 2 == (L:TypEntry, enum) 2 == and and and            
               if{ (@c:NearestVorCurrentICAO) (&gt;@c:FlightPlanNewWaypointICAO)          
                   (L:F111_Wpt_Sum, number) (&gt;@c:FlightPlanAddWaypoint)
                   (L:F111_Wpt_Sum, number) 1 + (&gt;@c:FlightPlanDeleteWaypoint) }
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 3 == (L:TypEntry, enum) 0 == and and and
               if{ (@c:NearestNdbCurrentICAO) (&gt;@c:FlightPlanNewWaypointICAO)          
                   (L:F111_Wpt_Sum, number) (&gt;@c:FlightPlanAddWaypoint) }
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 3 == (L:TypEntry, enum) 1 == and and and                  
               if{ 0 (&gt;@c:FlightPlanWaypointIndex)
                  (@c:NearestNdbCurrentICAO) (&gt;@c:FlightPlanNewWaypointICAO)
                  1 (&gt;@c:FlightPlanDirectToDestination) }
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 3 == (L:TypEntry, enum) 2 == and and and            
               if{ (@c:NearestNdbCurrentICAO) (&gt;@c:FlightPlanNewWaypointICAO)          
                   (L:F111_Wpt_Sum, number) (&gt;@c:FlightPlanAddWaypoint)
                   (L:F111_Wpt_Sum, number) 1 + (&gt;@c:FlightPlanDeleteWaypoint) }
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 4 == (L:TypEntry, enum) 0 == and and and
               if{ (@c:NearestIntersectionCurrentICAO) (&gt;@c:FlightPlanNewWaypointICAO)          
                   (L:F111_Wpt_Sum, number) (&gt;@c:FlightPlanAddWaypoint) }
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 4 == (L:TypEntry, enum) 1 == and and and                  
               if{ 0 (&gt;@c:FlightPlanWaypointIndex)
                  (@c:NearestIntersectionCurrentICAO) (&gt;@c:FlightPlanNewWaypointICAO)
                  1 (&gt;@c:FlightPlanDirectToDestination) }
            (L:DAT49 mode,enum) 4 == (L:Display mode,enum) 1 == (L:LLAptVorNdbInt,enum) 4 == (L:TypEntry, enum) 2 == and and and            
               if{ (@c:NearestIntersectionCurrentICAO) (&gt;@c:FlightPlanNewWaypointICAO)          
                   (L:F111_Wpt_Sum, number) (&gt;@c:FlightPlanAddWaypoint)
                   (L:F111_Wpt_Sum, number) 1 + (&gt;@c:FlightPlanDeleteWaypoint) }                  
            (L:DAT49 mode,enum) 4 == (L:StandOff mode,enum) 4 == and
                if{
                (L:DistMove,nmiles) 1 - (&gt;L:DistMove,nmiles) (L:DistMove,nmiles) -1 == if{ 0 (&gt;L:DistMove,nmiles) }
                }
          (L:DAT49 mode,enum) 4 == (L:StandOff mode, enum) 2 == (L:PrecisionLevel mode,enum) 0 == and and
          (L:DAT49 mode,enum) 4 == (L:StandOff mode, enum) 2 == (L:PrecisionLevel mode,enum) 1 == and and
                or
               if{ (L:ClikLatitude, degrees) (&gt;L:RequiredWaypointLatitude, degrees)
                (L:ClikLongitude, degrees) (&gt;L:RequiredWaypointLongitude, degrees)
                 }</Macro>
    <Area Left="197" Top="94" Width="20" Height="20">
      <Cursor Type="Hand"/>
      <Click Kind="LeftSingle" Repeat="Yes">(L:DAT49 mode,enum) 3 == if{ (&gt;K:HEADING_BUG_DEC) } @Button10</Click>
    </Area>

Cheers
Karol
 
Last edited:

taguilo

Resource contributor
Messages
1,585
Country
argentina
(M:Event) 'LeftSingle' scmp 0 == (L:Var1,bool) 1 == if{ ... }

No matter the <Click> kind condition (Left,Right,Left+Right, none, etc) , if it is met then the script will execute and if (L:Var1,bool) is true then the if{} portion will execute as well.
In that example 'LeftSingle' scmp 0 == becomes meaningless, and the only part of the script being interpreted is (L:Var1,bool) 1 == if{ ... }

(M:Event) 'LeftSingle' scmp 0 == (L:var1,bool) 1 == and if{ do something }

Yes, that's correct to include a check for Left button clicked. Even it is not necessary to write (L:var1,bool) 1 ==, making it ... (L:var1,bool) and if{ do something } will work too.


And it is not necessary to write &amp; &amp; in modeldef xml files, and works perfectly well, at least in FSX and P3D versions.
Also > can be used instead of &gt;

Tom
 
Messages
159
Country
us-colorado
I finally see the difference ( I hope.. sigh).

If, for example, the <Click> condition for a code block needs to specify both LeftSingle+RightSingle because of 'other' code in the block, then the line

(M:Event) 'LeftSingle' scmp 0 == (L:var1,bool) 1 == if{ do something } will execute for both a Right or Left click,

but if the code line includes the and operator

(M:Event) 'LeftSingle' scmp 0 == (L:var1,bool) 1 == and if{ do something }

it will only execute for a left click as intended.

However, if the <Click> condition only specifies LeftSingle, then the and operator will not make any difference.

Thank you for all the help and examples,
Al
 
Top