[Alpha]JoystickWrapper: Read Joysticks via DirectInput / XInput without loops (C# DLL) 0.0.5 - 18th Mar 2017

Post gaming related scripts
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

[Alpha]JoystickWrapper: Read Joysticks via DirectInput / XInput without loops (C# DLL) 0.0.5 - 18th Mar 2017

06 Mar 2017, 09:31

The included demo script in action showing off Capability detection (notice the missing X and Y axes), Multiple simultaneous subscriptions & Subscribing to POV directions as if they were buttons.
Image

Here you can see me subscribing to the same controller via DirectInput and XInput at the same time, and operating the triggers.
When reading an XBox controller via DirectInput (or WinMM which AHK uses), the triggers are merged into one axis, whereas with XInput you can see me subscribe to two axes and get individual reports.
Image


Github Page

Download

So this something I have been trying to achieve for like 5 years - full capability joystick support with no need for polling loops in your code.

This uses a C# DLL which wraps the SharpDX library, for reading of stick data via DirectInput and XInput.
Whenever a stick changes, a function in your AHK code is called.

Simple usage example:
Download release from github page, extract to a folder, then double-click one of the demo scripts (MonitorDemo.ahk or SimpleExample.ahk)
To write your own scripts, follow what SimpleExample.ahk does - you need to add the following lines to the start of your script:

Code: Select all

#Include JoystickWrapper.ahk
jw := new JoystickWrapper("JoystickWrapper.dll")
Then you need to obtain the GUID for the stick you wish to control - this GUID is constant between boots, so you only need to find it once.
You can call jw.GetAnyDeviceGuid() to get GUID of the first stick it finds, or call jw.GetDevices() to get a list of available devices - see MonitorDemo.ahk for how to do this.
A GUID will look like this: guid := "da2e2e00-19ea-11e6-8002-444553540000"

Once you have your stick GUID, you can subscribe to a button, axis or POV on the stick using one of the following commands:

Code: Select all

	jw.SubscribeAxis(guid, 1, Func("TestFunc").Bind("Axis"))
	jw.SubscribeButton(guid, 1, Func("TestFunc").Bind("Button"))
	jw.SubscribePov(guid, 1, Func("TestFunc").Bind("Pov"))
(All of the above call the function TestFunc, but you can call it anything you like)

So, putting that all together, you might end up with something like:

Code: Select all

#persistent
#Include JoystickWrapper.ahk
jw := new JoystickWrapper("JoystickWrapper.dll")

;guid := "da2e2e00-19ea-11e6-8002-444553540000"

if (guid := jw.GetAnyDeviceGuid()){
	jw.SubscribeAxis(guid, 1, Func("TestFunc").Bind("Axis"))
	jw.SubscribeButton(guid, 1, Func("TestFunc").Bind("Button"))
	jw.SubscribePov(guid, 1, Func("TestFunc").Bind("Pov"))
} else {
	MsgBox "No sticks found"
	ExitApp
}

TestFunc(type, value){
	Tooltip % type ": " value
}

^Esc::
	ExitApp
Please note that C# and especially CLR interop is all very new to me, so if you are experienced in this area, please feel free to pitch in on this one!
Last edited by evilC on 01 Aug 2017, 07:59, edited 17 times in total.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [POC Stage] Full event-based, 8 axis, 128 button, 4 POV joystick support for AHK (C# DLL)

06 Mar 2017, 11:43

Looks impressive, however, I cannot unzip the file :cry:
DLLs.zip wrote: ! [...]\DLLs.zip: The archive is corrupt
Edit:
evilC wrote:Should be fixed now.
Confirmed :thumbup:
Last edited by Helgef on 06 Mar 2017, 11:48, edited 1 time in total.
Noesis
Posts: 301
Joined: 26 Apr 2014, 07:57

Re: [POC Stage] JoystickWrapper: Full event-based, 8 axis, 128 button, 4 POV joystick support for AHK (C# DLL)

09 Mar 2017, 01:35

I like the idea of this. Unfortunately what happens with me is my overall cpu usage jumps up approx 20% per joystick I select (don't have to move them for it to happen). I've got 4 joysticks, and overall cpu usage sits around 90% if all 4 are selected, 70% if 3 selected, 50% if 2 selected 25% if 1 selected, and then back to 3% usage, if none selected. Anyone else experience a similar thing ? (FYI, Intel core i5-2500).
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [POC Stage] JoystickWrapper: Full event-based, 8 axis, 128 button, 4 POV joystick support for AHK (C# DLL)

09 Mar 2017, 01:51

I don't know if this is related, but if I recall correctly, there's a bug in windows causing high CPU usage from querying unplugged sticks. Are all sticks plugged in?
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: [POC Stage] JoystickWrapper: Full event-based, 8 axis, 128 button, 4 POV joystick support for AHK (C# DLL)

09 Mar 2017, 05:54

To be honest I had not looked at CPU usage yet, will see if I can repro.

It does not query sticks that you do not ask it to monitor. It only queries sticks that you subscribe to, so I am not sure it is that.

Whilst the callbacks to AHK are event-based, internally it is a loop. Currently, there is no sleep in the loop, so this is likely the cause.

I am thinking of trying to implement a different way of reading via DirectX - I do not want to have to do loops, even in the C# code.
Noesis
Posts: 301
Joined: 26 Apr 2014, 07:57

Re: [POC Stage] JoystickWrapper: Full event-based, 8 axis, 128 button, 4 POV joystick support for AHK (C# DLL)

09 Mar 2017, 06:51

Evil, I suspect you're correct. Haven't really looked at the code myself, but that makes sense. Also Helgef, yeah I remember reading a similar thing, but they're always connected (I tend to disable them with a script using devcon if some program plays up with controller(s) connected, manually unplugging & then remembering to re-plug is too much hard work imo).
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: [POC Stage] JoystickWrapper: Full event-based, 8 axis, 128 button, 4 POV joystick support for AHK (C# DLL)

09 Mar 2017, 13:23

I tried with a Thread.Sleep(10) in the loop, and it did not seem to make any difference.
It doesn't appear to be anything to do with AHK - I have now updated the repo with a C# Test app that uses the library, and the same thing happens.
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: [POC Stage] JoystickWrapper: Full event-based, 8 axis, 128 button, 4 POV joystick support for AHK (C# DLL)

09 Mar 2017, 15:22

OK, it seems that putting a sleep at the end of the while loop has little to no effect, but putting one at the start seems to lower the CPU usage.
LOL, I am such an idiot sometimes. Of course, a sleep is not going to do anything if there is a continue before it.

New DLL zip attached to the OP.
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: [Alpha 0.0.1] JoystickWrapper: Full event-based, 8 axis, 128 button, 4 POV joystick support for AHK (C# DLL)

11 Mar 2017, 13:25

Released version 0.0.1

All the basic goals have been achieved:

Can subscribe to individual axes/buttons/povs
Multiple subscriptions to same input allowed
Monitor thread automatically started / stopped as subscriptions are added/removed
Callback is now a Function Object instead of a class
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: [Alpha 0.0.1] JoystickWrapper: Full event-based, 8 axis, 128 button, 4 POV joystick support for AHK (C# DLL)

13 Mar 2017, 15:35

I completely refactored the code - gone are the confusing Dictionaries of Dictionaries - now everything is all classes so it is a lot more obvious how it all works.
I also optimized the way the polling thread works, so it should be less CPU intensive.
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: [Alpha]JoystickWrapper: Full event-based, 8 axis, 128 button, 4 POV joystick reading (C# DLL) 0.0.2 - 14th Mar 2017

13 Mar 2017, 19:26

0.0.2 released, you can now subscribe to POV cardinal directions as if they were buttons. There is a 90 degree tolerance on each, so with a diagonal you can trigger two subscriptions.

jw.SubscribePovDirection(<stick guid>. <pov #>, <direction>)
Directions are:
1 : Up / North
2: Right / East
3: Down / South
4: Left / West
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: [Alpha]JoystickWrapper: Full event-based, 8 axis, 128 button, 4 POV joystick reading (C# DLL) 0.0.4 - 17th Mar 2017

18 Mar 2017, 15:28

Version 0.0.5 has been released.

XInput support has been added.

DirectInput API calls remain unchanged, new XBox ones have been added:

SubscribeXboxAxis(controllerId, index, callback, id := 0)
UnSubscribeXboxAxis(controllerId, index, id := 0)
SubscribeXboxButton(controllerId, index, callback, id := 0)
UnSubscribeXboxButton(controllerId, index, id := 0)
SubscribeXboxPovDirection(controllerId, index, povDirection, callback, id := 0)
UnSubscribeXboxPovDirection(controllerId, index, povDirection, id := 0)
GetXInputDevices()

The Monitor Demo has been updated to allow subscribing to XBox devices.
See new recording in OP.

I opted to try and harmonize the axis reporting somewhat, so the axes match up to DirectInpur, except the triggers where the left trigger is on Z (Like DI's merged axis) and the right trigger is on Rz

I am thinking of harmonizing everything, so that axes whether DI or XI, report on the same scale. Trigger axes, dunno. Make them appear to be full axes, but they only ever use half? Stretch them? Provide an option for different ways of reporting? Per-device or global setting?
Answers on a postcard please...
Guest

Re: [Alpha]JoystickWrapper: Read Joysticks via DirectInput / XInput without loops (C# DLL) 0.0.5 - 18th Mar 2017

01 May 2017, 15:25

Code: Select all

jw.SubscribePov(<stick guid>, <pov id>, <callback>[ ,<subscriber id>])
jw.UnSubscribePov(<stick guid>, <pov id>, [ ,<subscriber id>])


jw.SubscribePovDirection(<stick guid>, <pov id>, <pov direction>,<callback>[ ,<subscriber id>])
jw.UnSubscribePovDirection(<stick guid>, <pov id>, <pov direction> ,[ ,<subscriber id>])

Directions are vague. Are we to include angled brackets within parenthesis?
Because my script comes back as invalid or library not recognized.
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: [Alpha]JoystickWrapper: Read Joysticks via DirectInput / XInput without loops (C# DLL) 0.0.5 - 18th Mar 2017

02 May 2017, 06:37

No, angle brackets signify parameters.
Stick GUID is a string eg "da2e2e00-19ea-11e6-8002-444553540000"
pov id is an int with 1 being the first POV
pov direction is an int with 1 being N, 2 being E, 3 being S and 4 being W
callback is a boundfunc
subscriber id is a string - can be anything you want
doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: [Alpha]JoystickWrapper: Read Joysticks via DirectInput / XInput without loops (C# DLL) 0.0.5 - 18th Mar 2017

14 May 2021, 10:02

Hi, not sure if you are still following this project but I am having some troubles getting my game controllers detected. I have tried multiple computers with multiple controllers and with the SimpleExample script I am consistently getting the "No Sticks found" message. I run it by downloading and extracting the source code zip from Alpha 0.0.5 and running the SimpleExample script. Monitor demo also shows no controllers. The controllers are picked up by windows and with basic ahk scripts that use Joy:: hotkeys. Both sticks are wired... any ideas how to proceed?
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: [Alpha]JoystickWrapper: Read Joysticks via DirectInput / XInput without loops (C# DLL) 0.0.5 - 18th Mar 2017

14 May 2021, 12:00

doubledave22 wrote:
14 May 2021, 10:02
I run it by downloading and extracting the source code zip from Alpha 0.0.5 and running the SimpleExample script.
If you downloaded the source code from the main GitHub page, then you won't have the DLLs, so it won't work.
You need to download from the Releases page (The "Download" link in this thread)
If you do have the right zip, then the problem is most likely that Windows has blocked the DLLs
Run Get-ChildItem -Path '.' -Recurse | Unblock-File in the unzipped folder in an admin powershell prompt

Return to “Gaming Scripts (v1)”

Who is online

Users browsing this forum: No registered users and 49 guests