SamsonGame/Assets/Editor/EditorDevUtils.cs

317 lines
9.1 KiB
C#
Raw Permalink Normal View History

2021-12-29 20:50:11 +03:00
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using game;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;
using Debug = UnityEngine.Debug;
using Object = UnityEngine.Object;
#if UNITY_IOS
using UnityEditor.iOS.Xcode;
#endif
public class EditorDevUtils
{
private static Process StartGamectlTask(string task)
{
var p = new Process();
//NOTE: Invoking command in shell on OSX to setup proper paths
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
PatchPATH();
p.StartInfo.FileName = "bash";
p.StartInfo.Arguments =
"-c 'source ~/.bash_profile; php " + Application.dataPath + "/../gamectl " + task + "'";
}
else
{
p.StartInfo.FileName = "php";
p.StartInfo.Arguments = Application.dataPath + "/../gamectl " + task;
}
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.Start();
return p;
}
private static void PatchPATH()
{
string path = Environment.GetEnvironmentVariable("PATH");
Environment.SetEnvironmentVariable("PATH", "/usr/local/bin:" + path);
}
public static void ProcessAdbTask(string task)
{
var p = new Process();
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
p.StartInfo.FileName = "bash";
p.StartInfo.Arguments = "-c 'source ~/.bash_profile; adb " + task + "'";
}
else
{
p.StartInfo.FileName = "adb";
p.StartInfo.Arguments = task;
}
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.Start();
p.WaitForExit();
Log.Debug($"Done running 'adb {task}', exit code: {p.ExitCode}");
if (p.ExitCode != 0)
ShowProcError(p);
}
public static void ShowProcError(Process p)
{
string err_msg = p.StandardError.ReadToEnd();
string out_msg = p.StandardOutput.ReadToEnd();
//NOTE: showing error first so that it's visible immediately in the console log
Debug.LogError(err_msg + "\n\n" + out_msg + err_msg);
}
public static void ProcessGamectlTask(string task, Action<Process, StreamReader> cb)
{
ClearCompilationErrors();
Process p = StartGamectlTask(task);
StreamReader s = p.StandardOutput;
p.WaitForExit();
cb(p, s);
if (p.ExitCode == 0)
return;
string errMsg = p.StandardError.ReadToEnd();
string outMsg = p.StandardOutput.ReadToEnd();
if (TryGuessErrorFileAndLine(errMsg, out string file, out int line))
EmulateCompilationError(errMsg, file, line);
else
Debug.LogError(errMsg + "\n\n" + outMsg + errMsg);
}
private static bool TryGuessErrorFileAndLine(string err_msg, out string file, out int line)
{
file = "";
line = -1;
var m = Regex.Match(err_msg, "File '([^']+)'");
if (!m.Success)
return false;
line = 0;
file = m.Groups[1].ToString();
return true;
}
private static void EmulateCompilationError(string err_msg, string file, int line)
{
var m = typeof(CompilationPipeline).GetMethod("LogEditorCompilationError",
BindingFlags.Static | BindingFlags.NonPublic);
string rel_file = Path.GetFullPath(file)
.Replace(Path.GetFullPath(Application.dataPath) + Path.DirectorySeparatorChar,
$"Assets{Path.DirectorySeparatorChar}");
var asset = AssetDatabase.LoadAssetAtPath<Object>(rel_file);
if (asset == null)
return;
m.Invoke(null, new object[] { rel_file + "(1,1): error: " + err_msg, asset.GetInstanceID() });
}
private static void ClearCompilationErrors()
{
var m = typeof(CompilationPipeline).GetMethod("ClearEditorCompilationErrors",
BindingFlags.Static | BindingFlags.NonPublic);
m?.Invoke(null, null);
}
public static bool ProcessGamectlTask(string task)
{
var success = false;
ProcessGamectlTask(task, (process, reader) =>
{
success = process.ExitCode == 0;
});
return success;
}
public static bool IsBatchMode()
{
string cli_opts = Environment.CommandLine;
return cli_opts.Contains("-batchmode");
}
public static string GameRoot()
{
char sep = Path.DirectorySeparatorChar;
return Path.GetFullPath(Application.dataPath + $"{sep}..{sep}..{sep}");
}
public static void DrawHorizontalSeparator(Color color, float padding = 4)
{
const float thickness = 1;
const float padding_y = 3;
GUILayout.Space(padding_y);
var r = EditorGUILayout.GetControlRect(GUILayout.Height(thickness));
r.height = thickness;
r.x += padding;
r.width -= 2 * padding;
EditorGUI.DrawRect(r, color);
GUILayout.Space(padding_y);
}
public static string GetFilePath(ConfBase cb)
{
return AliasToFilePath(cb.strid);
}
public static string AliasToFilePath(string conf_alias)
{
return conf_alias.Replace("@", GameRoot() + "configs/") + ".conf.js";
}
public static string FilePathToAlias(string file_path)
{
return file_path.Replace(GameRoot() + "configs/", "@").Replace(".conf.js", "");
}
public static void WriteConfByAlias(string alias, string content)
{
string file_path = AliasToFilePath(alias);
Directory.CreateDirectory(Path.GetDirectoryName(file_path));
WriteConfigPreserveHeader(file_path, content);
}
public static string ExtractJsonHeader(string json, out uint id, out string strid)
{
uint tmp_id = 0;
var tmp_strid = "";
json = Regex.Replace(json, "^\\{\\s*/\\*\\s*proto_id\\s*=\\s*(\\d+)\\s*;\\s*alias\\s*=\\s*(\\S+)\\s*\\*/",
delegate(Match m)
{
if (m.Success)
{
tmp_id = uint.Parse("" + m.Groups[1]);
tmp_strid = "" + m.Groups[2];
return "{\n";
}
return m.Value;
}
);
id = tmp_id;
strid = tmp_strid;
return json;
}
public static void RemoveConfigHeader(string path)
{
if (!File.Exists(path))
return;
string[] lines = File.ReadAllLines(path);
int idx = lines[0].IndexOf('/');
if (idx != -1)
lines[0] = lines[0].Remove(idx);
File.WriteAllLines(path, lines);
}
public static void WriteConfigPreserveHeader(string path, string json)
{
if (File.Exists(path))
{
string prev_json = File.ReadAllText(path);
//NOTE: let's preserve header info
uint id = 0;
var strid = "";
ExtractJsonHeader(prev_json, out id, out strid);
if (id != 0)
{
int first_bracket = json.IndexOf("{");
Error.Assert(first_bracket != -1);
json =
"{ /* proto_id = " + id + " ; alias = " + strid + " */" +
json.Substring(first_bracket + 1);
}
}
File.WriteAllText(path, json);
}
//public static string ReplaceIdToStrid<T>(string json, string field_name, Configs configs) where T : ConfBase
//{
// for(int i = 0; i < configs.Count; ++i)
// {
// uint id = configs[i].id;
// var conf = configs.Find<T>(id);
// if(conf != null && conf is T)
// json = json.Replace($"\"{field_name}\": {conf.id}", $"\"{field_name}\": \"{conf.strid}\"");
// }
// return json;
//}
public static string ReplaceI18N(string json, string field_name)
{
json = json.Replace($"\"_{field_name}\": ", $"\"{field_name}\": ");
json = Regex.Replace(json, $",(\n|\r|\r\n) .*\"__{field_name}\": \\[\\]", "", RegexOptions.Multiline);
json = json.Replace(@"\r", "");
return json;
}
//public static string ReplaceStridToId<T>(string json, string field_name, Configs configs) where T : ConfBase
//{
// for(int i = 0; i < configs.Count; ++i)
// {
// uint id = configs[i].id;
// var conf = configs.Find<T>(id);
// if(conf != null && conf is T)
// json = json.Replace($"\"{field_name}\": \"{conf.strid}\"", $"\"{field_name}\": {conf.id}");
// }
// return json;
//}
#if UNITY_IOS
public static void IOSAddLocalFile(string buildPath, PBXProject proj, string targetName, string fileDir,
string fileName)
{
string filePath = Path.Combine(fileDir, fileName);
File.Copy(filePath, Path.Combine(buildPath, fileName));
proj.AddFileToBuild(targetName, proj.AddFile(fileName, fileName));
}
#endif
public static string ToShortName(string file, string path)
{
return file.Replace(path + "/", "");
}
}