Getting assets / sub folders inside a folder

Hi

I’m experimenting with writing an editor window that is roughly similar to the project window, but specifically aimed at browsing and previewing audio assets efficiently. Partly as it’ll be useful, and partly as it is good practice! :slight_smile:

What I’m stuck on is exactly how I should navigate the folder hierachy. In very rough psuedo code I expected to write something along the lines of:

    void OnGUI()
    {
        AssetFolderGUI(Application.dataPath);
    }

    string AssetFolderGUI(string path)
    {
        //do a bit of GUI here to show the folder

        //now recurse to show sub folders
        string[] subfolders = GetSubFolders(path);
        foreach (string foldername in fldernames)
        {
            AssetFolderGUI(foldername);
        }

        //now show the assets
        string[] assetnames = GetAssets(path);
        foreach (string assetname in assetnames)
        {
            //put some gui in
        }
    }

However there’s no clear way to do the ‘GetAssets’ bit. I’ve seen LoadAllAssetsAtPath, but I don’t want to actually load them all - I just want their names (and maybe types)! Unless I’ve misunderstood what ‘load’ really means internally.

I can see a few options:

  • I’ve misunderstood what ‘load’ really means internally, and its perfectly fine to just ‘load’ every audio asset in the project folder (even if theres 1000s)
  • There’s no special way to do it, and I just have to check file extensions and things using the .net api
  • I’ve just missed some critical function somewhere and should have read the docs more carefully

Any help greatly appreciated!

p.s. cheeky extra question - if anybody knows any links that might show how to create the project window’s ‘drag-and-drop-into-inspector’ behavior I’d be very greatful.

cheers

-Chris

(EDIT) done a bit more work, and here’s the actual code I’ve written so far in case it helps.

    public class Folder
    {
        public string path = "";
        public int child_assets = 0;
        public bool open = false;
        public Dictionary<string, Folder> subfolders = new Dictionary<string, Folder>();
    }

    void OnGUI()
    {
        if (root == null)
        {
            root = new Folder();
            dirty = true;
        }
        root.path = Application.dataPath;

        if (GUILayout.Button("Refresh"))
            dirty = true;

        if (dirty)
        {
            Debug.Log("Refreshing audio folders");
            RefreshFolders(root);
            dirty = false;
        }

        scroll_pos = EditorGUILayout.BeginScrollView(scroll_pos);
        FolderGUI(root);
        EditorGUILayout.EndScrollView();
    }

    void RefreshFolders(Folder folder)
    {
        //mark folder and all known sub folders as having 0 relavent child assets
        folder.child_assets = 0;
        foreach (KeyValuePair<string, Folder> subfolder in folder.subfolders)
            subfolder.Value.child_assets = 0;

        //get all subdirectories of current folder, and iterate over them
        string[] folder_paths = Directory.GetDirectories(folder.path);
        foreach (string folder_path in folder_paths)
        {
            //attempt to get existing info for this folder. if it isn't already 'known', create it
            Folder f;
            if (!folder.subfolders.TryGetValue(folder_path, out f))
            {
                f = new Folder();
                f.path = folder_path;
                folder.subfolders.Add(f.path, f);
            }

            //recursively update the folder
            RefreshFolders(f);

            //update the child asset count
            folder.child_assets += f.child_assets;
        }

        //quick link query to remove any detected folders that have no relevant assets in (or have been deleted)
        string[] unseen = folder.subfolders.Where(a => a.Value.child_assets == 0).Select(a => a.Key).ToArray();
        foreach (string s in unseen)
            folder.subfolders.Remove(s);

        //THIS IS THE BAD BIT! I'd like to do this properly and find all audio assets unity knows about
        //count number of audio assets in this folder
        string[] file_paths = Directory.GetFiles(folder.path);
        foreach (string file_path in file_paths)
        {
            if(file_path.EndsWith(".wav"))
            {
                folder.child_assets++;
            }
        }
    }

I’ve missed off the ‘FolderGUI’ function and a few other bits as they aren’t relevant - the key is the bit where I iterate over files in RefreshFolder.

This should allow you to recursively loop through all of the files in the project folder. Can you post the FolderGUI function? I am curious how you ended up doing that

public static void CopyFiles(DirectoryInfo source, DirectoryInfo target, bool verbose)
    {
        Directory.CreateDirectory(target.FullName);

        foreach (var file in source.GetFiles())
        {
            
        }

        foreach (var sourceSubDir in source.GetDirectories())
        {
            CopyFiles(sourceSubDir, targetSubDir, verbose);
        }
    }

Are you doing this at runtime or editor?

If editor: use System.IO namespace and you get access to FileInfo and DirectoryInfo.
Pass Application.dataPath + “…/Resources” to DirectoryInfo and you get the info of the resources folder.

If runtime: best i can think of is you can save the paths in the editor, then load that at runtime to get the paths you need.