Skip to content

Instantly share code, notes, and snippets.

@leventeren
Forked from FreyaHolmer/AssetCopyUtils.cs
Created November 27, 2023 06:23
Show Gist options
  • Save leventeren/0a7ccbab0cefd57083a11f5dead3ca4a to your computer and use it in GitHub Desktop.
Save leventeren/0a7ccbab0cefd57083a11f5dead3ca4a to your computer and use it in GitHub Desktop.
Adds context menu items to assets: Copy/Paste import settings & Copy GUID. Put this script in any Editor/ folder in your project and recompile!
// written by https://github.com/FreyaHolmer so use at your own risk c:
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
/// <summary>Utility functions to copy GUIDs, as well as Copy/Paste import settings</summary>
public static class AssetCopyUtils {
const int CTX_MENU_LOCATION = 70;
[MenuItem( "Assets/Copy GUID", false, priority = CTX_MENU_LOCATION, secondaryPriority = 0 )]
public static void CopyGUID() => GUIUtility.systemCopyBuffer = string.Join( ", ", Selection.assetGUIDs );
[MenuItem( "Assets/Copy GUID", true )]
public static bool CopyGUIDValidate() => Selection.assetGUIDs.Length > 0;
static AssetImporter sourceImporter; // todo: doesn't survive assembly reload but I also don't care that much
[MenuItem( "Assets/Copy Import Settings", false, priority = CTX_MENU_LOCATION, secondaryPriority = 1 )]
public static void CopyImportSettings() {
string path = AssetDatabase.GetAssetPath( Selection.activeObject );
sourceImporter = AssetImporter.GetAtPath( path );
}
[MenuItem( "Assets/Copy Import Settings", true )]
public static bool CopyImportSettingsValidate() {
if( Selection.count != 1 )
return false; // too many things selected
if( AssetDatabase.Contains( Selection.activeObject ) == false )
return false; // not an asset
return true;
}
[MenuItem( "Assets/Paste Import Settings", false, priority = CTX_MENU_LOCATION, secondaryPriority = 2 )]
public static void PasteImportSettings() {
AssetDatabase.DisallowAutoRefresh();
try {
HashSet<string> paths = AllValidPasteTargetAssetPaths();
foreach( string assetPath in paths ) {
AssetImporter targetImporter = AssetImporter.GetAtPath( assetPath );
Undo.RecordObject( targetImporter, "Paste import settings" );
EditorUtility.SetDirty( targetImporter );
EditorUtility.CopySerialized( sourceImporter, targetImporter );
targetImporter.SaveAndReimport();
}
Debug.Log( $"Pasted {sourceImporter.GetType().Name} settings into {paths.Count} {( paths.Count == 1 ? "asset" : "assets" )}:\n{string.Join( "\n", paths )}" );
} finally {
AssetDatabase.AllowAutoRefresh();
}
AssetDatabase.Refresh();
}
static HashSet<string> AllValidPasteTargetAssetPaths() {
HashSet<string> assetPaths = new();
// todo: I couldn't get folders to work, bc for some reason editing assets that are not selected, makes for an Undo stack horror
// find folders and assets in selection
// List<string> folderPaths = new();
foreach( Object selObj in Selection.objects ) {
if( AssetDatabase.Contains( selObj ) == false )
continue; // not an asset
string path = AssetDatabase.GetAssetPath( selObj );
if( IsFolder( selObj ) ) {
// folderPaths.Add( path ); // to find all guids of assets in the folder
} else if( ObjectIsValidPasteTarget( path ) ) {
assetPaths.Add( path );
} else {
// something was explicitly selected, but doesn't match the copied type, pls warn
Debug.LogWarning( $"Can't paste {sourceImporter.GetType().Name} settings onto {selObj.GetType().Name} \"{selObj.name}\" at {path}" );
}
}
// then, also add all matching assets in the selected folders, if any
// if( folderPaths.Count > 0 ) { // deeply crucial if statement here do NOT remove lol
// foreach( string assetPath in AssetDatabase.FindAssets( "", folderPaths.ToArray() ).Select( AssetDatabase.GUIDToAssetPath ) ) {
// if( ObjectIsValidPasteTarget( assetPath ) )
// assetPaths.Add( assetPath ); // add non-folder assets found that have the same import type
// }
// }
return assetPaths;
}
static bool IsFolder( Object obj ) => AssetDatabase.Contains( obj ) && IsFolder( AssetDatabase.GetAssetPath( obj ) );
static bool IsFolder( string path ) => AssetDatabase.IsValidFolder( path );
[MenuItem( "Assets/Paste Import Settings", true )]
public static bool PasteImportSettingsValidate() {
if( Selection.count == 0 )
return false;
if( sourceImporter == null )
return false; // copied data got assembly reloaded
return true;
}
static bool ObjectIsValidPasteTarget( string path ) => IsFolder( path ) == false && AssetDatabase.GetImporterType( path ) == sourceImporter.GetType();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment