using System; using System.Collections.Generic; using UnityEngine; using ZXL; namespace ZXLA { public enum FileOperationType { Create, Rename, Move, Delete, } public enum FileObjectType { File, Directory } public class FileSystem : MonoBehaviour, IFileSystem { private SortedDictionary dic = new SortedDictionary(); public event Action OnCeateFile; public event Action OnCeateDirectory; public event Action OnFileSystemChanged; public void CreateFile(string path, int parentDepth) { dic.Add(path, new File(path, parentDepth + 1)); OnFileSystemChanged?.Invoke(new FileSystemOperation(FileObjectType.File, FileOperationType.Create, null, path, null, null)); } public bool FileExists(string path) { return dic.ContainsKey(path); } public void RenameFile(string path, string newName) { var fileSystemObject = TmpFile(path); DeleteFileInternal(path); var s = path.Split("/")[^1]; var replace = path.Replace(s, newName); dic.Add(replace, new File(replace, fileSystemObject.depth + 1, fileSystemObject.isDisplay)); OnFileSystemChanged?.Invoke(new FileSystemOperation(FileObjectType.File, FileOperationType.Rename, null, replace, null, null)); } public void MoveFile(string oldPath, string newPath) { var fileSystemObject = TmpFile(oldPath); DeleteFileInternal(oldPath); dic.Add(newPath, new File(newPath, fileSystemObject.depth + 1, fileSystemObject.isDisplay)); OnFileSystemChanged?.Invoke(new FileSystemOperation(FileObjectType.File, FileOperationType.Move, null, newPath, null, null)); } public void DeleteFile(string path) { DeleteFileInternal(path); OnFileSystemChanged?.Invoke(new FileSystemOperation(FileObjectType.File, FileOperationType.Delete, null, path, null, null)); } /// /// 缓存一下 /// FileSystemObject tmpFileSystemObject; FileSystemObject TmpFile(string path) { tmpFileSystemObject = new FileSystemObject(null, -1); tmpFileSystemObject.path = dic[path].path; tmpFileSystemObject.depth = dic[path].depth; tmpFileSystemObject.fileType = dic[path].fileType; tmpFileSystemObject.isDisplay = dic[path].isDisplay; return tmpFileSystemObject; } private void DeleteFileInternal(string path) { dic.Remove(path); } private List tmpFileSystemObjects; FileSystemObject TmpDirectory(string path) { tmpFileSystemObject = new FileSystemObject(null, -1); tmpFileSystemObject.path = dic[path].path; tmpFileSystemObject.depth = dic[path].depth; tmpFileSystemObject.fileType = dic[path].fileType; tmpFileSystemObject.isDisplay = dic[path].isDisplay; return tmpFileSystemObject; } List TmpDirectoryWithFiles(string path) { tmpFileSystemObjects ??= new List(); tmpFileSystemObjects.Clear(); var keys = dic.Keys.ToListPooled(); var indexOf = keys.IndexOf(path); for (int i = indexOf + 1; i < keys.Count; i++) { if (dic[keys[i]] is not File) break; var fileSystemObject = TmpFile(keys[i]); tmpFileSystemObjects.Add(fileSystemObject); DeleteFileInternal(keys[i]); } keys.Free(); return tmpFileSystemObjects; } public void CreateDirectory(string path, int parentDepth) { dic.Add(path, new Directory(path, parentDepth + 1)); OnFileSystemChanged?.Invoke(new FileSystemOperation(FileObjectType.Directory, FileOperationType.Create, null, path, null, null)); } public bool DirectoryExists(string path) { return dic.ContainsKey(path); } public void RenameDirectory(string path, string newName) { var s = path.Split("/")[^1]; var replace = path.Replace(s, newName); var fileSystemObject = TmpDirectory(path); dic.Remove(path); dic.Add(replace, fileSystemObject); OnFileSystemChanged?.Invoke(new FileSystemOperation(FileObjectType.Directory, FileOperationType.Rename, null, replace, null, null)); } public void MoveDirectory(string oldPath, string newPath) { var tmpDirectoryWithFiles = TmpDirectoryWithFiles(oldPath); DeleteDirectory(oldPath); var depth = dic[newPath].depth; foreach (var tmpDirectoryWithFile in tmpDirectoryWithFiles) { var replace = tmpDirectoryWithFile.path.Replace(oldPath, newPath); var tmp = new FileSystemObject(replace, depth + 1, tmpDirectoryWithFile.isDisplay); dic.Add(replace, tmp); } } public void DeleteDirectory(string path) { var keys = dic.Keys.ToListPooled(); var indexOf = keys.IndexOf(path); for (int i = indexOf + 1; i < keys.Count; i++) { if (dic[keys[i]] is not File) break; DeleteFileInternal(keys[i]); } keys.Free(); dic.Remove(path); OnFileSystemChanged?.Invoke(new FileSystemOperation(FileObjectType.Directory, FileOperationType.Delete, null, path, null, null)); } public IReadOnlyDictionary GetAllObjects() { return this.dic; } } }