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

相关推荐
舒一笑2 天前
程序员效率神器:一文掌握 tmux(服务器开发必备工具)
运维·后端·程序员
NineData2 天前
数据库管理工具NineData,一年进化成为数万+开发者的首选数据库工具?
运维·数据结构·数据库
梦想很大很大3 天前
拒绝“盲猜式”调优:在 Go Gin 项目中落地 OpenTelemetry 链路追踪
运维·后端·go
Sinclair3 天前
内网服务器离线安装 Nginx+PHP+MySQL 的方法
运维
叶落阁主3 天前
Tailscale 完全指南:从入门到私有 DERP 部署
运维·安全·远程工作
茶杯梦轩3 天前
从零起步学习RabbitMQ || 第二章:RabbitMQ 深入理解概念 Producer、Consumer、Exchange、Queue 与企业实战案例
服务器·后端·消息队列
甲鱼9294 天前
MySQL 实战手记:日志管理与主从复制搭建全指南
运维
YuMiao5 天前
gstatic连接问题导致Google Gemini / Studio页面乱码或图标缺失问题
服务器·网络协议
碳基沙盒6 天前
OpenClaw 多 Agent 配置实战指南
运维
Sinclair8 天前
简单几步,安卓手机秒变服务器,安装 CMS 程序
android·服务器