NLDClient-yudde/ProjectNLD/Assets/Editor/Tools/EditorUtil.cs

584 lines
17 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

//////////////////////////////////////////////////////////////////////////
//
// 文件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);
}
/// <summary>
/// 获取一个唯一的路径用于保存asset假设传入的路径已经存在则自动生成一个新的
/// </summary>
/// <param name="assetPath">尝试保存的路径</param>
/// <returns>第一个string是唯一路径第二个string是asset的新名字</returns>
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<UnityEngine.Object>(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<MeshRenderer>();
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<GameObject>("Assets/Scenes/Maps/Template/MapDefault/Art.prefab");
var tgsMat = AssetDatabase.LoadAssetAtPath<Material>("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<MapManager>() == null)
// {
// GameObject mapEditor = new("MapEditor");
// mapEditor.AddComponent<MapManager>();
// }
//
// if (UnityEngine.Object.FindObjectOfType<LevelEditor>() == null)
// {
// GameObject levelEditor = new("LevelEditor");
// levelEditor.AddComponent<LevelEditor>();
// }
var tgs = UnityEngine.Object.FindObjectOfType<TerrainGridSystem>();
var meshRenderer = tgs.GetComponent<MeshRenderer>();
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<Object>(SelectionMode.Assets))
{
var path = AssetDatabase.GetAssetPath(obj);
if (string.IsNullOrEmpty(path))
continue;
if (System.IO.Directory.Exists(path))
return path;
else if (System.IO.File.Exists(path))
return System.IO.Path.GetDirectoryName(path);
}
return "Assets";
}
public static void AddPathToAddressable(string assetPath,string groupName)
{
#if USE_ADDRESSABLES
// 获取 AddressableAssetSettings
var settings = AddressableAssetSettingsDefaultObject.Settings;
// 获取或创建一个资源组
var group = settings.FindGroup(groupName);
if (group == null)
{
Debug.LogError($"找不到资源组:{groupName}");
return;
}
// 创建或移动条目
var guid = AssetDatabase.AssetPathToGUID(assetPath);
var entry = settings.CreateOrMoveEntry(guid, group);
//为了防止出现增量更新bug需要将场景放在group的根下
List<AddressableAssetEntry> sceneEntries = new();
entry.GatherAllAssets(sceneEntries, true, true, false,
e => e.MainAssetType == typeof(SceneAsset) || e.IsFolder);
sceneEntries = sceneEntries.Where(e => e.MainAssetType == typeof(SceneAsset)).ToList();
if (sceneEntries.Count > 0)
{
EditorUtility.SetDirty(group);
foreach (var sceneEntry in sceneEntries)
{
settings.MoveEntry(sceneEntry, group);
}
}
#endif
}
}