Previous Thread
Next Thread
Print Thread
Rate This Thread
Hop To
#4394499 - 12/12/17 07:00 PM How to detect Shift key  
Joined: May 2006
Posts: 123
DarKcyde Offline
Member
DarKcyde  Offline
Member

Joined: May 2006
Posts: 123
Anyone know how to detect the Shift key without hardcoding the key in your script? I'm trying to think of ways to make my code more portable for others. People like to use different shift keys, like the Nosewheel button and Paddle.

Here's a use case:

Code
//Disable button when Shifted
MapKeyR(&Throttle, BSF, EXEC("if (!Joystick[S3]) PressSomeButtons;"));


So instead of Joystick[S3] I want to detect whatever the Shift key is. I suspect it involves layer() or layer_sw[] somehow.

Inline advert (2nd and 3rd post)

#4394523 - 12/12/17 09:36 PM Re: How to detect Shift key [Re: DarKcyde]  
Joined: Dec 2000
Posts: 529
RogueSqdn Offline
USAF Veteran
RogueSqdn  Offline
USAF Veteran
Member

Joined: Dec 2000
Posts: 529
Advance, NC
I don't know if what you ask is possible. At least the way I'm understanding your question. The following line should be near the top of your script:

Code
SetShiftButton(&Joystick, S3, &Throttle, BSF, BSB, 0);


Whoever's using your file can change the S3 to whatever they want, then move what was on the button they're using to S3. But I can't think of a way to automate this.


Jared
-----
FalconNW MachV, Obutto R3volution

DEFENSOR FORTIS

#4394625 - 12/13/17 03:26 PM Re: How to detect Shift key [Re: DarKcyde]  
Joined: May 2006
Posts: 123
DarKcyde Offline
Member
DarKcyde  Offline
Member

Joined: May 2006
Posts: 123
Yeah, there's a lot of bitwise math in the IO and UMD code, it's not easy to grok unless you recently took a computer science course.

I could simply use some alias variables, and abstract things that way. That might be the simplest solution, which is usually best.

Like so:


Code
alias IOdev = Joystick
int IObutton = S3
SetShiftButton(&IOdev, IObutton, &Throttle, BSF, BSB, 0);


Not tested btw, that code might not work.

Last edited by DarKcyde; 12/17/17 02:56 AM.
#4396360 - 12/23/17 03:37 AM Re: How to detect Shift key [Re: DarKcyde]  
Joined: Mar 2011
Posts: 14
Thermal Offline
Junior Member
Thermal  Offline
Junior Member

Joined: Mar 2011
Posts: 14
You can define the shift (and UMD) button to be whatever you want with "SetShiftButton"?

#4396960 - 12/27/17 05:23 AM Re: How to detect Shift key [Re: DarKcyde]  
Joined: May 2006
Posts: 123
DarKcyde Offline
Member
DarKcyde  Offline
Member

Joined: May 2006
Posts: 123
Yeah, you can define the shift as whatever you like. That's the issue... my code checks for MY shift button in several places. Explicitly it checks for Joystick[S3]. If a user wanted to change their shift key, they would have to go thru all kinds of code looking for all the occurrences of Joystick[S3] and replace them with whatever shift key they used.

Look at my example... perhaps it requires some explanation.

Code
MapKeyRIO(&Throttle, BSF, 0, PressSomeButtons);


That doesn't work. MapKeyR remembers the state of the key when pressed, and sends the IO key of whatever it was when pressed. So pressing shift on the Release never fires, because it was in the O state when pressed. I needed a way to disable the key, regardless of what I programmed on the MapKey part of the key.

Code
//Disable button when Shifted
MapKeyR(&Throttle, BSF, EXEC("if (!Joystick[S3]) PressSomeButtons;"));


That checks to make sure my IO button is NOT pressed before PressSomeButtons. If the IO button is pressed, it does nothing. This allows you to fix those switches that get out of sync with your game. For instance, gear Up/Down on a switch. You die, then start on the runway with your switch in the Gear Up position. Instead of doing all kinds of awkward workarounds, I fix this by disabling the output when shifted. My code does this on several switches that hold position, because its the best way to fix them while in-game.

Now, instead of "if (!Joystick[S3]" I want to detect the IO key, no matter what key it is. This kind of thing isn't in the Target manual, it's buried deep in Target.tmh somewhere.

#4397126 - 12/28/17 11:35 AM Re: How to detect Shift key [Re: DarKcyde]  
Joined: Mar 2011
Posts: 14
Thermal Offline
Junior Member
Thermal  Offline
Junior Member

Joined: Mar 2011
Posts: 14
Ok, I think I have it smile

Code
int main()
{
    if(Init(&EventHandle)) return 1; // declare the event handler, return on error
	
	// AP button/switch = Frameshift logic + deploy hard points
	MapKey(&Throttle, APALT, PULSE+'u');  // Deploy Hardpoints
	MapKeyR(&Throttle, APALT, PULSE+'u'); // Retract Hardpoints, then your in Frameshift mode

	MapKey(&Throttle, APENG, EXEC("FS();"));	// Call Function
}


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



My Warthog isnt connected at the moment, so cant test. I'm assuming you can call a function with MapKeyR.

So maybe combine this with a logical flag so you can have one place to set your shift key.




Last edited by Thermal; 12/28/17 11:36 AM.
#4408834 - 03/04/18 03:47 PM Re: How to detect Shift key [Re: DarKcyde]  
Joined: Mar 2003
Posts: 3,922
Paradaz Offline
Senior Member
Paradaz  Offline
Senior Member

Joined: Mar 2003
Posts: 3,922
UK
Can you make an LED on the throttle light up when shift is pressed as part of these scripts?


On the Eighth day God created Paratroopers and the Devil stood to attention.
#4408886 - 03/04/18 10:16 PM Re: How to detect Shift key [Re: DarKcyde]  
Joined: Jul 2016
Posts: 61
Drakoz Offline
Junior Member
Drakoz  Offline
Junior Member

Joined: Jul 2016
Posts: 61
Re turning on LED due to state of Shift key

You should just be able to do the following, but when I tried this in the past, I don't think it worked as well as I would like (or at all?). I'm using the Throttle MSP key for my shift key.

Code
MapKey(&Throttle, MSP, EXEC("ActKey(PULSE+KEYON+LED(&Throttle, LED_ONOFF, LED_CURRENT+LED1));");
MapKeyR(&Throttle, MSP, EXEC("ActKey(PULSE+KEYON+LED(&Throttle, LED_ONOFF, LED_CURRENT-LED1));");


If the above doesn't work, or if you want to do more special control over the state of the shift key, in your EventHandle(), do the following. This can work with any key if you want to add special coding that is real time and does not play well with an EXEC() on a MapKey() function.

My shift button is the MSP button on the Warthog Throttle.
&o is an alias for the device (e.g. &Throttle or &Joystick).
x is the button that caused EventHandle() to be called (the shift button is what we are looking for)
o[MSP] gives the current state of the MSP button. Pressed = 1, unpressed = 0.
The two ActKey() calls are right out of the script manual for turning LEDs on and off.

Code
int EventHandle(int type, alias o, int x)
{
	// MSP - Allow IO shift button to cause an action (turn on an LED when pressed))
	if ((&o == &Throttle) & (x == MSP)) {
		if (o[MSP]) {			// If Shift key pressed,	
			ActKey(PULSE+KEYON+LED(&Throttle, LED_ONOFF, LED_CURRENT+LED1));  // LED 1 on
		} 
		else {					// When Shift key released,
			ActKey(PULSE+KEYON+LED(&Throttle, LED_ONOFF, LED_CURRENT-LED1));  // LED 1 off
		}
	}
		
	DefaultMapping(&o, x);
}

#4408901 - 03/05/18 01:31 AM Re: How to detect Shift key [Re: DarKcyde]  
Joined: Jul 2016
Posts: 61
Drakoz Offline
Junior Member
Drakoz  Offline
Junior Member

Joined: Jul 2016
Posts: 61
Re: identifying the shift key without knowing what it is....

Yes, layer_sw[0] stores the value you are looking for, but how to use it is confusing. You have to understand the mapping of the &(devices) (e.g. &Joystick and &Throttle).

First some background. Bear with me here. Let's assume you have a Warthog Throttle and Joystick plugged in only (no other Thrustmaster devices). I'll use the Throttle as an example and the Throttle MSP button as the IO shift button.

&Throttle and &Joystick are simply referencing the memory addresses for joy1[0] and joy2[0]. Go look up joy1, joy2, etc. in hid.tmh (short joy1[296]). They are 296 element arrays of type short (a 16 bit or 2 byte integer). As each device is initialized by TARGET, the device is assigned to point to joy1, joy2, etc. in the order the devices are initialized. This is shown in the TARGET script editor output window as something like:

1: "Throttle - HOTAS Warthog" - "USB\VID_........"
2: "Joystick - HOTAS Warthog" - "USB\VID_......"
USB HID device "Throttle - HOTAS Warthog" (USB\VID_.....) selected
USB HID device "Joystick - HOTAS Warthog" (USB\VID_.....) selected

In the above, the Throttle is selected to be joy1, and the Joystick is selected to be joy2. It is the "selected" line that actually indicates a joy1 or joy2 has been assigned, not the 1: and 2: lines. For example if you used Configure(&Joystick, MODE_EXCLUDED); at the start of your script to exclude TARGET from using the Joystick, you would see:

1: "Throttle - HOTAS Warthog" - "USB\VID_........"
2: "Joystick - HOTAS Warthog" - "USB\VID_......"
USB HID device "Throttle - HOTAS Warthog" (USB\VID_.....) selected

No "selected" line for the Joystick. Only &Throttle points to joy1.

What is joy1[] or what is Throttle[]? Both represent the same thing - Throttle is an alias of joy1 meaning both are interchangeable. Hence Throttle[] is a 296 element array of short, and points to the same array as joy1[]. Being an array, we can access elements as Throttle[1] or joy1[1]. Both will return the same value as they are aliases of each other.

MSP is our current IO Shift button, and MSP = 1 according to the define statements in defines.tmh (define MSP 1). So Throttle[MSP] is the same as Throttle[1], and always contains the current state of the MSP button (1 means MSP pressed, 0 means MSP released).

So how do we use this to determine what the current IO shift button is without knowing?

&Throttle is the address in memory of the Throttle[] array. The & simply means "the address of". So &Throttle is the address of Throttle[0]. Since Throttle[1] is the value of the MSP button, &Throttle+2 is the address of the value of the MSP button. Why 2? Because Throttle is an array of short, and each short is 2 bytes long. So the address of Throttle[0] is &Throttle, and the address of Throttle[1] is &Throttle+2.

layer_sw[0] contains the address of the current IO shift button. So layer_sw[0] = &Throttle+2 when the MSP button is the shift button. If you assigned FLAPU as the IO Shift button, then layer_sw[0] = &Throttle+42 because FLAPU = 21 in defines.tmh.

Try the following. Add this to a script file and run it (add it anywhere before the end of main() and run the script and it will print out in the TARGET Script editor window).

Code
printf("layer_sw[0]: %x \xa", layer_sw[0]);
printf("&&Throttle: %x \xa", &&Throttle);


The result will be memory addresses in hexidecimal. For example, I got the following:

Code
layer_sw[0]: 44ba42
&&Throttle: 44ba40


The && is needed to properly use &Throttle in this case because we want to work directly with the value of &Throttle. Forgive me, I'm a little off on my understanding of & and &&, but I know how to use them.

So if you write a routine that can calculate and find out that layer_sw[0] = &&Throttle+2, then you know that the shift button is MSP.

Where you go from here depends on how you want to use this. That is why I explained it instead of just writing some code to do what you need. Now two examples - a complex one using EventHandle() and a simple example.

If you knew what the shift key was, you could simply use it in a script like my example above in the previous post to turn on/off the LED where I used o[MSP]. This is the same as saying Throttle[MSP]. But we don't know that it is MSP. We do know the address for the IO Shift button is layer_sw[0]. So we can get the same result with Throttle[layer_sw[0]-&&Throttle)] assuming we already knew that the IO shift key was on the Throttle. So in your EventHandle() routine, you could do the following:

Code
include "target.tmh"

int main()
{
	if(Init(&EventHandle)) return 1;
	SetShiftButton(&Throttle, MSP, &Throttle, 0, 0, 0);
	ActKey(PULSE+KEYON+LED(&Throttle, LED_ONOFF, LED_CURRENT-LED1));  // LED 1 off
	//MapKey() statements here
}

int EventHandle(int type, alias o, int x)
{
	int ShiftButtonVal = (layer_sw[0] - &&Throttle) >> 1;
	printf("ShiftButtonVal: %d\xa", ShiftButtonVal);
	if ((&o == &Throttle) & (x == ShiftButtonVal)) {
		if (o[ShiftButtonVal]) {			// If Shift key pressed,
			printf("LED ON\xa");
			ActKey(PULSE+KEYON+LED(&Throttle, LED_ONOFF, LED_CURRENT+LED1));  // LED 1 on
		} 
		else {					// When Shift key released,
			printf("LED OFF\xa");
			ActKey(PULSE+KEYON+LED(&Throttle, LED_ONOFF, LED_CURRENT-LED1));  // LED 1 off
		}
	}
	
	DefaultMapping(&o, x);
}


Again, this assumes we know the IO Shift key is set to the Throttle (more on that below). In the above example, the user set IO Shift as the MSP key. I use an ActKey() in main() to turn off LED1 just to make sure it is off for the purposes of my example.

Anytime any event occurs (a key is pressed or an axis is moved), EventHandle() is called by the TARGET FAST service and passed the following:

- alias o is the device, so &o is the same as &Throttle if a key was pressed on the Throttle.
- x is the event that happened. E.g. if the MSP key was pressed, x = MSP = 1.

int ShiftButtonVal = (layer_sw[0] - &&Throttle) >> 1; calculates the value of the button that is the shift key. In this case, with MSP as the shift key, ShiftButtonVal should equal 1 now. (layer_sw[0] - &&Throttle) = 2, and the >> 1 effectively does a divice by 2 (a bit wise right shift by 2 bits performs a divide by 2).

Then we just use ShiftButtonVal as if we were saying MSP. ShiftButtonVal is interchangable anywhere you would say MSP.

If you want to use int ShiftButtonVal = (layer_sw[0] - &&Throttle) >> 1; globally, then you need to do the following - define ShiftButtonVal before main() and then calculate ShiftButtonVal at some point before you try to use it. Here's a simple example.

Code
include "target.tmh"

int ShiftButtonVal;

int main()
{
	if(Init(&EventHandle)) return 1;
	SetShiftButton(&Throttle, MSP, &Throttle, 0, 0, 0);

	ShiftButtonVal = FindShiftButton();
	// now you can use ShiftButtonVal in your own functions defined below.  
	// MapKey() statements here
}

FindShiftButton()
{
    return (layer_sw[0] - &&Throttle) >> 1);
}

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


To do this with the UMD mode button, you would use layer_sw[3] for the U mode button and layer_sw[6] for the D button.

The only thing left is to figure out which device the IO Shift button is on. TARGET only supports 9 different controllers, so you could just brute force an if else routine to figure it out. The trick is to understand that layer_sw[0] is a number that is no greater than 296 * 2 from the address of joy1, joy2, etc. So you could update FindShiftButton() above with the following:

Code
alias ShiftButtonDev;		// Global var that retains value of the device that has the shift button
int ShiftButtonVal;			// Global var that retains value of the shift button
int FindShiftButton()
{
	// Figure out which device has the shift button
	int x = layer_sw[0];
	if ( x >= &&Throttle & x <= &&Throttle + 596 ) &ShiftButtonDev = &Throttle;
	else if ( x >= &&Joystick & x <= &&Joystick + 596 ) &ShiftButtonDev = &Joystick;
	else if ( x >= &&HCougar & x <= &&HCougar + 596 ) &ShiftButtonDev = &HCougar;
	// ... continue with all the devices you want to check
	
	// Calculate the value of the shift button
	ShiftButtonVal = (layer_sw[0] - &&Throttle) >> 1;
}


Putting it all together, here's my original EventHandle() routine using this to figure out when an unknown IO Shift key is pressed and turning an LED on and off as it is pressed.

Code
include "target.tmh"

alias ShiftButtonDev;		// Global var that retains value of the device that has the shift button
int ShiftButtonVal;			// Global var that retains value of the shift button

int main()
{
	if(Init(&EventHandle)) return 1;
	SetShiftButton(&Throttle, MSP, &Throttle, 0, 0, 0);
	ActKey(PULSE+KEYON+LED(&Throttle, LED_ONOFF, LED_CURRENT-LED1));  // LED 1 off

	FindShiftButton();		// Go find the shift button
	// MapKey() statements here
}

int FindShiftButton()
{
	// Figure out which device has the shift button
	int x = layer_sw[0];
	if ( x >= &&Throttle & x <= &&Throttle + 596 ) &ShiftButtonDev = &Throttle;
	else if ( x >= &&Joystick & x <= &&Joystick + 596 ) &ShiftButtonDev = &Joystick;
	
	// Calculate the value of the shift button
	ShiftButtonVal = (layer_sw[0] - &&Throttle) >> 1;
}

int EventHandle(int type, alias o, int x)
{
	if ((&o == &ShiftButtonDev) & (x == ShiftButtonVal)) {
		if (o[ShiftButtonVal]) {			// If Shift key pressed,
			printf("LED ON\xa");
			ActKey(PULSE+KEYON+LED(&Throttle, LED_ONOFF, LED_CURRENT+LED1));  // LED 1 on
		} 
		else {					// When Shift key released,
			printf("LED OFF\xa");
			ActKey(PULSE+KEYON+LED(&Throttle, LED_ONOFF, LED_CURRENT-LED1));  // LED 1 off
		}
	}
	
	DefaultMapping(&o, x);
}


Lengthy reply, but figuring this out as I wrote it helped me with greater understanding of &Throttle, &Joystick, joy1[], joy2[], etc. which is something I was working on this weekend anyway. The mud is a little more clear now. smile2


Moderated by  RacerGT 

Quick Search
Recent Articles
Support SimHQ

If you shop on Amazon use this Amazon link to support SimHQ
.
Social


Recent Topics
Dickey Betts was 80
by Rick_Rawlings. 04/19/24 01:11 AM
Exodus
by RedOneAlpha. 04/18/24 05:46 PM
Grumman Wildcat unique landing gear
by Coot. 04/17/24 03:54 PM
Peter Higgs was 94
by Rick_Rawlings. 04/17/24 12:28 AM
Whitey Herzog was 92
by F4UDash4. 04/16/24 04:41 PM
Anyone can tell me what this is?
by NoFlyBoy. 04/16/24 04:10 PM
10 Years ago MV Sewol
by wormfood. 04/15/24 08:25 PM
Pride Of Jenni race win
by NoFlyBoy. 04/15/24 12:22 AM
It's Friday: grown up humor for the weekend.
by NoFlyBoy. 04/12/24 01:41 PM
OJ Simpson Dead at 76
by bones. 04/11/24 03:02 PM
Copyright 1997-2016, SimHQ Inc. All Rights Reserved.

Powered by UBB.threads™ PHP Forum Software 7.6.0