简介
这是一个管理Unity宏设置的脚本工具,能快速的增删改查项目的脚本。
下面是效果图:
代码
依赖的代码
<details>
<summary> ResCatalog </summary>
/// <summary>
/// 资源路径
/// </summary>
public static class ResCatalog
{
public const string DefaultRes = "Library/unity default resources";
public const string Temporary = "Assets/_Temporary";
public const string Library = "Assets/_Library";
}
</details>
<details>
<summary> BuildTargetUtility </summary>
/// <summary>
/// 构建的辅助工具
/// </summary>
public class BuildTargetUtility
{
/// <summary>
/// 获取对应平台的组
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
public static BuildTargetGroup PlatformToGroup(RuntimePlatform p)
{
return p switch
{
RuntimePlatform.OSXEditor => BuildTargetGroup.Standalone,
RuntimePlatform.OSXPlayer => BuildTargetGroup.Standalone,
RuntimePlatform.WindowsPlayer => BuildTargetGroup.Standalone,
RuntimePlatform.WindowsEditor => BuildTargetGroup.Standalone,
RuntimePlatform.IPhonePlayer => BuildTargetGroup.iOS,
RuntimePlatform.Android => BuildTargetGroup.Android,
RuntimePlatform.LinuxPlayer => BuildTargetGroup.Standalone,
RuntimePlatform.LinuxEditor => BuildTargetGroup.Standalone,
RuntimePlatform.WebGLPlayer => BuildTargetGroup.WebGL,
RuntimePlatform.PS4 => BuildTargetGroup.PS4,
RuntimePlatform.XboxOne => BuildTargetGroup.XboxOne,
RuntimePlatform.tvOS => BuildTargetGroup.tvOS,
RuntimePlatform.Switch => BuildTargetGroup.Switch,
_ => BuildTargetGroup.Unknown
};
}
}
</details>
<details>
<summary> AssetLibrary </summary>
/// <summary>
/// 资源的Library
/// </summary>
public static class AssetLibrary
{
/// <summary>
/// 判断文件是否存在
/// </summary>
/// <param name="path"></param>
/// <param name="temporary"></param>
/// <returns></returns>
public static bool Exists(string path, bool temporary)
{
return File.Exists(GetPath(path, temporary));
}
/// <summary>
/// 获取文件的地址
/// </summary>
/// <param name="path">文件名字</param>
/// <param name="temporary">是否是临时文件</param>
/// <returns></returns>
public static string GetPath(string path, bool temporary)
{
return Path.Combine(temporary ? ResCatalog.Temporary : ResCatalog.Library, path);
}
/// <summary>
/// 保存文件
/// </summary>
/// <param name="path">文件地址</param>
/// <param name="text">文件内容</param>
/// <param name="temporary">是否是临时文件</param>
public static void Save(string path, string text, bool temporary)
{
WriteAllText(path, text, temporary);
}
/// <summary>
/// 保存文件
/// </summary>
/// <param name="path">文件地址</param>
/// <param name="bytes">写入的字节</param>
/// <param name="temporary">是否是临时资源</param>
public static void Save(string path, byte[] bytes, bool temporary)
{
WriteAllBytes(path, bytes, temporary);
}
/// <summary>
/// 获取文件内的所有内容
/// </summary>
/// <param name="path">文件地址</param>
/// <param name="temporary">是否是临时文件</param>
/// <returns></returns>
public static string GetString(string path, bool temporary)
{
return File.ReadAllText(GetPath(path, temporary));
}
/// <summary>
/// 获取文件的所有字节
/// </summary>
/// <param name="path">文件地址</param>
/// <param name="temporary">是否是临时资源</param>
/// <returns></returns>
public static byte[] GetBytes(string path, bool temporary)
{
return File.ReadAllBytes(GetPath(path, temporary));
}
/// <summary>
/// 写入所有的字节
/// </summary>
/// <param name="path">文件路径</param>
/// <param name="bytes">写入字节</param>
/// <param name="temporary">是否是临时资源</param>
private static void WriteAllBytes(string path, byte[] bytes, bool temporary)
{
var realPath = GetPath(path, temporary);
PathUtils.MakeDirectory(realPath);
File.WriteAllBytes(realPath, bytes);
}
/// <summary>
/// 写入所有的文本内容
/// </summary>
/// <param name="path">文件路径</param>
/// <param name="text">写入字符串</param>
/// <param name="temporary">是否是临时资源</param>
private static void WriteAllText(string path, string text, bool temporary)
{
var realPath = GetPath(path, temporary);
PathUtils.MakeDirectory(realPath);
File.WriteAllText(realPath, text);
}
}
</details>
<details>
<summary> SymbolsUtility </summary>
/// <summary>
/// 宏的辅助工具
/// </summary>
public static class SymbolsUtility
{
/// <summary>
/// 设置宏
/// </summary>
/// <param name="symbols"></param>
public static void SetSymbols(params string[] symbols)
{
var result = string.Join(";", symbols);
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Standalone, result);
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.iOS, result);
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, result);
}
/// <summary>
/// 获取所有的宏
/// </summary>
/// <returns></returns>
public static string[] GetSymbols()
{
var group = BuildTargetUtility.PlatformToGroup(Application.platform);
var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
return symbols.Split(';');
}
/// <summary>
/// 增加宏
/// </summary>
/// <param name="symbols">宏的组</param>
public static void AddSymbols(params string[] symbols)
{
SetSymbols(GetSymbols().Union(symbols).ToArray());
}
/// <summary>
/// 移除宏
/// </summary>
/// <param name="symbols">宏的组</param>
public static void RemoveSymbols(params string[] symbols)
{
SetSymbols(GetSymbols().Except(symbols).ToArray());
}
/// <summary>
/// 判断是否拥有宏
/// </summary>
/// <param name="symbol">宏的名字</param>
/// <returns></returns>
public static bool HasSymbols(string symbol)
{
return -1 != Array.IndexOf(GetSymbols(), symbol);
}
}
</details>
管理工具代码
internal class SymbolsManager : EditorWindow
{
/// <summary>
/// 宏的配置
/// </summary>
public class SymbolsConfig
{
/// <summary>
/// 宏的名字
/// </summary>
public string name;
/// <summary>
/// 是否使用
/// </summary>
[NonSerialized]
public bool used;
}
/// <summary>
/// 宏的组
/// </summary>
public class SymbolsGroup
{
/// <summary>
/// 组的名字
/// </summary>
public string name;
/// <summary>
/// 组的宏列表
/// </summary>
public List<SymbolsConfig> list;
/// <summary>
/// 用于显示的List
/// </summary>
[NonSerialized]
public ReorderableList reorderableList;
/// <summary>
/// 是否已经删除
/// </summary>
[NonSerialized]
public bool deleted;
}
/// <summary>
/// 组的列表
/// </summary>
private List<SymbolsGroup> m_Groups;
/// <summary>
/// 宏管理窗口
/// </summary>
[MenuItem("Tools/SymbolsManager", false)]
private static void OpenWindow()
{
var window = GetWindow<SymbolsManager>("SymbolsManager");
window.minSize = new Vector2(350, 100);
}
private void OnEnable()
{
var path = GetSettingsFileName();
if (AssetLibrary.Exists(path, false))
{
var text = AssetLibrary.GetString(path, false);
JsonUtils.ToObject(text, out m_Groups);
foreach (var group in m_Groups)
{
if (null == group.list)
{
group.list = new List<SymbolsConfig>();
}
else
{
foreach (var config in group.list)
{
config.used = SymbolsUtility.HasSymbols(config.name);
}
}
}
}
m_Groups ??= new List<SymbolsGroup>();
}
/// <summary>
/// 绘制面板
/// </summary>
private void OnGUI()
{
for (var i = 0; i < m_Groups.Count;)
{
var group = m_Groups[i];
GUILayout.BeginVertical(EditorStyles.helpBox);
{
if (null == group.reorderableList)
{
group.list ??= new List<SymbolsConfig>();
group.reorderableList = new ReorderableList(group.list, typeof(SymbolsConfig))
{
drawHeaderCallback = rect =>
{
var textRt = rect;
textRt.width /= 2f;
group.name = EditorGUI.TextField(textRt, group.name, EditorStyles.boldLabel);
var btnRt = rect;
btnRt.x = btnRt.xMax - Styles.closeButton.lineHeight;
if (GUI.Button(btnRt, GUIContent.none, Styles.closeButton))
{
if (EditorUtility.DisplayDialog(
"提示", "是否确认删除?", "确认", "取消"))
{
group.deleted = true;
}
}
},
drawElementCallback = (rect, index, active, focused) =>
{
var item = group.list[index];
var textRect = new Rect(
rect.position + Vector2.up * 2,
new Vector2(rect.width - 100, EditorGUIUtility.singleLineHeight));
item.name = GUI.TextField(textRect, item.name)?.Trim();
const int btnWidth = 80;
var oldColor = GUI.color;
GUI.color = SymbolsUtility.HasSymbols(item.name) ? Color.green : Color.red;
var btnRect = new Rect(
rect.position + Vector2.up + Vector2.right * (rect.width - btnWidth),
new Vector2(btnWidth, EditorGUIUtility.singleLineHeight));
item.used = GUI.Toggle(btnRect, item.used,
item.used ? Styles.used : Styles.unused,
EditorStyles.toolbarButton);
GUI.color = oldColor;
},
elementHeight = 22,
};
}
group.reorderableList.DoLayoutList();
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button(Styles.apply, GUILayout.Height(30), GUILayout.Width(100)))
{
foreach (var config in group.list)
{
if (config.used)
{
SymbolsUtility.AddSymbols(config.name);
}
else
{
SymbolsUtility.RemoveSymbols(config.name);
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.Space(5);
}
GUILayout.EndVertical();
if (group.deleted)
{
m_Groups.RemoveAt(i);
}
else
{
++i;
}
}
//
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button(Styles.addGroup, GUILayout.Height(30), GUILayout.Width(200)))
{
m_Groups.Add(new SymbolsGroup
{
name = Styles.customName,
list = new List<SymbolsConfig>()
});
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
var e = Event.current;
if (e.keyCode == KeyCode.S && e.type == EventType.KeyUp)
{
e.Use();
Save();
}
}
/// <summary>
/// 销毁的时候保存
/// </summary>
private void OnDisable()
{
Save();
}
/// <summary>
/// 保存
/// </summary>
private void Save()
{
JsonResolver.NotSerializeDefault = true;
var text = JsonUtils.ToPrettyString(m_Groups);
AssetLibrary.Save(GetSettingsFileName(), text, false);
JsonResolver.NotSerializeDefault = false;
}
/// <summary>
/// 序列化Json文件的名字,采用 “类名Settings.json”格式
/// </summary>
/// <returns></returns>
private string GetSettingsFileName()
{
return $"{GetType().Name}Settings.json";
}
#region 显示风格Style
/// <summary>
/// 编辑器的风格
/// </summary>
private static class Styles
{
/// <summary>
/// 已经使用
/// </summary>
public static GUIContent used;
/// <summary>
/// 未使用
/// </summary>
public static GUIContent unused;
/// <summary>
/// 应用
/// </summary>
public static GUIContent apply;
/// <summary>
/// 新增分组
/// </summary>
public static GUIContent addGroup;
/// <summary>
/// 自定义名称(点击修改)
/// </summary>
public static string customName;
/// <summary>
/// WinBtnClose
/// </summary>
public static GUIStyle closeButton;
static Styles()
{
used = new GUIContent("已使用");
unused = new GUIContent("未使用");
apply = new GUIContent("应用");
addGroup = new GUIContent("新增分组");
customName = "自定义名称(点击修改)";
closeButton = new GUIStyle("WinBtnClose");
}
}
#endregion
}