Unity编辑器拓展之十五:NGUI批量替换图集工具

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
欢迎加星

以上知识分享,如有错误,欢迎指出,共同学习,共同进步。

猜你喜欢

转载自blog.csdn.net/qq_26999509/article/details/81256493