using XGame.Editor.Build;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;
namespace XGame.Editor.Compiler
{
//[InitializeOnLoad]
public static class CompileScriptsHandle
{
private static CompileResult result;
[UnityEditor.Callbacks.DidReloadScripts]
static void OnDidReloadScripts()
{
//Debug.Log("CompileScriptsHandle OnDidReloadScripts.");
EditorApplication.quitting -= OnQuit;
EditorApplication.quitting += OnQuit;
CompilationPipeline.compilationFinished -= OnCompilationFinished;
CompilationPipeline.compilationFinished += OnCompilationFinished;
CompilationPipeline.assemblyCompilationFinished -= OnAssemblyCompilationFinished;
CompilationPipeline.assemblyCompilationFinished += OnAssemblyCompilationFinished;
//加载 初始化ICompileEvents
if (HasEvents)
{
EditorApplication.update += OnUpdate;
}
//Debug.Log($"CompileScriptsHandle InitializeOnLoad. isCompiling: {EditorApplication.isCompiling}");
}
//[InitializeOnLoadMethod]
//static void OnInitializeOnLoadMethod()
//{
// Debug.Log("CompileScriptsHandle OnInitializeOnLoadMethod.");
//}
///
/// 监听编辑器退出事件
///
private static void OnQuit()
{
//Debug.Log("EditorApplication OnQuit.");
Clear();
}
///
/// 监听Assembly编译事件
/// 编译失败时需要记录失败状态
///
///
///
private static void OnAssemblyCompilationFinished(string obj, CompilerMessage[] messages)
{
//Debug.Log($"OnAssemblyCompilationFinished. obj:{obj?.ToString() ?? "null"} msgCount:{messages?.Length ?? 0}");
if (messages != null && HasEvents)
{
foreach(var msg in messages)
{
if (msg.type == CompilerMessageType.Error)
{
result.isFailed = true;
result.message = msg.message;
if (result.isCopyAssemblyFailed == false && msg.message.Contains("Copying assembly from"))
{
//assembly拷贝失败
result.isCopyAssemblyFailed = true;
}
//打印错误信息
BuildLog.Error($"OnAssemblyCompilation error. msg:{msg.message} file:{msg.file} line:{msg.line} col:{msg.column}");
}
}
}
}
///
/// 监听编译结束回调事件
/// 编译失败时 Unity 不会执行InitializeOnLoad
/// 需要主动执行回调事件
///
///
private static void OnCompilationFinished(object obj)
{
//Debug.Log($"OnCompilationFinished. obj:{obj?.ToString() ?? "null"}");
if (result.isFailed == false) return;
//编译失败,主动执行回调
if (HasEvents)
{
EditorApplication.update += OnUpdate;
}
}
private static void OnUpdate()
{
//Debug.Log($"CompileScriptsHandle OnUpdate. isCompiling: {EditorApplication.isCompiling} isFailed:{result.isFailed}");
EditorApplication.update -= OnUpdate;
if (UnityEditorInternal.InternalEditorUtility.inBatchMode == false && result.isFailed && result.isCopyAssemblyFailed)
{
//非BatchMode下, 编译失败,并且是拷贝Assembly失败,重新编译
BuildLog.Log($"Compile Scripts Error: Assembly copy failed. Restart RequestScriptCompilation.");
result = default;
CompilationPipeline.RequestScriptCompilation();
return;
}
var events = ReadEvents();
if (events != null)
{
var tempResult = result;
result = default;
for (int i = 0; i < events.Length; i++)
{
if (tempResult.isFailed)
{
events[i].OnCompileFailed(tempResult);
}
else
{
events[i].OnCompileSuccess();
}
}
events = null;
}
}
private static string OutputPath
{
get
{
return Path.GetFullPath($"{Application.dataPath}/../ExtAssets/Editor/CompileEvents.json").Replace("\\", "/");
}
}
///
/// 是否有监听事件
///
private static bool HasEvents => File.Exists(OutputPath);
public static void RegistEvent(ICompileEvent compileEvent)
{
var filePath = OutputPath;
var dir = Path.GetDirectoryName(filePath);
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
var str = $"";
try
{
var writer = File.Exists(filePath) ? new StreamWriter(filePath, true) : new StreamWriter(filePath);
writer.WriteLine(str);
writer.Flush();
writer.Close();
BuildLog.Log($"CompileScriptsHandle RegistEvent:{str}");
}
catch (Exception ex)
{
BuildLog.Exception(ex);
}
}
private static ICompileEvent[] ReadEvents()
{
var path = OutputPath;
if (File.Exists(path))
{
List lst = new List();
try
{
Regex regex = new Regex(@"", RegexOptions.Multiline);
var lines = File.ReadAllLines(path);
foreach (var line in lines)
{
var match = regex.Match(line);
if (match.Success)
{
var typeName = match.Groups[1].Value;
var eventValue = match.Groups[2].Value;
BuildLog.Log($"CompileScriptsHandle ReadEvents type:{typeName} value:{eventValue}");
Type type = Type.GetType(typeName);
var compileEvent = LitJson.JsonMapper.ToObject(eventValue, type) as ICompileEvent;
lst.Add(compileEvent);
}
}
lst.Sort((a, b) =>
{
return a.Priority - b.Priority;
});
}
catch (Exception ex)
{
BuildLog.Exception(ex);
}
//删除文件
Clear();
return lst.ToArray();
}
return null;
}
public static void Clear()
{
var path = OutputPath;
if (File.Exists(path))
{
File.Delete(path);
}
}
}
}