internal static string OnFindLayoutForDevice(ref InputDeviceDescription description, string matchedLayout, InputDeviceExecuteCommandDelegate executeCommandDelegate) { // If the device isn't a WebGL device, we're not interested. if (string.Compare(description.interfaceName, InterfaceName, StringComparison.InvariantCultureIgnoreCase) != 0) { return(null); } // If it was matched by the standard mapping, we don't need to fall back to generating a layout. if (!string.IsNullOrEmpty(matchedLayout) && matchedLayout != "Gamepad") { return(null); } var deviceMatcher = InputDeviceMatcher.FromDeviceDescription(description); var layout = new WebGLLayoutBuilder { capabilities = WebGLDeviceCapabilities.FromJson(description.capabilities) }; InputSystem.RegisterLayoutBuilder(() => layout.Build(), description.product, "Joystick", deviceMatcher); return(description.product); }
internal static string OnFindLayoutForDevice(ref InputDeviceDescription description, string matchedTemplate, InputDeviceExecuteCommandDelegate executeCommandDelegate) { if (description.interfaceName != "Android" || string.IsNullOrEmpty(description.capabilities)) { return(null); } ////TODO: these should just be Controller and Sensor; the interface is already Android switch (description.deviceClass) { case "AndroidGameController": { var caps = AndroidDeviceCapabilities.FromJson(description.capabilities); // Note: Gamepads have both AndroidInputSource.Gamepad and AndroidInputSource.Joystick in input source, while // Joysticks don't have AndroidInputSource.Gamepad in their input source if ((caps.inputSources & AndroidInputSource.Gamepad) != AndroidInputSource.Gamepad) { return("AndroidJoystick"); } if (caps.motionAxes == null) { return("AndroidGamepadWithDpadButtons"); } // Vendor Ids, Product Ids can be found here http://www.linux-usb.org/usb.ids const int kVendorMicrosoft = 0x045e; if (caps.vendorId == kVendorMicrosoft && caps.motionAxes != null && caps.motionAxes.Contains(AndroidAxis.Rx) && caps.motionAxes.Contains(AndroidAxis.Ry) && caps.motionAxes.Contains(AndroidAxis.HatX) && caps.motionAxes.Contains(AndroidAxis.HatY)) { return("AndroidGamepadXboxController"); } // Fallback to generic gamepads if (caps.motionAxes.Contains(AndroidAxis.HatX) && caps.motionAxes.Contains(AndroidAxis.HatY)) { return("AndroidGamepadWithDpadAxes"); } return("AndroidGamepadWithDpadButtons"); } default: return(null); } }
private string OnFindLayout(ref InputDeviceDescription description, string matchedLayout, InputDeviceExecuteCommandDelegate executeCommandDelegate) { // If there's no matched layout, there's a chance this device will go in // the unsupported list. There's no direct notification for that so we // preemptively trigger a refresh. if (string.IsNullOrEmpty(matchedLayout)) { Refresh(); } return(null); }
internal static string OnFindLayoutForDevice(ref InputDeviceDescription description, string matchedLayout, InputDeviceExecuteCommandDelegate executeCommandDelegate) { if (description.interfaceName != LinuxSupport.kInterfaceName) { return(null); } if (string.IsNullOrEmpty(description.capabilities)) { return(null); } // Try to parse the SDL descriptor. SDLDeviceDescriptor deviceDescriptor; try { deviceDescriptor = SDLDeviceDescriptor.FromJson(description.capabilities); } catch (Exception exception) { Debug.LogError($"{exception} while trying to parse descriptor for SDL device: {description.capabilities}"); return(null); } if (deviceDescriptor == null) { return(null); } string layoutName; if (string.IsNullOrEmpty(description.manufacturer)) { layoutName = $"{SanitizeName(description.interfaceName)}::{SanitizeName(description.product)}"; } else { layoutName = $"{SanitizeName(description.interfaceName)}::{SanitizeName(description.manufacturer)}::{SanitizeName(description.product)}"; } var layout = new SDLLayoutBuilder { m_Descriptor = deviceDescriptor, m_ParentLayout = matchedLayout }; InputSystem.RegisterLayoutBuilder(() => layout.Build(), layoutName, matchedLayout); return(layoutName); }
internal static string OnFindLayoutForDevice(ref InputDeviceDescription description, string matchedLayout, InputDeviceExecuteCommandDelegate executeCommandDelegate) { // If the device isn't a XRInput, we're not interested. if (description.interfaceName != XRUtilities.InterfaceCurrent && description.interfaceName != XRUtilities.InterfaceV1) { return(null); } // If the description doesn't come with a XR SDK descriptor, we're not // interested either. if (string.IsNullOrEmpty(description.capabilities)) { return(null); } // Try to parse the XR descriptor. XRDeviceDescriptor deviceDescriptor; try { deviceDescriptor = XRDeviceDescriptor.FromJson(description.capabilities); } catch (Exception) { return(null); } if (deviceDescriptor == null) { return(null); } if (string.IsNullOrEmpty(matchedLayout)) { #if UNITY_2019_3_OR_NEWER const InputDeviceCharacteristics controllerCharacteristics = InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.Controller; if ((deviceDescriptor.characteristics & InputDeviceCharacteristics.HeadMounted) != 0) { matchedLayout = "XRHMD"; } else if ((deviceDescriptor.characteristics & controllerCharacteristics) == controllerCharacteristics) { matchedLayout = "XRController"; } #else //UNITY_2019_3_OR_NEWER if (deviceDescriptor.deviceRole == InputDeviceRole.LeftHanded || deviceDescriptor.deviceRole == InputDeviceRole.RightHanded) { matchedLayout = "XRController"; } else if (deviceDescriptor.deviceRole == InputDeviceRole.Generic) { matchedLayout = "XRHMD"; } #endif //UNITY_2019_3_OR_NEWER } string layoutName; if (string.IsNullOrEmpty(description.manufacturer)) { layoutName = $"{SanitizeName(description.interfaceName)}::{SanitizeName(description.product)}"; } else { layoutName = $"{SanitizeName(description.interfaceName)}::{SanitizeName(description.manufacturer)}::{SanitizeName(description.product)}"; } var layout = new XRLayoutBuilder { descriptor = deviceDescriptor, parentLayout = matchedLayout, interfaceName = description.interfaceName }; InputSystem.RegisterLayoutBuilder(() => layout.Build(), layoutName, matchedLayout); return(layoutName); }
internal static string OnFindLayoutForDevice(ref InputDeviceDescription description, string matchedLayout, InputDeviceExecuteCommandDelegate executeCommandDelegate) { // If we already have a matching layout, someone registered a better match. // We only want to act as a fallback. if (!string.IsNullOrEmpty(matchedLayout) && matchedLayout != "AndroidGamepad" && matchedLayout != "AndroidJoystick") { return(null); } if (description.interfaceName != "Android" || string.IsNullOrEmpty(description.capabilities)) { return(null); } ////TODO: these should just be Controller and Sensor; the interface is already Android switch (description.deviceClass) { case "AndroidGameController": { var caps = AndroidDeviceCapabilities.FromJson(description.capabilities); // Note: Gamepads have both AndroidInputSource.Gamepad and AndroidInputSource.Joystick in input source, while // Joysticks don't have AndroidInputSource.Gamepad in their input source if ((caps.inputSources & AndroidInputSource.Gamepad) != AndroidInputSource.Gamepad) { return("AndroidJoystick"); } if (caps.motionAxes == null) { return("AndroidGamepadWithDpadButtons"); } // Vendor Ids, Product Ids can be found here http://www.linux-usb.org/usb.ids const int kVendorMicrosoft = 0x045e; const int kVendorSony = 0x054c; // Tested with controllers: PS4 DualShock; XboxOne; Nvidia Shield // Tested on devices: Shield console Android 9; Galaxy s9+ Android 10 if (caps.motionAxes.Contains(AndroidAxis.Z) && caps.motionAxes.Contains(AndroidAxis.Rz) && caps.motionAxes.Contains(AndroidAxis.HatX) && caps.motionAxes.Contains(AndroidAxis.HatY)) { if (caps.vendorId == kVendorMicrosoft) { return("XboxOneGamepadAndroid"); } if (caps.vendorId == kVendorSony) { return("DualShock4GamepadAndroid"); } } // Fallback to generic gamepads if (caps.motionAxes.Contains(AndroidAxis.HatX) && caps.motionAxes.Contains(AndroidAxis.HatY)) { return("AndroidGamepadWithDpadAxes"); } return("AndroidGamepadWithDpadButtons"); } default: return(null); } }