/// <summary> /// Initializes a new instance of the <see cref="DirectInputDevice"/> class. /// </summary> /// <param name="deviceInfo">The gaming device information for the specific device to use.</param> /// <param name="directInput">The direct input interface to use when creating the object.</param> public DirectInputDevice(DirectInputDeviceInfo deviceInfo, DI.DirectInput directInput) : base(deviceInfo) { _directInput = directInput; _info = deviceInfo; _joystick = new Lazy <DI.Joystick>(() => CreateJoystick(directInput, deviceInfo), true); }
/// <summary> /// Function to enumerate the gaming devices supported by this driver. /// </summary> /// <param name="connectedOnly">[Optional] <b>true</b> to only enumerate devices that are connected, or <b>false</b> to enumerate all devices.</param> /// <returns>A read only list of gaming device info values.</returns> /// <remarks> /// This will return only the devices supported by the driver. In some cases, the driver may not return a complete listing of all gaming devices attached to the system because the underlying provider /// may not support those device types. /// </remarks> public override IReadOnlyList <IGorgonGamingDeviceInfo> EnumerateGamingDevices(bool connectedOnly = false) { IList <DI.DeviceInstance> devices = _directInput.Value.GetDevices(DI.DeviceClass.GameControl, DI.DeviceEnumerationFlags.AttachedOnly); Log.Print("Enumerating DirectInput gaming devices...", LoggingLevel.Verbose); // Enumerate all controllers. IReadOnlyList <DirectInputDeviceInfo> result = devices .Where(item => { bool notXInputController = !IsXInputController(item); if (!notXInputController) { Log.Print("WARNING: Found XInput controller. The Direct Input driver does not support this type of controller. Skipping...", LoggingLevel.Verbose); return(false); } bool isAttached = _directInput.Value.IsDeviceAttached(item.InstanceGuid); if ((connectedOnly) || (isAttached)) { return(true); } Log.Print("WARNING: Found gaming device '{0}', but it is not attached and enumeration is filtered for attached devices only. Skipping...", LoggingLevel.Verbose, item.ProductName); return(false); }) .Select(item => { var info = new DirectInputDeviceInfo(item); using (var joystick = new DI.Joystick(_directInput.Value, info.InstanceGuid)) { info.GetDeviceCaps(joystick); Log.Print("Found DirectInput gaming device \"{0}\"", LoggingLevel.Verbose, info.Description); } return(info); }) .ToArray(); return(result); }
/// <summary> /// Function to perform the creation of the DirectInput joystick object. /// </summary> /// <param name="directInput">The direct input interface.</param> /// <param name="deviceInfo">The device information for the gaming device to use.</param> /// <returns>The DirectInput joystick object.</returns> private DI.Joystick CreateJoystick(DI.DirectInput directInput, DirectInputDeviceInfo deviceInfo) { var result = new DI.Joystick(directInput, deviceInfo.InstanceGuid); IntPtr mainWindow = FindMainApplicationWindow(); if (mainWindow == IntPtr.Zero) { // We have no main window, and DI requires one, so we need to kill this. throw new InvalidOperationException(Resources.GORINP_ERR_DI_COULD_NOT_FIND_APP_WINDOW); } result.SetCooperativeLevel(mainWindow, DI.CooperativeLevel.Foreground | DI.CooperativeLevel.NonExclusive); result.Properties.AxisMode = DI.DeviceAxisMode.Absolute; // Set up dead zones. foreach (GorgonGamingDeviceAxis axis in Axis) { // Skip the throttle. Dead zones on the throttle don't work too well for regular joysticks. // Game pads may be another story, but the user can manage those settings if required. if (axis.Axis == GamingDeviceAxis.Throttle) { continue; } GorgonGamingDeviceAxisInfo info = Info.AxisInfo[axis.Axis]; DI.ObjectProperties properties = result.GetObjectPropertiesById(_info.AxisMappings[axis.Axis]); if (properties == null) { continue; } // Set a 0 dead zone. properties.DeadZone = 0; // Make the dead zone 10% of the range for all axes. float deadZone = axis.Axis == GamingDeviceAxis.Throttle ? 0.02f : 0.10f; int deadZoneActual = (int)(info.Range.Range * deadZone); axis.DeadZone = new GorgonRange(info.DefaultValue - deadZoneActual, info.DefaultValue + deadZoneActual); } return(result); }