| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 | using System;using System.Collections.Generic;using UnityEngine;using Object = UnityEngine.Object;namespace FairyGUI{    [Flags]    public enum MaterialFlags    {        Clipped = 1,        SoftClipped = 2,        StencilTest = 4,        AlphaMask = 8,        Grayed = 16,        ColorFilter = 32    }    /// <summary>    /// Every texture-shader combination has a MaterialManager.    /// </summary>    public class MaterialManager    {        public event Action<Material> onCreateNewMaterial;        public bool firstMaterialInFrame;        NTexture _texture;        Shader _shader;        List<string> _addKeywords;        Dictionary<int, List<MaterialRef>> _materials;        bool _combineTexture;        class MaterialRef        {            public Material material;            public int frame;            public BlendMode blendMode;            public uint group;        }        const int internalKeywordsCount = 6;        static string[] internalKeywords = new[] { "CLIPPED", "SOFT_CLIPPED", null, "ALPHA_MASK", "GRAYED", "COLOR_FILTER" };        /// <summary>        ///         /// </summary>        /// <param name="texture"></param>        /// <param name="shader"></param>        internal MaterialManager(NTexture texture, Shader shader)        {            _texture = texture;            _shader = shader;            _materials = new Dictionary<int, List<MaterialRef>>();            _combineTexture = texture.alphaTexture != null;        }        /// <summary>        ///         /// </summary>        /// <param name="keywords"></param>        /// <returns></returns>        public int GetFlagsByKeywords(IList<string> keywords)        {            if (_addKeywords == null)                _addKeywords = new List<string>();            int flags = 0;            for (int i = 0; i < keywords.Count; i++)            {                string s = keywords[i];                if (string.IsNullOrEmpty(s))                    continue;                int j = _addKeywords.IndexOf(s);                if (j == -1)                {                    j = _addKeywords.Count;                    _addKeywords.Add(s);                }                flags += (1 << (j + internalKeywordsCount));            }            return flags;        }        /// <summary>        ///         /// </summary>        /// <param name="flags"></param>        /// <param name="blendMode"></param>        /// <param name="group"></param>        /// <returns></returns>        public Material GetMaterial(int flags, BlendMode blendMode, uint group)        {            if (blendMode != BlendMode.Normal && BlendModeUtils.Factors[(int)blendMode].pma)                flags |= (int)MaterialFlags.ColorFilter;            List<MaterialRef> items;            if (!_materials.TryGetValue(flags, out items))            {                items = new List<MaterialRef>();                _materials[flags] = items;            }            int frameId = Time.frameCount;            int cnt = items.Count;            MaterialRef result = null;            for (int i = 0; i < cnt; i++)            {                MaterialRef item = items[i];                if (item.group == group && item.blendMode == blendMode)                {                    if (item.frame != frameId)                    {                        firstMaterialInFrame = true;                        item.frame = frameId;                    }                    else                        firstMaterialInFrame = false;                    if (_combineTexture)                        item.material.SetTexture(ShaderConfig.ID_AlphaTex, _texture.alphaTexture);                    return item.material;                }                else if (result == null && (item.frame > frameId || item.frame < frameId - 1)) //collect materials if it is unused in last frame                    result = item;            }            if (result == null)            {                result = new MaterialRef() { material = CreateMaterial(flags) };                items.Add(result);            }            else if (_combineTexture)                result.material.SetTexture(ShaderConfig.ID_AlphaTex, _texture.alphaTexture);            if (result.blendMode != blendMode)            {                BlendModeUtils.Apply(result.material, blendMode);                result.blendMode = blendMode;            }            result.group = group;            result.frame = frameId;            firstMaterialInFrame = true;            return result.material;        }        /// <summary>        ///         /// </summary>        /// <returns></returns>        Material CreateMaterial(int flags)        {            Material mat = new Material(_shader);            mat.mainTexture = _texture.nativeTexture;            if (_texture.alphaTexture != null)            {                mat.EnableKeyword("COMBINED");                mat.SetTexture(ShaderConfig.ID_AlphaTex, _texture.alphaTexture);            }            for (int i = 0; i < internalKeywordsCount; i++)            {                if ((flags & (1 << i)) != 0)                {                    string s = internalKeywords[i];                    if (s != null)                        mat.EnableKeyword(s);                }            }            if (_addKeywords != null)            {                int keywordCnt = _addKeywords.Count;                for (int i = 0; i < keywordCnt; i++)                {                    if ((flags & (1 << (i + internalKeywordsCount))) != 0)                        mat.EnableKeyword(_addKeywords[i]);                }            }            mat.hideFlags = DisplayObject.hideFlags;            if (onCreateNewMaterial != null)                onCreateNewMaterial(mat);            return mat;        }        /// <summary>        ///         /// </summary>        public void DestroyMaterials()        {            var iter = _materials.GetEnumerator();            while (iter.MoveNext())            {                List<MaterialRef> items = iter.Current.Value;                if (Application.isPlaying)                {                    int cnt = items.Count;                    for (int j = 0; j < cnt; j++)                        Object.Destroy(items[j].material);                }                else                {                    int cnt = items.Count;                    for (int j = 0; j < cnt; j++)                        Object.DestroyImmediate(items[j].material);                }                items.Clear();            }            iter.Dispose();        }        /// <summary>        ///         /// </summary>        public void RefreshMaterials()        {            _combineTexture = _texture.alphaTexture != null;            var iter = _materials.GetEnumerator();            while (iter.MoveNext())            {                List<MaterialRef> items = iter.Current.Value;                int cnt = items.Count;                for (int j = 0; j < cnt; j++)                {                    Material mat = items[j].material;                    mat.mainTexture = _texture.nativeTexture;                    if (_combineTexture)                    {                        mat.EnableKeyword("COMBINED");                        mat.SetTexture(ShaderConfig.ID_AlphaTex, _texture.alphaTexture);                    }                }            }            iter.Dispose();        }    }}
 |