csharp/abist-co-ltd/hololens-opencv-laserpointer/Assets/MRTK/Core/Inspectors/Utilities/Search/MixedRealitySearchUtility.cs

MixedRealitySearchUtility.cs
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using Microsoft.MixedReality.Toolkit.SceneSystem;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;

namespace Microsoft.MixedReality.Toolkit.Utilities.Editor.Search
{
    /// 
    /// Utility for retrieving a Unity object's serialized fields with a configurable search.
    /// 
    public static clast MixedRealitySearchUtility
    {
        /// 
        /// True if a search is being executed. This must be false before calling StartProfileSearch.
        /// 
        public static bool Searching { get { return activeTask != null && !activeTask.IsCompleted; } }

        private const int maxChildSearchDepth = 5;
        private const int minSearchStringLength = 3;
        private static Task activeTask;

        /// 
        /// Field names that shouldn't be displayed in a profile field search.
        /// 
        private static readonly HashSet serializedPropertiesToIgnore = new HashSet()
        {
            // Unity base clast fields
            "m_Name",
            "m_Script",
            "m_Enabled",
            "m_GameObject",
            "m_ObjectHideFlags",
            "m_CorrespondingSourceObject",
            "m_PrefabInstance",
            "m_Prefabastet",
            "m_EditorHideFlags",
            "m_EditorClastIdentifier",
            // Profile base clast fields
            "isCustomProfile",
        };

        /// 
        /// Field types that don't need their child properties displayed.
        /// 
        private static readonly HashSet serializedPropertyTypesToFlatten = new HashSet()
        {
            typeof(SystemType).Name,
            typeof(SceneInfo).Name,
        };

        /// 
        /// Starts a profile search. 'Searching' must be false or an exception will be thrown.
        /// 
        /// Profile object to search.
        /// Configuration for the search.
        /// Action to invoke once search is complete - delivers final results.
        public static async void StartProfileSearch(UnityEngine.Object profile, SearchConfig config, Action onSearchComplete)
        {
            if (activeTask != null && !activeTask.IsCompleted)
            {
                throw new Exception("Can't start a new search until the old one has completed.");
            }

            List searchResults = new List();

            // Validate search configuration
            if (string.IsNullOrEmpty(config.SearchFieldString))
            {   // If the config is empty, bail early
                onSearchComplete?.Invoke(true, profile, searchResults);
                return;
            }

            // Generate keywords if we haven't yet
            if (config.Keywords == null)
            {
                config.Keywords = new HashSet(config.SearchFieldString.Split(new string[] { " ", "," }, StringSplitOptions.RemoveEmptyEntries));
                config.Keywords.RemoveWhere(s => s.Length < minSearchStringLength);
            }

            if (config.Keywords.Count == 0)
            {   // If there are no useful keywords, bail early
                onSearchComplete?.Invoke(true, profile, searchResults);
                return;
            }

            // Launch the search task
            bool cancelled = false;
            try
            {
                activeTask = SearchProfileField(profile, config, searchResults);
                await activeTask;
            }
            catch (Exception e)
            {
                // Profile was probably deleted in the middle of searching.
                Debug.LogException(e);
                cancelled = true;
            }
            finally
            {
                searchResults.Sort(delegate (ProfileSearchResult r1, ProfileSearchResult r2)
                {
                    if (r1.ProfileMatchStrength != r2.ProfileMatchStrength)
                    {
                        return r2.ProfileMatchStrength.CompareTo(r1.ProfileMatchStrength);
                    }
                    else
                    {
                        return r2.Profile.name.CompareTo(r1.Profile.name);
                    }
                });

                searchResults.RemoveAll(r => r.Fields.Count