-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathAssetDirectoryCache.cs
147 lines (119 loc) · 4.47 KB
/
AssetDirectoryCache.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// This file is part of the Prowl Game Engine
// Licensed under the MIT License. See the LICENSE file in the project root for details.
namespace Prowl.Editor.Assets;
public class AssetDirectoryCache(DirectoryInfo root)
{
public class DirNode(DirectoryInfo directory, DirNode parent)
{
public DirectoryInfo Directory = directory;
public DirNode Parent = parent;
public List<DirNode> SubDirectories = [];
public List<FileNode> Files = [];
public IEnumerable<FileNode> Search(string searchPattern, bool recursive = false)
{
foreach (FileNode file in Files)
{
if (file.File.Name.Contains(searchPattern, StringComparison.OrdinalIgnoreCase))
yield return file;
}
if (recursive)
{
foreach (DirNode subDir in SubDirectories)
{
foreach (FileNode file in subDir.Search(searchPattern, true))
yield return file;
}
}
}
}
public class FileNode
{
public FileInfo File;
public Guid AssetID;
public AssetDatabase.SubAssetCache[] SubAssets;
public FileNode(FileInfo file)
{
File = file;
AssetID = Guid.Empty;
SubAssets = [];
if (AssetDatabase.TryGetGuid(file, out var guid))
{
AssetID = guid;
SubAssets = AssetDatabase.GetSubAssetsCache(guid);
}
}
}
public DirNode RootNode => _rootNode;
public DirectoryInfo Root => _rootNode.Directory;
public string RootName => _rootNode.Directory.Name;
public string RootDirectoryPath => _rootNode.Directory.FullName;
private DirNode _rootNode;
private readonly DirectoryInfo _rootDir = root;
public bool PathToNode(string path, out DirNode node)
{
node = _rootNode;
if (!IsPathInsideDirectory(path, node.Directory, out var relativePath))
return false;
string[] pathParts = relativePath.Split(Path.DirectorySeparatorChar);
for (int i = 0; i < pathParts.Length; i++)
{
string part = pathParts[i];
if (string.IsNullOrEmpty(part))
continue;
DirNode nextNode = node.SubDirectories.Find(n =>
n.Directory.Name.Equals(part, StringComparison.OrdinalIgnoreCase));
if (nextNode is null)
return false;
node = nextNode;
}
return true;
}
static bool IsPathInsideDirectory(string path, DirectoryInfo directoryInfo, out string relativePath)
{
relativePath = string.Empty;
ArgumentException.ThrowIfNullOrEmpty(path, "Path cannot be null or empty.");
ArgumentNullException.ThrowIfNull(nameof(directoryInfo), "DirectoryInfo cannot be null.");
// Get the absolute paths
string directoryFullPath = Path.GetFullPath(directoryInfo.FullName);
string fullPath = Path.GetFullPath(path);
// Check if the fullPath starts with the directoryFullPath
bool result = fullPath.StartsWith(directoryFullPath, StringComparison.OrdinalIgnoreCase);
if (result) // Get the relative path
relativePath = fullPath.Substring(directoryFullPath.Length);
return result;
}
public void Refresh()
{
_rootNode = BuildDirectoryTree(_rootDir, null);
}
private DirNode BuildDirectoryTree(DirectoryInfo directory, DirNode parent)
{
DirNode node = new(directory, parent);
try
{
var directories = directory.GetDirectories();
foreach (DirectoryInfo subDirectory in directories)
{
if (!subDirectory.Exists)
continue;
DirNode subNode = BuildDirectoryTree(subDirectory, node);
node.SubDirectories.Add(subNode);
}
var files = directory.GetFiles();
foreach (FileInfo file in files)
{
if (!File.Exists(file.FullName))
continue;
// Ignore ".meta" files
if (file.Extension.Equals(".meta", StringComparison.OrdinalIgnoreCase))
continue;
node.Files.Add(new(file));
}
}
catch (Exception)
{
// Handle any exceptions that occur during directory traversal
}
return node;
}
}