/// <summary> /// オブジェクトをユニークIDに変換 /// </summary> public static AssetUniqueID ConvertObjectToUniqueID(Object obj) { var assetPath = AssetDatabase.GetAssetPath(obj); var guid = AssetDatabase.AssetPathToGUID(assetPath); var result = new AssetUniqueID(guid); bool hasFileID; var linkerType = GetLinkerType(assetPath); switch (linkerType) { case GetLinkerTypeReturn.Home: case GetLinkerTypeReturn.MetaHome: case GetLinkerTypeReturn.Script: hasFileID = false; break; case GetLinkerTypeReturn.Importer: hasFileID = AssetDatabase.IsSubAsset(obj); break; default: hasFileID = true; break; } if (hasFileID) { var instanceID = obj.GetInstanceID(); var fileID = Unsupported.GetLocalIdentifierInFile(instanceID); result.fileID = fileID; } return(result); }
/// <summary> /// SpritePackingTagをユニークIDに変換 /// </summary> public static string ConvertUniqueIDToSpritePackingTag(AssetUniqueID uniqueID) { string result = null; if (IsSpritePackingTag(uniqueID)) { result = uniqueID.guid.Substring(spritePackingTagsPrefix.Length); } return(result); }
/// <summary> /// ユニークIDの梱包情報取得 /// </summary> public IncludeStateFlags GetIncludeStateFlags(AssetUniqueID uniqueID) { IncludeStateFlags result = 0; if (analyzeData.ContainsKey(uniqueID)) { result = analyzeData[uniqueID].state; } return(result); }
/// <summary> /// パスの梱包情報取得 /// </summary> public IncludeStateFlags GetIncludeStateFlags(string path) { IncludeStateFlags result = 0; if (pathToGuid.ContainsKey(path)) { var uniqueID = new AssetUniqueID(pathToGuid[path]); result = GetIncludeStateFlags(uniqueID); } return(result); }
/// <summary> /// スプライトパッキングユニークID確認 /// </summary> public static bool IsSpritePackingTag(AssetUniqueID uniqueID) { var result = false; if (!string.IsNullOrEmpty(uniqueID.guid)) { result = uniqueID.guid.StartsWith(spritePackingTagsPrefix); result = result && (uniqueID.fileID == 0); } return(result); }
/// <summary> /// アセットユニークID確認 /// </summary> public static bool IsAsset(AssetUniqueID uniqueID) { var result = false; if (!string.IsNullOrEmpty(uniqueID.guid)) { var match = guidMatchRegex.Match("guid: " + uniqueID.guid); result = match.Success; } return(result); }
/// <summary> /// 逆リンク取得 /// </summary> public List <AssetUniqueID> GetInboundLinks(string path) { List <AssetUniqueID> result = null; if (pathToGuid.ContainsKey(path)) { var guid = pathToGuid[path]; var uniqueID = new AssetUniqueID(guid); result = GetInboundLinks(uniqueID); } return(result); }
/// <summary> /// 残りを除外判定 /// </summary> private void ExcludeForLeftovers(ref float doneCount, float progressUnit) { foreach (var analyzePath in pathToGuid.Keys) { var analyzeUniqueID = new AssetUniqueID(pathToGuid[analyzePath]); var includeCount = 0; if (!analyzeData.ContainsKey(analyzeUniqueID) || analyzeData[analyzeUniqueID].state == 0) { var linkInfos = GetLinkUniqueIDsFromAssetPath(analyzePath); foreach (var linkInfo in linkInfos) { if (!analyzeData.ContainsKey(linkInfo.Key)) { analyzeData.Add(linkInfo.Key, new AssetInfo()); } var dat = analyzeData[linkInfo.Key]; IncludeStateFlags datState = 0; dat.linkInfo = linkInfo.Value; if (!string.IsNullOrEmpty(dat.spritePackingTag)) { var spritePackingTagUniqueID = ConvertSpritePackingTagToUniqueID(dat.spritePackingTag); if (!analyzeData.ContainsKey(spritePackingTagUniqueID)) { analyzeData.Add(spritePackingTagUniqueID, new AssetInfo(0, new List <AssetUniqueID>(), null)); } analyzeData[spritePackingTagUniqueID].links.Add(analyzeUniqueID); datState = analyzeData[spritePackingTagUniqueID].state; } if (datState == 0) { datState = IncludeStateFlags.NonInclude; } else { ++includeCount; } dat.state = datState; } var includeGuidState = IsIncludeReturn.False; if (0 < includeCount) { includeGuidState = ((linkInfos.Count == includeCount)? IsIncludeReturn.True: IsIncludeReturn.Ambiguous); } includeGuid.Add(analyzeUniqueID.guid, includeGuidState); ++doneCount; analyzeProgress = doneCount * progressUnit; } } }
/// <summary> /// fileIDの正規化 /// </summary> private void FileIDNormalize(ref float doneCount, float progressUnit) { foreach (var dat in analyzeData) { var assetInfo = dat.Value; if (assetInfo.links != null) { var uniqueID = dat.Key; var links = assetInfo.links; for (int i = 0, iMax = links.Count; i < iMax; ++i) { if ((links[i].fileID != 0) && !analyzeData.ContainsKey(links[i])) { var normalizedLink = new AssetUniqueID(links[i].guid); if ((uniqueID.guid == normalizedLink.guid) && (uniqueID.fileID == normalizedLink.fileID)) { links.RemoveAt(i); --i; --iMax; continue; } else if (analyzeData.ContainsKey(normalizedLink)) { links[i] = normalizedLink; } if (0 < i) { if ((links[i].guid == links[i - 1].guid) && (links[i].fileID == links[i - 1].fileID)) { links.RemoveAt(i); --i; --iMax; } } } } links.Sort((x, y) => { var compare = string.Compare(guidToPath[x.guid], guidToPath[y.guid]); if (compare == 0) { compare = x.fileID - y.fileID; } return(compare); }); } } ++doneCount; analyzeProgress = doneCount * progressUnit; }
/// <summary> /// パスからスプライトパッキングタグ取得 /// </summary> public string GetSpritePackingTag(AssetUniqueID uniqueID) { string result = null; if (!analyzing && analyzeData.ContainsKey(uniqueID) && (analyzeData[uniqueID].state != 0)) { result = analyzeData[uniqueID].spritePackingTag; } else if (uniqueID.fileID != 0) { uniqueID.fileID = 0; result = GetSpritePackingTag(uniqueID); } return(result); }
/// <summary> /// 逆リンク取得 /// </summary> public List <AssetUniqueID> GetInboundLinks(AssetUniqueID uniqueID) { List <AssetUniqueID> result = null; if (!analyzing && analyzeData.ContainsKey(uniqueID) && (analyzeData[uniqueID].state != 0)) { result = analyzeData[uniqueID].inboundLinks; } else if (uniqueID.fileID != 0) { uniqueID.fileID = 0; result = GetInboundLinks(uniqueID); } return(result); }
/// <summary> /// ユニークIDの梱包確認 /// </summary> public IsIncludeReturn IsInclude(AssetUniqueID uniqueID) { var result = IsIncludeReturn.Unknown; if (analyzeData.ContainsKey(uniqueID)) { var state = analyzeData[uniqueID].state; switch (state) { case 0: //empty. break; case IncludeStateFlags.NonInclude: result = IsIncludeReturn.False; break; default: result = IsIncludeReturn.True; break; } } return(result); }
/// <summary> /// アセットからリンクパスを取得 /// </summary> private Dictionary <AssetUniqueID, LinkInfo> GetLinkUniqueIDsFromAssetPath(string path) { var result = new Dictionary <AssetUniqueID, LinkInfo>(); List <string> text; var linkerType = GetLinkerType(path); switch (linkerType) { case GetLinkerTypeReturn.Home: case GetLinkerTypeReturn.Apartment: text = readTextFromAsset(path); break; case GetLinkerTypeReturn.MetaHome: case GetLinkerTypeReturn.MetaApartment: case GetLinkerTypeReturn.Importer: text = readTextFromAsset(path + ".meta"); break; case GetLinkerTypeReturn.Unknown: default: text = null; break; } if ((text == null) || (text.Count == 0)) { return(result); } var linkInfo = new LinkInfo(); var uniqueID = new AssetUniqueID(); if (pathToGuid.ContainsKey(path)) { uniqueID.guid = pathToGuid[path]; } foreach (var line in text) { //SubAsset確認 switch (linkerType) { case GetLinkerTypeReturn.Home: case GetLinkerTypeReturn.MetaHome: case GetLinkerTypeReturn.Importer: //empty. break; default: { var subAssetMatch = subAssetMatchRegex.Match(line); int fileID; if (subAssetMatch.Success && int.TryParse(subAssetMatch.Groups[1].Value, out fileID)) { if (uniqueID.fileID != fileID) { //サブアセット区切りなら //解析分を現サブアセットに反映 result.Add(uniqueID, linkInfo); //次サブアセットを新規作成 uniqueID.fileID = fileID; linkInfo.links = null; linkInfo.spritePackingTag = null; } } } break; } //リンクGUID列挙 do { var fileIDMatch = fileIDMatchRegex.Match(line); var guidMatch = guidMatchRegex.Match(line); if (fileIDMatch.Success) { int fileID = 0; int.TryParse(fileIDMatch.Groups[1].Value, out fileID); string guid; if (guidMatch.Success) { guid = guidMatch.Groups[1].Value; } else { guid = uniqueID.guid; } if (!guidToPath.ContainsKey(guid)) { break; } if ((uniqueID.guid != guid) || (uniqueID.fileID != fileID)) { if (linkInfo.links == null) { linkInfo.links = new List <AssetUniqueID>(); } var linkUniqueID = new AssetUniqueID(guid, fileID); linkInfo.links.Add(linkUniqueID); } } } while(false); //SpritePackingTag取得 if (linkerType == GetLinkerTypeReturn.Importer) { var match = spritePackingTagMatchRegex.Match(line); if (match.Success) { var spritePackingTag = match.Groups[1].Value; if (spritePackingTag[0] == '\'') { spritePackingTag = spritePackingTag.Substring(1, spritePackingTag.Length - 2).Replace("''", "'"); } linkInfo.spritePackingTag = spritePackingTag; } } } //Importer系LinkerのfileID解析 if (linkerType == GetLinkerTypeReturn.Importer) { var i = 0; var iMax = text.Count; while (i < iMax) { var line = text[i++]; var match = fileIDToRecycleNameRootMatchRegex.Match(line); if (match.Success) { break; } } while (i < iMax) { var line = text[i++]; var match = fileIDToRecycleNameNodeMatchRegex.Match(line); if (!match.Success) { break; } int fileID; if (int.TryParse(match.Groups[1].Value, out fileID)) { var nodeUniqueId = new AssetUniqueID(uniqueID.guid, fileID); var nodeLinkInfo = new LinkInfo() { links = new List <AssetUniqueID>() { uniqueID } }; //Importer系なら無条件で親を参照 result.Add(nodeUniqueId, nodeLinkInfo); } } } result.Add(uniqueID, linkInfo); //重複リンク削除 foreach (var key in result.Keys) { var links = result[key].links; if (links != null) { links.Sort((x, y) => { var compare = string.Compare(x.guid, y.guid); if (compare == 0) { compare = x.fileID - y.fileID; } return(compare); }); for (var i = links.Count - 2; 0 <= i; --i) { if ((links[i].guid == links[i + 1].guid) && (links[i].fileID == links[i + 1].fileID)) { links.RemoveAt(i + 1); } } } } return(result); }
/// <summary> /// アセット梱包判定 /// </summary> private void AnalyzeForAsset(ref float doneCount, float progressUnit) { var analyzeQueue = new Queue <AssetUniqueID>(); //信頼されたルートの検索 var trustedRootPaths = GetTrustedRootPaths(); foreach (var trustedRootPath in trustedRootPaths.Keys) { if (pathToGuid.ContainsKey(trustedRootPath)) { var trustedRootUniqueID = new AssetUniqueID(pathToGuid[trustedRootPath]); analyzeQueue.Enqueue(trustedRootUniqueID); } } while (0 < analyzeQueue.Count) { var analyzeUniqueID = analyzeQueue.Dequeue(); var analyzePath = guidToPath[analyzeUniqueID.guid]; var nonIncludeCount = 0; if (!analyzeData.ContainsKey(analyzeUniqueID) || (analyzeData[analyzeUniqueID].state == 0)) { var linkInfos = GetLinkUniqueIDsFromAssetPath(analyzePath); if (!linkInfos.ContainsKey(analyzeUniqueID)) { analyzeUniqueID.fileID = 0; } foreach (var linkInfo in linkInfos) { if (!analyzeData.ContainsKey(linkInfo.Key)) { analyzeData.Add(linkInfo.Key, new AssetInfo()); } var dat = analyzeData[linkInfo.Key]; dat.linkInfo = linkInfo.Value; if ((dat.links != null)) { foreach (var link in dat.links.Where(x => x.guid != analyzeUniqueID.guid)) { analyzeQueue.Enqueue(link); } } if (!string.IsNullOrEmpty(dat.spritePackingTag)) { var spritePackingTagUniqueID = ConvertSpritePackingTagToUniqueID(dat.spritePackingTag); if (!analyzeData.ContainsKey(spritePackingTagUniqueID)) { analyzeData.Add(spritePackingTagUniqueID, new AssetInfo(IncludeStateFlags.Link, new List <AssetUniqueID>(), null)); } analyzeData[spritePackingTagUniqueID].links.Add(analyzeUniqueID); } if (trustedRootPaths.ContainsKey(analyzePath)) { dat.state = trustedRootPaths[analyzePath]; } else { if (linkInfo.Key.fileID == analyzeUniqueID.fileID) { dat.state = IncludeStateFlags.Link; } else { dat.state = IncludeStateFlags.NonInclude; ++nonIncludeCount; } } if ((dat.state != IncludeStateFlags.NonInclude) && (dat.links != null)) { foreach (var link in dat.links) { if ((link.guid == analyzeUniqueID.guid) && linkInfos.ContainsKey(link)) { analyzeQueue.Enqueue(link); } } } } if (!includeGuid.ContainsKey(analyzeUniqueID.guid)) { includeGuid.Add(analyzeUniqueID.guid, ((0 < nonIncludeCount)? IsIncludeReturn.Ambiguous: IsIncludeReturn.True)); } else if ((nonIncludeCount == 0) && (includeGuid[analyzeUniqueID.guid] == IsIncludeReturn.Ambiguous)) { includeGuid[analyzeUniqueID.guid] = IsIncludeReturn.True; } ++doneCount; analyzeProgress = doneCount * progressUnit; } else if (analyzeData[analyzeUniqueID].state == IncludeStateFlags.NonInclude) { analyzeData[analyzeUniqueID].state = IncludeStateFlags.Link; if (analyzeData[analyzeUniqueID].links != null) { foreach (var d in analyzeData[analyzeUniqueID].links) { if (analyzeData.ContainsKey(d) && (analyzeData[d].state == IncludeStateFlags.NonInclude)) { analyzeQueue.Enqueue(d); } } } if (!analyzeData.Where(x => x.Key.guid == analyzeUniqueID.guid).Any(x => x.Value.state == IncludeStateFlags.NonInclude)) { includeGuid[analyzeUniqueID.guid] = IsIncludeReturn.True; } } } }
/// <summary> /// 逆リンク判定 /// </summary> private void AnalyzeForInboundLink(ref float doneCount, float progressUnit) { foreach (var dat in analyzeData) { if (IsSpritePackingTag(dat.Key)) { continue; } if (dat.Value.links != null) { #if SEARCH_TOOLS_DEBUG foreach (var link2 in dat.Value.links) { var link = link2; if (!analyzeData.ContainsKey(link)) { var l = new AssetUniqueID(link.guid); var noFileID = analyzeData.ContainsKey(l); Debug.Log(link + ":" + ((noFileID)? "O": "X") + ": " + guidToPath[link.guid]); if (!noFileID) { continue; } else { link = l; } } #else foreach (var link in dat.Value.links) { #endif var inboundLinkObject = analyzeData[link]; if (inboundLinkObject.inboundLinks != null) { inboundLinkObject.inboundLinks.Add(dat.Key); } else { inboundLinkObject.inboundLinks = new List <AssetUniqueID>() { dat.Key }; } } } } foreach (var assetInfo in analyzeData.Values) { if (assetInfo.inboundLinks != null) { assetInfo.inboundLinks.Sort((x, y) => { var compare = string.Compare(guidToPath[x.guid], guidToPath[y.guid]); if (compare == 0) { compare = x.fileID - y.fileID; } return(compare); }); } } ++doneCount; analyzeProgress = doneCount * progressUnit; } }