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
|
|
|
|
}
|