扩展 Unity的 TextureImporterEditor

Posted u010019717

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了扩展 Unity的 TextureImporterEditor相关的知识,希望对你有一定的参考价值。

孙广东  2016.8.31


            这个Unity在定制的时候就遇到问题, 最好(不是必须的, 可以自己实现啊)反射系统的,


下面有些代码是之前  的文章中介绍过的。  比如 scene 场景文件的 Inspector 面板显示。   文件夹的 Inspector面板显示等!!!

    正常的逻辑做法;
    [CustomEditor(typeof(TextureImporter))]
    public class CustomTextureAssetInspector : Editor
    
        public override void OnInspectorGUI()
        
            DrawDefaultInspector();      // 首先我希望显示默认的 系统的内容(但是不是我想要的!)
            string path = AssetDatabase.GetAssetPath(target);
            // 1
            GUI.enabled = true;
            if (path.EndsWith(".png") || path.EndsWith(".jpg"))
            
                if (GUILayout.Button("Setup2UI"))
                

                
                if (GUILayout.Button("Setup2SpineTexture"))
                

                
            
            Debug.Log("=============显示 TextureAssetInspector ======");
        
    

结果如下图所示,  这种肯定不是我想要的。 


http://blog.csdn.net/u010019717



所以只能使用反射解决:

using UnityEngine;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using System.Reflection;
using System;

/// <summary>
/// 描述:注: 音频、贴图、材质、预制体、模型、脚本、特殊不识别的资源等都不是 DefaultAsset
/// author: 孙广东
/// </summary>
[CustomEditor(typeof(UnityEditor.DefaultAsset))]
public class CustomDefaultAssetInspector : Editor

    #region ===字段===

    private static string prePath = string.Empty;

    #endregion

    #region ===Unity事件=== 快捷键: Ctrl + Shift + M /Ctrl + Shift + Q  实现

    // 1、如果是场景就显示  场景的所有引用。
    // 2、如果是文件夹,就显示 文件夹下的所有文件和子目录
    public override void OnInspectorGUI()
    
        base.OnInspectorGUI();
        string path = AssetDatabase.GetAssetPath(target);

        // 1
        GUI.enabled = true;
        FileInfo fil = new FileInfo(path);
        if (fil.Attributes == FileAttributes.Directory)//判断类型是选择的是文件夹还是文件
        
            GUILayout.Label("文件夹下的所有内容:");
            var filePaths = Directory.GetFiles(path, "*", SearchOption.AllDirectories);
            int i = 1;
            for (int j = 0; j < filePaths.Length; j++)
            
                if (!filePaths[j].EndsWith(".meta"))
                
                    GUILayout.Label(i + "、" + filePaths[j]);
                    i++;
                
            
        
    

    #endregion



[CustomEditor(typeof(UnityEditor.SceneAsset))]
public class CustomSceneAssetInspector : Editor

    public override void OnInspectorGUI()    // todo 这个太卡了!
    
        base.OnInspectorGUI();
        string path = AssetDatabase.GetAssetPath(target);

        // 1
        GUI.enabled = true;
        if (path.EndsWith(".unity"))
        
            GUILayout.Label("场景的所有引用:");
            var depends = AssetDatabase.GetDependencies(new[]  path );
            for (int i = 0; i < depends.Length; i++)
            
                GUILayout.Label(i + "、" + depends[i]);
            
        

        Debug.Log("=============显示 SceneAssetInspector ======");
    


// http://forum.unity3d.com/threads/custom-textureimporterinspector.260833/
[CustomEditor(typeof(TextureImporter))]
public class CustomTextureAssetInspector : Editor

    private SerializedObject serializedTarget;
    private Editor nativeEditor;

    public void OnEnable()
    
        serializedTarget = new SerializedObject(target);

        SceneView.onSceneGUIDelegate = TargetUpdate;

        Type t = null;

        foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
        
            foreach (Type type in assembly.GetTypes())
            
                if (type.Name.ToLower().Contains("textureimporterinspector"))
                
                    t = type;
                    break;
                
            
        
        nativeEditor = Editor.CreateEditor(serializedObject.targetObject, t);
    


    void TargetUpdate(SceneView sceneview)
    
        Event e = Event.current;
    


    public override void OnInspectorGUI()
    
        if (nativeEditor != null)
        
            bool isCustom = false;// check  ((TextureImporter)serializedObject.targetObject).assetPath for file formats you need
            if (isCustom)
            
                // Do your stuff here
                // you can use ((TextureImporter)serializedObject.targetObject).userData to store your stuff between sessions

            
            else
            
                // 如果没有Header 相关的显示就解注下面的代码。
                //MethodInfo dynMethod = nativeEditor.GetType().GetMethod("OnHeaderGUI", BindingFlags.NonPublic | BindingFlags.Instance);
                //dynMethod.Invoke(nativeEditor, new object[]  );

                nativeEditor.OnInspectorGUI();
                GUILayout.Space(50);

                if (GUILayout.Button("Setup2UI"))
                
                    string assetPath = AssetDatabase.GetAssetPath(target);
                    TextureImporter texImport = AssetImporter.GetAtPath(assetPath) as TextureImporter;

                    TextureImporterProcessor.SetSpriteTexture(texImport, assetPath);
                
                if (GUILayout.Button("Setup2SpineTexture"))
                
                    string assetPath = AssetDatabase.GetAssetPath(target);
                    TextureImporter texImport = AssetImporter.GetAtPath(assetPath) as TextureImporter;

                    TextureImporterProcessor.SetSpineTexture(texImport, assetPath);
                
            
        

        // Unfortuanaly we cant hide ImportedObject section because InspectorWindow check it by
        //  if (editor is AssetImporterEditor) and all flags that this check sets are method local variables
        //  so aside from direct patching UnityEditor.dll no luck for reflection here :(
        //  in my case i just moved ImportedObject section out of view

        GUILayout.Space(2048);
        SceneView.RepaintAll();
    

    //protected override void OnHeaderGUI()
    //
    //    // 注意:  这下面注释的两个方法都不行(这连个方法也不等价), 回到值Unity崩溃!(所以我就放在 OnInspectorGUI() 中调用了)
    //    //base.DrawHeader();    

    //    //MethodInfo dynMethod = nativeEditor.GetType().GetMethod("OnHeaderGUI", BindingFlags.NonPublic | BindingFlags.Instance);
    //    //dynMethod.Invoke(nativeEditor, new object[]  );
    //

     todo 这是有问题的 案例!!!!!   所以必须要反射
    //public override void OnInspectorGUI()
    //
    //    DrawDefaultInspector();
    //    string path = AssetDatabase.GetAssetPath(target);
    //    // 1
    //    GUI.enabled = true;
    //    if (path.EndsWith(".png") || path.EndsWith(".jpg"))
    //    
    //        if (GUILayout.Button("Setup2UI"))
    //        

    //        
    //        if (GUILayout.Button("Setup2SpineTexture"))
    //        

    //        
    //    
    //    Debug.Log("=============显示 TextureAssetInspector ======");
    //




最终的结果就是这样了。


using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;

public class TextureImporterProcessor/// : AssetPostprocessor

     系统调用 :导入的时候处理图片的设置
    //void OnPreprocessTexture()
    //
    //    TextureImporter texImport = assetImporter as TextureImporter;

    //    // 没办法, 这个处理太容易触发, 就会出现强制设置, 无法特殊的更改了!!!!!
    //    //if (assetPath.Contains("/Sprites/"))
    //    //
    //    //    Debug.Log("导入时前处理 UI  Sprite");
    //    //    SetSpriteTexture(texImport, assetPath);
    //    //
    //    //else if (assetPath.Contains("/Spines/"))
    //    //
    //    //    Debug.Log("导入时前处理 Spine Texture");
    //    //    SetSpineTexture(texImport, assetPath);
    //    //
    //

    /// <summary>
    ///! 在这个函数中设置  UI 资源的标准
    /// </summary>
    /// <param name="texImport"></param>
    /// <param name="assetPath"></param>
    public static void SetSpriteTexture(TextureImporter texImport, string assetPath)
    
        texImport.textureType = TextureImporterType.Sprite;
        var tests = assetPath.Split('\\\\');
        texImport.spritePackingTag = tests[tests.Length - 2];           // 所在文件夹的名字 作为图集的名字
        texImport.mipmapEnabled = false;
        texImport.maxTextureSize = 2048;
        texImport.textureFormat = TextureImporterFormat.AutomaticCompressed;

        AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);  // 这个导致资源导入,造成死循环啊
    

    /// <summary>
    ///! 在这个函数中设置  Spine图片 的标准
    /// </summary>
    /// <param name="texImport"></param>
    public static void SetSpineTexture(TextureImporter texImport, string assetPath)
    
        texImport.textureType = TextureImporterType.Advanced;
        texImport.spriteImportMode = SpriteImportMode.None;
        texImport.spritePackingTag = "";
        texImport.alphaIsTransparency = false;
        texImport.mipmapEnabled = false;
        texImport.maxTextureSize = 2048;
        texImport.textureFormat = TextureImporterFormat.ETC2_RGBA8;

        AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
    


    /// 通过菜单命令进行设置 ///
    static string withoutExtensions = "*.png*.jpg";
    static string SpritePath = Application.dataPath + "\\\\Arts\\\\Sprites\\\\";
    static string SpinePath = Application.dataPath + "\\\\Arts\\\\Spines\\\\";


    [MenuItem("DajiaGame/Custom/SetupSpriteImage")]
    static void SetupSpriteImage()
    
        string[] files = Directory.GetFiles(SpritePath, "*.*", SearchOption.AllDirectories)
            .Where(s => withoutExtensions.Contains(Path.GetExtension(s).ToLower())).ToArray();
        //int startIndex = 0;     // 不支持线程
        bool keyCodeCancel = false;

        for (int startIndex = 0; startIndex < files.Length; startIndex++)
        
            string assetPath = files[startIndex].Replace(Application.dataPath, "Assets");

            bool isCancel = EditorUtility.DisplayCancelableProgressBar(
                "匹配资源中", assetPath, (float)startIndex / files.Length);

            TextureImporter texImport = AssetImporter.GetAtPath(assetPath) as TextureImporter;

            SetSpriteTexture(texImport, assetPath);

            if (isCancel || keyCodeCancel || startIndex >= files.Length)
            
                EditorUtility.ClearProgressBar();
                Debug.Log("设置结束");
                EditorApplication.update = null;
                break;
            
        

        // 点击取消按钮 会很费劲,所以使用这个
        EditorApplication.update = () =>
        
            if (Input.GetKeyDown(KeyCode.Escape))
            
                keyCodeCancel = true;
                Debug.LogError("取消了设置");
            
        ;
    

    [MenuItem("DajiaGame/Custom/SetupSpineTexture")]
    static void SetupSpineTexture()
    
        string[] files = Directory.GetFiles(SpinePath, "*.*", SearchOption.AllDirectories)
            .Where(s => withoutExtensions.Contains(Path.GetExtension(s).ToLower())).ToArray();

        bool keyCodeCancel = false;

        for (int startIndex = 0; startIndex < files.Length; startIndex++)
        
            string assetPath = files[startIndex];

            bool isCancel = EditorUtility.DisplayCancelableProgressBar(
                "匹配资源中", assetPath, (float)startIndex / files.Length);

            TextureImporter texImport = AssetImporter.GetAtPath(assetPath) as TextureImporter;

            SetSpineTexture(texImport, assetPath);

            if (isCancel || keyCodeCancel || startIndex >= files.Length)
            
                EditorUtility.ClearProgressBar();
                Debug.Log("设置结束");

                break;
            
        

        // 点击取消按钮 会很费劲,所以使用这个
        EditorApplication.update = () =>
        
            if (Input.GetKeyDown(KeyCode.Escape))
            
                keyCodeCancel = true;
                Debug.LogError("取消了设置");
            
        ;
    

    static Object[] GetSelectedTextures()
    
        return Selection.GetFiltered(typeof(Texture2D), SelectionMode.DeepAssets);
    


    /// 通过菜单命令进行设置 ///


http://blog.csdn.net/u010019717


以上是关于扩展 Unity的 TextureImporterEditor的主要内容,如果未能解决你的问题,请参考以下文章

Unity中实现通过代码设置资源导入设置

Sprite (2D and UI)

关于“importer.GetNPOTScale() == TextureImporter::kNPOTKeep”问题的简单处理方法

Unity3D编辑器扩展——扩展自己的组件

扩展Unity的方法

unity 原生UGUI代码扩展