void FolderBrowsing()
        {
            // We are not concerned with assets being added multiple times as we only show the contents
            // of each selected folder. This is an issue when searching recursively into child folders.
            List <FilterResult> list = new List <FilterResult>();
            HierarchyProperty   property;

            foreach (string folderPath in m_SearchFilter.folders)
            {
                if (folderPath == PackageManager.Folders.GetPackagesPath())
                {
                    var packages = PackageManagerUtilityInternal.GetAllVisiblePackages(m_SearchFilter.skipHidden);
                    foreach (var package in packages)
                    {
                        var packageFolderInstanceId = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(package.assetPath);
                        property = new HierarchyProperty(package.assetPath);
                        if (property.Find(packageFolderInstanceId, null))
                        {
                            FilterResult result = new FilterResult();
                            CopyPropertyData(ref result, property);
                            result.name = !string.IsNullOrEmpty(package.displayName) ? package.displayName : package.name;
                            list.Add(result);
                        }
                    }
                    continue;
                }

                if (m_SearchFilter.skipHidden && !PackageManagerUtilityInternal.IsPathInVisiblePackage(folderPath))
                {
                    continue;
                }

                int folderInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(folderPath);
                property = new HierarchyProperty(folderPath);
                property.SetSearchFilter(m_SearchFilter);

                int   folderDepth = property.depth;
                int[] expanded    = { folderInstanceID };
                while (property.Next(expanded))
                {
                    if (property.depth <= folderDepth)
                    {
                        break; // current property is outside folder
                    }
                    FilterResult result = new FilterResult();
                    CopyPropertyData(ref result, property);
                    list.Add(result);

                    // Fetch sub assets by expanding the main asset (ignore folders)
                    if (property.hasChildren && !property.isFolder)
                    {
                        System.Array.Resize(ref expanded, expanded.Length + 1);
                        expanded[expanded.Length - 1] = property.instanceID;
                    }
                }
            }
            m_Results = list.ToArray();
        }
Beispiel #2
0
        private static IEnumerator <T> FindInFolders <T>(SearchFilter searchFilter, Func <HierarchyProperty,  T> selector)
        {
            var folders = new List <string>();

            folders.AddRange(searchFilter.folders);
            if (folders.Remove(PackageManager.Folders.GetPackagesPath()))
            {
                var packages = PackageManagerUtilityInternal.GetAllVisiblePackages(searchFilter.skipHidden);
                foreach (var package in packages)
                {
                    if (!folders.Contains(package.assetPath))
                    {
                        folders.Add(package.assetPath);
                    }
                }
            }

            foreach (var folderPath in folders)
            {
                var sanitizedFolderPath = folderPath.ConvertSeparatorsToUnity().TrimTrailingSlashes();
                var folderInstanceID    = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(sanitizedFolderPath);
                var rootPath            = "Assets";

                // Find the right rootPath if folderPath is part of a package
                var packageInfo = PackageManager.PackageInfo.FindForAssetPath(sanitizedFolderPath);
                if (packageInfo != null)
                {
                    rootPath = packageInfo.assetPath;
                    if (searchFilter.skipHidden && !PackageManagerUtilityInternal.IsPathInVisiblePackage(rootPath))
                    {
                        continue;
                    }
                }

                // Set empty filter to ensure we search all assets to find folder
                var property = new HierarchyProperty(rootPath);
                property.SetSearchFilter(new SearchFilter());
                if (property.Find(folderInstanceID, null))
                {
                    // Set filter after we found the folder
                    property.SetSearchFilter(searchFilter);
                    int   folderDepth = property.depth;
                    int[] expanded    = null; // enter all children of folder
                    while (property.NextWithDepthCheck(expanded, folderDepth + 1))
                    {
                        yield return(selector(property));
                    }
                }
                else
                {
                    Debug.LogWarning("AssetDatabase.FindAssets: Folder not found: '" + sanitizedFolderPath + "'");
                }
            }
        }
        internal void Show(UnityObject obj, Type[] requiredTypes, UnityObject objectBeingEdited, bool allowSceneObjects, List <int> allowedInstanceIDs = null, Action <UnityObject> onObjectSelectorClosed = null, Action <UnityObject> onObjectSelectedUpdated = null)
        {
            m_ObjectSelectorReceiver = null;
            m_AllowSceneObjects      = allowSceneObjects;
            m_IsShowingAssets        = true;
            m_SkipHiddenPackages     = true;
            m_AllowedIDs             = allowedInstanceIDs;
            m_ObjectBeingEdited      = objectBeingEdited;
            m_LastSelectedInstanceId = obj?.GetInstanceID() ?? 0;
            m_SelectionCancelled     = false;

            m_OnObjectSelectorClosed  = onObjectSelectorClosed;
            m_OnObjectSelectorUpdated = onObjectSelectedUpdated;

            // Do not allow to show scene objects if the object being edited is persistent
            if (m_ObjectBeingEdited != null && EditorUtility.IsPersistent(m_ObjectBeingEdited))
            {
                m_AllowSceneObjects = false;
            }

            // Set which tab should be visible at startup
            if (m_AllowSceneObjects)
            {
                if (obj != null)
                {
                    if (typeof(Component).IsAssignableFrom(obj.GetType()))
                    {
                        obj = ((Component)obj).gameObject;
                    }
                    // Set the right tab visible (so we can see our selection)
                    m_IsShowingAssets = EditorUtility.IsPersistent(obj);
                }
                else
                {
                    foreach (var requiredType in requiredTypes)
                    {
                        m_IsShowingAssets &= (requiredType != typeof(GameObject) && !typeof(Component).IsAssignableFrom(requiredType));
                    }
                }
            }
            else
            {
                m_IsShowingAssets = true;
            }

            // Set member variables
            m_DelegateView = GUIView.current;
            // type filter requires unqualified names for built-in types, but will prioritize them over user types, so ensure user types are namespace-qualified
            if (m_RequiredTypes == null)
            {
                m_RequiredTypes = new string[requiredTypes.Length];
            }
            for (int i = 0; i < requiredTypes.Length; i++)
            {
                if (requiredTypes[i] != null)
                {
                    m_RequiredTypes[i] = typeof(ScriptableObject).IsAssignableFrom(requiredTypes[i]) || typeof(MonoBehaviour).IsAssignableFrom(requiredTypes[i]) ? requiredTypes[i].FullName : requiredTypes[i].Name;
                }
            }
            m_SearchFilter      = "";
            m_OriginalSelection = obj;
            m_ModalUndoGroup    = Undo.GetCurrentGroup();

            // Show custom selector if available
            if (ObjectSelectorSearch.HasEngineOverride())
            {
                m_SearchSessionHandler.BeginSession(() =>
                {
                    return(new SearchService.ObjectSelectorSearchContext
                    {
                        currentObject = obj,
                        editedObjects = m_EditedProperty != null ? m_EditedProperty.serializedObject.targetObjects : new[] { objectBeingEdited },
                        requiredTypes = requiredTypes,
                        requiredTypeNames = m_RequiredTypes,
                        allowedInstanceIds = allowedInstanceIDs,
                        visibleObjects = allowSceneObjects ? SearchService.VisibleObjects.All : SearchService.VisibleObjects.Assets,
                    });
                });

                Action <UnityObject> onSelectionChanged = selectedObj =>
                {
                    m_LastSelectedInstanceId = selectedObj == null ? 0 : selectedObj.GetInstanceID();
                    NotifySelectionChanged(false);
                };
                Action <UnityObject, bool> onSelectorClosed = (selectedObj, canceled) =>
                {
                    m_SearchSessionHandler.EndSession();
                    if (canceled)
                    {
                        // Undo changes we have done in the ObjectSelector
                        Undo.RevertAllDownToGroup(m_ModalUndoGroup);
                        m_LastSelectedInstanceId = 0;
                        m_SelectionCancelled     = true;
                    }
                    else
                    {
                        m_LastSelectedInstanceId = selectedObj == null ? 0 : selectedObj.GetInstanceID();
                        NotifySelectionChanged(false);
                    }

                    m_EditedProperty = null;
                    NotifySelectorClosed(false);
                };

                if (m_SearchSessionHandler.SelectObject(onSelectorClosed, onSelectionChanged))
                {
                    return;
                }
                else
                {
                    m_SearchSessionHandler.EndSession();
                }
            }

            // Freeze to prevent flicker on OSX.
            // Screen will be updated again when calling
            // SetFreezeDisplay(false) further down.
            ContainerWindow.SetFreezeDisplay(true);

            var shouldRepositionWindow = m_Parent != null;

            ShowWithMode(ShowMode.AuxWindow);
            string text = "Select " + (requiredTypes[0] == null ? m_RequiredTypes[0] : requiredTypes[0].Name);

            for (int i = 1; i < requiredTypes.Length; i++)
            {
                text += (i == requiredTypes.Length - 1 ? " or " : ", ") + (requiredTypes[i] == null ? m_RequiredTypes[i] : requiredTypes[i].Name);
            }
            titleContent = EditorGUIUtility.TrTextContent(text);

            // Deal with window size
            if (shouldRepositionWindow)
            {
                m_Parent.window.LoadInCurrentMousePosition();
                m_Parent.window.FitWindowToScreen(true);
            }
            Rect p = m_Parent == null ? new Rect(0, 0, 1, 1) : m_Parent.window.position;

            p.width  = EditorPrefs.GetFloat("ObjectSelectorWidth", 200);
            p.height = EditorPrefs.GetFloat("ObjectSelectorHeight", 390);
            position = p;
            minSize  = new Vector2(kMinWidth, kMinTopSize + kPreviewExpandedAreaHeight + 2 * kPreviewMargin);
            maxSize  = new Vector2(10000, 10000);
            SetupPreview();

            // Focus
            Focus();
            ContainerWindow.SetFreezeDisplay(false);

            m_FocusSearchFilter = true;

            // Add after unfreezing display because AuxWindowManager.cpp assumes that aux windows are added after we get 'got/lost'- focus calls.
            if (m_Parent != null)
            {
                m_Parent.AddToAuxWindowList();
            }

            // Initial selection
            int initialSelection = obj != null?obj.GetInstanceID() : 0;

            if (initialSelection != 0)
            {
                var assetPath = AssetDatabase.GetAssetPath(initialSelection);
                if (m_SkipHiddenPackages && !PackageManagerUtilityInternal.IsPathInVisiblePackage(assetPath))
                {
                    m_SkipHiddenPackages = false;
                }
            }

            if (m_RequiredTypes.All(t => ShouldTreeViewBeUsed(t)))
            {
                m_ObjectTreeWithSearch.Init(position, this, CreateAndSetTreeView, TreeViewSelection, ItemWasDoubleClicked, initialSelection, 0);
            }
            else
            {
                // To frame the selected item we need to wait to initialize the search until our window has been setup
                InitIfNeeded();
                m_ListArea.InitSelection(new[] { initialSelection });
                if (initialSelection != 0)
                {
                    m_ListArea.Frame(initialSelection, true, false);
                }
            }
        }
        internal void Show(UnityObject obj, Type requiredType, SerializedProperty property, bool allowSceneObjects, List <int> allowedInstanceIDs, Action <UnityObject> onObjectSelectorClosed, Action <UnityObject> onObjectSelectedUpdated)
        {
            m_ObjectSelectorReceiver = null;
            m_AllowSceneObjects      = allowSceneObjects;
            m_IsShowingAssets        = true;
            m_SkipHiddenPackages     = true;
            m_AllowedIDs             = allowedInstanceIDs;

            m_OnObjectSelectorClosed  = onObjectSelectorClosed;
            m_OnObjectSelectorUpdated = onObjectSelectedUpdated;

            if (property != null)
            {
                if (requiredType == null)
                {
                    ScriptAttributeUtility.GetFieldInfoFromProperty(property, out requiredType);
                    // case 951876: built-in types do not actually have reflectable fields, so their object types must be extracted from the type string
                    // this works because built-in types will only ever have serialized references to other built-in types, which this window's filter expects as unqualified names
                    if (requiredType == null)
                    {
                        m_RequiredType = s_MatchPPtrTypeName.Match(property.type).Groups[1].Value;
                    }
                }

                obj = property.objectReferenceValue;
                m_ObjectBeingEdited = property.serializedObject.targetObject;

                // Do not allow to show scene objects if the object being edited is persistent
                if (m_ObjectBeingEdited != null && EditorUtility.IsPersistent(m_ObjectBeingEdited))
                {
                    m_AllowSceneObjects = false;
                }
            }

            // Set which tab should be visible at startup
            if (m_AllowSceneObjects)
            {
                if (obj != null)
                {
                    if (typeof(Component).IsAssignableFrom(obj.GetType()))
                    {
                        obj = ((Component)obj).gameObject;
                    }
                    // Set the right tab visible (so we can see our selection)
                    m_IsShowingAssets = EditorUtility.IsPersistent(obj);
                }
                else
                {
                    m_IsShowingAssets = (requiredType != typeof(GameObject) && !typeof(Component).IsAssignableFrom(requiredType));
                }
            }
            else
            {
                m_IsShowingAssets = true;
            }

            // Set member variables
            m_DelegateView = GUIView.current;
            // type filter requires unqualified names for built-in types, but will prioritize them over user types, so ensure user types are namespace-qualified
            if (requiredType != null)
            {
                m_RequiredType = typeof(ScriptableObject).IsAssignableFrom(requiredType) || typeof(MonoBehaviour).IsAssignableFrom(requiredType) ? requiredType.FullName : requiredType.Name;
            }
            m_SearchFilter      = "";
            m_OriginalSelection = obj;
            m_ModalUndoGroup    = Undo.GetCurrentGroup();

            // Freeze to prevent flicker on OSX.
            // Screen will be updated again when calling
            // SetFreezeDisplay(false) further down.
            ContainerWindow.SetFreezeDisplay(true);

            ShowWithMode(ShowMode.AuxWindow);
            titleContent = EditorGUIUtility.TrTextContent("Select " + (requiredType == null ? m_RequiredType : requiredType.Name));

            // Deal with window size
            Rect p = m_Parent == null ? new Rect(0, 0, 1, 1) : m_Parent.window.position;

            p.width  = EditorPrefs.GetFloat("ObjectSelectorWidth", 200);
            p.height = EditorPrefs.GetFloat("ObjectSelectorHeight", 390);
            position = p;
            minSize  = new Vector2(kMinWidth, kMinTopSize + kPreviewExpandedAreaHeight + 2 * kPreviewMargin);
            maxSize  = new Vector2(10000, 10000);
            SetupPreview();

            // Focus
            Focus();
            ContainerWindow.SetFreezeDisplay(false);

            m_FocusSearchFilter = true;

            // Add after unfreezing display because AuxWindowManager.cpp assumes that aux windows are added after we get 'got/lost'- focus calls.
            if (m_Parent != null)
            {
                m_Parent.AddToAuxWindowList();
            }

            // Initial selection
            int initialSelection = obj != null?obj.GetInstanceID() : 0;

            if (property != null && property.hasMultipleDifferentValues)
            {
                initialSelection = 0; // don't select anything on multi selection
            }
            if (initialSelection != 0)
            {
                var assetPath = AssetDatabase.GetAssetPath(initialSelection);
                if (m_SkipHiddenPackages && !PackageManagerUtilityInternal.IsPathInVisiblePackage(assetPath))
                {
                    m_SkipHiddenPackages = false;
                }
            }

            if (ShouldTreeViewBeUsed(m_RequiredType))
            {
                m_ObjectTreeWithSearch.Init(position, this, CreateAndSetTreeView, TreeViewSelection, ItemWasDoubleClicked, initialSelection, 0);
            }
            else
            {
                // To frame the selected item we need to wait to initialize the search until our window has been setup
                InitIfNeeded();
                m_ListArea.InitSelection(new[] { initialSelection });
                if (initialSelection != 0)
                {
                    m_ListArea.Frame(initialSelection, true, false);
                }
            }
        }