It works if I used right click to show the creation popup menu but does not work if I click on the Create Button in the toolbar of the Project Window.
I tried to add a MenuCommand to my menu item function but the context object is null. Does anyone know how to get the current selected folder in the Project Window?
You can use built-in property to generate a “create asset” menu
[CreateAssetMenu( menuName = "Wappen Asset/WaveBankData" )]
public class WaveBankData : ScriptableObject
{
And it will magically added to right click menu → Create. Has same functionality as Unity’s one. It will be created in current browser location, prompt for a rename, etc.
As a bonus
, here is how TextMesh pro determine current right-click folder. If you call Selection.assetGUIDs under MenuItem call back, it will guarantee current displaying folder (the one that you clicked on its empty space)
[MenuItem("Assets/Create/TextMeshPro/Color Gradient", false, 115)]
public static void CreateColorGradient(MenuCommand context)
{
string filePath;
if (Selection.assetGUIDs.Length == 0)
filePath = "Assets/New TMP Color Gradient.asset";
else
filePath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);
The TRUE Project browser current directory
Is hidden inside internal unity ProjectWindowUtil.TryGetActiveFolderPath static function and needs reflector to access it. If you are coder wiz and really want to have it, here it is. (For non coder, I wont explain this, please do C# research on your own)
using UnityEngine;
using UnityEditor;
using System.Reflection;
// Define this function somewhere in your editor class to make a shortcut to said hidden function
private static bool TryGetActiveFolderPath( out string path )
{
var _tryGetActiveFolderPath = typeof(ProjectWindowUtil).GetMethod( "TryGetActiveFolderPath", BindingFlags.Static | BindingFlags.NonPublic );
object[] args = new object[] { null };
bool found = (bool)_tryGetActiveFolderPath.Invoke( null, args );
path = (string)args[0];
return found;
}
Note: tested in Unity 2019.4.19f
Tested in 2020, works like a charm 'TryGetActiveFolderPath'
Works in Unity 6. The reflection method call is the ONLY solution that will always return the currently selected folder in project view. All the Selection-based solutions suffer from the issue that the project view may have lost focus, and even though there is a visual selection it's technically unselected. Easy to confirm if you select a folder, then click on another window, then run a script that shows you the current selection (none).
Came here to upvote this and say that I find it bizarre that there is no public api for this and we have to cheat the private modifier with reflection to do something as simple as getting the file explorer context.
I converted it to CSharp and specifically made it a method to check if an asset is a folder.... private static bool IsAssetAFolder(Object obj){ string path = ""; if (obj == null){ return false; } path = AssetDatabase.GetAssetPath(obj.GetInstanceID()); if (path.Length > 0) { if (Directory.Exists(path)) { return true; } else { return false; } } return false; }
It shows not only to get a selected folder in Project view but also all files under the selected folder even with filtering by its file extension.
/// <summary>
/// Retrieves selected folder on Project view.
/// </summary>
/// <returns></returns>
public static string GetSelectedPathOrFallback()
{
string path = "Assets";
foreach (UnityEngine.Object obj in Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets))
{
path = AssetDatabase.GetAssetPath(obj);
if (!string.IsNullOrEmpty(path) && File.Exists(path))
{
path = Path.GetDirectoryName(path);
break;
}
}
return path;
}
/// <summary>
/// Recursively gather all files under the given path including all its subfolders.
/// </summary>
static IEnumerable<string> GetFiles(string path)
{
Queue<string> queue = new Queue<string>();
queue.Enqueue(path);
while (queue.Count > 0)
{
path = queue.Dequeue();
try
{
foreach (string subDir in Directory.GetDirectories(path))
{
queue.Enqueue(subDir);
}
}
catch (System.Exception ex)
{
Debug.LogError(ex.Message);
}
string[] files = null;
try
{
files = Directory.GetFiles(path);
}
catch (System.Exception ex)
{
Debug.LogError(ex.Message);
}
if (files != null)
{
for (int i = 0; i < files.Length; i++)
{
yield return files*;*
} } } }
// You can either filter files to get only neccessary files by its file extension using LINQ. // It excludes .meta files from all the gathers file list. var assetFiles = GetFiles(GetSelectedPathOrFallback()).Where(s => s.Contains(“.meta”) == false);
foreach (string f in assetFiles) { Debug.Log("Files: " + f); }
Now you see, the only Object typed object is the folder.
NOTE:
This works works only if you put just files that unity can recognize. (PDF, jar, and other funky stuff will also be detected as UnityEngine.Object)
This may be a solution for some cases but does not resolve all of them (try to play with the selection and you 'll see problems). Moreover, as you said, specific files and elements are Object too and you can not be sure. That's why I won't mark it as a solution. Thanks for the answer anyway. If you use this code, I would suggest you not to use DeepAssets for the SelectionMode. It will send you all the subfolders of the selected folder too so you can't select the right one from the list.
Yep, you are right about the DeepAssets part. I thought 'bout the question one more time, and maybe we could use .Net api to check if the object on the specified path is a folder or a file. (See System.IO) How's that sounds? XD
actually, I found some cases with a selected (but not active) folder and the selection does not get it. Too much time for too few features, I ll use the right click popup menu instead.
This is a really good solution, in my opinion. To add on to this, once you have the selected objects you can use: Path.GetExtension( AssetDatabase.GetAssetPath( obj ) ) This will give you the extension of the file which could help narrow down the type of object you're looking for. This answer helped me a ton! Thanks!
Here you have my implementation to get the full path of a folder right-clicked on Project View.
I am not sure if this what you were asking for, but I hope it helps someone.
Tested in 2020, works like a charm 'TryGetActiveFolderPath'
– IliqNikushevWorks in Unity 6. The reflection method call is the ONLY solution that will always return the currently selected folder in project view. All the Selection-based solutions suffer from the issue that the project view may have lost focus, and even though there is a visual selection it's technically unselected. Easy to confirm if you select a folder, then click on another window, then run a script that shows you the current selection (none).
– CodeSmileCame here to upvote this and say that I find it bizarre that there is no public api for this and we have to cheat the private modifier with reflection to do something as simple as getting the file explorer context.
– Sealer0