Jump to content

TARGET - multiple buttons to generate a delayed keystroke


krel

Recommended Posts

I've been trying to find an answer to this - I am certain it can be done, but I lack the experience with TARGET to sort it out, so I'm hoping I can get some guidance.

 

I'm looking to set up a mapping/function such that when I press and hold a button on two devices - ie. S1 on the Warthog and LTB on the throttle - after a three second delay it sends a keystroke. Is this doable?

Link to comment
Share on other sites

Of course but not any key, you have to set S1 or S3 as SHIFT key.

 

Then when is pressed you get the function you want when you press the second key.

 

Also you can toggle the SHIFT key.

 

For instance, the settings below will give "f" after 3 secs if you press MSP and you have SHIFT Key pressed.

i-o.png.211b7ee3419831ecc89b26fa9ff0518b.png


Edited by Swaty
typo
Link to comment
Share on other sites

I am not using the GUI - I'm doing it via script. The buttons will normally each have another function, but when pressed together and held for three seconds I want to send a different keystroke - it doesn't matter if I send the normal function with the "special" one or not. The image you shared definitely gives me hope that this is doable, thanks. :)

Link to comment
Share on other sites

  • 3 months later...

include "target.tmh"

int main()
{
   if(Init(&EventHandle)) return 1; 

   // Send different keys depending on the state of the Autopilot switch
   MapKey(&Throttle, APENG, EXEC("FS();"));

}

int FS() {  
   if(Throttle[APPAT]) {
       ActKey(PULSE+KEYON+F3);
   }
   else if(Throttle[APAH])    {
       ActKey(PULSE+KEYON+F2);
   }
}

int EventHandle(int type, alias o, int x)
{
   DefaultMapping(&o, x);
}

 

There are probably other ways to do it too :)

 

You could SEQ in a delay before the EXEC ... you might get some weird logic or edge cases because the test for the AP switch position is executed after the delay, so I dont know how to solve that issue.

 

DeferCall in main has the same issue - delay and then call the function. So I am not sure...


Edited by Thermal
Link to comment
Share on other sites

I worked out DeferCall in a function :)

 

When the function executes it basically forks both of the ActKey's into their own process. So in three seconds the first F3 is send, then 3 seconds later the second F3 is sent (not 9 seconds later).

 

int FS() {  
   if(Throttle[APPAT]) {
       ActKey(DeferCall(3000, &ActKey, PULSE+KEYON+F3 ));
       ActKey(DeferCall(6000, &ActKey, PULSE+KEYON+F3 ));
   }
   else if(Throttle[APAH])    {
       ActKey(DeferCall(3000, &ActKey, PULSE+KEYON+F2 ));
   }
}

Link to comment
Share on other sites

I can propose you a very much more complicated way to achieve that, with a very different structure of programming teached by ivanwfr many years ago on those forums

once you understand the architecture, it is very powerfull

 

general rules :

you define global vars for each btn status

you map the btns using these vars and a function call in the main{} statements of your main tmc file that wil use MapKey() and your vars to map btns on the stick (same for throttle)

then in the main{} of your main tmc you can either use functions call or direct vars editing to have your vars updated to do what you want for your that specific tmc mapping will do

using functions you gain a great freedom in programming

using those definitions you can map what you want

 

but it will destruct directX mapping in DCS, unless you use a layer reserved for DX definitions

 

for detailed infos search past years forum for ivanwfr posts, credits to him

 

some example

 

in main tmc use include and path to a js_declare.tmc (same for throttle)

include "js_declare.tmc"

 

in the js_declare.tmc you will have something like that (definitions are in predicate part to be globals, empty function is needed for to read the definitions on initialize via that function call from main tmc)

 

int H2D_DI=0; int H2D_DO=0; int H2D_MI=0; int H2D_MO=0; int H2D_UI=0; int H2D_UO=0;

int js_declare(){

}

 

and so on to declare vars used for btns mapping...

 

 

in main tmc use include and a path to a js_map.tmc

include "js_map.tmc"

 

in which you have a function that will execute

 

int js_map(){

MapKeyIOUMD(&Joystick, H2D, H2D_UI, H2D_UO, H2D_MI, H2D_MO, H2D_DI, H2D_DO);

}

 

call that function in the main tmc in the main section as an initialization runtime

 

int main(){

js_declare();

}

 

then directly in main tmc and main section, or via a include of a more specified tmc

update your btns declarations vars to define the action you want them to do

maybe a macro, maybe a pulse+USB statement or anything you want... as a function call...

 

from there you can define a function call that returns the 1st btn status, or easier a function that updates and stores that status in a flag

by example

to do that define that flag in the main tmc file and in the predicate to have it act as global var :

 

flag_Btn1_Pressed_ForTime = 0;

 

int main(){

btn1_ioumd = func_flagBtn1() ;

btn2_uiomd = func_Btn2();

}

 

then below main section of main tmc, or in your specific tmc file declared with include

add your functions

something like

 

int func_flagBtn1(){

return TEMPO(0, EXEC("func_flagBtn1True();"), 800);

}

 

where 800 will be the delay in msec you want 1st buton to stay pressed

you can replace 0 by any input you want your btn press to produce at the same time

 

then you will have

int func_flagBtn1True(){

flag_Btn1_Pressed_ForTime = 1;

}

 

then you can proceed the same way with btn2

define a func call with the tempo statement for the second delay

 

I you don't want consecutives delays ( because that way you 'll have btn 1 for 800 msc then btn 2 for ... msec as explained below) but at the same time delay

use two flags and another function in the event handler as proposed previously that will check the both flags status if they are true at the same time

and then from that condition, you can return to what you want... another function call, a macro, and so on...

don't forget to reset your flag to 0 at some conditions...

 

 

 

so basically :

 

btn press is relative to a func call to update global vars = flags

how to have the flags updated after a maintained delay of press : use TEMPO statement in the above funcs to avoid defercall and sleep problems

how to check your flags : either call a fucntion that tests the flags in the event handler

or either (the better) use that test from one function call depending on your mappings logic and what you want to do with it... cannot have it in mind for you...

 

one point to keep in mind :

if using sleep instead of defercall, you'll down any user key input down to 1-2 msec...

 

 

always do the simplest way:

 

basically for you the shame is

 

btn1 press : tempo : flag1=1

btn1 release : flag1 = 0

 

btn2 press: tempo : if flag1==1 then flag2 =2

btn2 release: flag2 = 0

 

no need to test flag1 and flag2 continuously, only check flag 1 when you are in conditions flag2 becomes true

except you have to take care of the orders of your presses : if you press btn2 before btn1, may lead to some malfunction...

 

but you can have reflexion about different ways to do your checks and logical programming

 

a bit long answer but hope it can help


Edited by C6_Hellfrog
Link to comment
Share on other sites

Having started that thread, I'll just say that the way Thermal has it is the simplest means of executing it.

 

The thread was also for using toe brakes with the Cougar as digital axes to get around the 8 axis limit. Nicu has some great ideas, that's for sure, but my rudder pedals are old and the pots were screwing with that solution.

  • Like 1
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...