private static int GetNumPropertiesIn(InputDeviceDescription description) { var count = 0; if (!string.IsNullOrEmpty(description.interfaceName)) { count += 1; } if (!string.IsNullOrEmpty(description.deviceClass)) { count += 1; } if (!string.IsNullOrEmpty(description.manufacturer)) { count += 1; } if (!string.IsNullOrEmpty(description.product)) { count += 1; } if (!string.IsNullOrEmpty(description.version)) { count += 1; } if (!string.IsNullOrEmpty(description.capabilities)) { count += 1; } return(count); }
/// <summary> /// Produce a matcher that matches the given device description verbatim. /// </summary> /// <param name="deviceDescription">A device description.</param> /// <returns>A matcher that matches <paramref name="deviceDescription"/> exactly.</returns> /// <remarks> /// This method can be used to produce a matcher for an existing device description, /// e.g. when writing a layout <see cref="InputControlLayout.Builder"/> that produces /// layouts for devices on the fly. /// </remarks> public static InputDeviceMatcher FromDeviceDescription(InputDeviceDescription deviceDescription) { var matcher = new InputDeviceMatcher(); if (!string.IsNullOrEmpty(deviceDescription.interfaceName)) { matcher = matcher.WithInterface(deviceDescription.interfaceName, false); } if (!string.IsNullOrEmpty(deviceDescription.deviceClass)) { matcher = matcher.WithDeviceClass(deviceDescription.deviceClass, false); } if (!string.IsNullOrEmpty(deviceDescription.manufacturer)) { matcher = matcher.WithManufacturer(deviceDescription.manufacturer, false); } if (!string.IsNullOrEmpty(deviceDescription.product)) { matcher = matcher.WithProduct(deviceDescription.product, false); } if (!string.IsNullOrEmpty(deviceDescription.version)) { matcher = matcher.WithVersion(deviceDescription.version, false); } // We don't include capabilities in this conversion. return(matcher); }
public void Setup(InternedString layout, InternedString variants, InputDeviceDescription deviceDescription = default) { InstantiateLayout(layout, variants, new InternedString(), null); FinalizeControlHierarchy(); m_Device.m_Description = deviceDescription; m_Device.CallFinishSetupRecursive(); }
public void Setup(InternedString layout, InternedString variants, InputDeviceDescription deviceDescription = default) { m_LayoutCacheRef = InputControlLayout.CacheRef(); InstantiateLayout(layout, variants, new InternedString(), null); FinalizeControlHierarchy(); m_StateOffsetToControlMap.Sort(); m_Device.m_Description = deviceDescription; m_Device.m_StateOffsetToControlMap = m_StateOffsetToControlMap.ToArray(); m_Device.CallFinishSetupRecursive(); }
/// <summary> /// Return the level of matching to the given <paramref name="deviceDescription"/>. /// </summary> /// <param name="deviceDescription">A device description.</param> /// <returns>A score usually in the range between 0 and 1.</returns> /// <remarks> /// The algorithm computes a score of how well the matcher matches the given description. /// Essentially, a matcher that matches every single property that is present (as in /// not <c>null</c> and not an empty string) in <paramref name="deviceDescription"/> receives /// a score of 1, a matcher that matches none a score of 0. Matches that match only a subset /// receive a score in-between. /// /// An exception to this are capabilities. Every single match of a capability is counted /// as one property match and added to the score. This means that matchers that match /// on multiple capabilities may actually achieve a score >1. /// /// <example> /// <code> /// var description = new InputDeviceDescription /// { /// interfaceName = "HID", /// product = "MadeUpDevice", /// capabilities = new HID.HIDDeviceDescriptor /// { /// vendorId = 0xABC, /// productId = 0xDEF /// }.ToJson() /// }; /// /// // This matcher will achieve a score of 0.666 (2/3) as it /// // matches two out of three available properties. /// new InputDeviceMatcher() /// .WithInterface("HID") /// .WithProduct("MadeUpDevice"); /// /// // This matcher will achieve a score of 1 despite not matching /// // 'product'. The reason is that it matches two keys in /// // 'capabilities'. /// new InputDeviceMatcher() /// .WithInterface("HID") /// .WithCapability("vendorId", 0xABC) /// .WithCapability("productId", 0xDEF); /// </code> /// </example> /// </remarks> public float MatchPercentage(InputDeviceDescription deviceDescription) { if (empty) { return(0); } // Go through all patterns. Score is 0 if any of the patterns // doesn't match. var numPatterns = m_Patterns.Length; for (var i = 0; i < numPatterns; ++i) { var key = m_Patterns[i].Key; var pattern = m_Patterns[i].Value; if (key == kInterfaceKey) { if (string.IsNullOrEmpty(deviceDescription.interfaceName) || !MatchSingleProperty(pattern, deviceDescription.interfaceName)) { return(0); } } else if (key == kDeviceClassKey) { if (string.IsNullOrEmpty(deviceDescription.deviceClass) || !MatchSingleProperty(pattern, deviceDescription.deviceClass)) { return(0); } } else if (key == kManufacturerKey) { if (string.IsNullOrEmpty(deviceDescription.manufacturer) || !MatchSingleProperty(pattern, deviceDescription.manufacturer)) { return(0); } } else if (key == kProductKey) { if (string.IsNullOrEmpty(deviceDescription.product) || !MatchSingleProperty(pattern, deviceDescription.product)) { return(0); } } else if (key == kVersionKey) { if (string.IsNullOrEmpty(deviceDescription.version) || !MatchSingleProperty(pattern, deviceDescription.version)) { return(0); } } else { // Capabilities match. Take the key as a path into the JSON // object and match the value found at the given path. if (string.IsNullOrEmpty(deviceDescription.capabilities)) { return(0); } var graph = new JsonParser(deviceDescription.capabilities); if (!graph.NavigateToProperty(key.ToString()) || !graph.CurrentPropertyHasValueEqualTo(new JsonParser.JsonValue { type = JsonParser.JsonValueType.Any, anyValue = pattern })) { return(0); } } } // All patterns matched. Our score is determined by the number of properties // we matched against. var propertyCountInDescription = GetNumPropertiesIn(deviceDescription); var scorePerProperty = 1.0f / propertyCountInDescription; return(numPatterns * scorePerProperty); }