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

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

csharp 复制代码
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并不支持项目外的文件夹拖拽,只能点按钮选择路径,为了更加方便的支持拖拽,我新增了一个属性拓展了它的功能,代码如下:

csharp 复制代码
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 = 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区域可以支持拖拽,拷贝不同项目的文件更加方便。

相关推荐
Z21-X1 小时前
云原生运维学习笔记:容器技术的演进、底层原理与 Docker 全生命周期管理
运维·笔记·学习·云原生
Decay__9 小时前
18_MySQL 智能巡检方案 —— 巡检项清单 / 一键巡检脚本 / 健康评分
运维·数据库·sql·mysql·架构
天远API14 小时前
零信任架构实战:基于天远运营商三要素详版V即时版构建自动化消费电子大促电商平台高价值权益秒杀与优惠券防羊毛高并发实名核验网关
运维·人工智能·架构·自动化
Android系统攻城狮14 小时前
Linux FFmpeg深度解析之avcodec_default_get_encode_buffer调用流程与实战(二十八)
linux·运维·服务器·ffmpeg·车载音视频·ffmpeg音视频
乐维_lwops15 小时前
案例解读:大型综合性科创产业园运维监控落地实践
运维·网络·人工智能·安全·it监控·国产运维智能体
番茄啊16 小时前
linux 开启xftp连接
linux·运维·服务器
IT利刃出鞘17 小时前
Docker Compose--解决修改配置后不生效的问题
运维·docker·容器
Lsetea17 小时前
Docker更新SSL证书后容器仍读旧文件:单文件挂载与目录挂载排查
运维·nginx·docker·https·ssl证书
Julien200418 小时前
管理机密(一)
运维·服务器·开发语言·学习方法
十碗饭吃不饱18 小时前
后端运维:网络联通、进程查询、Java服务启动脚本
java·运维·网络