Files
DefendNJ/Assets/Plugins/ThirdParty/FindReference2/Editor/Script/FR2_Asset.cs
2025-09-04 14:31:28 +08:00

1653 lines
53 KiB
C#

using System.Globalization;
//#define FR2_DEBUG_BRACE_LEVEL
//#define FR2_DEBUG_SYMBOL
//#define FR2_DEBUG
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
#if FR2_ADDRESSABLE
using UnityEditor.AddressableAssets;
using UnityEngine.AddressableAssets;
#endif
using UnityObject = UnityEngine.Object;
namespace vietlabs.fr2
{
public enum FR2_AssetType
{
UNKNOWN,
FOLDER,
SCRIPT,
SCENE,
DLL,
REFERENCABLE,
BINARY_ASSET,
MODEL,
TERRAIN,
NON_READABLE
}
public enum FR2_AssetState
{
NEW,
CACHE,
MISSING
}
[Serializable]
public class FR2_Asset
{
// ------------------------------ CONSTANTS ---------------------------
private static readonly HashSet<string> SCRIPT_EXTENSIONS = new HashSet<string>
{
".cs", ".js", ".boo", ".h", ".java", ".cpp", ".m", ".mm"
};
private static readonly HashSet<string> REFERENCABLE_EXTENSIONS = new HashSet<string>
{
".anim", ".controller", ".mat", ".unity", ".guiskin", ".prefab",
".overridecontroller", ".mask", ".rendertexture", ".cubemap", ".flare",
".mat", ".prefab", ".physicsmaterial", ".fontsettings", ".asset", ".prefs", ".spriteatlas"
};
private static readonly Dictionary<int, Type> HashClasses = new Dictionary<int, Type>();
internal static Dictionary<string, GUIContent> cacheImage = new Dictionary<string, GUIContent>();
private bool _isExcluded;
private Dictionary<string, HashSet<int>> _UseGUIDs;
private float excludeTS;
public static float ignoreTS;
// ----------------------------- DRAW ---------------------------------------
[NonSerialized] private GUIContent fileSizeText;
// ----------------------------- DRAW ---------------------------------------
[SerializeField] public string guid;
// easy to recalculate: will not cache
[NonSerialized] private bool m_pathLoaded;
[NonSerialized] private string m_assetFolder;
[NonSerialized] private string m_assetName;
[NonSerialized] private string m_assetPath;
[NonSerialized] private string m_extension;
[NonSerialized] private bool m_inEditor;
[NonSerialized] private bool m_inPlugins;
[NonSerialized] private bool m_inResources;
[NonSerialized] private bool m_inStreamingAsset;
[NonSerialized] private bool m_isAssetFile;
// Need to read FileInfo: soft-cache (always re-read when needed)
[SerializeField] public FR2_AssetType type;
[SerializeField] private string m_fileInfoHash;
[SerializeField] private string m_assetbundle;
[SerializeField] private string m_addressable;
[SerializeField] private string m_atlas;
[SerializeField] private long m_fileSize;
[SerializeField] private int m_assetChangeTS; // Realtime when asset changed (trigger by import asset operation)
[SerializeField] private int m_fileInfoReadTS; // Realtime when asset being read
[SerializeField] private int m_fileWriteTS; // file's lastModification (file content + meta)
[SerializeField] private int m_cachefileWriteTS; // file's lastModification at the time the content being read
[SerializeField] internal int refreshStamp; // use to check if asset has been deleted (refreshStamp not updated)
// Do not cache
[NonSerialized] internal FR2_AssetState state;
internal Dictionary<string, FR2_Asset> UsedByMap = new Dictionary<string, FR2_Asset>();
internal HashSet<int> HashUsedByClassesIds = new HashSet<int>();
[SerializeField] private List<Classes> UseGUIDsList = new List<Classes>();
public FR2_Asset(string guid)
{
this.guid = guid;
type = FR2_AssetType.UNKNOWN;
}
// ----------------------- PATH INFO ------------------------
public void LoadPathInfo()
{
if (m_pathLoaded) return;
m_pathLoaded = true;
m_assetPath = AssetDatabase.GUIDToAssetPath(guid);
if (string.IsNullOrEmpty(assetPath))
{
state = FR2_AssetState.MISSING;
return;
}
#if FR2_DEBUG
Debug.LogWarning("Refreshing ... " + loadInfoTS + ":" + AssetDatabase.GUIDToAssetPath(guid));
if (!m_assetPath.StartsWith("Assets"))
{
Debug.Log("LoadAssetInfo: " + m_assetPath);
}
#endif
FR2_Unity.SplitPath(m_assetPath, out m_assetName, out m_extension, out m_assetFolder);
if (m_assetFolder.StartsWith("Assets/"))
{
m_assetFolder = m_assetFolder.Substring(7);
}
else if (!FR2_Unity.StringStartsWith(m_assetPath, "Packages/", "Project Settings/", "Library/"))
{
m_assetFolder = "built-in/";
}
m_inEditor = m_assetPath.Contains("/Editor/") || m_assetPath.Contains("/Editor Default Resources/");
m_inResources = m_assetPath.Contains("/Resources/");
m_inStreamingAsset = m_assetPath.Contains("/StreamingAssets/");
m_inPlugins = m_assetPath.Contains("/Plugins/");
m_isAssetFile = m_assetPath.EndsWith(".asset", StringComparison.Ordinal);
}
public string assetName
{
get
{
LoadPathInfo();
return m_assetName;
}
}
public string assetPath
{
get
{
if (!string.IsNullOrEmpty(m_assetPath)) return m_assetPath;
m_assetPath = AssetDatabase.GUIDToAssetPath(guid);
if (string.IsNullOrEmpty(m_assetPath))
{
state = FR2_AssetState.MISSING;
}
return m_assetPath;
}
}
public string parentFolderPath { get { LoadPathInfo(); return m_assetFolder; } }
public string assetFolder { get { LoadPathInfo(); return m_assetFolder; } }
public string extension { get { LoadPathInfo(); return m_extension; } }
public bool inEditor { get { LoadPathInfo(); return m_inEditor; } }
public bool inPlugins { get { LoadPathInfo(); return m_inPlugins; } }
public bool inResources { get { LoadPathInfo(); return m_inResources; } }
public bool inStreamingAsset { get { LoadPathInfo(); return m_inStreamingAsset; } }
// ----------------------- TYPE INFO ------------------------
internal bool IsFolder { get { return type == FR2_AssetType.FOLDER; } }
internal bool IsScript { get { return type == FR2_AssetType.SCRIPT; } }
internal bool IsMissing { get { return state == FR2_AssetState.MISSING; } }
internal bool IsReferencable
{
get
{
return type == FR2_AssetType.REFERENCABLE ||
type == FR2_AssetType.SCENE;
}
}
internal bool IsBinaryAsset
{
get
{
return type == FR2_AssetType.BINARY_ASSET ||
type == FR2_AssetType.MODEL ||
type == FR2_AssetType.TERRAIN;
}
}
// ----------------------- PATH INFO ------------------------
public bool fileInfoDirty { get { return (type == FR2_AssetType.UNKNOWN) || (m_fileInfoReadTS <= m_assetChangeTS); } }
public bool fileContentDirty { get { return m_fileWriteTS != m_cachefileWriteTS; } }
public bool isDirty
{
get { return fileInfoDirty || fileContentDirty; }
}
bool ExistOnDisk()
{
if (IsMissing) return false; // asset not exist - no need to check FileSystem!
if (type == FR2_AssetType.FOLDER || type == FR2_AssetType.UNKNOWN)
{
if (Directory.Exists(m_assetPath))
{
if (type == FR2_AssetType.UNKNOWN) type = FR2_AssetType.FOLDER;
return true;
}
if (type == FR2_AssetType.FOLDER) return false;
}
// must be file here
if (!File.Exists(m_assetPath)) return false;
if (type == FR2_AssetType.UNKNOWN) GuessAssetType();
return true;
}
internal void LoadFileInfo()
{
if (!fileInfoDirty) return;
if (string.IsNullOrEmpty(m_assetPath)) LoadPathInfo(); // always reload Path Info
//Debug.Log("--> Read: " + assetPath + " --> " + m_fileInfoReadTS + "<" + m_assetChangeTS);
m_fileInfoReadTS = FR2_Unity.Epoch(DateTime.Now);
if (IsMissing)
{
Debug.LogWarning("Should never be here! - missing files can not trigger LoadFileInfo()");
return;
}
if (!ExistOnDisk())
{
state = FR2_AssetState.MISSING;
return;
}
if (type == FR2_AssetType.FOLDER) return; // nothing to read
var assetType = AssetDatabase.GetMainAssetTypeAtPath(m_assetPath);
if (assetType == typeof(FR2_Cache)) return;
var info = new FileInfo(m_assetPath);
m_fileSize = info.Length;
m_fileInfoHash = info.Length + info.Extension;
m_addressable = FR2_Unity.GetAddressable(guid);
//if (!string.IsNullOrEmpty(m_addressable)) Debug.LogWarning(guid + " --> " + m_addressable);
m_assetbundle = AssetDatabase.GetImplicitAssetBundleName(m_assetPath);
if (assetType == typeof(Texture2D))
{
var importer = AssetImporter.GetAtPath(m_assetPath);
if (importer is TextureImporter)
{
var tImporter = importer as TextureImporter;
if (tImporter.qualifiesForSpritePacking)
{
m_atlas = tImporter.spritePackingTag;
}
}
}
// check if file content changed
var metaInfo = new FileInfo(m_assetPath + ".meta");
var assetTime = FR2_Unity.Epoch(info.LastWriteTime);
var metaTime = FR2_Unity.Epoch(metaInfo.LastWriteTime);
// update fileChangeTimeStamp
m_fileWriteTS = Mathf.Max(metaTime, assetTime);
}
internal string fileInfoHash { get { LoadFileInfo(); return m_fileInfoHash; } }
internal long fileSize { get { LoadFileInfo(); return m_fileSize; } }
public string AtlasName { get { LoadFileInfo(); return m_atlas; } }
public string AssetBundleName { get { LoadFileInfo(); return m_assetbundle; } }
public string AddressableName { get { LoadFileInfo(); return m_addressable; } }
public Dictionary<string, HashSet<int>> UseGUIDs
{
get
{
if (_UseGUIDs != null)
{
return _UseGUIDs;
}
_UseGUIDs = new Dictionary<string, HashSet<int>>(UseGUIDsList.Count);
for (var i = 0; i < UseGUIDsList.Count; i++)
{
string guid = UseGUIDsList[i].guid;
if (_UseGUIDs.ContainsKey(guid))
{
for (var j = 0; j < UseGUIDsList[i].ids.Count; j++)
{
int val = UseGUIDsList[i].ids[j];
if (_UseGUIDs[guid].Contains(val))
{
continue;
}
_UseGUIDs[guid].Add(UseGUIDsList[i].ids[j]);
}
}
else
{
_UseGUIDs.Add(guid, new HashSet<int>(UseGUIDsList[i].ids));
}
}
return _UseGUIDs;
}
}
// ------------------------------- GETTERS -----------------------------
internal bool IsExcluded
{
get
{
if (excludeTS >= ignoreTS)
{
return _isExcluded;
}
excludeTS = ignoreTS;
_isExcluded = false;
HashSet<string> h = FR2_Setting.IgnoreAsset;
foreach (string item in FR2_Setting.IgnoreAsset)
{
if (m_assetPath.StartsWith(item, false, CultureInfo.InvariantCulture))
{
_isExcluded = true;
break;
}
}
return _isExcluded;
}
}
public void AddUsedBy(string guid, FR2_Asset asset)
{
if (UsedByMap.ContainsKey(guid))
{
return;
}
if (guid == this.guid)
{
//Debug.LogWarning("self used");
return;
}
UsedByMap.Add(guid, asset);
HashSet<int> output;
if (HashUsedByClassesIds == null)
{
HashUsedByClassesIds = new HashSet<int>();
}
if (asset.UseGUIDs.TryGetValue(this.guid, out output))
{
foreach (int item in output)
{
HashUsedByClassesIds.Add(item);
}
}
// int classId = HashUseByClassesIds
}
public int UsageCount()
{
return UsedByMap.Count;
}
public override string ToString()
{
return string.Format("FR2_Asset[{0}]", m_assetName);
}
//--------------------------------- STATIC ----------------------------
internal static bool IsValidGUID(string guid)
{
return AssetDatabase.GUIDToAssetPath(guid) != FR2_Cache.CachePath; // just skip FR2_Cache asset
}
internal void MarkAsDirty(bool isMoved = true, bool force = false)
{
if (isMoved)
{
var newPath = AssetDatabase.GUIDToAssetPath(guid);
if (newPath != m_assetPath)
{
m_pathLoaded = false;
m_assetPath = newPath;
}
}
state = FR2_AssetState.CACHE;
m_assetChangeTS = FR2_Unity.Epoch(DateTime.Now); // re-read FileInfo
if (force) m_cachefileWriteTS = 0;
}
// --------------------------------- APIs ------------------------------
internal void GuessAssetType()
{
if (SCRIPT_EXTENSIONS.Contains(m_extension))
{
type = FR2_AssetType.SCRIPT;
}
else if (REFERENCABLE_EXTENSIONS.Contains(m_extension))
{
bool isUnity = m_extension == ".unity";
type = isUnity ? FR2_AssetType.SCENE : FR2_AssetType.REFERENCABLE;
if (m_extension == ".asset" || isUnity || m_extension == ".spriteatlas")
{
var buffer = new byte[5];
FileStream stream = null;
try
{
stream = File.OpenRead(m_assetPath);
stream.Read(buffer, 0, 5);
stream.Close();
}
#if FR2_DEBUG
catch (Exception e)
{
Debug.LogWarning("Guess Asset Type error :: " + e + "\n" + m_assetPath);
#else
catch
{
#endif
if (stream != null) stream.Close();
state = FR2_AssetState.MISSING;
return;
}
finally
{
if (stream != null) stream.Close();
}
string str = string.Empty;
foreach (byte t in buffer)
{
str += (char)t;
}
if (str != "%YAML")
{
type = FR2_AssetType.BINARY_ASSET;
}
}
}
else if (m_extension == ".fbx")
{
type = FR2_AssetType.MODEL;
}
else if (m_extension == ".dll")
{
type = FR2_AssetType.DLL;
}
else
{
type = FR2_AssetType.NON_READABLE;
}
}
internal void LoadContent()
{
if (!fileContentDirty) return;
m_cachefileWriteTS = m_fileWriteTS;
if (IsMissing || type == FR2_AssetType.NON_READABLE)
{
return;
}
if (type == FR2_AssetType.DLL)
{
#if FR2_DEBUG
Debug.LogWarning("Parsing DLL not yet supportted ");
#endif
return;
}
if (!ExistOnDisk())
{
state = FR2_AssetState.MISSING;
return;
}
ClearUseGUIDs();
if (IsFolder)
{
LoadFolder();
}
else if (IsReferencable)
{
LoadYAML2();
}
else if (IsBinaryAsset)
{
LoadBinaryAsset();
}
}
internal void AddUseGUID(string fguid, int fFileId = -1, bool checkExist = true)
{
// if (checkExist && UseGUIDs.ContainsKey(fguid)) return;
if (!IsValidGUID(fguid))
{
return;
}
if (!UseGUIDs.ContainsKey(fguid))
{
UseGUIDsList.Add(new Classes
{
guid = fguid,
ids = new List<int>()
});
UseGUIDs.Add(fguid, new HashSet<int>());
}
if (fFileId != -1)
{
if (UseGUIDs[fguid].Contains(fFileId))
{
return;
}
UseGUIDs[fguid].Add(fFileId);
Classes i = UseGUIDsList.FirstOrDefault(x => x.guid == fguid);
if (i != null)
{
i.ids.Add(fFileId);
}
}
}
// ----------------------------- STATIC ---------------------------------------
internal static int SortByExtension(FR2_Asset a1, FR2_Asset a2)
{
if (a1 == null)
{
return -1;
}
if (a2 == null)
{
return 1;
}
int result = string.Compare(a1.m_extension, a2.m_extension, StringComparison.Ordinal);
return result == 0 ? string.Compare(a1.m_assetName, a2.m_assetName, StringComparison.Ordinal) : result;
}
internal static List<FR2_Asset> FindUsage(FR2_Asset asset)
{
if (asset == null)
{
return null;
}
List<FR2_Asset> refs = FR2_Cache.Api.FindAssets(asset.UseGUIDs.Keys.ToArray(), true);
return refs;
}
internal static List<FR2_Asset> FindUsedBy(FR2_Asset asset)
{
return asset.UsedByMap.Values.ToList();
}
internal static List<string> FindUsageGUIDs(FR2_Asset asset, bool includeScriptSymbols)
{
var result = new HashSet<string>();
if (asset == null)
{
Debug.LogWarning("Asset invalid : " + asset.m_assetName);
return result.ToList();
}
// for (var i = 0;i < asset.UseGUIDs.Count; i++)
// {
// result.Add(asset.UseGUIDs[i]);
// }
foreach (KeyValuePair<string, HashSet<int>> item in asset.UseGUIDs)
{
result.Add(item.Key);
}
//if (!includeScriptSymbols) return result.ToList();
//if (asset.ScriptUsage != null)
//{
// for (var i = 0; i < asset.ScriptUsage.Count; i++)
// {
// var symbolList = FR2_Cache.Api.FindAllSymbol(asset.ScriptUsage[i]);
// if (symbolList.Contains(asset)) continue;
// var symbol = symbolList[0];
// if (symbol == null || result.Contains(symbol.guid)) continue;
// result.Add(symbol.guid);
// }
//}
return result.ToList();
}
internal static List<string> FindUsedByGUIDs(FR2_Asset asset)
{
return asset.UsedByMap.Keys.ToList();
}
internal float Draw(Rect r,
bool highlight,
bool drawPath = true,
bool showFileSize = true,
bool showABName = false,
bool showAtlasName = false,
bool showUsageIcon = true,
IWindow window = null
)
{
bool singleLine = r.height <= 18f;
float rw = r.width;
bool selected = FR2_Bookmark.Contains(guid);
r.height = 16f;
bool hasMouse = Event.current.type == EventType.MouseUp && r.Contains(Event.current.mousePosition);
if (hasMouse && Event.current.button == 1)
{
var menu = new GenericMenu();
if (m_extension == ".prefab")
{
menu.AddItem(new GUIContent("Edit in Scene"), false, EditPrefab);
}
menu.AddItem(new GUIContent("Open"), false, Open);
menu.AddItem(new GUIContent("Ping"), false, Ping);
menu.AddItem(new GUIContent(guid), false, CopyGUID);
//menu.AddItem(new GUIContent("Reload"), false, Reload);
menu.AddSeparator(string.Empty);
menu.AddItem(new GUIContent("Bookmark"), selected, AddToSelection);
menu.AddSeparator(string.Empty);
menu.AddItem(new GUIContent("Copy path"), false, CopyAssetPath);
menu.AddItem(new GUIContent("Copy full path"), false, CopyAssetPathFull);
//if (IsScript)
//{
// menu.AddSeparator(string.Empty);
// AddArray(menu, ScriptSymbols, "+ ", "Definitions", "No Definition", false);
// menu.AddSeparator(string.Empty);
// AddArray(menu, ScriptUsage, "-> ", "Depends", "No Dependency", true);
//}
menu.ShowAsContext();
Event.current.Use();
}
if (IsMissing)
{
if (!singleLine)
{
r.y += 16f;
}
if (Event.current.type != EventType.Repaint)
{
return 0;
}
GUI.Label(r, "(missing) " + guid, EditorStyles.whiteBoldLabel);
return 0;
}
Rect iconRect = GUI2.LeftRect(16f, ref r);
if (Event.current.type == EventType.Repaint)
{
Texture icon = AssetDatabase.GetCachedIcon(m_assetPath);
if (icon != null)
{
GUI.DrawTexture(iconRect, icon);
}
}
if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
{
Rect pingRect = FR2_Setting.PingRow ? new Rect(0, r.y, r.x + r.width, r.height) : iconRect;
if (pingRect.Contains(Event.current.mousePosition))
{
if (Event.current.control || Event.current.command)
{
if (selected)
{
RemoveFromSelection();
}
else
{
AddToSelection();
}
if (window != null)
{
window.Repaint();
}
}
else
{
Ping();
}
//Event.current.Use();
}
}
if (Event.current.type != EventType.Repaint)
{
return 0;
}
if (UsedByMap != null && UsedByMap.Count > 0)
{
var str = new GUIContent(UsedByMap.Count.ToString());
Rect countRect = iconRect;
countRect.x -= 16f;
countRect.xMin = -10f;
GUI.Label(countRect, str, GUI2.miniLabelAlignRight);
}
float pathW = drawPath ? EditorStyles.miniLabel.CalcSize(new GUIContent(m_assetFolder)).x : 0;
float nameW = EditorStyles.boldLabel.CalcSize(new GUIContent(m_assetName)).x;
Color cc = FR2_Cache.Api.setting.SelectedColor;
if (singleLine)
{
Rect lbRect = GUI2.LeftRect(pathW + nameW, ref r);
if (selected)
{
Color c1 = GUI.color;
GUI.color = cc;
GUI.DrawTexture(lbRect, EditorGUIUtility.whiteTexture);
GUI.color = c1;
}
if (drawPath)
{
Color c2 = GUI.color;
GUI.color = new Color(c2.r, c2.g, c2.b, c2.a * 0.5f);
GUI.Label(GUI2.LeftRect(pathW, ref lbRect), m_assetFolder, EditorStyles.miniLabel);
GUI.color = c2;
lbRect.xMin -= 4f;
GUI.Label(lbRect, m_assetName, EditorStyles.boldLabel);
}
else
{
GUI.Label(lbRect, m_assetName);
}
}
else
{
if (drawPath)
{
GUI.Label(new Rect(r.x, r.y + 16f, r.width, r.height), m_assetFolder, EditorStyles.miniLabel);
}
Rect lbRect = GUI2.LeftRect(nameW, ref r);
if (selected)
{
GUI2.Rect(lbRect, cc);
}
GUI.Label(lbRect, m_assetName, EditorStyles.boldLabel);
}
var rr = GUI2.RightRect(10f, ref r); //margin
if (highlight)
{
rr.xMin += 2f;
rr.width = 1f;
GUI2.Rect(rr, GUI2.darkGreen);
}
Color c = GUI.color;
GUI.color = new Color(c.r, c.g, c.b, c.a * 0.5f);
if (showFileSize)
{
Rect fsRect = GUI2.RightRect(40f, ref r); // filesize label
if (fileSizeText == null)
{
fileSizeText = new GUIContent(FR2_Helper.GetfileSizeString(fileSize));
}
GUI.Label(fsRect, fileSizeText, GUI2.miniLabelAlignRight);
}
if (!string.IsNullOrEmpty(m_addressable))
{
Rect adRect = GUI2.RightRect(100f, ref r);
GUI.Label(adRect, m_addressable, GUI2.miniLabelAlignRight);
}
if (showUsageIcon && HashUsedByClassesIds != null)
{
foreach (int item in HashUsedByClassesIds)
{
if (!FR2_Unity.HashClassesNormal.ContainsKey(item))
{
continue;
}
string name = FR2_Unity.HashClassesNormal[item];
Type t = null;
if (!HashClasses.TryGetValue(item, out t))
{
t = FR2_Unity.GetType(name);
HashClasses.Add(item, t);
}
GUIContent content = null;
var isExisted = cacheImage.TryGetValue(name, out content);
if (content == null) content = new GUIContent(EditorGUIUtility.ObjectContent(null, t).image, name);
if (!isExisted)
{
cacheImage.Add(name, content);
}
else
{
cacheImage[name] = content;
}
if (content != null)
{
try
{
GUI.Label(GUI2.RightRect(15f, ref r), content, GUI2.miniLabelAlignRight);
}
#if !FR2_DEBUG
catch { }
#else
catch (Exception e)
{
UnityEngine.Debug.LogWarning(e);
}
#endif
}
}
}
if (showAtlasName)
{
GUI2.RightRect(10f, ref r); //margin
Rect abRect = GUI2.RightRect(120f, ref r); // filesize label
if (!string.IsNullOrEmpty(m_atlas))
{
GUI.Label(abRect, m_atlas, GUI2.miniLabelAlignRight);
}
}
if (showABName)
{
GUI2.RightRect(10f, ref r); //margin
Rect abRect = GUI2.RightRect(100f, ref r); // filesize label
if (!string.IsNullOrEmpty(m_assetbundle))
{
GUI.Label(abRect, m_assetbundle, GUI2.miniLabelAlignRight);
}
}
if (true)
{
GUI2.RightRect(10f, ref r); //margin
Rect abRect = GUI2.RightRect(100f, ref r); // filesize label
if (!string.IsNullOrEmpty(m_addressable))
{
GUI.Label(abRect, m_addressable, GUI2.miniLabelAlignRight);
}
}
GUI.color = c;
if (Event.current.type == EventType.Repaint)
{
return rw < pathW + nameW ? 32f : 18f;
}
return r.height;
}
internal GenericMenu AddArray(GenericMenu menu, List<string> list, string prefix, string title,
string emptyTitle, bool showAsset, int max = 10)
{
//if (list.Count > 0)
//{
// if (list.Count > max)
// {
// prefix = string.Format("{0} _{1}/", title, list.Count) + prefix;
// }
// //for (var i = 0; i < list.Count; i++)
// //{
// // var def = list[i];
// // var suffix = showAsset ? "/" + FR2_Cache.Api.FindSymbol(def).assetName : string.Empty;
// // menu.AddItem(new GUIContent(prefix + def + suffix), false, () => OpenScript(def));
// //}
//}
//else
{
menu.AddItem(new GUIContent(emptyTitle), true, null);
}
return menu;
}
internal void CopyGUID()
{
EditorGUIUtility.systemCopyBuffer = guid;
Debug.Log(guid);
}
internal void CopyName()
{
EditorGUIUtility.systemCopyBuffer = m_assetName;
Debug.Log(m_assetName);
}
internal void CopyAssetPath()
{
EditorGUIUtility.systemCopyBuffer = m_assetPath;
Debug.Log(m_assetPath);
}
internal void CopyAssetPathFull()
{
string fullName = new FileInfo(m_assetPath).FullName;
EditorGUIUtility.systemCopyBuffer = fullName;
Debug.Log(fullName);
}
internal void AddToSelection()
{
if (!FR2_Bookmark.Contains(guid))
{
FR2_Bookmark.Add(guid);
}
//var list = Selection.objects.ToList();
//var obj = FR2_Unity.LoadAssetAtPath<Object>(assetPath);
//if (!list.Contains(obj))
//{
// list.Add(obj);
// Selection.objects = list.ToArray();
//}
}
internal void RemoveFromSelection()
{
if (FR2_Bookmark.Contains(guid))
{
FR2_Bookmark.Remove(guid);
}
}
internal void Ping()
{
EditorGUIUtility.PingObject(
AssetDatabase.LoadAssetAtPath(m_assetPath, typeof(UnityObject))
);
}
internal void Open()
{
AssetDatabase.OpenAsset(
AssetDatabase.LoadAssetAtPath(m_assetPath, typeof(UnityObject))
);
}
internal void EditPrefab()
{
UnityObject prefab = AssetDatabase.LoadAssetAtPath(m_assetPath, typeof(UnityObject));
UnityObject.Instantiate(prefab);
}
//internal void OpenScript(string definition)
//{
// var asset = FR2_Cache.Api.FindSymbol(definition);
// if (asset == null) return;
// EditorGUIUtility.PingObject(
// AssetDatabase.LoadAssetAtPath(asset.assetPath, typeof(Object))
// );
//}
// ----------------------------- SERIALIZED UTILS ---------------------------------------
// ----------------------------- LOAD ASSETS ---------------------------------------
internal void LoadGameObject(GameObject go)
{
Component[] compList = go.GetComponentsInChildren<Component>();
for (var i = 0; i < compList.Length; i++)
{
LoadSerialized(compList[i]);
}
}
internal void LoadSerialized(UnityObject target)
{
SerializedProperty[] props = FR2_Unity.xGetSerializedProperties(target, true);
for (var i = 0; i < props.Length; i++)
{
if (props[i].propertyType != SerializedPropertyType.ObjectReference)
{
continue;
}
UnityObject refObj = props[i].objectReferenceValue;
if (refObj == null)
{
continue;
}
string refGUID = AssetDatabase.AssetPathToGUID(
AssetDatabase.GetAssetPath(refObj)
);
//Debug.Log("Found Reference BinaryAsset <" + assetPath + "> : " + refGUID + ":" + refObj);
AddUseGUID(refGUID);
}
}
internal void LoadTerrainData(TerrainData terrain)
{
#if UNITY_2018_3_OR_NEWER
TerrainLayer[] arr0 = terrain.terrainLayers;
for (var i = 0; i < arr0.Length; i++)
{
string aPath = AssetDatabase.GetAssetPath(arr0[i]);
string refGUID = AssetDatabase.AssetPathToGUID(aPath);
AddUseGUID(refGUID);
}
#endif
DetailPrototype[] arr = terrain.detailPrototypes;
for (var i = 0; i < arr.Length; i++)
{
string aPath = AssetDatabase.GetAssetPath(arr[i].prototypeTexture);
string refGUID = AssetDatabase.AssetPathToGUID(aPath);
AddUseGUID(refGUID);
}
TreePrototype[] arr2 = terrain.treePrototypes;
for (var i = 0; i < arr2.Length; i++)
{
string aPath = AssetDatabase.GetAssetPath(arr2[i].prefab);
string refGUID = AssetDatabase.AssetPathToGUID(aPath);
AddUseGUID(refGUID);
}
FR2_Unity.TerrainTextureData[] arr3 = FR2_Unity.GetTerrainTextureDatas(terrain);
for (var i = 0; i < arr3.Length; i++)
{
FR2_Unity.TerrainTextureData texs = arr3[i];
for (var k = 0; k < texs.textures.Length; k++)
{
Texture2D tex = texs.textures[k];
if (tex == null)
{
continue;
}
string aPath = AssetDatabase.GetAssetPath(tex);
if (string.IsNullOrEmpty(aPath))
{
continue;
}
string refGUID = AssetDatabase.AssetPathToGUID(aPath);
if (string.IsNullOrEmpty(refGUID))
{
continue;
}
AddUseGUID(refGUID);
}
}
}
private void ClearUseGUIDs()
{
#if FR2_DEBUG
Debug.Log("ClearUseGUIDs: " + assetPath);
#endif
UseGUIDs.Clear();
UseGUIDsList.Clear();
}
static int binaryLoaded;
internal void LoadBinaryAsset()
{
ClearUseGUIDs();
UnityObject assetData = AssetDatabase.LoadAssetAtPath(m_assetPath, typeof(UnityObject));
if (assetData is GameObject)
{
type = FR2_AssetType.MODEL;
LoadGameObject(assetData as GameObject);
}
else if (assetData is TerrainData)
{
type = FR2_AssetType.TERRAIN;
LoadTerrainData(assetData as TerrainData);
}
else
{
LoadSerialized(assetData);
}
#if FR2_DEBUG
Debug.Log("LoadBinaryAsset :: " + assetData + ":" + type);
#endif
assetData = null;
if (binaryLoaded++ <= 30) return;
binaryLoaded = 0;
FR2_Unity.UnloadUnusedAssets();
}
internal void LoadYAML()
{
if (!File.Exists(m_assetPath))
{
state = FR2_AssetState.MISSING;
return;
}
if (m_isAssetFile)
{
var s = AssetDatabase.LoadAssetAtPath<FR2_Cache>(m_assetPath);
if (s != null)
{
return;
}
}
string text = string.Empty;
try
{
text = File.ReadAllText(m_assetPath);
}
#if FR2_DEBUG
catch (Exception e)
{
Debug.LogWarning("Guess Asset Type error :: " + e + "\n" + assetPath);
#else
catch
{
#endif
state = FR2_AssetState.MISSING;
return;
}
#if FR2_DEBUG
Debug.Log("LoadYAML: " + assetPath);
#endif
//if(assetPath.Contains("Myriad Pro - Bold SDF"))
//{
// Debug.Log("no ne");
//}
// PERFORMANCE HOG!
// var matches = Regex.Matches(text, @"\bguid: [a-f0-9]{32}\b");
MatchCollection matches = Regex.Matches(text, @".*guid: [a-f0-9]{32}.*\n");
foreach (Match match in matches)
{
Match guidMatch = Regex.Match(match.Value, @"\bguid: [a-f0-9]{32}\b");
string refGUID = guidMatch.Value.Replace("guid: ", string.Empty);
Match fileIdMatch = Regex.Match(match.Value, @"\bfileID: ([0-9]*).*");
int id = -1;
try
{
id = int.Parse(fileIdMatch.Groups[1].Value) / 100000;
}
catch { }
AddUseGUID(refGUID, id);
}
//var idx = text.IndexOf("guid: ");
//var counter=0;
//while (idx != -1)
//{
// var guid = text.Substring(idx + 6, 32);
// if (UseGUIDs.Contains(guid)) continue;
// AddUseGUID(guid);
// idx += 39;
// if (idx > text.Length-40) break;
// //Debug.Log(assetName + ":" + guid);
// idx = text.IndexOf("guid: ", idx + 39);
// if (counter++ > 100) break;
//}
//if (counter > 100){
// Debug.LogWarning("Never finish on " + assetName);
//}
}
internal void LoadYAML2()
{
if (!File.Exists(m_assetPath))
{
state = FR2_AssetState.MISSING;
return;
}
if (m_assetPath == "ProjectSettings/EditorBuildSettings.asset")
{
var listScenes = EditorBuildSettings.scenes;
foreach (var scene in listScenes)
{
if (!scene.enabled) continue;
var path = scene.path;
var guid = AssetDatabase.AssetPathToGUID(path);
AddUseGUID(guid, 0);
#if FR2_DEBUG
Debug.Log("AddScene: " + path);
#endif
}
}
// var text = string.Empty;
try
{
using (var sr = new StreamReader(m_assetPath))
{
while (sr.Peek() >= 0)
{
string line = sr.ReadLine();
int index = line.IndexOf("guid: ");
if (index < 0)
{
continue;
}
string refGUID = line.Substring(index + 6, 32);
int indexFileId = line.IndexOf("fileID: ");
int fileID = -1;
if (indexFileId >= 0)
{
indexFileId += 8;
string fileIDStr =
line.Substring(indexFileId, line.IndexOf(',', indexFileId) - indexFileId);
try
{
fileID = int.Parse(fileIDStr) / 100000;
}
catch { }
}
AddUseGUID(refGUID, fileID);
}
}
#if FR2_DEBUG
if (UseGUIDsList.Count > 0)
{
Debug.Log(assetPath + ":" + UseGUIDsList.Count);
}
#endif
}
#if FR2_DEBUG
catch (Exception e)
{
Debug.LogWarning("Guess Asset Type error :: " + e + "\n" + assetPath);
#else
catch
{
#endif
state = FR2_AssetState.MISSING;
}
}
internal void LoadFolder()
{
if (!Directory.Exists(m_assetPath))
{
state = FR2_AssetState.MISSING;
return;
}
// do not analyse folders outside project
if (!m_assetPath.StartsWith("Assets/")) return;
try
{
string[] files = Directory.GetFiles(m_assetPath);
string[] dirs = Directory.GetDirectories(m_assetPath);
foreach (string f in files)
{
if (f.EndsWith(".meta", StringComparison.Ordinal))
{
continue;
}
string fguid = AssetDatabase.AssetPathToGUID(f);
if (string.IsNullOrEmpty(fguid))
{
continue;
}
// AddUseGUID(fguid, true);
AddUseGUID(fguid);
}
foreach (string d in dirs)
{
string fguid = AssetDatabase.AssetPathToGUID(d);
if (string.IsNullOrEmpty(fguid))
{
continue;
}
// AddUseGUID(fguid, true);
AddUseGUID(fguid);
}
}
#if FR2_DEBUG
catch (Exception e)
{
Debug.LogWarning("LoadFolder() error :: " + e + "\n" + assetPath);
#else
catch
{
#endif
state = FR2_AssetState.MISSING;
}
//Debug.Log("Load Folder :: " + assetName + ":" + type + ":" + UseGUIDs.Count);
}
// ----------------------------- REPLACE GUIDS ---------------------------------------
internal bool ReplaceReference(string fromGUID, string toGUID, TerrainData terrain = null)
{
if (IsMissing)
{
return false;
}
if (IsReferencable)
{
string text = string.Empty;
if (!File.Exists(m_assetPath))
{
state = FR2_AssetState.MISSING;
return false;
}
try
{
text = File.ReadAllText(m_assetPath).Replace("\r", "\n");
File.WriteAllText(m_assetPath, text.Replace(fromGUID, toGUID));
// AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.Default);
return true;
}
catch (Exception e)
{
state = FR2_AssetState.MISSING;
//#if FR2_DEBUG
Debug.LogWarning("Replace Reference error :: " + e + "\n" + m_assetPath);
//#endif
}
return false;
}
if (type == FR2_AssetType.TERRAIN)
{
var fromObj = FR2_Unity.LoadAssetWithGUID<UnityObject>(fromGUID);
var toObj = FR2_Unity.LoadAssetWithGUID<UnityObject>(toGUID);
var found = 0;
// var terrain = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Object)) as TerrainData;
if (fromObj is Texture2D)
{
DetailPrototype[] arr = terrain.detailPrototypes;
for (var i = 0; i < arr.Length; i++)
{
if (arr[i].prototypeTexture == (Texture2D)fromObj)
{
found++;
arr[i].prototypeTexture = (Texture2D)toObj;
}
}
terrain.detailPrototypes = arr;
FR2_Unity.ReplaceTerrainTextureDatas(terrain, (Texture2D)fromObj, (Texture2D)toObj);
}
if (fromObj is GameObject)
{
TreePrototype[] arr2 = terrain.treePrototypes;
for (var i = 0; i < arr2.Length; i++)
{
if (arr2[i].prefab == (GameObject)fromObj)
{
found++;
arr2[i].prefab = (GameObject)toObj;
}
}
terrain.treePrototypes = arr2;
}
// EditorUtility.SetDirty(terrain);
// AssetDatabase.SaveAssets();
fromObj = null;
toObj = null;
terrain = null;
// FR2_Unity.UnloadUnusedAssets();
return found > 0;
}
Debug.LogWarning("Something wrong, should never be here - Ignored <" + m_assetPath +
"> : not a readable type, can not replace ! " + type);
return false;
}
internal bool ReplaceReference(string fromGUID, string toGUID, long toFileId, TerrainData terrain = null)
{
// Debug.Log("ReplaceReference: from " + fromGUID + " to: " + toGUID + " toFileId: " + toFileId);
if (IsMissing)
{
// Debug.Log("this asset is missing");
return false;
}
if (IsReferencable)
{
if (!File.Exists(m_assetPath))
{
state = FR2_AssetState.MISSING;
// Debug.Log("this asset not exits");
return false;
}
try
{
var sb = new StringBuilder();
string text = File.ReadAllText(assetPath).Replace("\r", "\n");
var lines = text.Split('\n');
//string result = "";
for (int i = 0; i < lines.Length; i++)
{
var line = lines[i];
if (line.IndexOf(fromGUID, StringComparison.Ordinal) >= 0)
{
if (toFileId > 0)
{
const string FileID = "fileID: ";
var index = line.IndexOf(FileID, StringComparison.Ordinal);
if (index >= 0)
{
var fromFileId = line.Substring(index + FileID.Length, line.IndexOf(',', index) - (index + FileID.Length));
long fileType = 0;
if (!long.TryParse(fromFileId, out fileType))
{
Debug.LogWarning("cannot parse file");
return false;
}
if (fileType.ToString().Substring(0, 3) != toFileId.ToString().Substring(0, 3))
{
//difference file type
Debug.LogWarning("Difference file type");
return false;
}
Debug.Log("ReplaceReference: fromFileId " + fromFileId + " to File Id " + toFileId);
line = line.Replace(fromFileId, toFileId.ToString());
}
}
line = line.Replace(fromGUID, toGUID);
}
sb.Append(line);
sb.AppendLine();
//result += line + "\n";
}
//File.WriteAllText(assetPath, result.Trim());
File.WriteAllText(assetPath, sb.ToString());
//AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.Default);
return true;
}
catch (Exception e)
{
state = FR2_AssetState.MISSING;
//#if FR2_DEBUG
Debug.LogWarning("Replace Reference error :: " + e + "\n" + m_assetPath);
//#endif
}
return false;
}
if (type == FR2_AssetType.TERRAIN)
{
var fromObj = FR2_Unity.LoadAssetWithGUID<UnityObject>(fromGUID);
var toObj = FR2_Unity.LoadAssetWithGUID<UnityObject>(toGUID);
var found = 0;
// var terrain = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Object)) as TerrainData;
if (fromObj is Texture2D)
{
DetailPrototype[] arr = terrain.detailPrototypes;
for (var i = 0; i < arr.Length; i++)
{
if (arr[i].prototypeTexture == (Texture2D)fromObj)
{
found++;
arr[i].prototypeTexture = (Texture2D)toObj;
}
}
terrain.detailPrototypes = arr;
FR2_Unity.ReplaceTerrainTextureDatas(terrain, (Texture2D)fromObj, (Texture2D)toObj);
}
if (fromObj is GameObject)
{
TreePrototype[] arr2 = terrain.treePrototypes;
for (var i = 0; i < arr2.Length; i++)
{
if (arr2[i].prefab == (GameObject)fromObj)
{
found++;
arr2[i].prefab = (GameObject)toObj;
}
}
terrain.treePrototypes = arr2;
}
// EditorUtility.SetDirty(terrain);
// AssetDatabase.SaveAssets();
// FR2_Unity.UnloadUnusedAssets();
return found > 0;
}
Debug.LogWarning("Something wrong, should never be here - Ignored <" + m_assetPath +
"> : not a readable type, can not replace ! " + type);
return false;
}
[Serializable]
private class Classes
{
public string guid;
public List<int> ids;
}
}
}