/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * Licensed under the Oculus SDK License Agreement (the "License"); * you may not use the Oculus SDK except in compliance with the License, * which is provided at the time of installation or download, or which * otherwise accompanies this software in either electronic or hard copy form. * * You may obtain a copy of the License at * * https://developer.oculus.com/licenses/oculussdk/ * * Unless required by applicable law or agreed to in writing, the Oculus SDK * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; /// /// Utility to assist with queries for s. /// internal static class OVRSpaceQuery { /// /// Represents options used to generate an . /// public struct Options { /// /// The maximum number of UUIDs which can be used in a . /// public const int MaxUuidCount = OVRPlugin.SpaceFilterInfoIdsMaxSize; private static readonly Guid[] Ids = new Guid[MaxUuidCount]; private static readonly OVRPlugin.SpaceComponentType[] ComponentTypes = new OVRPlugin.SpaceComponentType[OVRPlugin.SpaceFilterInfoComponentsMaxSize]; /// /// The maximum number of results the query can return. /// public int MaxResults { get; set; } /// /// The timeout, in seconds for the query. /// /// /// Zero indicates the query does not timeout. /// public double Timeout { get; set; } /// /// The storage location to query. /// public OVRSpace.StorageLocation Location { get; set; } /// /// The type of query to perform. /// public OVRPlugin.SpaceQueryType QueryType { get; set; } /// /// The type of action to perform. /// public OVRPlugin.SpaceQueryActionType ActionType { get; set; } private OVRPlugin.SpaceComponentType _componentType; private IEnumerable _uuidFilter; /// /// The components which must be present on the space in order to match the query. /// /// /// The query will be limited to spaces that have this set of components. You may filter by component type or /// UUID (see ), but not both at the same time. /// /// Currently, only one component is allowed at a time. /// /// Thrown if is not `null`. public OVRPlugin.SpaceComponentType ComponentFilter { get => _componentType; set { ValidateSingleFilter(_uuidFilter, value); _componentType = value; } } /// /// A set of UUIDs used to filter the query. /// /// /// The query will look for this set of UUIDs and only return matching UUIDs up to . /// You may filter by component type (see ) or UUIDs, but not both at the same /// time. /// /// Thrown if is not 0. /// Thrown if is set to a value that contains more /// than UUIDs. public IEnumerable UuidFilter { get => _uuidFilter; set { ValidateSingleFilter(value, _componentType); if (value is IReadOnlyCollection collection && collection.Count > MaxUuidCount) throw new ArgumentException( $"There must not be more than {MaxUuidCount} UUIDs specified by the {nameof(UuidFilter)} (new value contains {collection.Count} UUIDs).", nameof(value)); _uuidFilter = value; } } /// /// Creates a copy of . /// /// The options to copy. public Options(Options other) { QueryType = other.QueryType; MaxResults = other.MaxResults; Timeout = other.Timeout; Location = other.Location; ActionType = other.ActionType; _componentType = other._componentType; _uuidFilter = other._uuidFilter; } /// /// Creates a new from this. /// /// The newly created info. public OVRPlugin.SpaceQueryInfo ToQueryInfo() { var filterType = OVRPlugin.SpaceQueryFilterType.None; var numIds = 0; var numComponents = 0; if (_uuidFilter != null) { filterType = OVRPlugin.SpaceQueryFilterType.Ids; foreach (var id in _uuidFilter.ToNonAlloc()) { if (numIds >= MaxUuidCount) throw new InvalidOperationException( $"{nameof(UuidFilter)} must not contain more than {MaxUuidCount} UUIDs."); Ids[numIds++] = id; } } else { filterType = OVRPlugin.SpaceQueryFilterType.Components; ComponentTypes[numComponents++] = _componentType; } return new OVRPlugin.SpaceQueryInfo { QueryType = QueryType, MaxQuerySpaces = MaxResults, Timeout = Timeout, Location = Location.ToSpaceStorageLocation(), ActionType = ActionType, FilterType = filterType, IdInfo = new OVRPlugin.SpaceFilterInfoIds { Ids = Ids, NumIds = numIds }, ComponentsInfo = new OVRPlugin.SpaceFilterInfoComponents { Components = ComponentTypes, NumComponents = numComponents, } }; } /// /// Initiates a space query. /// /// When this method returns, will represent a valid /// request if successful, or an invalid request if not. This parameter is passed initialized. /// `true` if the query was successfully started; otherwise, `false`. public bool TryQuerySpaces(out ulong requestId) { var querySpaces = OVRPlugin.QuerySpaces(ToQueryInfo(), out requestId); OVRTelemetry.Client.MarkerStart(OVRTelemetryConstants.Scene.MarkerId.SpatialAnchorQuery, requestId.GetHashCode()); if (!querySpaces) { OVRTelemetry.Client.MarkerEnd(OVRTelemetryConstants.Scene.MarkerId.SpatialAnchorQuery, OVRPlugin.Qpl.ResultType.Fail, requestId.GetHashCode()); } return querySpaces; } private static void ValidateSingleFilter(IEnumerable uuidFilter, OVRPlugin.SpaceComponentType componentFilter) { if (uuidFilter != null && componentFilter != 0) throw new InvalidOperationException($"You may only query by UUID or by component type."); } } }