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

584 lines
17 KiB
C#
Raw Normal View History

2023-08-22 19:08:45 +08:00
//////////////////////////////////////////////////////////////////////////
//
// 文件Assets/Editor/Tools/EditorUtil.cs
// 作者Xoen Xie
// 时间2023/07/18
// 描述:工具通用函数集
// 说明:
//
//////////////////////////////////////////////////////////////////////////
using System;
2024-01-30 14:25:25 +08:00
using System.Collections.Generic;
2023-08-22 19:08:45 +08:00
using UnityEditor;
using UnityEngine;
using System.IO;
using System.Diagnostics;
2024-01-30 14:25:25 +08:00
using System.Linq;
2023-08-22 19:08:45 +08:00
using System.Xml;
2023-12-20 15:55:42 +08:00
using TGS;
2023-12-20 14:59:08 +08:00
using UnityEditor.SceneManagement;
2023-12-08 20:02:39 +08:00
using UnityEditorInternal;
2023-12-20 14:59:08 +08:00
using UnityEngine.SceneManagement;
2023-12-07 16:41:41 +08:00
using Debug = UnityEngine.Debug;
2023-12-20 14:59:08 +08:00
using Object = System.Object;
2023-12-07 16:41:41 +08:00
using Random = UnityEngine.Random;
2023-08-22 19:08:45 +08:00
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:
2023-12-12 20:03:44 +08:00
{
sSrcContent += lines[i] + "\n";
2023-08-22 19:08:45 +08:00
2023-12-12 20:03:44 +08:00
if (lines[i].Contains(sTagStart))
{
nFindFlag = FindOp.End;
2023-08-22 19:08:45 +08:00
2023-12-12 20:03:44 +08:00
sSrcContent += sNewContent;
2023-08-22 19:08:45 +08:00
2023-12-12 20:03:44 +08:00
bFindStart = true;
2023-08-22 19:08:45 +08:00
}
2023-12-12 20:03:44 +08:00
}
2023-08-22 19:08:45 +08:00
break;
case FindOp.End:
2023-12-12 20:03:44 +08:00
{
if (lines[i].Contains(sTagEnd))
2023-08-22 19:08:45 +08:00
{
2023-12-12 20:03:44 +08:00
nFindFlag = FindOp.None;
2023-08-22 19:08:45 +08:00
2023-12-12 20:03:44 +08:00
sSrcContent += lines[i] + "\n";
bFindEnd = true;
2023-08-22 19:08:45 +08:00
}
2023-12-12 20:03:44 +08:00
}
2023-08-22 19:08:45 +08:00
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)
{
2023-12-12 20:03:44 +08:00
if (string.IsNullOrEmpty(sNewContent))
{
2023-08-22 19:08:45 +08:00
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:
2023-12-12 20:03:44 +08:00
{
if (lines[i].Contains(sTag))
2023-08-22 19:08:45 +08:00
{
2023-12-12 20:03:44 +08:00
nFindFlag = FindOp.None;
2023-08-22 19:08:45 +08:00
2023-12-12 20:03:44 +08:00
sSrcContent += "\n";
sSrcContent += sNewContent;
2023-08-22 19:08:45 +08:00
2023-12-12 20:03:44 +08:00
bFindTag = true;
2023-08-22 19:08:45 +08:00
}
2023-12-12 20:03:44 +08:00
sSrcContent += lines[i] + "\n";
}
2023-08-22 19:08:45 +08:00
break;
default:
sSrcContent += lines[i] + "\n";
break;
}
}
if (bFindTag)
{
File.WriteAllText(sFilename, sSrcContent);
return true;
}
return false;
}
2023-12-12 20:03:44 +08:00
public static string FirstLetterToUpper(string str)
2023-08-22 19:08:45 +08:00
{
2023-12-12 20:03:44 +08:00
if (str.Length > 0)
2023-08-22 19:08:45 +08:00
return char.ToUpper(str[0]) + str.Substring(1);
2023-12-12 20:03:44 +08:00
2023-08-22 19:08:45 +08:00
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;
}
2023-12-12 20:03:44 +08:00
2023-10-26 13:25:54 +08:00
public static string GetRealPath(string savePath)
{
var finalPath = savePath;
if (finalPath.StartsWith("/"))
{
finalPath = Application.dataPath + finalPath;
}
2023-12-12 20:03:44 +08:00
2023-10-26 13:25:54 +08:00
{
var dirInfo = new DirectoryInfo(finalPath);
if (dirInfo.Exists)
{
return dirInfo.FullName;
}
}
{
var fileInfo = new FileInfo(finalPath);
if (fileInfo.Exists)
{
return fileInfo.FullName;
}
}
2023-12-12 20:03:44 +08:00
2023-10-26 13:25:54 +08:00
return finalPath;
}
2023-12-07 16:41:41 +08:00
//调用此函数可以保证你保存的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);
}
2023-12-12 20:03:44 +08:00
2023-12-08 20:02:39 +08:00
public static void LockInspector(bool isLock)
{
Type t = typeof(EditorWindow).Assembly.GetType("UnityEditor.InspectorWindow");
var window = EditorWindow.GetWindow(t);
2023-12-12 20:03:44 +08:00
2023-12-08 20:02:39 +08:00
t.GetProperty("isLocked").SetValue(window, isLock);
}
2023-12-12 20:03:44 +08:00
public static bool IsStringContains(this string str1, string str2)
2023-12-08 20:02:39 +08:00
{
return str1.ToLower().Contains(str2.ToLower());
}
2023-12-12 20:03:44 +08:00
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;
}
2023-12-20 14:59:08 +08:00
2023-12-20 15:55:42 +08:00
//[MenuItem("Tools/批量修改场景")]
2023-12-20 14:59:08 +08:00
public static void CorrectLevels()
{
2023-12-20 17:19:51 +08:00
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");
2023-12-20 14:59:08 +08:00
foreach (var guid in guids)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
if (string.IsNullOrEmpty(path) || path.Contains("LevelDefault"))
continue;
EditorSceneManager.OpenScene(path, OpenSceneMode.Single);
2023-12-20 15:55:42 +08:00
// 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;
2023-12-20 14:59:08 +08:00
EditorSceneManager.MarkAllScenesDirty();
EditorSceneManager.SaveOpenScenes();
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
2023-12-20 17:19:51 +08:00
2023-12-21 19:08:04 +08:00
//[MenuItem("Tools/修改level为map")]
2023-12-20 17:19:51 +08:00
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));
}
}
}
2023-12-22 15:26:48 +08:00
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);
}
2023-12-22 19:00:27 +08:00
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";
}
2024-01-04 17:22:36 +08:00
public static void AddPathToAddressable(string assetPath,string groupName)
{
2024-02-27 15:07:59 +08:00
#if USE_ADDRESSABLES
2024-01-04 17:22:36 +08:00
// 获取 AddressableAssetSettings
var settings = AddressableAssetSettingsDefaultObject.Settings;
// 获取或创建一个资源组
var group = settings.FindGroup(groupName);
if (group == null)
{
Debug.LogError($"找不到资源组:{groupName}");
return;
}
// 创建或移动条目
var guid = AssetDatabase.AssetPathToGUID(assetPath);
2024-01-30 14:25:25 +08:00
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);
}
}
2024-02-27 15:07:59 +08:00
#endif
2024-01-04 17:22:36 +08:00
}
2023-08-22 19:08:45 +08:00
}