| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842 | using System;using System.Collections.Generic;using UnityEngine;using FairyGUI.Utils;using Object = UnityEngine.Object;namespace FairyGUI{    /// <summary>    ///     /// </summary>    public class NGraphics : IMeshFactory    {        /// <summary>        ///         /// </summary>        public GameObject gameObject { get; private set; }        /// <summary>        ///         /// </summary>        public MeshFilter meshFilter { get; private set; }        /// <summary>        ///         /// </summary>        public MeshRenderer meshRenderer { get; private set; }        /// <summary>        ///         /// </summary>        public Mesh mesh { get; private set; }        /// <summary>        ///         /// </summary>        public BlendMode blendMode;        /// <summary>        /// 不参与剪裁        /// </summary>        public bool dontClip;        /// <summary>        /// 当Mesh更新时触发        /// </summary>        public event Action meshModifier;        NTexture _texture;        string _shader;        Material _material;        int _customMatarial; //0-none, 1-common, 2-support internal mask, 128-owns material        MaterialManager _manager;        string[] _shaderKeywords;        int _materialFlags;        IMeshFactory _meshFactory;        float _alpha;        Color _color;        bool _meshDirty;        Rect _contentRect;        FlipType _flip;        public class VertexMatrix        {            public Vector3 cameraPos;            public Matrix4x4 matrix;        }        VertexMatrix _vertexMatrix;        bool hasAlphaBackup;        List<byte> _alphaBackup; //透明度改变需要通过修改顶点颜色实现,但顶点颜色本身可能就带有透明度,所以这里要有一个备份        internal int _maskFlag;        StencilEraser _stencilEraser;#if !UNITY_5_6_OR_NEWER        Color32[] _colors;#endif        MaterialPropertyBlock _propertyBlock;        bool _blockUpdated;        /// <summary>        ///         /// </summary>        /// <param name="gameObject"></param>        public NGraphics(GameObject gameObject)        {            this.gameObject = gameObject;            _alpha = 1f;            _shader = ShaderConfig.imageShader;            _color = Color.white;            _meshFactory = this;            meshFilter = gameObject.AddComponent<MeshFilter>();            meshRenderer = gameObject.AddComponent<MeshRenderer>();            meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;            meshRenderer.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off;            meshRenderer.receiveShadows = false;            mesh = new Mesh();            mesh.name = gameObject.name;            mesh.MarkDynamic();            meshFilter.mesh = mesh;            meshFilter.hideFlags = DisplayObject.hideFlags;            meshRenderer.hideFlags = DisplayObject.hideFlags;            mesh.hideFlags = DisplayObject.hideFlags;            Stats.LatestGraphicsCreation++;        }        /// <summary>        ///         /// </summary>        public IMeshFactory meshFactory        {            get { return _meshFactory; }            set            {                if (_meshFactory != value)                {                    _meshFactory = value;                    _meshDirty = true;                }            }        }        /// <summary>        ///         /// </summary>        /// <typeparam name="T"></typeparam>        /// <returns></returns>        public T GetMeshFactory<T>() where T : IMeshFactory, new()        {            if (!(_meshFactory is T))            {                _meshFactory = new T();                _meshDirty = true;            }            return (T)_meshFactory;        }        /// <summary>        ///         /// </summary>        public Rect contentRect        {            get { return _contentRect; }            set            {                _contentRect = value;                _meshDirty = true;            }        }        /// <summary>        ///         /// </summary>        public FlipType flip        {            get { return _flip; }            set            {                if (_flip != value)                {                    _flip = value;                    _meshDirty = true;                }            }        }        /// <summary>        ///         /// </summary>        public NTexture texture        {            get { return _texture; }            set            {                if (_texture != value)                {                    if (value != null)                        value.AddRef();                    if (_texture != null)                        _texture.ReleaseRef();                    _texture = value;                    if (_customMatarial != 0 && _material != null)                        _material.mainTexture = _texture != null ? _texture.nativeTexture : null;                    _meshDirty = true;                    UpdateManager();                }            }        }        /// <summary>        ///         /// </summary>        public string shader        {            get { return _shader; }            set            {                _shader = value;                UpdateManager();            }        }        /// <summary>        ///         /// </summary>        /// <param name="shader"></param>        /// <param name="texture"></param>        public void SetShaderAndTexture(string shader, NTexture texture)        {            _shader = shader;            if (_texture != texture)                this.texture = texture;            else                UpdateManager();        }        /// <summary>        ///         /// </summary>        public Material material        {            get            {                if (_customMatarial == 0 && _material == null && _manager != null)                    _material = _manager.GetMaterial(_materialFlags, blendMode, 0);                return _material;            }            set            {                if ((_customMatarial & 128) != 0 && _material != null)                    Object.DestroyImmediate(_material);                _material = value;                if (_material != null)                {                    _customMatarial = 1;                    if (_material.HasProperty(ShaderConfig.ID_Stencil) || _material.HasProperty(ShaderConfig.ID_ClipBox))                        _customMatarial |= 2;                    meshRenderer.sharedMaterial = _material;                    if (_texture != null)                        _material.mainTexture = _texture.nativeTexture;                }                else                {                    _customMatarial = 0;                    meshRenderer.sharedMaterial = null;                }            }        }        /// <summary>        /// Same as material property except that ownership is transferred to this object.        /// </summary>        /// <param name="material"></param>        public void SetMaterial(Material material)        {            this.material = material;            _customMatarial |= 128;        }        /// <summary>        ///         /// </summary>        public string[] materialKeywords        {            get { return _shaderKeywords; }            set            {                _shaderKeywords = value;                UpdateMaterialFlags();            }        }        /// <summary>        ///         /// </summary>        /// <param name="keyword"></param>        /// <param name="enabled"></param>        public void ToggleKeyword(string keyword, bool enabled)        {            if (enabled)            {                if (_shaderKeywords == null)                {                    _shaderKeywords = new string[] { keyword };                    UpdateMaterialFlags();                }                else if (Array.IndexOf(_shaderKeywords, keyword) == -1)                {                    Array.Resize(ref _shaderKeywords, _shaderKeywords.Length + 1);                    _shaderKeywords[_shaderKeywords.Length - 1] = keyword;                    UpdateMaterialFlags();                }            }            else            {                if (_shaderKeywords != null)                {                    int i = Array.IndexOf(_shaderKeywords, keyword);                    if (i != -1)                    {                        _shaderKeywords[i] = null;                        UpdateMaterialFlags();                    }                }            }        }        void UpdateManager()        {            if (_texture != null)                _manager = _texture.GetMaterialManager(_shader);            else                _manager = null;            UpdateMaterialFlags();        }        void UpdateMaterialFlags()        {            if (_customMatarial != 0)            {                if (material != null)                    material.shaderKeywords = _shaderKeywords;            }            else if (_shaderKeywords != null && _manager != null)                _materialFlags = _manager.GetFlagsByKeywords(_shaderKeywords);            else                _materialFlags = 0;        }        /// <summary>        ///         /// </summary>        public bool enabled        {            get { return meshRenderer.enabled; }            set { meshRenderer.enabled = value; }        }        /// <summary>        ///         /// </summary>        public int sortingOrder        {            get { return meshRenderer.sortingOrder; }            set { meshRenderer.sortingOrder = value; }        }        /// <summary>        ///         /// </summary>        /// <param name="value"></param>        internal void _SetStencilEraserOrder(int value)        {            _stencilEraser.meshRenderer.sortingOrder = value;        }        /// <summary>        ///         /// </summary>        /// <param name="value"></param>        public Color color        {            get { return _color; }            set { _color = value; }        }        /// <summary>        ///         /// </summary>        public void Tint()        {            if (_meshDirty)                return;            int vertCount = mesh.vertexCount;            if (vertCount == 0)                return;#if !UNITY_5_6_OR_NEWER            Color32[] colors = _colors;            if (colors == null)                colors = mesh.colors32;#else            VertexBuffer vb = VertexBuffer.Begin();            mesh.GetColors(vb.colors);            List<Color32> colors = vb.colors;#endif            for (int i = 0; i < vertCount; i++)            {                Color32 col = _color;                col.a = (byte)(_alpha * (hasAlphaBackup ? _alphaBackup[i] : (byte)255));                colors[i] = col;            }#if !UNITY_5_6_OR_NEWER            mesh.colors32 = colors;#else            mesh.SetColors(vb.colors);            vb.End();#endif        }        void ChangeAlpha(float value)        {            _alpha = value;            int vertCount = mesh.vertexCount;            if (vertCount == 0)                return;#if !UNITY_5_6_OR_NEWER            Color32[] colors = _colors;            if (colors == null)                colors = mesh.colors32;#else            VertexBuffer vb = VertexBuffer.Begin();            mesh.GetColors(vb.colors);            List<Color32> colors = vb.colors;#endif            for (int i = 0; i < vertCount; i++)            {                Color32 col = colors[i];                col.a = (byte)(_alpha * (hasAlphaBackup ? _alphaBackup[i] : (byte)255));                colors[i] = col;            }#if !UNITY_5_6_OR_NEWER            mesh.colors32 = colors;#else            mesh.SetColors(vb.colors);            vb.End();#endif        }        /// <summary>        ///         /// </summary>        public VertexMatrix vertexMatrix        {            get { return _vertexMatrix; }            set            {                _vertexMatrix = value;                _meshDirty = true;            }        }        /// <summary>        ///         /// </summary>        /// <returns></returns>        public MaterialPropertyBlock materialPropertyBlock        {            get            {                if (_propertyBlock == null)                    _propertyBlock = new MaterialPropertyBlock();                _blockUpdated = true;                return _propertyBlock;            }        }        /// <summary>        ///         /// </summary>        public void SetMeshDirty()        {            _meshDirty = true;        }        /// <summary>        ///         /// </summary>        /// <returns></returns>        public bool UpdateMesh()        {            if (_meshDirty)            {                UpdateMeshNow();                return true;            }            else                return false;        }        /// <summary>        ///         /// </summary>        public void Dispose()        {            if (mesh != null)            {                if (Application.isPlaying)                    Object.Destroy(mesh);                else                    Object.DestroyImmediate(mesh);                mesh = null;            }            if ((_customMatarial & 128) != 0 && _material != null)                Object.DestroyImmediate(_material);            if (_texture != null)            {                _texture.ReleaseRef();                _texture = null;            }            _manager = null;            _material = null;            meshRenderer = null;            meshFilter = null;            _stencilEraser = null;            meshModifier = null;        }        /// <summary>        ///         /// </summary>        /// <param name="context"></param>        /// <param name="alpha"></param>        /// <param name="grayed"></param>        public void Update(UpdateContext context, float alpha, bool grayed)        {            Stats.GraphicsCount++;            if (_meshDirty)            {                _alpha = alpha;                UpdateMeshNow();            }            else if (_alpha != alpha)                ChangeAlpha(alpha);            if (_propertyBlock != null && _blockUpdated)            {                meshRenderer.SetPropertyBlock(_propertyBlock);                _blockUpdated = false;            }            if (_customMatarial != 0)            {                if ((_customMatarial & 2) != 0 && _material != null)                    context.ApplyClippingProperties(_material, false);            }            else            {                if (_manager != null)                {                    if (_maskFlag == 1)                    {                        _material = _manager.GetMaterial((int)MaterialFlags.AlphaMask | _materialFlags, BlendMode.Normal, context.clipInfo.clipId);                        context.ApplyAlphaMaskProperties(_material, false);                    }                    else                    {                        int matFlags = _materialFlags;                        if (grayed)                            matFlags |= (int)MaterialFlags.Grayed;                        if (context.clipped)                        {                            if (context.stencilReferenceValue > 0)                                matFlags |= (int)MaterialFlags.StencilTest;                            if (context.rectMaskDepth > 0)                            {                                if (context.clipInfo.soft)                                    matFlags |= (int)MaterialFlags.SoftClipped;                                else                                    matFlags |= (int)MaterialFlags.Clipped;                            }                            _material = _manager.GetMaterial(matFlags, blendMode, context.clipInfo.clipId);                            if (_manager.firstMaterialInFrame)                                context.ApplyClippingProperties(_material, true);                        }                        else                            _material = _manager.GetMaterial(matFlags, blendMode, 0);                    }                }                else                    _material = null;                if (!Material.ReferenceEquals(_material, meshRenderer.sharedMaterial))                    meshRenderer.sharedMaterial = _material;            }            if (_maskFlag != 0)            {                if (_maskFlag == 1)                    _maskFlag = 2;                else                {                    if (_stencilEraser != null)                        _stencilEraser.enabled = false;                    _maskFlag = 0;                }            }        }        internal void _PreUpdateMask(UpdateContext context, uint maskId)        {            //_maskFlag: 0-new mask, 1-active mask, 2-mask complete            if (_maskFlag == 0)            {                if (_stencilEraser == null)                {                    _stencilEraser = new StencilEraser(gameObject.transform);                    _stencilEraser.meshFilter.mesh = mesh;                }                else                    _stencilEraser.enabled = true;            }            _maskFlag = 1;            if (_manager != null)            {                //这里使用maskId而不是clipInfo.clipId,是因为遮罩有两个用途,一个是写入遮罩,一个是擦除,两个不能用同一个材质                Material mat = _manager.GetMaterial((int)MaterialFlags.AlphaMask | _materialFlags, BlendMode.Normal, maskId);                if (!Material.ReferenceEquals(mat, _stencilEraser.meshRenderer.sharedMaterial))                    _stencilEraser.meshRenderer.sharedMaterial = mat;                context.ApplyAlphaMaskProperties(mat, true);            }        }        void UpdateMeshNow()        {            _meshDirty = false;            if (_texture == null || _meshFactory == null)            {                if (mesh.vertexCount > 0)                {                    mesh.Clear();                    if (meshModifier != null)                        meshModifier();                }                return;            }            VertexBuffer vb = VertexBuffer.Begin();            vb.contentRect = _contentRect;            vb.uvRect = _texture.uvRect;            if (_texture != null)                vb.textureSize = new Vector2(_texture.width, _texture.height);            else                vb.textureSize = new Vector2(0, 0);            if (_flip != FlipType.None)            {                if (_flip == FlipType.Horizontal || _flip == FlipType.Both)                {                    float tmp = vb.uvRect.xMin;                    vb.uvRect.xMin = vb.uvRect.xMax;                    vb.uvRect.xMax = tmp;                }                if (_flip == FlipType.Vertical || _flip == FlipType.Both)                {                    float tmp = vb.uvRect.yMin;                    vb.uvRect.yMin = vb.uvRect.yMax;                    vb.uvRect.yMax = tmp;                }            }            vb.vertexColor = _color;            _meshFactory.OnPopulateMesh(vb);            int vertCount = vb.currentVertCount;            if (vertCount == 0)            {                if (mesh.vertexCount > 0)                {                    mesh.Clear();                    if (meshModifier != null)                        meshModifier();                }                vb.End();                return;            }            if (_texture.rotated)            {                float xMin = _texture.uvRect.xMin;                float yMin = _texture.uvRect.yMin;                float yMax = _texture.uvRect.yMax;                float tmp;                for (int i = 0; i < vertCount; i++)                {                    Vector2 vec = vb.uvs[i];                    tmp = vec.y;                    vec.y = yMin + vec.x - xMin;                    vec.x = xMin + yMax - tmp;                    vb.uvs[i] = vec;                }            }            hasAlphaBackup = vb._alphaInVertexColor;            if (hasAlphaBackup)            {                if (_alphaBackup == null)                    _alphaBackup = new List<byte>();                else                    _alphaBackup.Clear();                for (int i = 0; i < vertCount; i++)                {                    Color32 col = vb.colors[i];                    _alphaBackup.Add(col.a);                    col.a = (byte)(col.a * _alpha);                    vb.colors[i] = col;                }            }            else if (_alpha != 1)            {                for (int i = 0; i < vertCount; i++)                {                    Color32 col = vb.colors[i];                    col.a = (byte)(col.a * _alpha);                    vb.colors[i] = col;                }            }            if (_vertexMatrix != null)            {                Vector3 camPos = _vertexMatrix.cameraPos;                Vector3 center = new Vector3(camPos.x, camPos.y, 0);                center -= _vertexMatrix.matrix.MultiplyPoint(center);                for (int i = 0; i < vertCount; i++)                {                    Vector3 pt = vb.vertices[i];                    pt = _vertexMatrix.matrix.MultiplyPoint(pt);                    pt += center;                    Vector3 vec = pt - camPos;                    float lambda = -camPos.z / vec.z;                    pt.x = camPos.x + lambda * vec.x;                    pt.y = camPos.y + lambda * vec.y;                    pt.z = 0;                    vb.vertices[i] = pt;                }            }            mesh.Clear();#if UNITY_5_2 || UNITY_5_3_OR_NEWER            mesh.SetVertices(vb.vertices);            if (vb._isArbitraryQuad)                mesh.SetUVs(0, vb.FixUVForArbitraryQuad());            else                mesh.SetUVs(0, vb.uvs);            mesh.SetColors(vb.colors);            mesh.SetTriangles(vb.triangles, 0);            if (vb.uvs2.Count == vb.uvs.Count)                mesh.SetUVs(1, vb.uvs2);#if !UNITY_5_6_OR_NEWER            _colors = null;#endif#else            Vector3[] vertices = new Vector3[vertCount];            Vector2[] uv = new Vector2[vertCount];            _colors = new Color32[vertCount];            int[] triangles = new int[vb.triangles.Count];            vb.vertices.CopyTo(vertices);            vb.uvs.CopyTo(uv);            vb.colors.CopyTo(_colors);            vb.triangles.CopyTo(triangles);            mesh.vertices = vertices;            mesh.uv = uv;            mesh.triangles = triangles;            mesh.colors32 = _colors;            if(vb.uvs2.Count==uv.Length)            {                uv = new Vector2[vertCount];                vb.uvs2.CopyTo(uv);                mesh.uv2 = uv;            }#endif            vb.End();            if (meshModifier != null)                meshModifier();        }        public void OnPopulateMesh(VertexBuffer vb)        {            Rect rect = texture.GetDrawRect(vb.contentRect);            vb.AddQuad(rect, vb.vertexColor, vb.uvRect);            vb.AddTriangles();            vb._isArbitraryQuad = _vertexMatrix != null;        }        class StencilEraser        {            public GameObject gameObject;            public MeshFilter meshFilter;            public MeshRenderer meshRenderer;            public StencilEraser(Transform parent)            {                gameObject = new GameObject("StencilEraser");                gameObject.transform.SetParent(parent, false);                meshFilter = gameObject.AddComponent<MeshFilter>();                meshRenderer = gameObject.AddComponent<MeshRenderer>();                meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;                meshRenderer.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off;                meshRenderer.receiveShadows = false;                gameObject.layer = parent.gameObject.layer;                gameObject.hideFlags = parent.gameObject.hideFlags;                meshFilter.hideFlags = parent.gameObject.hideFlags;                meshRenderer.hideFlags = parent.gameObject.hideFlags;            }            public bool enabled            {                get { return meshRenderer.enabled; }                set { meshRenderer.enabled = value; }            }        }    }}
 |