Jump to content
jshock

Checking Multi-key Return Value KeyDown DisplayEH

Recommended Posts

Well, this will be my first question in the forums in I don't know how long, and I'm having a bit of trouble trying to articulate the question into something understandable, so bear with me :D. I feel I am either overthinking this or it's not possible to accomplish what I want, or I'm just missing some necessary knowledge.

 

So, I am working with a KeyDown displayEH, the "key press" that I check for is the actionKeys within a User Custom Action. I can get the code to execute perfectly when a single key is defined and pressed (i.e. 'Y'), but the issue that arises is when I do a combination of a key with control/shift/alt (i.e. "Left Ctrl + Y"). I know that within the EH you can check to see if control/shift/alt have been pressed, however, I cannot check to see if the user has defined control/shift/alt as an additional key that needs to be pressed in conjunction with another key (i.e. 'Y').

 

The command "actionKeys" returns an array of all the keys defined for that particular action (under configure>controls), for example, if the only key I have defined for custom User Action #9 is 'Y' the return of the command would be:

[21]

Which is easy enough to check within the EH by:

(_this select 1) in actionKeys "User9"

However, if I have the keybind set to "Left Ctrl + Y" it returns:

[4.86539e+008]

Which within the scope of this particular EH instance would return true that a control key is pressed, however, as far as I can tell, I can't check to make sure 'Y' is pressed along with it because the keybinding value of "Left Ctrl + Y" is some large number of (I assume) the two combined key values.

 

So, question being, how would I calculate combined key values to be able to check against what is being returned by actionKeys, or what other means by which can I check to see if any particular key combination defined within a User Custom Action are pressed at the same time.

 

And again stating that I feel I may simply be overthinking this as I've looked at this code quite late the last few nights, but still can't come to a final working set of code.

 

Here is a semi-psuedo as to what I'm after (doing):

fnc_checkKeyBinding =
{
	/*????*/
};

(findDisplay 46) displayAddEventHandler 
[
	"KeyDown", 
	{
		_handled = false;
		if ([_this] call fnc_checkKeyBinding) then
		{
			[] call fnc;
			_handled = true;
		};
		_handled;
	}
];

Share this post


Link to post
Share on other sites

The "KeyDown" EH returns 5 parameters:

_source  = _this select 0;
_keyCode = _this select 1;
_isShift = _this select 2;
_isCtrl  = _this select 3;
_isAlt   = _this select 4;

So if you e.g. want to check CTRL + "Y", check for _isCtrl and key code 44 (I recommend making defines to avoid messing with numbers):

findDisplay 46 displayAddEventHandler ["KeyDown", {
    _source  = _this select 0;
    _keyCode = _this select 1;
    _isShift = _this select 2;
    _isCtrl  = _this select 3;
    _isAlt   = _this select 4;
    
    if (_keyCode isEqualTo 44 && _isCtrl) exitWith {
        //your code
    };
}];

Hope I didn't overread something in your question. ;)

Share this post


Link to post
Share on other sites

It's a User Defined key combination, so I can't assume what keys they will pick. And I understand I could easily check key, plus get a boolean return on if control/shift/alt is pressed, but when in the User custom action they define it as any combination of "Control/Shift/Alt + SomeOtherKey" or just "SomeKey" (the latter works without issue) it returns a weird value that I can't check against.

 

In simplified terms, there is no way, that I can tell, to say "User Action Key Combination # has been used".

Share this post


Link to post
Share on other sites

OK, so I clearly overread this actionKey thing. So if you test a few combinations, you may - if you're lucky - find a pattern or something.

 

Otherwise, the next best quick thing coming to my mind is to create a mapping table where you simply log all reasonable (not necessarily all possible) key combinations and simply check against that mapping table. But that's probably too much effort for such a bit of usability.

Share this post


Link to post
Share on other sites

In simplified terms, there is no way, that I can tell, to say "User Action Key Combination # has been used".

 

Surely using inputAction would give you your desired outcome? In the comments it says that it can be unreliable in the sense that it can return values such as 0.02 and 1.3 instead of 1. So as long as you check if the value is greater than 0, you should be able to tell if a certain user action key was used.

 

Sorry if I have misread your intentions :P

 

EDIT: I think I understand what you want now. You want to return the actual key combination, whether that's Shift + Y or Ctrl + Y.

Share this post


Link to post
Share on other sites

One of the quotes in inputAction says

inputAction does not return the actual state of the queried key when a dialog screen is open. Instead, it will always return 0.

Whether this is true or still applicable i have no idea. If it is and is a problem for what your are trying to do maybe..

EDIT: code changed, did not account for multiple binds for a action, fixed.

h = [] spawn {
	
	_bindings = actionKeysNamesArray "User9";
	
	_ctrl = false;
	_shift = false;
	_alt = false;
	
	_keysArray = [];
	{
		_keysArray set [ _forEachIndex, [] ];
		_index = _keysArray select _forEachIndex;
		
		_keycombo = toLower _x;
		_keys = _keycombo splitString "+";
		
		{
			_key = _x;
			_multi = _key find "2x";
			if ( _multi > -1 ) then {
				_key = _key select [ 2, count _key - 2 ];
				_multi = true;
			}else{
				_multi = false;
			};
			
			if ( {
					if ( [ _x, _key ] call BIS_fnc_inString ) then {
						switch ( _x ) do {
							case "ctrl" : {
								_ctrl = true;
							};
							case "shift" : {
								_shift = true;
							};
							case "alt" : {
								_alt = true;
							};
						};
						_nul = _index pushBack [ _x, _multi ];
						true
					}else{
						false
					};
				}count [ "ctrl", "shift", "alt" ] isEqualTo 0 ) then {
				_nul = _index pushBack [ _key, _multi ];
			};
		}forEach _keys;
	}forEach _bindings;
	
	ctrl = _ctrl;
	shift = _shift;
	alt = _alt;
	keys = _keysArray;
};
As code to check in debug console.

Returns true/false in ctrl,shift and alt variables.

Keys is a multi array of binds for the specified command

e.g my compassToggle which has either '2xK' or 'right arrow' as possible keys looks like

//bindings
[
	//bind 1
	[
		["k",true] // double tap k
	],
	//bind 2
	[
		["right",false] // arrow right
	]
]
OR my headlight toggle which has either 'L' or 'left windows + backspace' look like

[
	//bind 1
	[
		["l",false]
	],
	//bind 2
	[
		["left windows",false],
		["backspace",false]
	]
]
where select 1 or each key denotes whether its a double tap key.

Loosely based of some code i wrote HERE.

Share this post


Link to post
Share on other sites

You know Larrow, I had been looking at actionKeysNamesArray as a possible outlet to check this, but hadn't gotten around to messing with it, will let you know the verdict on your code when I can.

Share this post


Link to post
Share on other sites

If you need to detect mutltiple keys pressed at the same time, consider this:

when you press any key combination - EH fires for each key in order you pressed them. Multikey press means that KeyUp did not fire yet, when keydown for second key fired.

So you may just have some kind of array variable in missionNamespace which tracks currently pressed keys.

Share this post


Link to post
Share on other sites

If you need to detect mutltiple keys pressed at the same time, consider this:

when you press any key combination - EH fires for each key in order you pressed them. Multikey press means that KeyUp did not fire yet, when keydown for second key fired.

So you may just have some kind of array variable in missionNamespace which tracks currently pressed keys.

 

Yea that's the problem with this whole thing thus far is the shear number of possible inputs you have to look for, and each has its own challenges in checking to see if it has occurred or not.

 

-Single key (number/character)

-Single key (ctrl/shift/alt)

-Two keys (number/character-ctrl/shift/alt)

-Two keys (number/character-number/character)

-Two keys (ctrl/shift/alt-ctrl/shift/alt)

-Double tapped key

-And probably some other combinations

 

The nice thing (as far as I saw) is the custom user action bindings can only go up to two keys per binding.

 

Note on implementation of aforementioned code, I haven't had a lot of time this week to test and what not, hopefully have something together by end of week, early next week.

Share this post


Link to post
Share on other sites

Just in case, detecting double tap appeared to be tricky, I tried to implement it, but later ceased detecting double tap, you may refer to this code as an example for double tap, at least it worked:

commented out code from:

https://github.com/ussrlongbow/RWT/blob/master/rwt.Altis/RWT/functions/forControls/fn_keyDown.sqf

and

https://github.com/ussrlongbow/RWT/blob/master/rwt.Altis/RWT/functions/forControls/fn_keyUp.sqf

for me it worked to distinguish on the same key: single tap, double tap and hold key

Share this post


Link to post
Share on other sites

If this can help, here is how I detect a key combo for "CycleThrownItems" in my stance mod :

 
 //// CycleThrownItems hotkey detection - (limited to Lctrl, LAlt, Lshift because inputAction is erratic)
 
 YourTag_AKNA_cycleThrownItems = call compile format ["%1",ActionKeysNamesArray 'cycleThrownItems', 1];
 YourTag_AKI_Throw = ActionKeysImages "Throw"; 
  
 YourTag_CTIString1 = "Left Ctrl+"+ (call compile format ["%1", YourTag_AKI_Throw]);
 YourTag_CTIString2 = (call compile format ["%1", YourTag_AKI_Throw]) + "+Left Ctrl";
 YourTag_CTIString3 = "Left Alt+"+ (call compile format ["%1", YourTag_AKI_Throw]);
 YourTag_CTIString4 = (call compile format ["%1", YourTag_AKI_Throw]) + "+Left Alt";
 YourTag_CTIString5 = "Left Shift+"+ (call compile format ["%1", YourTag_AKI_Throw]);
 YourTag_CTIString6 = (call compile format ["%1", YourTag_AKI_Throw]) + "+Left Shift";
   

and, in your KeyDown_fnc :

  if (YourTag_CTIString1 in YourTag_AKNA_cycleThrownItems or YourTag_CTIString2 in YourTag_AKNA_cycleThrownItems) then {YourTag_cycleHotkey = _this select 3};
  if (YourTag_CTIString3 in YourTag_AKNA_cycleThrownItems or YourTag_CTIString4 in YourTag_AKNA_cycleThrownItems) then {YourTag_cycleHotkey = _this select 4};
  if (YourTag_CTIString5 in YourTag_AKNA_cycleThrownItems or YourTag_CTIString6 in YourTag_AKNA_cycleThrownItems) then {YourTag_cycleHotkey = _this select 2};


///

if (_code in ActionKeys "Throw" and YourTag_cycleHotkey) then { ...};


   

Regards,

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×