BITKit/Src/Core/Storage/ApplicationFile.cs

230 lines
5.3 KiB
C#

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Threading;
#if UNITY_WINDOW
using AnotherFileBrowser.Windows;
#endif
#if UNITY_5_3_OR_NEWER
using UnityEngine;
#endif
using Cysharp.Threading.Tasks;
namespace BITKit.IO
{
public interface IApplicationFile
{
string Extension { get; set; }
IStorageFile Current { get; }
event Func<(string, byte[])> DataHandle;
event Action<IStorageFile, IStorageFile> OnPathChanged;
void Save();
void SaveAs(string path=null);
void Load(IStorageFile file=null);
void Reload();
void AddListener(string key, Action<byte[]> action);
void RemoveListener(string key, Action<byte[]> action);
}
#if UNITY_WINDOW
[Serializable]
public sealed class ApplicationFile:IApplicationFile
{
private const string DefaultPath = nameof(ApplicationFile)+"."+nameof(DefaultPath);
#if UNITY_5_3_OR_NEWER
[UnityEngine.RuntimeInitializeOnLoadMethod]
private static void Reload()
{
Current = null;
DataHandle = null;
_genericEvent.Clear();
_OpenFileCancellationTokenSource = new();
}
#endif
public static IStorageFile Current
{
get => _current;
set
{
OnPathChanged?.Invoke(_current,value);
_current = value;
}
}
private static IStorageFile _current;
public static event Func<(string, byte[])> DataHandle;
public static event Action<IStorageFile, IStorageFile> OnPathChanged;
private static readonly GenericEvent _genericEvent = new();
private static CancellationTokenSource _OpenFileCancellationTokenSource = new();
private static string Extension { get; set; } = "zip";
private static BrowserProperties _browserProperties
{
get
{
var bp = new BrowserProperties();
#if UNITY_5_3_OR_NEWER
if (PlayerPrefs.HasKey(DefaultPath))
{
bp.initialDir = PlayerPrefs.GetString(DefaultPath);
}
#endif
if (string.IsNullOrEmpty(Extension) is false)
{
bp.filter = $"{Extension} files (*.{Extension})|*.{Extension}";
}
return bp;
}
}
public static void Save()
{
if (Current is null)
{
var bp = _browserProperties;
new Thread(() =>
{
new FileBrowser().SaveFileBrowser(bp, nameof(ApplicationFile), $".{Extension}", async path =>
{
await BITApp.SwitchToMainThread();
Current = new FileProvider(path);
Save();
});
}).Start();
BIT4Log.Log<IApplicationFile>($"无已加载的数据,等待选择保存地址");
return;
}
if (DataHandle is null)
{
BIT4Log.Log<IApplicationFile>("无任何可保存的数据");
}
List<IAsset> assets = new();
foreach (var func in DataHandle.CastAsFunc())
{
(string name,byte[] bytes) value = func.Invoke();
var asset = new BITAsset(value.name,value.bytes);
assets.Add(asset);
}
BITAssets.Build(Current.GetPath(),assets.ToArray());
BIT4Log.Log<IApplicationFile>($"已保存为:{Current.GetPath()}");
}
public static async void SaveAs(string path)
{
if (path is null)
{
var bp = _browserProperties;
new Thread(() =>
{
new FileBrowser().SaveFileBrowser(bp, nameof(ApplicationFile), $".{Extension}", async path =>
{
await BITApp.SwitchToMainThread();
Current = new FileProvider(path);
SaveAs(path);
});
}).Start();
return;
}
Current = new FileProvider(path);
Save();
}
public void AddListener(string key, Action<byte[]> action)
{
_genericEvent.AddListener<byte[]>(key,action);
}
public void RemoveListener(string key, Action<byte[]> action)
{
_genericEvent.RemoveListener<byte[]>(key,action);
}
public static void ReloadFile()
{
Load(Current);
}
public static void Load(IStorageFile file=null)
{
if (file is null)
{
_OpenFileCancellationTokenSource.Cancel();
_OpenFileCancellationTokenSource = new();
BIT4Log.Log<IApplicationFile>("正在选择文件,跳过该次载入");
var bp = _browserProperties;
new Thread(() =>
{
new FileBrowser().OpenFileBrowser(bp, Filepath);
return;
async void Filepath(string path)
{
await BITApp.SwitchToMainThread();
Current = new FileProvider(path);
Load(Current);
}
}).Start();
return;
}
Current = file;
var path = file.GetPath();
var header = BITAssets.ReadHeader(path);
foreach (var name in header.Files)
{
var asset = BITAssets.ReadAsset(path, name);
_genericEvent.Invoke(asset.Name,asset.Buffer);
}
BIT4Log.Log<IApplicationFile>($"已加载{header.Files.Count}个数据");
}
string IApplicationFile.Extension
{
get => Extension;
set => Extension = value;
}
IStorageFile IApplicationFile.Current => Current;
event Func<(string, byte[])> IApplicationFile.DataHandle
{
add => DataHandle += value;
remove => DataHandle -= value;
}
event Action<IStorageFile,IStorageFile> IApplicationFile.OnPathChanged
{
add => OnPathChanged += value;
remove=>OnPathChanged -= value;
}
void IApplicationFile.Save() => Save();
void IApplicationFile.SaveAs(string path) => SaveAs(path);
void IApplicationFile.Load(IStorageFile file) => Load(file);
void IApplicationFile.Reload()=>ReloadFile();
}
#endif
}