forked from BilalY/Rasagar
276 lines
9.1 KiB
C#
276 lines
9.1 KiB
C#
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using UnityEngine;
|
||
|
using System.IO;
|
||
|
|
||
|
namespace UnityEditor.Formats.Fbx.Exporter
|
||
|
{
|
||
|
internal class RepairMissingScripts
|
||
|
{
|
||
|
private const string ForumPackageGUID = "2d81c55c4d9d85146b1d2de96e084b63";
|
||
|
private const string AssetStorePackageGUID = "628ffbda3fdf4df4588770785d91a698";
|
||
|
|
||
|
private const string FbxPrefabDLLFileId = "69888640";
|
||
|
|
||
|
private const string IdFormat = "{{fileID: {0}, guid: {1}, type:";
|
||
|
|
||
|
private static List<string> s_searchIDsToReplace;
|
||
|
private static List<string> SearchIDsToReplace
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (s_searchIDsToReplace == null || s_searchIDsToReplace.Count <= 0)
|
||
|
{
|
||
|
s_searchIDsToReplace = new List<string>()
|
||
|
{
|
||
|
string.Format(IdFormat, FbxPrefabDLLFileId, ForumPackageGUID),
|
||
|
string.Format(IdFormat, FbxPrefabDLLFileId, AssetStorePackageGUID)
|
||
|
};
|
||
|
}
|
||
|
return s_searchIDsToReplace;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private string[] m_assetsToRepair;
|
||
|
private string[] AssetsToRepair
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (m_assetsToRepair == null)
|
||
|
{
|
||
|
m_assetsToRepair = FindAssetsToRepair();
|
||
|
}
|
||
|
return m_assetsToRepair;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static string SourceCodeSearchID
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
var fbxPrefabObj = AssetDatabase.LoadMainAssetAtPath(FindFbxPrefabAssetPath());
|
||
|
string searchID = null;
|
||
|
string guid;
|
||
|
long fileId;
|
||
|
if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(fbxPrefabObj, out guid, out fileId))
|
||
|
{
|
||
|
searchID = string.Format(IdFormat, fileId, guid);
|
||
|
}
|
||
|
return searchID;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if COM_UNITY_FORMATS_FBX_AS_ASSET
|
||
|
public const string FbxPrefabFile = "/UnityFbxPrefab.dll";
|
||
|
#else
|
||
|
public const string FbxPrefabFile = "Packages/com.unity.formats.fbx/Runtime/FbxPrefab.cs";
|
||
|
#endif
|
||
|
public static string FindFbxPrefabAssetPath()
|
||
|
{
|
||
|
#if COM_UNITY_FORMATS_FBX_AS_ASSET
|
||
|
// Find guids that are scripts that look like FbxPrefab.
|
||
|
// That catches FbxPrefabTest too, so we have to make sure.
|
||
|
var allGuids = AssetDatabase.FindAssets("FbxPrefab t:MonoScript");
|
||
|
string foundPath = "";
|
||
|
foreach (var guid in allGuids)
|
||
|
{
|
||
|
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||
|
if (path.EndsWith(FbxPrefabFile))
|
||
|
{
|
||
|
if (!string.IsNullOrEmpty(foundPath))
|
||
|
{
|
||
|
// How did this happen? Anyway, just don't try.
|
||
|
Debug.LogWarning(string.Format("{0} found in multiple places; did you forget to delete one of these?\n{1}\n{2}",
|
||
|
FbxPrefabFile.Substring(1), foundPath, path));
|
||
|
return "";
|
||
|
}
|
||
|
foundPath = path;
|
||
|
}
|
||
|
}
|
||
|
if (string.IsNullOrEmpty(foundPath))
|
||
|
{
|
||
|
Debug.LogWarning(string.Format("{0} not found; are you trying to uninstall {1}?", FbxPrefabFile.Substring(1), ModelExporter.PACKAGE_UI_NAME));
|
||
|
}
|
||
|
return foundPath;
|
||
|
#else
|
||
|
// In Unity 2018.1 and 2018.2.0b7, FindAssets can't find FbxPrefab.cs in a package.
|
||
|
// So we hardcode the path.
|
||
|
var path = FbxPrefabFile;
|
||
|
if (System.IO.File.Exists(System.IO.Path.GetFullPath(path)))
|
||
|
{
|
||
|
return path;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Debug.LogWarningFormat("{0} not found; update FbxPrefabFile variable in FbxExporterRepairMissingScripts.cs to point to FbxPrefab.cs path.", FbxPrefabFile);
|
||
|
return "";
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
public int AssetsToRepairCount
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return AssetsToRepair.Length;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public string[] GetAssetsToRepair()
|
||
|
{
|
||
|
return AssetsToRepair;
|
||
|
}
|
||
|
|
||
|
public static string[] FindAssetsToRepair()
|
||
|
{
|
||
|
// search project for assets containing old GUID
|
||
|
|
||
|
// ignore if forced binary
|
||
|
if (UnityEditor.EditorSettings.serializationMode == SerializationMode.ForceBinary)
|
||
|
{
|
||
|
return new string[] {};
|
||
|
}
|
||
|
|
||
|
// check all scenes and prefabs
|
||
|
string[] searchFilePatterns = new string[] { "*.prefab", "*.unity" };
|
||
|
|
||
|
List<string> assetsToRepair = new List<string>();
|
||
|
foreach (string searchPattern in searchFilePatterns)
|
||
|
{
|
||
|
foreach (string file in Directory.GetFiles(Application.dataPath, searchPattern, SearchOption.AllDirectories))
|
||
|
{
|
||
|
if (AssetNeedsRepair(file))
|
||
|
{
|
||
|
assetsToRepair.Add(file);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return assetsToRepair.ToArray();
|
||
|
}
|
||
|
|
||
|
private static bool AssetNeedsRepair(string filePath)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
using (var sr = new StreamReader(filePath))
|
||
|
{
|
||
|
if (sr.Peek() > -1)
|
||
|
{
|
||
|
var firstLine = sr.ReadLine();
|
||
|
if (!firstLine.StartsWith("%YAML"))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var contents = sr.ReadToEnd();
|
||
|
if (SearchIDsToReplace.Exists(searchId => contents.Contains(searchId)))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
catch (IOException e)
|
||
|
{
|
||
|
Debug.LogError(string.Format("Failed to check file for component update: {0} (error={1})", filePath, e));
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public bool ReplaceGUIDInTextAssets()
|
||
|
{
|
||
|
string sourceCodeSearchID = SourceCodeSearchID;
|
||
|
if (string.IsNullOrEmpty(sourceCodeSearchID))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
bool replacedGUID = false;
|
||
|
foreach (string file in AssetsToRepair)
|
||
|
{
|
||
|
replacedGUID |= ReplaceGUIDInFile(file, sourceCodeSearchID);
|
||
|
}
|
||
|
if (replacedGUID)
|
||
|
{
|
||
|
AssetDatabase.Refresh();
|
||
|
}
|
||
|
return replacedGUID;
|
||
|
}
|
||
|
|
||
|
private static bool ReplaceID(string searchId, string replacementId, ref string line)
|
||
|
{
|
||
|
if (line.Contains(searchId))
|
||
|
{
|
||
|
line = line.Replace(searchId, replacementId);
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
private static bool ReplaceGUIDInFile(string path, string replacementSearchID)
|
||
|
{
|
||
|
// try to read file, assume it's a text file for now
|
||
|
bool modified = false;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
var tmpFile = Path.GetTempFileName();
|
||
|
if (string.IsNullOrEmpty(tmpFile))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
using (var sr = new StreamReader(path))
|
||
|
{
|
||
|
// verify that this is a text file
|
||
|
var firstLine = "";
|
||
|
if (sr.Peek() > -1)
|
||
|
{
|
||
|
firstLine = sr.ReadLine();
|
||
|
if (!firstLine.StartsWith("%YAML"))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
using (var sw = new StreamWriter(tmpFile, false))
|
||
|
{
|
||
|
if (!string.IsNullOrEmpty(firstLine))
|
||
|
{
|
||
|
sw.WriteLine(firstLine);
|
||
|
}
|
||
|
|
||
|
while (sr.Peek() > -1)
|
||
|
{
|
||
|
var line = sr.ReadLine();
|
||
|
SearchIDsToReplace.ForEach(searchId =>
|
||
|
modified |= ReplaceID(searchId, replacementSearchID, ref line)
|
||
|
);
|
||
|
|
||
|
sw.WriteLine(line);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (modified)
|
||
|
{
|
||
|
File.Delete(path);
|
||
|
File.Move(tmpFile, path);
|
||
|
|
||
|
Debug.LogFormat("Updated FbxPrefab components in file {0}", path);
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
File.Delete(tmpFile);
|
||
|
}
|
||
|
}
|
||
|
catch (IOException e)
|
||
|
{
|
||
|
Debug.LogError(string.Format("Failed to replace GUID in file {0} (error={1})", path, e));
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|