/* * 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; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using UnityEngine; namespace Oculus.Interaction.DebugTree { /// /// Interface indicating the inheriting type can be represented as a node in a tree-like structure for debugging /// and other development purposes. /// /// /// This type is explicitly intended for use alongside ; for a canonical usage example, /// see . /// /// public interface ITreeNode where TLeaf : class { /// /// The value "contained" in this node, which the containing makes available for /// debugging and development purposes. /// /// /// For example, for , this value is an individual /// . /// TLeaf Value { get; } /// /// The children of this node in the . /// IEnumerable> Children { get; } } public abstract class DebugTree where TLeaf : class { private class Node : ITreeNode { TLeaf ITreeNode.Value => Value; IEnumerable> ITreeNode.Children => Children; public TLeaf Value { get; set; } public List Children { get; set; } } private Dictionary _existingNodes = new Dictionary(); private readonly TLeaf Root; private Node _rootNode; public DebugTree(TLeaf root) { Root = root; } public ITreeNode GetRootNode() { return _rootNode; } [Obsolete("Use async method instead.", true)] public void Rebuild() { throw new System.NotImplementedException(); } public async Task RebuildAsync() { var rootNode = await BuildTreeAsync(Root); _rootNode = rootNode; } private async Task BuildTreeAsync(TLeaf root) { _existingNodes.Clear(); return await BuildTreeRecursiveAsync(root); } private async Task BuildTreeRecursiveAsync(TLeaf value) { if (value == null) { return null; } if (_existingNodes.ContainsKey(value)) { return _existingNodes[value]; } List children = new List(); var asyncChildren = await TryGetChildrenAsync(value); foreach (var child in asyncChildren) { var result = await BuildTreeRecursiveAsync(child); if (result != null) { children.Add(result); } } Node self = new Node() { Value = value, Children = children, }; _existingNodes.Add(value, self); return self; } [Obsolete("Use async method instead.", true)] protected virtual bool TryGetChildren(TLeaf node, out IEnumerable children) => throw new System.NotImplementedException(); protected abstract Task> TryGetChildrenAsync(TLeaf node); } }