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

Long Press Multiple Command Button?

Messages
10,149
Country
us-arizona
Hey all,

So, lets say if you click on a button on a gauge, it will 'do this'.

But.... If you hold down the button for 2+ seconds, then it will 'do that'.

How do you do this?

How would the logic be written where it would do something different if you held the left mouse down 2+ seconds?


This is for Altimeter in an Autopilot. If you long press, it would go into a settings mode.

I have wanted to know how to do this for years, just never learned to do it.

Many thanks for any help.



Bill
 
Try this...

update section:
Code:
(L:ButtonStatus,enum) 1 ==
if{
    (P:Absolute time,number) (L:ButtonStartTime,number) - 2 >=
    if{
        2 (>L:ButtonStatus,enum)

        (* insert long press code here *)

    }
}

mouse section:
Code:
<Cursor Type="CrossHair"/>
<Click Kind="LeftSingle+LeftDrag+LeftRelease">
    (M:Event) 'LeftSingle' scmp 0 ==
    if{
        1 (>L:ButtonStatus,enum)
        (P:Absolute time,number) (>L:ButtonStartTime,number)
    }

    (M:Event) 'LeftRelease' scmp 0 ==
    if{
        0 (>L:ButtonStatus,enum)
        (L:ButtonStartTime,number) (P:Absolute time,number) 2 - >
        if{

            (* insert short click code here *)

        }
    }
</Click>
 
I won't give you a specific example because it will blow your brain out with the amount of code involved so I will just give you some pointers.

Here is some basic mouse area code.

Code:
        <Click Kind="LeftSingle+RightSingle+LeftRelease+RightRelease+Leave">
            (M:Event) 'LeftSingle' scmp 0 == (M:Event) 'RightSingle' scmp 0 == ||
            if{
                (L:MOUSE_CLICKED,number) 0 ==
                if{
<!-- mouse_clicked prevents repeated leftsingle events, see text -->
                    1 (&gt;L:MOUSE_CLICKED,number)
<!-- set a timer to start counting -->
                    1 (&gt;L:RADIO_TIMER,number)
<!-- Now do any sort of processing you may need to do when the button is first clicked -->
                }
            }
            (M:Event) 'Leave' scmp 0 ==
            if{
<!-- clear the mouse click -->
                0 (&gt;L:MOUSE_CLICKED,number)
<!-- check to make sure that your timer was legitimately started -->
                (L:RADIO_TIMER,number) 0 &gt;
                if{
<!-- Do the processing for the short button push. The long hold button push should be processed in your gauge update routing. -->
<!-- clear the timer -->
                    0 (&gt;L:RADIO_TIMER,number)

<!-- check the number of brackets, the number I have here probably isn't right                     
                    }
                }
            }
        </Click>

I wouldn't process the long hold action in the mouse area. This should be done in the update area of your gauge. In the update area you would increment the radio_timer if it was more than 0. When the radio_timer gets above the hold time (if the hold time is 2 seconds then that would be 2*18 = 36) then you would do the processing for the long hold time and reset the radio_timer to zero. Resetting the radio_timer to zero will prevent the short button push processing happening in the mouse area "Leave" section.

By using this method the long hold processing will happen when the required hold time is reached even if the user is still holding the button down. If you need the processing to happen only when the user releases the button then you would just check if the radio_timer is above or below the hold time in the mouse area "Leave" section and process accordingly.

A note about the mouse_clicked variable. When you use the "Leave" click kind this changes the behaviour of leftsingle and rightsingle. They now become repeating and if you hold down the leftsingle then you will get a constant stream of leftsingle commands. Using the mouse_clicked variable means that only the first leftsingle will be actioned.

Note: I use Leave rather than leftrelease as there are some situations where you can get a button to hang if you only use leftrelease. I think moving out of the window while holding the button down and then releasing is one of them. In those cases you get the leftsingle but may not get a leftrelease.
 
Many thanks Anthony. I tried and tried to get this to work (not yours, but others) and just couldnt. I might try it again. This is not an easy thing to do. Glad you were able to get it to work, so that means its possible.

I never knew there was a 'mouse_clicked' variable. Nice....
 
Bill, what you intend to do should not be difficult at all. Just important to know is how must the code behave in all cases.
For example

-First click does X and stops, or keeps doing X until released?
or
-First click does X and keeps doing X until time elapsed 2+ seconds when does Y instead?
or
-First click does X and keeps doing X until released and also when time elapsed 2+ seconds does Y as well?

In all three cases all of your related code should go in <Click...> </Click> section.

Tom
 
I never knew there was a 'mouse_clicked' variable. Nice....
Um, there isn't. He just made up a custom (L:variable,unit) which anyone can do.

Tom has the right idea though. First write down in short statements precisely what you want to accomplish. Then worry about translating that into XML script.
 
Yep, MOUSE_CLICKED is just a custom variable I made. The problem with using the "Leave" mouse kind is that it actually changes the behaviour of LeftSingle and RightSingle. Normally they only are true when you first click the mouse button but with the "Leave" mouse kind in there they become repeating so will constantly trigger. MOUSE_CLICKED is used to prevent the repeat triggering.

The differences between Leave and LeftRelease are these:

Leave will be true when you release the mouse button or leave the mouse zone. In this case you just need to make sure the mouse zone is large enough to avoid having the user accidentally leave the mouse zone.

LeftRelease will be true when you release the mouse button but only when you are still in the mouse zone. If you the user drags outside the mouse zone and then releases the mouse button then LeftRelease will never be true. This can lead to any timer functions hanging unless you write them to account for this. For example, if the timer reaches your time limit you can clear any mouse functions and reset the timer. The problem is the user may drag outside the mouse area and release the mouse key before the hold time is complete but you have no way of knowing if this has actually happened and you would then have to assume the user has held the key for the full hold time.

I have made a little demo gauge which uses the code I posted earlier. There is a big button to push and two text displays. One showing the timer (I use a 3 second timer which means it counts to 54 ie 3*18) and another showing the status of MOUSE_CLICKED. Mouse clicked will effectively equal 1 when the mouse button is pressed and you are still in the mouse zone. It will change to zero if you leave the mouse zone or you release the mouse button.

I must respectfully disagree with Tom about having all functions within the mouse click function. The mouse click function will only be run when one of the mouse kind conditions is true. This will not happen on each cycle so the timer and checking that the timer has reached the hold time must be performed in an update cycle in your gauge outside of the mouse click function.
 

Attachments

Last edited:
I must respectfully disagree with Tom about having all functions within the mouse click function. The mouse click function will only be run when one of the mouse kind conditions is true. This will not happen on each cycle so the timer and checking that the timer has reached the hold time must be performed in an update cycle in your gauge outside of the mouse click function.

Anthony,

All you've said regarding LeftSingle, LeftRelease and Leave is of course true. That's the reason I used to code a timer in some complex switches to "release" the mouse when focus goes outside the area clicked.

Now, you yourself stated that LeftSingle repeats when button is held down constantly and Leave is part of the <Click Kind>.
Therefore, as long as button is kept pressed, a timer may be checked without any trouble.

See this example:

Code:
     <Click Kind="LeftSingle+Leave">
          (M:Event) 'LeftSingle' scmi 0 == sp0
          (L:Timer Control,seconds) sp1
          l0 l1 0 == and
          if{
               (P:Absolute time,seconds) (>L:Timer Control,seconds)
               (L:My_FirstAction,number) ++ (>L:My_FirstAction,number)
             }

          l0 l1 -1 != and (P:Absolute time,seconds) (L:Timer Control,seconds) - abs 2 > and
          if{
               (L:My_SecondAction,number) ++ (>L:My_SecondAction,number)
               -1 (>L:Timer Control,seconds)
             }
          (M:Event) 'Leave' scmi 0 ==
          if{
               0 (>L:Timer Control,seconds)
             }
     </Click>

(L:My_FirstAction,number) var increments by 1 each time the user does a single click.
If the user clicks and holds the button down, (L:My_FirstAction,number) increments only by one and after two seconds (L:My_SecondAction,number) also increments by one. Once the button is released the entire process is "armed" for the next click.

This is a basic example that can have multiple variations depending on the user needs.
I asked Bill (lionheart) to give an example of what he has in mind precisely for that.

Tom
 
Ah yes, you are right Tom.

It hadn't occurred to me that you could use the bug/change in behaviour of "leftsingle" repeating when you use the "leave" click kind. I was more worried about getting the damn thing to work than trying to finesse it.
 
Codes from my previous post works just fine in my xml gauges, and the same approach I've successfully used in C++ gauges too.

I think that "Leave" only works with 2D gauges, while "LeftSingle+LeftDrag+LeftRelease" works with 3D-parts too. The idea is from an earlier topic, where @Vitus and @n4gix wrote about this. With "LeftDrag" the only problem is that cursor becomes a "Grab" when the button is pressed, but this can be prevented with the "CrossHair" cursor type. Visually, "CrossHair" looks exactly like the "Hand".

Also, I'm not sure that "Mouse Repeat" is suitable for precise timing, due to different keyboard and mouse settings on each particular PC.
 
Codes from my previous post works just fine in my xml gauges, and the same approach I've successfully used in C++ gauges too.

Perhaps your example is not quite suitable for what Bill seems to need. Check it and you'll see that short click code executes only when button is released. So, as long as button is held down or dragged there will be no action. Besides, as ButtonStatus resets when button is released (which is correct), long click code won't execute either. As a result, it is not possible to mix short and long click codes in a single action.

And if Leave is not appropriate, it can be replaced by <Click Kind="LeftSingle+LeftRelease+Whatever..." Repeat="Yes"> or similar construction.

Also, I'm not sure that "Mouse Repeat" is suitable for precise timing, due to different keyboard and mouse settings on each particular PC.
No problem at all here, because a real timer (like the one you actually wrote in your example), not a counter, is used. Precision's differences would be insignificants.

Tom
 
Thanks guys for this discussion. So much learned....

Thanks Anthony for posting that code.

Thanks Tom for that sample.

Once again I am shown one could write many ways to get something to work in code.
 
Try this...
Man, you've just got to love these archived messages! Thanks for the script example Luka, it works wonderfully for my clock's timer CLR button; start/stop and hold 2 seconds for reset... :wave:
 
Back
Top