用odin实现的资源复制编辑器

发布于:2024-04-19 ⋅ 阅读:(25) ⋅ 点赞:(0)

用odin实现了一个资源复制编辑器,使用要安装odin,功能是把要复制的资源路径一个个添加设置,点copy能把列表里的资源全部复制,支持目录复制到目录,文件复制到目录,文件复制替换。提升效率,让自己有更多的时间研究其他东西或者休息,需要注意的是只有一个目标路径的情况下,不能同时填源文件路径和源文件夹路径,不然不知道要拷贝文件还是文件夹,这个应该很好理解吧。代码如下:

using UnityEditor;
using UnityEngine;
using Sirenix.OdinInspector.Editor;
using Sirenix.OdinInspector;
using System;
using System.IO;
using System.Collecttions.Generic;
public class PathTableListWindow : OdinEditorWindow
{
    [MenuItem("Window/Open Path Table List")]
    private static void OpenWindow()
    {
        // GetExistingOrCreateNewWindow 是一个用于创建或获取已存在窗口的辅助方法
        var window = GetWindow<PathTableListWindow>();
        window.Show();
    }

    // 示例数据,用于在编辑器窗口中显示
    [TableList]
    public List<Item> PathItems = new List<Item>();

    [Button("Copy")]
    private void CopyAssets()
    {
        foreach(var item in PathItems)
        {
			if (Directory.Exists(item.SourcePath))
	        {
	            // 如果源路径是文件夹,则递归复制所有文件和子文件夹
	            CopyDirectory(item.SourcePath, item.TargetPath);
	        }
	        else if (File.Exists(item.SourcePath))
	        {
	            // 如果源路径是文件,则直接复制文件
	            string destDir = Path.GetDirectoryName(item.TargetPath);
	            if (!Directory.Exists(destDir))
	            {
	                Directory.CreateDirectory(destDir);
	            }
	            File.Copy(item.SourcePath, item.TargetPath, true);
	        }
	        if(!string.IsNullOrEmpty(item.SourceFilePath))
	        {
				if(string.IsNullOrEmpty(item.TargetFilePath)
				{
					var destFile = Path.Combine(item.TargetPath,Path.GetFileName(item.TargetFilePath));
					File.Copy(item.SourceFilePath, destFile, true);
				}
				else
				{
					File.Copy(item.SourceFilePath, item.TargetFilePath, true);
				}
			}
		}
    }
	 private void CopyDirectory(string source, string destination)
    {
       	if(File.GetAttributes(source).HasFlag(FileAttributes.Directory))
       	{
			 string targetDest = Path.Combine(destination,Path.GetFileName(source));
	        if(!Directory.Exists(targetDest))
	        {
				// 创建目标目录
	        	Directory.CreateDirectory(targetDest );
			}
			 
		        // 递归复制子目录
		        string[] dirs = Directory.GetDirectories(source);
		        foreach (string dir in dirs)
		        {
		            string destDir = Path.Combine(targetDest, Path.GetFileName(dir));
		            CopyDirectory(dir, destDir);
		        }
		         // 获取源目录下的所有文件
        		string[] files = Directory.GetFiles(source);
        		 foreach (string file in files)
		        {
		            string destFile = Path.Combine(targetDest, Path.GetFileName(file));
		            File.Copy(file, destFile, true);
		        }
		}
		else
		{
			 // 获取源目录下的所有文件
        		string[] files = Directory.GetFiles(source);
        		
        		 foreach (string file in files)
		        {
		            string destFile = Path.Combine(destination, Path.GetFileName(file));
		            File.Copy(file, destFile, true);
		        }
		}
       
        
        

      
       

        
    }
   
    [System.Serializable]
        public class Item
        {
            [TableColumnWidth(60)]
            [FolderPath, PropertyOrder(-1),HorizontalGroup("资源路径列表",0.25f)]
            public string SourcePath;

            [FolderPath, PropertyOrder(-1),HorizontalGroup("资源路径列表",0.25f)]
            public string TargetPath;
            [FilePath, PropertyOrder(-2),HorizontalGroup("资源路径列表",0.25f)]
            public string TargeFiletPath;
            [FilePath, PropertyOrder(-2),HorizontalGroup("资源路径列表",0.25f)]
            public string SourceFilePath;
        }
}

扩展:odin本身的floderpath并不支持项目外的文件夹拖拽,只能点按钮选择路径,为了更加方便的支持拖拽,我新增了一个属性拓展了它的功能,代码如下:

public class DraggableFloderPath:Attribute
{
}
public class DraggableFolderPathAttributeProcessor : OdinAttributeProcessor<DraggableFloderPath>
{
    public override void ProcessSelfAttributes(InspectorProperty property, List<Attribute> attributes)
    {
        base.ProcessSelfAttributes(property,attributes);
        attributes.Add(new FolderPathAttribute());
    }
}
public class DraggableFolderPathDrawer : OdinAttributeDrawer<DraggableFloderPath, string>
{
    protected override void DrawPropertyLayout(GUIContent label)
    {
       
        EditorGUILayout.BeginHorizontal(); 
      
        // 创建输入框和拖拽区域
        Rect dragArea= EditorGUILayout.GetControlRect();
        
        ValueEntry.SmartValue = EditorGUI.TextField(dragArea, label, ValueEntry.SmartValue);

        // 拖拽功能
        if ((Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform) && dragArea.Contains(Event.current.mousePosition))
        {
            DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
            if (Event.current.type == EventType.DragPerform)
            {
                DragAndDrop.AcceptDrag();
                foreach (var path in DragAndDrop.paths)
                {
                   /* if(File.GetAttributes(source).HasFlag(FileAttributes.Directory))
                    {
						if (!string.IsNullOrEmpty(path) && Directory.Exists(path))
	                    {
	                        
	                        this.ValueEntry.SmartValue = path;
	                        break;
	                    }
					}
                    else
                    {*/
						this.ValueEntry.SmartValue = path;
	                    break;
					//}
                }
                Event.current.Use();
            }
        }

        // 绘制一个按钮
        if (GUILayout.Button(EditorGUIUtility.IconContent("Folder Icon"),GUILayout.Width(30),GUILayout.Height(20)))
        {
        	 string selectedPath = "";
        	 if(label.text.Contains("File"))
        	 {
				selectedPath = EditorUtility.OpenFilePanel("Select File", "", "");
			}else
			{
				 selectedPath = EditorUtility.OpenFolderPanel("Select Folder", "", "");
			}
            
            if (!string.IsNullOrEmpty(selectedPath))
            {
                this.ValueEntry.SmartValue = selectedPath;
            }
        }

        EditorGUILayout.EndHorizontal(); 
    }
}
//然后就可以直接使用了
[System.Serializable]
        public class Item
        {
            [TableColumnWidth(60)]
            [DraggableFloderPath, PropertyOrder(-1),HorizontalGroup("资源路径列表",0.25f)]
            public string SourcePath;

            [DraggableFloderPath, PropertyOrder(-1),HorizontalGroup("资源路径列表",0.25f)]
            public string TargetPath;
            [DraggableFloderPath, PropertyOrder(-2),HorizontalGroup("资源路径列表",0.25f)]
            public string TargeFiletPath;
            [DraggableFloderPath, PropertyOrder(-2),HorizontalGroup("资源路径列表",0.25f)]
            public string SourceFilePath;
        }

这样生成出来的样式几乎跟floderpath一样,但是text区域可以支持拖拽,拷贝不同项目的文件更加方便。