异步更新

This commit is contained in:
2025-10-13 19:47:39 +08:00
parent 6271171ab4
commit 41d502b239
2 changed files with 103 additions and 87 deletions

View File

@@ -4,7 +4,6 @@ using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
@@ -58,24 +57,28 @@ namespace Convention
};
}
private string FullPath;
private string OriginPath;
private FileSystemInfo OriginInfo;
public ToolFile(string path)
{
FullPath = Path.GetFullPath(Environment.ExpandEnvironmentVariables(path));
OriginPath = Environment.ExpandEnvironmentVariables(path).Replace('\\', '/');
Refresh();
}
public override string ToString()
{
return this.FullPath;
return this.OriginPath;
}
#region Path
public static implicit operator string(ToolFile data) => data.FullPath;
public static implicit operator string(ToolFile data) => data.OriginPath;
public string GetAbsPath()
{
return Path.GetFullPath(OriginPath);
}
public string GetFullPath()
{
return this.FullPath;
return this.OriginPath;
}
public string GetName(bool is_ignore_extension = false)
{
@@ -86,13 +89,13 @@ namespace Convention
else if (OriginInfo is DirectoryInfo dinfo)
return dinfo.Name;
}
var result = this.FullPath[..(
(this.FullPath.Contains('.') && is_ignore_extension)
? this.FullPath.LastIndexOf('.')
var result = this.OriginPath[..(
(this.OriginPath.Contains('.') && is_ignore_extension)
? this.OriginPath.LastIndexOf('.')
: ^0
)]
[..(
(this.FullPath[^1] == '/' || this.FullPath[^1] == '\\')
(this.OriginPath[^1] == '/' || this.OriginPath[^1] == '\\')
? ^1
: ^0
)];
@@ -103,32 +106,32 @@ namespace Convention
{
if (IsDir())
return "";
return this.FullPath[(
(this.FullPath.Contains('.'))
? this.FullPath.LastIndexOf('.')
return this.OriginPath[(
(this.OriginPath.Contains('.'))
? this.OriginPath.LastIndexOf('.')
: ^0
)..];
}
public string GetFilename(bool is_without_extension = false)
{
if (is_without_extension && Path.HasExtension(FullPath))
if (is_without_extension && Path.HasExtension(OriginPath))
{
return Path.GetFileNameWithoutExtension(FullPath);
return Path.GetFileNameWithoutExtension(OriginPath);
}
else if (FullPath.EndsWith(Path.DirectorySeparatorChar.ToString()) || FullPath.EndsWith(Path.AltDirectorySeparatorChar.ToString()))
else if (OriginPath.EndsWith(Path.DirectorySeparatorChar.ToString()) || OriginPath.EndsWith(Path.AltDirectorySeparatorChar.ToString()))
{
return Path.GetFileName(FullPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
return Path.GetFileName(OriginPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
}
else
{
return Path.GetFileName(FullPath);
return Path.GetFileName(OriginPath);
}
}
public string GetDir()
{
return Path.GetDirectoryName(FullPath);
return Path.GetDirectoryName(OriginPath);
}
public ToolFile GetDirToolFile()
@@ -138,7 +141,7 @@ namespace Convention
public string GetCurrentDirName()
{
return Path.GetDirectoryName(FullPath);
return Path.GetDirectoryName(OriginPath);
}
public ToolFile GetParentDir()
@@ -150,7 +153,7 @@ namespace Convention
#region Exists
public bool Exists() => File.Exists(FullPath) || Directory.Exists(FullPath);
public bool Exists() => File.Exists(OriginPath) || Directory.Exists(OriginPath);
public static implicit operator bool(ToolFile file) => file.Exists();
@@ -162,13 +165,13 @@ namespace Convention
OriginInfo = null;
else if (IsDir())
{
OriginInfo = new DirectoryInfo(FullPath);
FullPath = Path.GetFullPath(FullPath);
OriginInfo = new DirectoryInfo(OriginPath);
OriginPath = Path.GetFullPath(OriginPath);
}
else
{
OriginInfo = new FileInfo(FullPath);
FullPath = Path.GetFullPath(FullPath);
OriginInfo = new FileInfo(OriginPath);
OriginPath = Path.GetFullPath(OriginPath);
}
return this;
}
@@ -181,7 +184,7 @@ namespace Convention
}
public T LoadAsJson<T>(string key = "data")
{
return ES3.Load<T>(key, FullPath);
return ES3.Load<T>(key, OriginPath);
}
public string LoadAsText()
{
@@ -217,7 +220,7 @@ namespace Convention
if (IsFile() == false)
throw new InvalidOperationException("Target is not a file");
var lines = File.ReadAllLines(FullPath);
var lines = File.ReadAllLines(OriginPath);
var result = new List<string[]>();
foreach (var line in lines)
@@ -244,11 +247,11 @@ namespace Convention
public Texture2D LoadAsImage()
{
return ES3Plugin.LoadImage(FullPath);
return ES3Plugin.LoadImage(OriginPath);
}
public IEnumerator LoadAsImage([In] Action<Texture2D> callback)
{
UnityWebRequest request = UnityWebRequestTexture.GetTexture(FullPath);
UnityWebRequest request = UnityWebRequestTexture.GetTexture(OriginPath);
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
@@ -259,11 +262,11 @@ namespace Convention
}
public AudioClip LoadAsAudio()
{
return ES3Plugin.LoadAudio(FullPath, GetAudioType(FullPath));
return ES3Plugin.LoadAudio(OriginPath, GetAudioType(OriginPath));
}
public IEnumerator LoadAsAudio([In] Action<AudioClip> callback)
{
UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(FullPath, GetAudioType(FullPath));
UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(OriginPath, GetAudioType(OriginPath));
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
@@ -274,18 +277,18 @@ namespace Convention
}
public AssetBundle LoadAsAssetBundle()
{
return AssetBundle.LoadFromFile(FullPath);
return AssetBundle.LoadFromFile(OriginPath);
}
public IEnumerator LoadAsAssetBundle([In] Action<AssetBundle> callback)
{
AssetBundleCreateRequest result = AssetBundle.LoadFromFileAsync(FullPath);
AssetBundleCreateRequest result = AssetBundle.LoadFromFileAsync(OriginPath);
yield return result;
callback(result.assetBundle);
yield return null;
}
public IEnumerator LoadAsAssetBundle([In]Action<float> progress, [In] Action<AssetBundle> callback)
{
AssetBundleCreateRequest result = AssetBundle.LoadFromFileAsync(FullPath);
AssetBundleCreateRequest result = AssetBundle.LoadFromFileAsync(OriginPath);
while (result.isDone == false)
{
progress(result.progress);
@@ -311,11 +314,11 @@ namespace Convention
}
public void SaveAsJson<T>(T data, string key = "data")
{
ES3.Save(key, data,FullPath);
ES3.Save(key, data,OriginPath);
}
public void SaveAsText(string data)
{
using var fs = new FileStream(FullPath, FileMode.CreateNew, FileAccess.Write);
using var fs = new FileStream(OriginPath, FileMode.CreateNew, FileAccess.Write);
using var sw = new StreamWriter(fs);
sw.Write(data);
sw.Flush();
@@ -337,7 +340,7 @@ namespace Convention
public void SaveAsBinary(byte[] data)
{
SaveDataAsBinary(FullPath, data, (OriginInfo as FileInfo).OpenWrite());
SaveDataAsBinary(OriginPath, data, (OriginInfo as FileInfo).OpenWrite());
}
public void SaveAsCsv(List<string[]> csvData)
@@ -346,7 +349,7 @@ namespace Convention
throw new InvalidOperationException("Target is not a file");
var lines = csvData.Select(row => string.Join(",", row));
File.WriteAllLines(FullPath, lines);
File.WriteAllLines(OriginPath, lines);
}
public void SaveAsXml(string xmlData)
@@ -380,9 +383,9 @@ namespace Convention
{
if (Exists())
{
return Directory.Exists(this.FullPath);
return Directory.Exists(this.OriginPath);
}
return this.FullPath[^1] == '\\' || this.FullPath[^1] == '/';
return this.OriginPath[^1] == '\\' || this.OriginPath[^1] == '/';
}
public bool IsFile()
@@ -420,7 +423,7 @@ namespace Convention
{
if (IsDir())
{
return GetDirectorySize(FullPath);
return GetDirectorySize(OriginPath);
}
else
{
@@ -458,6 +461,20 @@ namespace Convention
#region Operator
public static ToolFile operator |(ToolFile left, string rightPath)
{
if (rightPath == null)
{
return new ToolFile(left.IsDir() ? left.GetFullPath() : $"{left.GetFullPath().Replace('\\', '/')}/");
}
string first = left.GetFullPath().Replace('\\','/');
string second = rightPath.Replace('\\', '/');
if (first == "./")
return new ToolFile(second);
else if (first == "../")
return new ToolFile($"{new ToolFile(left.GetAbsPath()).GetParentDir()}/{second}");
return new ToolFile($"{first}/{second}");
}
public static ToolFile operator |(ToolFile left, ToolFile rightPath)
{
string lp = left.GetFullPath();
return new ToolFile(Path.Combine(lp, rightPath));
@@ -467,19 +484,19 @@ namespace Convention
{
if (obj is ToolFile other)
{
return Path.GetFullPath(FullPath).Equals(Path.GetFullPath(other.FullPath), StringComparison.OrdinalIgnoreCase);
return Path.GetFullPath(OriginPath).Equals(Path.GetFullPath(other.OriginPath), StringComparison.OrdinalIgnoreCase);
}
return false;
}
public override int GetHashCode()
{
return Path.GetFullPath(FullPath).GetHashCode();
return Path.GetFullPath(OriginPath).GetHashCode();
}
public ToolFile Open(string path)
{
this.FullPath = path;
this.OriginPath = path;
Refresh();
return this;
}
@@ -492,9 +509,9 @@ namespace Convention
if (Exists() == false)
{
if (IsDir())
Directory.CreateDirectory(this.FullPath);
Directory.CreateDirectory(this.OriginPath);
else
File.Create(this.FullPath).Close();
File.Create(this.OriginPath).Close();
Refresh();
}
return this;
@@ -511,7 +528,7 @@ namespace Convention
var file = OriginInfo as FileInfo;
file.MoveTo(newPath);
}
FullPath = newPath;
OriginPath = newPath;
return this;
}
public ToolFile Move(string path)
@@ -537,7 +554,7 @@ namespace Convention
public ToolFile Copy(string targetPath = null)
{
if (targetPath == null)
return new ToolFile(FullPath);
return new ToolFile(OriginPath);
if (!Exists())
throw new FileNotFoundException("File not found");
@@ -547,9 +564,9 @@ namespace Convention
targetFile = targetFile | GetFilename();
if (IsDir())
CopyDirectory(FullPath, targetFile.GetFullPath());
CopyDirectory(OriginPath, targetFile.GetFullPath());
else
File.Copy(FullPath, targetFile.GetFullPath());
File.Copy(OriginPath, targetFile.GetFullPath());
return targetFile;
}
@@ -575,9 +592,9 @@ namespace Convention
public ToolFile Delete()
{
if (IsDir())
Directory.Delete(FullPath);
Directory.Delete(OriginPath);
else
File.Delete(FullPath);
File.Delete(OriginPath);
return this;
}
@@ -598,7 +615,7 @@ namespace Convention
}
public ToolFile TryCreateParentPath()
{
string dirPath = Path.GetDirectoryName(FullPath);
string dirPath = Path.GetDirectoryName(OriginPath);
if (!string.IsNullOrEmpty(dirPath) && !Directory.Exists(dirPath))
{
Directory.CreateDirectory(dirPath);
@@ -609,14 +626,14 @@ namespace Convention
{
if (!IsDir())
throw new InvalidOperationException("Target is not a directory");
return Directory.GetFileSystemEntries(FullPath).ToList();
return Directory.GetFileSystemEntries(OriginPath).ToList();
}
public List<ToolFile> DirToolFileIter()
{
if (!IsDir())
throw new InvalidOperationException("Target is not a directory");
var result = new List<ToolFile>();
foreach (var entry in Directory.GetFileSystemEntries(FullPath))
foreach (var entry in Directory.GetFileSystemEntries(OriginPath))
{
result.Add(new ToolFile(entry));
}
@@ -624,7 +641,7 @@ namespace Convention
}
public ToolFile BackToParentDir()
{
FullPath = GetDir();
OriginPath = GetDir();
Refresh();
return this;
}
@@ -633,7 +650,7 @@ namespace Convention
if (!IsDir())
throw new InvalidOperationException("Target is not a directory");
var entries = Directory.GetFileSystemEntries(FullPath);
var entries = Directory.GetFileSystemEntries(OriginPath);
if (ignore_folder)
{
return entries.Count(entry => File.Exists(entry));
@@ -740,13 +757,13 @@ namespace Convention
{
if (IsDir())
{
ZipFile.CreateFromDirectory(FullPath, outputPath);
ZipFile.CreateFromDirectory(OriginPath, outputPath);
}
else
{
using (var archive = ZipFile.Open(outputPath, ZipArchiveMode.Create))
{
archive.CreateEntryFromFile(FullPath, GetFilename());
archive.CreateEntryFromFile(OriginPath, GetFilename());
}
}
}
@@ -778,7 +795,7 @@ namespace Convention
try
{
ZipFile.ExtractToDirectory(FullPath, outputPath);
ZipFile.ExtractToDirectory(OriginPath, outputPath);
return new ToolFile(outputPath);
}
catch (Exception ex)
@@ -897,7 +914,7 @@ namespace Convention
try
{
using (var hashAlgorithm = GetHashAlgorithm(algorithm))
using (var stream = File.OpenRead(FullPath))
using (var stream = File.OpenRead(OriginPath))
{
byte[] hash = hashAlgorithm.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLower();
@@ -955,7 +972,7 @@ namespace Convention
// 注意:这是一个简化实现,实际的文件监控需要更复杂的实现
// 可以使用 FileSystemWatcher 来实现完整功能
var watcher = new FileSystemWatcher(FullPath)
var watcher = new FileSystemWatcher(OriginPath)
{
IncludeSubdirectories = recursive,
EnableRaisingEvents = true
@@ -1087,7 +1104,7 @@ namespace Convention
try
{
var fileInfo = new FileInfo(FullPath);
var fileInfo = new FileInfo(OriginPath);
var attributes = fileInfo.Attributes;
permissions["read"] = true; // 如果能获取到文件信息,说明可读
@@ -1114,7 +1131,7 @@ namespace Convention
try
{
var fileInfo = new FileInfo(FullPath);
var fileInfo = new FileInfo(OriginPath);
var attributes = fileInfo.Attributes;
if (write.HasValue)

View File

@@ -262,30 +262,29 @@ namespace Convention
public IEnumerator LoadAsAssetBundle(Action<float> progress, Action<AssetBundle> onSuccess, Action<string> onError = null)
{
yield return LoadAsBinaryAsync(
progress,
data =>
AssetBundleCreateRequest request = null;
yield return LoadAsBinaryAsync(x => progress(x * 0.5f), data => request = AssetBundle.LoadFromMemoryAsync(data), onError);
while (request.isDone == false)
{
progress(0.5f + request.progress * 0.5f);
}
try
{
AssetBundle bundle = request.assetBundle;
if (bundle != null)
{
try
{
AssetBundle bundle = AssetBundle.LoadFromMemory(data);
if (bundle != null)
{
cachedData = bundle;
onSuccess?.Invoke(bundle);
}
else
{
onError?.Invoke($"Failed to load AssetBundle from data.");
}
}
catch (Exception e)
{
onError?.Invoke($"Failed to load AssetBundle: {e.Message}");
}
},
onError
);
cachedData = bundle;
onSuccess?.Invoke(bundle);
}
else
{
onError?.Invoke($"Failed to load AssetBundle from data.");
}
}
catch (Exception e)
{
onError?.Invoke($"Failed to load AssetBundle: {e.Message}");
}
}
#endregion