/*
* 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.");
}
}
}