Files
aibis-dream/Assets/Editor/TimelineNameCollector/TimelineNameCache.cs
T

186 lines
5.9 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;
using UnityEditor;
using UnityEngine;
namespace AibisDream.EditorTools
{
[Serializable]
public class TimelineNameCacheEntry
{
public string guid;
public string assetPath;
public string fileHash;
public string lastModified;
public string timelineName;
public string gameObjectPath;
public bool isInScene;
public int lineNumber;
}
[Serializable]
public class TimelineNameCache
{
public const int CurrentVersion = 1;
public int version = CurrentVersion;
public string lastFullScanTime;
public List<TimelineNameCacheEntry> entries = new List<TimelineNameCacheEntry>();
private static readonly string CacheFolderRelativePath = "Assets/Editor/TimelineNameCollector/Cache";
private static readonly string CacheFileName = "timeline_name_cache.json";
public static string CacheFolderFullPath =>
Path.Combine(Application.dataPath, "Editor/TimelineNameCollector/Cache");
public static string CacheFileFullPath =>
Path.Combine(CacheFolderFullPath, CacheFileName);
public static TimelineNameCache Load()
{
try
{
if (!File.Exists(CacheFileFullPath))
{
return new TimelineNameCache
{
version = CurrentVersion,
lastFullScanTime = null,
entries = new List<TimelineNameCacheEntry>()
};
}
var json = File.ReadAllText(CacheFileFullPath, Encoding.UTF8);
if (string.IsNullOrEmpty(json))
{
return new TimelineNameCache
{
version = CurrentVersion,
lastFullScanTime = null,
entries = new List<TimelineNameCacheEntry>()
};
}
var cache = JsonConvert.DeserializeObject<TimelineNameCache>(json);
if (cache == null)
{
cache = new TimelineNameCache();
}
if (cache.version != CurrentVersion)
{
cache.version = CurrentVersion;
cache.lastFullScanTime = null;
cache.entries = cache.entries ?? new List<TimelineNameCacheEntry>();
}
return cache;
}
catch (Exception e)
{
Debug.LogError($"[TimelineNameCache] Failed to load cache: {e}");
return new TimelineNameCache
{
version = CurrentVersion,
lastFullScanTime = null,
entries = new List<TimelineNameCacheEntry>()
};
}
}
public void Save()
{
try
{
if (!Directory.Exists(CacheFolderFullPath))
{
Directory.CreateDirectory(CacheFolderFullPath);
}
entries ??= new List<TimelineNameCacheEntry>();
var settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
StringEscapeHandling = StringEscapeHandling.Default
};
var json = JsonConvert.SerializeObject(this, settings);
File.WriteAllText(CacheFileFullPath, json, Encoding.UTF8);
}
catch (Exception e)
{
Debug.LogError($"[TimelineNameCache] Failed to save cache: {e}");
}
}
public void SetLastFullScanNow()
{
lastFullScanTime = DateTime.UtcNow.ToString("o");
}
public static string ComputeFileHash(string fullPath)
{
try
{
if (!File.Exists(fullPath))
{
return null;
}
using (var stream = File.OpenRead(fullPath))
using (var md5 = MD5.Create())
{
var hash = md5.ComputeHash(stream);
var sb = new StringBuilder(hash.Length * 2);
foreach (var b in hash)
{
sb.Append(b.ToString("x2"));
}
return sb.ToString();
}
}
catch (Exception e)
{
Debug.LogError($"[TimelineNameCache] Failed to compute file hash for '{fullPath}': {e}");
return null;
}
}
public static string GetAssetFullPath(string assetPath)
{
if (string.IsNullOrEmpty(assetPath))
return null;
if (!assetPath.StartsWith("Assets/", StringComparison.OrdinalIgnoreCase) &&
!assetPath.Equals("Assets", StringComparison.OrdinalIgnoreCase))
{
return null;
}
var relative = assetPath.Substring("Assets".Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
return Path.Combine(Application.dataPath, relative);
}
public void RemoveEntriesForAsset(string assetPath)
{
if (entries == null || string.IsNullOrEmpty(assetPath)) return;
entries.RemoveAll(e => e != null && e.assetPath == assetPath);
}
public void CleanupDeletedAssets()
{
if (entries == null) return;
entries.RemoveAll(e =>
{
if (e == null || string.IsNullOrEmpty(e.assetPath)) return true;
return AssetDatabase.LoadMainAssetAtPath(e.assetPath) == null;
});
}
}
}