//////////////////////////////////////////////////////////////////////////
//
// 文件:Assets/Editor/Tools/EditorUtil.cs
// 作者:Xoen Xie
// 时间:2023/07/18
// 描述:工具通用函数集
// 说明:
//
//////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using System.IO;
using System.Diagnostics;
using System.Linq;
using System.Xml;
using TGS;
using UnityEditor.SceneManagement;
using UnityEditorInternal;
using UnityEngine.SceneManagement;
using Debug = UnityEngine.Debug;
using Object = System.Object;
using Random = UnityEngine.Random;
public static class EditorUtil
{
public static bool StartProcess(string sFilename, string sArgs, string sWorkDir)
{
Process ps = null;
bool fail = false;
try
{
ProcessStartInfo StartInfo = new ProcessStartInfo();
StartInfo.FileName = sFilename;
StartInfo.Arguments = sArgs;
StartInfo.CreateNoWindow = true;
StartInfo.UseShellExecute = false;
if (!string.IsNullOrEmpty(sWorkDir))
StartInfo.WorkingDirectory = sWorkDir;
StartInfo.RedirectStandardError = true;
StartInfo.RedirectStandardOutput = true;
ps = new Process();
ps.StartInfo = StartInfo;
ps.Start();
StreamReader readerErr = ps.StandardError; //截取错误流
string line = readerErr.ReadLine();
while (!readerErr.EndOfStream)
{
line = readerErr.ReadLine();
line = line + "\r\n";
}
ps.WaitForExit();
var strOut = ps.StandardOutput.ReadToEnd();
UnityEngine.Debug.Log(strOut);
string fileName = null;
string arguments = null;
if (ps.ExitCode != 0 && !fail)
{
fail = true;
fileName = ps.StartInfo.FileName;
arguments = ps.StartInfo.Arguments;
}
if (fail)
{
throw new Exception(string.Format("ExitCode:{0}]\nStartProcess Fail.FileName=[{1}]\nArg=[{2}\n{3}",
ps.ExitCode, fileName, arguments, line));
}
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e.Message);
}
finally
{
ps.Dispose();
}
return !fail;
}
enum FindOp
{
None = 0,
Start,
End,
}
public static bool ReplaceContentByTag(string sFilename, string sTagStart, string sTagEnd, string sNewContent)
{
bool bFindStart = false;
bool bFindEnd = false;
string[] lines = File.ReadAllLines(sFilename);
string sSrcContent = "";
FindOp nFindFlag = FindOp.Start;
for (uint i = 0; i < lines.Length; ++i)
{
switch (nFindFlag)
{
case FindOp.Start:
{
sSrcContent += lines[i] + "\n";
if (lines[i].Contains(sTagStart))
{
nFindFlag = FindOp.End;
sSrcContent += sNewContent;
bFindStart = true;
}
}
break;
case FindOp.End:
{
if (lines[i].Contains(sTagEnd))
{
nFindFlag = FindOp.None;
sSrcContent += lines[i] + "\n";
bFindEnd = true;
}
}
break;
default:
sSrcContent += lines[i] + "\n";
break;
}
}
if (bFindStart && bFindEnd)
{
File.WriteAllText(sFilename, sSrcContent);
return true;
}
return false;
}
public static bool AppendFileByTag(string sFilename, string sTag, string sNewContent)
{
if (string.IsNullOrEmpty(sNewContent))
{
return false;
}
bool bFindTag = false;
string[] lines = File.ReadAllLines(sFilename);
string sSrcContent = "";
FindOp nFindFlag = FindOp.Start;
for (uint i = 0; i < lines.Length; ++i)
{
switch (nFindFlag)
{
case FindOp.Start:
{
if (lines[i].Contains(sTag))
{
nFindFlag = FindOp.None;
sSrcContent += "\n";
sSrcContent += sNewContent;
bFindTag = true;
}
sSrcContent += lines[i] + "\n";
}
break;
default:
sSrcContent += lines[i] + "\n";
break;
}
}
if (bFindTag)
{
File.WriteAllText(sFilename, sSrcContent);
return true;
}
return false;
}
public static string FirstLetterToUpper(string str)
{
if (str.Length > 0)
return char.ToUpper(str[0]) + str.Substring(1);
return str.ToUpper();
}
public static int GetInt(XmlElement e, string attribute = null)
{
string tmp = null;
if (string.IsNullOrEmpty(attribute))
tmp = e.InnerText;
else
tmp = e.GetAttribute(attribute);
if (string.IsNullOrEmpty(tmp))
{
return 0;
}
try
{
return Convert.ToInt32(tmp);
}
catch (Exception)
{
throw;
}
}
public static uint GetUInt(XmlElement e, string attribute = null)
{
string tmp = null;
if (string.IsNullOrEmpty(attribute))
tmp = e.InnerText;
else
tmp = e.GetAttribute(attribute);
if (string.IsNullOrEmpty(tmp))
{
return 0;
}
try
{
return Convert.ToUInt32(tmp);
}
catch (Exception)
{
throw;
}
}
public static long GetLong(XmlElement e, string attribute = null)
{
string tmp = null;
if (string.IsNullOrEmpty(attribute))
tmp = e.InnerText;
else
tmp = e.GetAttribute(attribute);
if (string.IsNullOrEmpty(tmp))
{
return 0;
}
try
{
return Convert.ToInt64(tmp);
}
catch (Exception)
{
throw;
}
}
public static ulong GetULong(XmlElement e, string attribute = null)
{
string tmp = null;
if (string.IsNullOrEmpty(attribute))
tmp = e.InnerText;
else
tmp = e.GetAttribute(attribute);
if (string.IsNullOrEmpty(tmp))
{
return 0;
}
try
{
return Convert.ToUInt64(tmp);
}
catch (Exception)
{
throw;
}
}
public static float GetFloat(XmlElement e, string attribute = null)
{
string tmp = null;
if (string.IsNullOrEmpty(attribute))
tmp = e.InnerText;
else
tmp = e.GetAttribute(attribute);
if (string.IsNullOrEmpty(tmp))
{
return 0;
}
try
{
return Convert.ToSingle(tmp);
}
catch (Exception)
{
throw;
}
}
public static string GetString(XmlElement e, string attribute = null)
{
if (string.IsNullOrEmpty(attribute))
return e.InnerText;
return e.GetAttribute(attribute);
}
public static bool GetBoolean(XmlElement e, string attribute = null)
{
string tmp = null;
if (string.IsNullOrEmpty(attribute))
tmp = e.InnerText;
else
tmp = e.GetAttribute(attribute);
if (string.IsNullOrEmpty(tmp))
return false;
tmp = tmp.ToLower();
if (tmp.Equals("true") || tmp.Equals("1"))
return true;
return false;
}
public static string GetRealPath(string savePath)
{
var finalPath = savePath;
if (finalPath.StartsWith("/"))
{
finalPath = Application.dataPath + finalPath;
}
{
var dirInfo = new DirectoryInfo(finalPath);
if (dirInfo.Exists)
{
return dirInfo.FullName;
}
}
{
var fileInfo = new FileInfo(finalPath);
if (fileInfo.Exists)
{
return fileInfo.FullName;
}
}
return finalPath;
}
//调用此函数可以保证你保存的asset的路径不会覆盖到其他asset,此函数会自动给asset重命名,所以限制是你不能将asset的名字作为你逻辑的数据
public static void CreateAnUniqueAsset(UnityEngine.Object asset, string path)
{
if (asset == null || string.IsNullOrEmpty(path))
{
Debug.LogError("输入参数不合法!");
return;
}
var savePath = GetAssetUniquePath(path, out var assetName);
asset.name = assetName;
AssetDatabase.CreateAsset(asset, savePath);
}
///
/// 获取一个唯一的路径用于保存asset,假设传入的路径已经存在,则自动生成一个新的
///
/// 尝试保存的路径
/// 第一个string是唯一路径,第二个string是asset的新名字
public static string GetAssetUniquePath(string assetPath, out string assetName)
{
assetName = Path.GetFileNameWithoutExtension(assetPath);
var extension = Path.GetExtension(assetPath);
var dir = Path.GetDirectoryName(assetPath);
var savedAsset = AssetDatabase.LoadAssetAtPath(assetPath);
if (savedAsset == null)
{
return assetPath;
}
assetName = $"{assetName}_{Random.Range(0, 10000)}";
var newAssetPath = $"{dir}/{assetName}{extension}";
return GetAssetUniquePath(newAssetPath, out assetName);
}
public static void LockInspector(bool isLock)
{
Type t = typeof(EditorWindow).Assembly.GetType("UnityEditor.InspectorWindow");
var window = EditorWindow.GetWindow(t);
t.GetProperty("isLocked").SetValue(window, isLock);
}
public static bool IsStringContains(this string str1, string str2)
{
return str1.ToLower().Contains(str2.ToLower());
}
public static Bounds? GetMaxBounds(this GameObject go)
{
var meshRenderers = go.GetComponentsInChildren();
if (meshRenderers == null || meshRenderers.Length == 0)
return null;
Bounds result = new();
bool hasSetFirst = false;
foreach (var msr in meshRenderers)
{
if (!hasSetFirst)
{
result = msr.bounds;
hasSetFirst = true;
}
else
{
result.Encapsulate(msr.bounds);
}
}
return result;
}
//[MenuItem("Tools/批量修改场景")]
public static void CorrectLevels()
{
var guids = AssetDatabase.FindAssets("t:SceneAsset", new[] { "Assets/Scenes/Maps" });
var ArtPrefab = AssetDatabase.LoadAssetAtPath("Assets/Scenes/Maps/Template/MapDefault/Art.prefab");
var tgsMat = AssetDatabase.LoadAssetAtPath("Assets/Scenes/Maps/Template/MapDefault/TGS_Default.mat");
foreach (var guid in guids)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
if (string.IsNullOrEmpty(path) || path.Contains("LevelDefault"))
continue;
EditorSceneManager.OpenScene(path, OpenSceneMode.Single);
// var Art = GameObject.Find("Art");
// if (Art != null && !PrefabUtility.IsAnyPrefabInstanceRoot(Art))
// {
// var convertSetting = new ConvertToPrefabInstanceSettings
// {
// objectMatchMode = ObjectMatchMode.ByName,
// componentsNotMatchedBecomesOverride = true,
// recordPropertyOverridesOfMatches = true,
// gameObjectsNotMatchedBecomesOverride = true
// };
// PrefabUtility.ConvertToPrefabInstance(Art, ArtPrefab, convertSetting, InteractionMode.AutomatedAction);
// }
//
// if (UnityEngine.Object.FindObjectOfType() == null)
// {
// GameObject mapEditor = new("MapEditor");
// mapEditor.AddComponent();
// }
//
// if (UnityEngine.Object.FindObjectOfType() == null)
// {
// GameObject levelEditor = new("LevelEditor");
// levelEditor.AddComponent();
// }
var tgs = UnityEngine.Object.FindObjectOfType();
var meshRenderer = tgs.GetComponent();
meshRenderer.sharedMaterial = tgsMat;
EditorSceneManager.MarkAllScenesDirty();
EditorSceneManager.SaveOpenScenes();
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
//[MenuItem("Tools/修改level为map")]
private static void ChangeStringLevelToMap()
{
var guids = AssetDatabase.FindAssets("t:Object", new[] { "Assets/Scenes/Maps" });
foreach (var guid in guids)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
if (string.IsNullOrEmpty(path))
continue;
var oldName = Path.GetFileName(path);
var levelName = "Level";
var mapName = "Map";
if (oldName.Contains(levelName))
{
AssetDatabase.RenameAsset(path, oldName.Replace(levelName, mapName));
}
}
}
public static void DrawArrowInScene(Vector3 start,Vector3 end,float arrowLength = 1)
{
Handles.DrawLine(start, end);
Vector3 direction = (end - start).normalized;
Vector3 arrowEnd = end - (direction * arrowLength);
float arrowHeadAngle = 20f;
Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * Vector3.forward;
Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * Vector3.forward;
Handles.DrawLine(end, arrowEnd + right * (arrowLength * 0.4f));
Handles.DrawLine(end, arrowEnd + left * (arrowLength * 0.4f));
Handles.DrawLine(arrowEnd + right * (arrowLength * 0.4f), arrowEnd);
Handles.DrawLine(arrowEnd + left * (arrowLength * 0.4f), arrowEnd);
}
public static string GetCurrentAssetDirectory()
{
foreach (UnityEngine.Object obj in Selection.GetFiltered