Skip to content

Instantly share code, notes, and snippets.

@SolarianZ
Last active May 22, 2024 02:43
Show Gist options
  • Save SolarianZ/405ffa7acdce2138e3b4517eefdea342 to your computer and use it in GitHub Desktop.
Save SolarianZ/405ffa7acdce2138e3b4517eefdea342 to your computer and use it in GitHub Desktop.
{"category": "Unity Engine/Editor/Extensions", "keywords": "Unity, Editor, Asset, Move"} Add 'Move to' menu item to move selected assets to a folder.
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
public static class AssetTool
{
// Add 'Move to' menu item to move selected assets to a folder
[MenuItem("Tools/Bamboo/Asset/Move Selected Assets to Folder")]
[MenuItem("Assets/Move to", priority = 20)]
public static void MoveSelectedAssetsToFolder()
{
// Filter root assets
// `Selection.objects` contains `null` when selecting a Scene in the Hierarchy window
IEnumerable<UnityEngine.Object> assets = Selection.objects
.Where(obj => obj && !AssetDatabase.IsSubAsset(obj) && EditorUtility.IsPersistent(obj));
string targetFolderPath = EditorUtility.OpenFolderPanel("Select Folder", "Assets", "");
if (string.IsNullOrEmpty(targetFolderPath))
{
return;
}
if (!targetFolderPath.StartsWith(Application.dataPath))
{
Debug.LogError("Can not move assets to outside of the project folder.");
return;
}
try
{
AssetDatabase.StartAssetEditing();
bool noAssetsSelected = true;
foreach (Object asset in assets)
{
noAssetsSelected = false;
string folderRelativePath = targetFolderPath.Replace(Application.dataPath, "Assets");
string assetPath = AssetDatabase.GetAssetPath(asset);
string assetExt = System.IO.Path.GetExtension(assetPath);
string newAssetPath = $"{folderRelativePath}/{asset.name}{assetExt}";
if (assetPath.Equals(newAssetPath))
{
continue;
}
Object assetAtNewPath = AssetDatabase.LoadAssetAtPath<Object>(newAssetPath);
if (assetAtNewPath)
{
int operation = EditorUtility.DisplayDialogComplex("Alert",
$"Asset '{asset.name}' already exists at '{targetFolderPath}', please select an operation:\n" +
$"- Replace: Replace the existing asset with the selected asset, the reference to the existing asset will be lost.\n" +
$"- Generate suffix: Generate a unique suffix for the selected asset and move it to the folder.\n" +
$"- Cancel move: Cancel the move operation.",
"Replace", "Cancel move", "Generate suffix");
switch (operation)
{
case 0: // Overwrite
AssetDatabase.DeleteAsset(newAssetPath);
break;
case 1: // Cancel move
continue;
case 2: // Generate suffix
newAssetPath = AssetDatabase.GenerateUniqueAssetPath(newAssetPath);
break;
}
}
AssetDatabase.MoveAsset(assetPath, newAssetPath);
UnityEngine.Debug.Log($"Move asset: {assetPath} -> {newAssetPath}", asset);
EditorGUIUtility.PingObject(asset);
}
if (noAssetsSelected)
{
Debug.LogError("No root asset selected for move.");
return;
}
}
finally
{
AssetDatabase.StopAssetEditing();
}
}
[MenuItem("Tools/Bamboo/Asset/Move Selected Assets to Folder", validate = true)]
[MenuItem("Assets/Move to", priority = 20, validate = true)]
public static bool HasMovableAssetsSelected()
{
return Selection.objects
.Any(obj => obj && !AssetDatabase.IsSubAsset(obj) && EditorUtility.IsPersistent(obj));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment