Attached is the ZInput controller system I use with AGK-Studio (and should also be fully compatible with AGKV2 'classic') for my projects. This is not my work, but I have asked for permission from the author to post this to share with other developers so it can also be accessible to them. The author is 'Rudolpho' here on the forum.
ZInput is a comprehensive control device input system that provides a wide array of options with a lot of customizing capabilities for range and device management. ZInput is only compatible with the Windows desktop platform (it is a native Windows library using default Windows API's after all). This post provides the download and some basic instructions on getting up and running with the library.
The benefits of ZInput include full DI8 input support beyond XInput and other systems that may limit the number of devices, axis inputs, button inputs, and/or POV/HAT inputs. ZInput can detect pretty much any device that Windows detects while also handling the full array of signals they provide. This includes gamepads, joysticks, throttles, rudders, wheels, button panels, and more. A common command interface is used to retrieve such signals, so the developer does not have to contend with split commands (such as 'slider', 'twist', 'RX/Y/Z', etc). All variable analogue signals are 'axis', all buttons are 'buttons', and all POV/HAT's are 'POV's'.
ZInput supports many simultaneous devices (far beyond the typical 6-8), 128 buttons (well beyond the typical 32 max), multiple POV/HAT's (beyond the typical 1), and as many axis inputs as can return a signal.
Another key benefit of ZInput is no dependency on outside libraries (such as 'xinput1_3.dll'), so only default Windows libraries are needed. As a result, with ZInput, you do not introduce any dependencies that require installation of outside runtimes before players can enjoy your game. This helps prevent delays, confusion, and error messages/crashes.
To install ZInput, place the files in the attached ZIP inside the plugins folder within a folder named ZInput (the ZIP contains a ZInput folder, so you can extract directly to the \plugins folder). Then in your code, it's a good idea to create some small arrays for storing device ID information for use later (we'll start with 20):
dim devicename$[20]
dim deviceindex[20]
dim deviceaxis[20]
dim devicebuttons[20]
dim devicepov[20]
DeviceCount=0 ` a value to keep track of total devices we want to listen to
Then include this line to activate it:
A good next step is to set the error reporting mode. This tells ZInput how to handle errors if any are encountered. Here is an example:
ZInput.SetErrorReportingMode(1)
0 is for debug with a message popup whenever there's an error, 1 is for silent and retrieving errors manually (ie error$=ZInput.GetLastErrorMessage(1)). More details and options are available in the 'Commands.txt' file included in the ZIP as the file is noted.
Next, we must initialize ZInput:
s=ZInput.Initialize(0)
ZInput.RescanForInputDevices()
Next, it's a good idea to get the total number of available devices:
devicetotal=ZInput.GetInputDeviceCount()
This will return the total number, if any, above zero. Keep in mind that device and signal indexes start at 0 while counts will be above 0. Next, we need to run through all of the devices to 'acquire' them. This can be done with a quick 'for i' loop and remember to start at index 0 (so if there are no devices, devicetotal will be 0, so -1 below and the loop will pass):
for i = 0 to devicetotal-1
deviceacquire=ZInput.AcquireInputDevice(i)
next i
With that out of the way, we can start to retrieve details about each device. Again, we'll go through a 'for i' loop to retrieve and analyze each device's type (or you can combine these operations with the first 'for i' loop above):
for i = 0 to devicetotal-1
` This command reports what kind of controller is in the index.
` You'll generally only want to pay attention to devices in the 1-9 range.
` 0=" (Generic Device)"
` 1=" (Gamepad Device)"
` 2=" (Joystick Device)"
` 3=" (FPS/Gyro Device)"
` 4=" (Six DOF Device)"
` 5=" (Wheel/Racing Device)"
` 6=" (Flight Device)"
` 7=" (Remote Device)"
` 8=" (Pointing Device)"
` 9=" (Secondary Device)"
` 10=" (Unknown Device)"
DType=ZInput.GetInputDeviceType(i)
` if the device type is one we want to listen to, retrieve details about it
` you can optionally include generic and unknown devices, then scan for axis/button/pov inputs before
` adding them to the array list for listening
if DType>0 and DType<=9 and DeviceCount<20
` advance counter to start storing values in array index 1
DeviceCount=DeviceCount+1
deviceindex[DeviceCount]=i ` store the index for this device in the listening list
devicename$[DeviceCount]=ZInput.GetInputDeviceName(i) ` return string name description
s$=ZInput.GetInputDeviceTypeName(i) ` return string device description (optional)
deviceaxis[DeviceCount]=ZInput.GetInputDeviceAxisCount(i) ` number of axis channels
devicepov[DeviceCount]=ZInput.GetInputDevicePovCount(i) ` number of POV/HAT inputs
devicebuttons[DeviceCount]=ZInput.GetInputDeviceButtonCount(i) ` number of buttons
` s=ZInput.GetInputDeviceForceFeedbackMotorCount(i) ` number of force feedback motors (optional)
endif
next i
Now that we have a list of devices we want to listen to, we can retrieve values from them at any time. Here is some example code to do so:
for i = 1 to DeviceCount
ZInput.PollInputDevice(deviceindex[i]) ` update device
` now get any inputs that we want
if deviceaxis[i]>0
for ii = 1 to deviceaxis[i]
` if any axis channels exist, retrieve values, the -1.0 to 1.0 value will specify the -/+ range to use
axisfloat#=ZInput.GetInputDeviceAxisValue(deviceindex[i],ii-1,-1.0,1.0) ` axis input, store or apply as desired
next ii
endif
if devicebuttons[i]>0
for ii = 1 to devicebuttons[i]
` if any buttons exist, retrieve values, 0 or 1 is returned
buttonactive=IsInputDeviceButtonDown(deviceindex[i],ii-1) ` button input, store or apply as desired
next ii
endif
if devicepov[i]>0
for ii = 1 to devicepov[i]
` if any POV/HAT inputs exist, check for active input first, then retrieve values, angle is returned
if ZInput.IsInputDevicePovPressed(deviceindex[i],ii-1)>0
povangle=GetInputDevicePovAngle(deviceindex[i],ii-1) ` POV/HAT input, store or apply as desired
endif
next ii
endif
next i
And that's basically it. You change the range for an axis input on the fly, listen to only select axis channels or buttons, or mix and match values for custom mappings. If you need extensive support for control devices for your project, ZInput provides an excellent array of options and can detect just about anything.