/// <summary>
        /// Constructs a <see cref="Configuration"/>.
        /// </summary>
        /// <param name="descriptor">A <see cref="ConfigurationDescriptor"/> for this configuration.</param>
        /// <param name="features">A set of <see cref="Feature"/>(s) that should be enabled for this configuraton.
        /// Exaclty zero or one camera mode must be enabled (see <see cref="Feature.UserFacingCamera"/> and <see cref="Feature.WorldFacingCamera"/>).
        /// If zero camera modes are enabled, no camera texture will be available. Some platforms may support a configuration that does
        /// not provide camera textures, which can be more performant if they are not necessary.
        /// All <paramref name="features"/> must be supported by the <paramref name="descriptor"/>.</param>
        /// <exception cref="System.InvalidOperationException">Thrown if multiple camera modes are enabled.</exception>
        /// <exception cref="System.InvalidOperationException">Thrown if multiple tracking modes are enabled.</exception>
        /// <exception cref="System.NotSupportedException">Thrown if the <paramref name="descriptor"/> does not support one or more <paramref name="features"/>.</exception>
        public Configuration(ConfigurationDescriptor descriptor, Feature features)
        {
            if (!descriptor.capabilities.All(features))
            {
                throw new NotSupportedException($"The configuration does not support the following requested features: {features.SetDifference(descriptor.capabilities).ToStringList()}.");
            }

            var cameraMode = features.Cameras();

            if (cameraMode.Any(Feature.AnyCamera))
            {
                if (cameraMode.Count() > 1)
                {
                    throw new InvalidOperationException($"Either zero or one camera mode must be enabled. The following modes are enabled: {cameraMode.ToStringList()}");
                }
            }

            var trackingMode = features.TrackingModes();

            if (trackingMode.Count() > 1)
            {
                throw new InvalidOperationException($"Either zero or one tracking modes must be enabled. The following modes are enabled: {trackingMode.ToStringList()}");
            }

            this.descriptor = descriptor;
            this.features   = features;
        }
Example #2
0
        /// <summary>
        /// Selects a configuration from the given <paramref name="descriptors"/> and <paramref name="requestedFeatures"/>.
        /// </summary>
        /// <remarks>
        /// Selection works as follows:
        /// For each of the configuration <paramref name="descriptors"/>, compute the number of supported
        /// <see cref="Feature"/>s that are present in <paramref name="requestedFeatures"/> and choose the
        /// configuration descriptor with the highest count. <see cref="ConfigurationDescriptor.rank"/> is
        /// used to break ties.
        /// </remarks>
        /// <param name="descriptors">A set of <see cref="ConfigurationDescriptor"/>s supported by the <see cref="XRSessionSubsystem"/>.</param>
        /// <param name="requestedFeatures">A set of requested <see cref="Feature"/>s.</param>
        /// <returns>The configuration that best matches the <paramref name="requestedFeatures"/>.</returns>
        /// <exception cref="System.ArgumentException">Thrown if <paramref name="descriptors"/> does not contain any descriptors.</exception>
        /// <exception cref="System.ArgumentException">Thrown if <paramref name="requestedFeatures"/> contains more than one tracking mode.</exception>
        /// <exception cref="System.ArgumentException">Thrown if <paramref name="requestedFeatures"/> contains more than one camera mode.</exception>
        public override Configuration ChooseConfiguration(NativeSlice <ConfigurationDescriptor> descriptors, Feature requestedFeatures)
        {
            if (descriptors.Length == 0)
            {
                throw new ArgumentException("No configuration descriptors to choose from.", nameof(descriptors));
            }

            if (requestedFeatures.Intersection(Feature.AnyTrackingMode).Count() > 1)
            {
                throw new ArgumentException($"Zero or one tracking mode must be requested. Requested tracking modes => {requestedFeatures.Intersection(Feature.AnyTrackingMode).ToStringList()}", nameof(requestedFeatures));
            }

            if (requestedFeatures.Intersection(Feature.AnyCamera).Count() > 1)
            {
                throw new ArgumentException($"Zero or one camera mode must be requested. Requested camera modes => {requestedFeatures.Intersection(Feature.AnyCamera).ToStringList()}", nameof(requestedFeatures));
            }

            int highestFeatureCount = -1;
            int highestRank         = int.MinValue;
            ConfigurationDescriptor bestDescriptor = default;

            foreach (var descriptor in descriptors)
            {
                int featureCount = requestedFeatures.Intersection(descriptor.capabilities).Count();
                if ((featureCount > highestFeatureCount) ||
                    (featureCount == highestFeatureCount && descriptor.rank > highestRank))
                {
                    highestFeatureCount = featureCount;
                    highestRank         = descriptor.rank;
                    bestDescriptor      = descriptor;
                }
            }

            return(new Configuration(bestDescriptor, requestedFeatures.Intersection(bestDescriptor.capabilities)));
        }