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; }
- }
- }
- }
- }
|