NGUI批量替换图集工具
工具目的
因项目需要实现换肤的功能,也就是多套UI图集,提供工具批量换图集,方便查看Prebab各皮肤(图集)下的效果
示意图
Gif 操作动图:
工具截图:
工具左侧是工程所有Prefab列表,右侧是替换图集的功能菜单,从指定原图集替换成目标图集
逻辑
与上文:Unity编辑器之十四:字体替换工具 https://blog.csdn.net/qq_26999509/article/details/81106083 一样,其实找到Prebfab下所有UISprite,并将其所有指定原图集 替换成 指定的目标图集,以此实现换肤的功能,当然两图集的SpriteName应该保持一致,不然没办法知道要换成目标图集里的那张图。
重点代码
private void ReplacePrefabAtalas(GameObject prefab , UIAtlas atlas,UIAtlas targetAtlas)
{
if(prefab == null || atlas == null) return;
UISprite[] sprites = prefab.GetComponentsInChildren<UISprite>(true);
if(sprites != null && sprites.Length > 0)
{
int num = sprites.Length;
for (int i = 0; i < num; i++)
{
UISprite s = sprites[i];
if(s != null && s.atlas == atlas)
{
s.atlas = targetAtlas;
EditorUtility.SetDirty(s);
}
}
}
AssetDatabase.SaveAssets();
}
使用
1、Tools->ReplaceAtalas 打开工具
2、选中待处理预制体,鼠标右键->替换图集
3、
4、
工具代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using UnityEditor.IMGUI.Controls;
public class ReplaceAtalas : EditorWindow
{
private static ReplaceAtalas window = null;
private static List<string> prefabPathList = new List<string> ();
private static string assetPath;
Rect SearchFieldRect
{
get
{
return new Rect(interval,interval,position.width * 0.3f,20f);
}
}
Rect prefabListRect
{
get { return new Rect (interval, interval + SearchFieldRect.yMax, SearchFieldRect.width, window.position.height - SearchFieldRect.yMax - 2 * interval); }
}
Rect replaceAtalsRect
{
get{return new Rect(prefabListRect.xMax + interval,interval,window.position.width - SearchFieldRect.width - 3 * interval,window.position.height - 2 * interval);}
}
private Vector2 scrollWidgetPos;
private float interval = 20f;
private string searchStr = "";
private SearchField searchField;
private bool initialized = false;
[MenuItem("Assets/替换图集", false, 2001)]
public static void OpenWindow()
{
string selectedAssetPath = AssetDatabase.GetAssetPath (Selection.activeObject);
if(!string.IsNullOrEmpty(selectedAssetPath) && selectedAssetPath.EndsWith(".prefab"))
{
ReplaceAtalas window = ShowWindow();
if(window != null)
{
window.AutoSelctPrefab(selectedAssetPath);
}
}
}
[MenuItem("Tools/ReplaceAtalas")]
public static ReplaceAtalas ShowWindow()
{
prefabPathList.Clear ();
assetPath = Application.dataPath;
GetFiles (new DirectoryInfo (assetPath), "*.prefab", ref prefabPathList);
if (window == null)
window = EditorWindow.GetWindow(typeof(ReplaceAtalas)) as ReplaceAtalas;
window.titleContent = new GUIContent("ReplaceAtalas");
window.Show();
return window;
}
public static void GetFiles (DirectoryInfo directory, string pattern, ref List<string> fileList)
{
if (directory != null && directory.Exists && !string.IsNullOrEmpty (pattern)) {
try {
foreach (FileInfo info in directory.GetFiles (pattern)) {
string path = info.FullName.ToString ();
fileList.Add (path.Substring (path.IndexOf ("Assets")));
}
} catch (System.Exception)
{
throw;
}
foreach (DirectoryInfo info in directory.GetDirectories ())
{
GetFiles (info, pattern, ref fileList);
}
}
}
private void OnGUI()
{
InitIfNeeded();
DrawWindow();
}
private void DrawWindow()
{
DrawSearchField();
DrawPrefabList();
DrawReplaceAtalasTool();
}
private void InitIfNeeded()
{
if(!initialized)
{
if (null == searchField)
searchField = new SearchField ();
}
initialized = true;
}
private void DrawSearchField()
{
GUI.backgroundColor = Color.white;
searchStr = searchField.OnGUI (SearchFieldRect, searchStr);
searchStr = searchStr.ToLower();
}
private void DrawPrefabList()
{
GUI.backgroundColor = Color.white;
GUI.Box(prefabListRect,"");
GUILayout.BeginArea(prefabListRect);
scrollWidgetPos = EditorGUILayout.BeginScrollView(scrollWidgetPos);
for (int i = 0; i < prefabPathList.Count; i++)
{
if(CheckShowPrefab(prefabPathList[i],searchStr))
{
if(GUILayout.Button(prefabPathList[i]))
{
curReplacePrefabPath = prefabPathList[i];
curPrefabAtlas = GetPrefabAllAtlas(curReplacePrefabPath);
}
}
}
EditorGUILayout.EndScrollView();
GUILayout.EndArea();
}
private string curReplacePrefabPath = "";
private bool CheckShowPrefab(string path,string searchstr)
{
if(string.IsNullOrEmpty(searchStr)) return true;
if(string.IsNullOrEmpty(path)) return false;
return GetFileNameWithSuffix(path.ToLower()).Contains(searchStr);
}
//包括后缀名
private string GetFileNameWithSuffix(string path)
{
if(string.IsNullOrEmpty(path)) return string.Empty;
return path.Substring(path.LastIndexOf("/")+1);
}
private UIAtlas curAtlas;
private UIAtlas targetAtlas;
void OnSelectAtlas (Object obj)
{
UIAtlas atlas = obj as UIAtlas;
if(isSelectCurAtlas)
{
curAtlas = obj as UIAtlas;
}
else if(isSelectTargetAtlas)
{
targetAtlas = obj as UIAtlas;
}
isSelectCurAtlas = false;
isSelectTargetAtlas = false;
}
private bool isSelectCurAtlas = false;
private bool isSelectTargetAtlas = false;
private List<UIAtlas> curPrefabAtlas = new List<UIAtlas>();
private void DrawReplaceAtalasTool()
{
GUI.backgroundColor = Color.white;
GUILayout.BeginArea(replaceAtalsRect);
EditorGUILayout.LabelField(curReplacePrefabPath);
GUILayout.BeginHorizontal();
EditorGUILayout.LabelField("该预制体含有的所有图集:",GUILayout.Width(150));
if(curPrefabAtlas.Count > 0)
{
for (int i = 0; i < curPrefabAtlas.Count; i++)
{
if(GUILayout.Button(curPrefabAtlas[i].name))
{
curAtlas = curPrefabAtlas[i];
}
if(GUILayout.Button("Edit"))
{
//NGUISettings.atlas = mFont.atlas;
//NGUISettings.selectedSprite = sym.spriteName;
NGUIEditorTools.Select(curPrefabAtlas[i].gameObject);
}
}
}
GUILayout.EndHorizontal();
//原图集
GUILayout.BeginHorizontal();
curAtlas = (UIAtlas)EditorGUILayout.ObjectField("被替换图集", curAtlas, typeof(UIAtlas), true);
if (NGUIEditorTools.DrawPrefixButton("选择Atlas",GUILayout.Width(200)))
{
isSelectCurAtlas = true;
ComponentSelector.Show<UIAtlas>(OnSelectAtlas);
}
GUILayout.EndHorizontal();
//目标图集
GUILayout.BeginHorizontal();
targetAtlas = (UIAtlas)EditorGUILayout.ObjectField("目标图集", targetAtlas, typeof(UIAtlas), true);
if (NGUIEditorTools.DrawPrefixButton("选择Atlas",GUILayout.Width(200)))
{
isSelectTargetAtlas = true;
ComponentSelector.Show<UIAtlas>(OnSelectAtlas);
}
GUILayout.EndHorizontal();
if(GUILayout.Button("互换"))
{
UIAtlas tmpCurAtlas = curAtlas;
curAtlas = targetAtlas;
targetAtlas = tmpCurAtlas;
}
//替换按钮
if(GUILayout.Button("替换图集"))
{
if(string.IsNullOrEmpty(curReplacePrefabPath))
{
EditorUtility.DisplayDialog("提示", "请先选择一个预制体!", "确定");
}
else if (curAtlas == null)
{
EditorUtility.DisplayDialog("提示", "请先指定被替换图集!", "确定");
}
else
{
if(targetAtlas == null)
{
if(EditorUtility.DisplayDialog("提示", "原图集将被清空,确定替换吗?", "确定","取消"))
{
ReplacePrefabAtalas(curReplacePrefabPath);
}
}
else
{
ReplacePrefabAtalas(curReplacePrefabPath);
}
}
}
//保存按钮
//撤销按钮
GUILayout.EndArea();
}
private void ReplacePrefabAtalas(string path)
{
if(string.IsNullOrEmpty(path)) return;
GameObject gameObj = AssetDatabase.LoadAssetAtPath<GameObject>(path);
ReplacePrefabAtalas(gameObj,curAtlas,targetAtlas);
}
private List<UIAtlas> GetPrefabAllAtlas(string path)
{
if(string.IsNullOrEmpty(path)) return null;
GameObject gameObj = AssetDatabase.LoadAssetAtPath<GameObject>(path);
return GetPrefabAllAtlas(gameObj);
}
private List<UIAtlas> GetPrefabAllAtlas(GameObject prefab)
{
if(null == prefab) return null;
List<UIAtlas> atlass = new List<UIAtlas>();
UISprite[] sprites = prefab.GetComponentsInChildren<UISprite>(true);
if(sprites != null && sprites.Length > 0)
{
int num = sprites.Length;
for (int i = 0; i < num; i++)
{
UISprite s = sprites[i];
if(s != null && !atlass.Contains(s.atlas))
{
atlass.Add(s.atlas);
}
}
}
return atlass;
}
private void ReplacePrefabAtalas(GameObject prefab , UIAtlas atlas,UIAtlas targetAtlas)
{
if(prefab == null || atlas == null) return;
UISprite[] sprites = prefab.GetComponentsInChildren<UISprite>(true);
if(sprites != null && sprites.Length > 0)
{
int num = sprites.Length;
for (int i = 0; i < num; i++)
{
UISprite s = sprites[i];
if(s != null && s.atlas == atlas)
{
s.atlas = targetAtlas;
EditorUtility.SetDirty(s);
}
}
}
AssetDatabase.SaveAssets();
}
public void AutoSelctPrefab(string prefabPath)
{
if(string.IsNullOrEmpty(prefabPath)) return;
curReplacePrefabPath = prefabPath;
curPrefabAtlas = GetPrefabAllAtlas(curReplacePrefabPath);
curAtlas = null;
targetAtlas = null;
}
}
代码Git地址
https://github.com/JingFengJi/ReplaceAtlas
欢迎加星
以上知识分享,如有错误,欢迎指出,共同学习,共同进步。