context: using UnityEngine;
  using UnityEditor;
  using UnityEditor.Sprites;
  using System.IO;
  using System.Linq;
  using System.Collections;
  using System.Collections.Generic;
  using System.Reflection;
  using TriangleNet.Geometry;
  
  namespace Anima2D 
  {
  	public class SpriteMeshUtils
  	{
  		static Material m_DefaultMaterial = null;
  		public static Material defaultMaterial {
  			get {
  				if(!m_DefaultMaterial)
  				{
  					GameObject go = new GameObject();
  					SpriteRenderer sr = go.AddComponent<SpriteRenderer>();
  					m_DefaultMaterial = sr.sharedMaterial;
  					GameObject.DestroyImmediate(go);
  				}
  				
  				return m_DefaultMaterial;
  			}
  		}
  		public class WeightedTriangle
  		{
  			int m_P1;
  			int m_P2;
  			int m_P3;
  			float m_W1;
  			float m_W2;
  			float m_W3;
  			float m_Weight;
  			
  			public int p1 { get { return m_P1; } }
  			public int p2 { get { return m_P2; } }
  			public int p3 { get { return m_P3; } }
  			public float w1 { get { return m_W1; } }
  			public float w2 { get { return m_W2; } }
  			public float w3 { get { return m_W3; } }
  			public float weight { get { return m_Weight; } }
  			
  			public WeightedTriangle(int _p1, int _p2, int _p3,
  			                        float _w1, float _w2, float _w3)
  			{
  				m_P1 = _p1;
  				m_P2 = _p2;
  				m_P3 = _p3;
  				m_W1 = _w1;
  				m_W2 = _w2;
  				m_W3 = _w3;
  				m_Weight = (w1 + w2 + w3) / 3f;
  			}
  		}
  		
  		public static SpriteMesh CreateSpriteMesh(Sprite sprite)
  		{
  			SpriteMesh spriteMesh = SpriteMeshPostprocessor.GetSpriteMeshFromSprite(sprite);
  			SpriteMeshData spriteMeshData = null;
  			
  			if(!spriteMesh && sprite)
  			{
  				string spritePath = AssetDatabase.GetAssetPath(sprite);
  				string directory = Path.GetDirectoryName(spritePath);
  				string assetPath = AssetDatabase.GenerateUniqueAssetPath(directory + Path.DirectorySeparatorChar + sprite.name + ".asset");
  				
  				spriteMesh = ScriptableObject.CreateInstance<SpriteMesh>();
  				InitFromSprite(spriteMesh,sprite);
  				AssetDatabase.CreateAsset(spriteMesh,assetPath);
  				
  				spriteMeshData = ScriptableObject.CreateInstance<SpriteMeshData>();
  				spriteMeshData.name = spriteMesh.name + "_Data";
  				spriteMeshData.hideFlags = HideFlags.HideInHierarchy;
  				InitFromSprite(spriteMeshData,sprite);
  				AssetDatabase.AddObjectToAsset(spriteMeshData,assetPath);
  				
  				UpdateAssets(spriteMesh,spriteMeshData);
  				
  				AssetDatabase.SaveAssets();
  				AssetDatabase.ImportAsset(assetPath);
  				
  				Selection.activeObject = spriteMesh;
  			}
  			
  			return spriteMesh;
  		}
  		
  		public static void CreateSpriteMesh(Texture2D texture)
  		{
  			if(texture)
  			{
  				Object[] objects = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(texture));
  				
  				for (int i = 0; i < objects.Length; i++)
  				{
  					Object o = objects [i];
  					Sprite sprite = o as Sprite;
  					if (sprite) {
  						EditorUtility.DisplayProgressBar ("Processing " + texture.name, sprite.name, (i+1) / (float)objects.Length);
  						CreateSpriteMesh(sprite);
  					}
  				}
  				
  				EditorUtility.ClearProgressBar();
  			}
  		}
  		
  		public static SpriteMeshData LoadSpriteMeshData(SpriteMesh spriteMesh)
  		{
  			if(spriteMesh)
  			{
  				UnityEngine.Object[] assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(spriteMesh));
  				
  				foreach(UnityEngine.Object asset in assets)
  				{
  					SpriteMeshData data = asset as SpriteMeshData;
  					
  					if(data)
  					{
  						return data;
  					}
  				}
  			}
  			
  			return null;
  		}
  		
  		public static void UpdateAssets(SpriteMesh spriteMesh)
  		{
  			UpdateAssets(spriteMesh, SpriteMeshUtils.LoadSpriteMeshData(spriteMesh));
  		}
  		
  		public static void UpdateAssets(SpriteMesh spriteMesh, SpriteMeshData spriteMeshData)
  		{
  			if(spriteMesh && spriteMeshData)
  			{
  				string spriteMeshPath = AssetDatabase.GetAssetPath(spriteMesh);
  				
  				SerializedObject spriteMeshSO = new SerializedObject(spriteMesh);
  				SerializedProperty sharedMeshProp = spriteMeshSO.FindProperty("m_SharedMesh");
  				SerializedProperty sharedMaterialsProp = spriteMeshSO.FindProperty("m_SharedMaterials");
  				
  				if(!spriteMesh.sharedMesh)
  				{
  					Mesh mesh = new Mesh();
  					mesh.hideFlags = HideFlags.HideInHierarchy;
  					AssetDatabase.AddObjectToAsset(mesh,spriteMeshPath);
  					
  					spriteMeshSO.Update();
  					sharedMeshProp.objectReferenceValue = mesh;
  					spriteMeshSO.ApplyModifiedProperties();
  					EditorUtility.SetDirty(mesh);
  				}
  				
  				spriteMesh.sharedMesh.name = spriteMesh.name;
  				
  				if(spriteMesh.sharedMaterials.Length == 0)
  				{
  					Material material = new Material(Shader.Find("Sprites/Default"));
  					material.mainTexture = SpriteUtility.GetSpriteTexture(spriteMesh.sprite,false);
  					
  					AssetDatabase.AddObjectToAsset(material,spriteMeshPath);
  					
  					spriteMeshSO.Update();
  					sharedMaterialsProp.arraySize = 1;
  					sharedMaterialsProp.GetArrayElementAtIndex(0).objectReferenceValue = material;
  					spriteMeshSO.ApplyModifiedProperties();
  				}
  				
  				for (int i = 0; i < spriteMesh.sharedMaterials.Length; i++)
  				{
  					Material material = spriteMesh.sharedMaterials [i];
  					
  					if(material)
  					{
  						if(spriteMesh.sprite)
  						{
  							material.mainTexture = SpriteUtility.GetSpriteTexture(spriteMesh.sprite,false);
  						}
  						
  						material.name = spriteMesh.name + "_" + i;
  						material.hideFlags = HideFlags.HideInHierarchy;
  						EditorUtility.SetDirty(material);
  					}
  				}
  				
  				spriteMeshData.hideFlags = HideFlags.HideInHierarchy;
  				EditorUtility.SetDirty(spriteMeshData);
  				
  				int width = 0;
  				int height = 0;
  				
  				GetSpriteTextureSize(spriteMesh.sprite,ref width,ref height);
  
  				Vector3[] vertices = GetMeshVertices(spriteMesh.sprite, spriteMeshData);
  
  				Vector2 textureWidthHeightInv = new Vector2(1f/width,1f/height);
  				
  				Vector2[] uvs = (new List<Vector2>(spriteMeshData.vertices)).ConvertAll( v => Vector2.Scale(v,textureWidthHeightInv)).ToArray();
  				
  				Vector3[] normals = (new List<Vector3>(vertices)).ConvertAll( v => Vector3.back ).ToArray();
  				
  				BoneWeight[] boneWeightsData = spriteMeshData.boneWeights;
  				
  				if(boneWeightsData.Length != spriteMeshData.vertices.Length)
  				{
  					boneWeightsData = new BoneWeight[spriteMeshData.vertices.Length];
  				}
  				
  				List<UnityEngine.BoneWeight> boneWeights = new List<UnityEngine.BoneWeight>(boneWeightsData.Length);
  				
  				List<float> verticesOrder = new List<float>(spriteMeshData.vertices.Length);
  				
  				for (int i = 0; i < boneWeightsData.Length; i++)
  				{
  					BoneWeight boneWeight = boneWeightsData[i];
  					
  					List< KeyValuePair<int,float> > pairs = new List<KeyValuePair<int, float>>();
  					pairs.Add(new KeyValuePair<int, float>(boneWeight.boneIndex0,boneWeight.weight0));
  					pairs.Add(new KeyValuePair<int, float>(boneWeight.boneIndex1,boneWeight.weight1));
  					pairs.Add(new KeyValuePair<int, float>(boneWeight.boneIndex2,boneWeight.weight2));
  					pairs.Add(new KeyValuePair<int, float>(boneWeight.boneIndex3,boneWeight.weight3));
  					
  					pairs = pairs.OrderByDescending(s=>s.Value).ToList();
  					
  					UnityEngine.BoneWeight boneWeight2 = new UnityEngine.BoneWeight();
  					boneWeight2.boneIndex0 = Mathf.Max(0,pairs[0].Key);
  					boneWeight2.boneIndex1 = Mathf.Max(0,pairs[1].Key);
  					boneWeight2.boneIndex2 = Mathf.Max(0,pairs[2].Key);
  					boneWeight2.boneIndex3 = Mathf.Max(0,pairs[3].Key);
  					boneWeight2.weight0 = pairs[0].Value;
  					boneWeight2.weight1 = pairs[1].Value;
  					boneWeight2.weight2 = pairs[2].Value;
  					boneWeight2.weight3 = pairs[3].Value;
  					
  					boneWeights.Add(boneWeight2);
  					
  					float vertexOrder = i;
  					
  					if(spriteMeshData.bindPoses.Length > 0)
  					{
  						vertexOrder = spriteMeshData.bindPoses[boneWeight2.boneIndex0].zOrder * boneWeight2.weight0 +
  							spriteMeshData.bindPoses[boneWeight2.boneIndex1].zOrder * boneWeight2.weight1 +
  								spriteMeshData.bindPoses[boneWeight2.boneIndex2].zOrder * boneWeight2.weight2 +
  								spriteMeshData.bindPoses[boneWeight2.boneIndex3].zOrder * boneWeight2.weight3;
  					}
  					
  					verticesOrder.Add(vertexOrder);
  				}
  				
  				List<WeightedTriangle> weightedTriangles = new List<WeightedTriangle>(spriteMeshData.indices.Length / 3);
  				
  				for(int i = 0; i < spriteMeshData.indices.Length; i+=3)
  				{
  					int p1 = spriteMeshData.indices[i];
  					int p2 = spriteMeshData.indices[i+1];
  					int p3 = spriteMeshData.indices[i+2];
  					
  					weightedTriangles.Add(new WeightedTriangle(p1,p2,p3,
  					                                           verticesOrder[p1],
  					                                           verticesOrder[p2],
  					                                           verticesOrder[p3]));
  				}
  				
  				weightedTriangles = weightedTriangles.OrderBy( t => t.weight ).ToList();
  				
  				List<int> indices = new List<int>(spriteMeshData.indices.Length);
  				
  				for(int i = 0; i < weightedTriangles.Count; ++i)
  				{
  					WeightedTriangle t = weightedTriangles[i];
  					indices.Add(t.p1);
  					indices.Add(t.p2);
  					indices.Add(t.p3);
  				}
  
  				List<Matrix4x4> bindposes = (new List<BindInfo>(spriteMeshData.bindPoses)).ConvertAll( p => p.bindPose );
  
  				for (int i = 0; i < bindposes.Count; i++)
  				{
  					Matrix4x4 bindpose = bindposes [i];
  
  					bindpose.m23 = 0f;
  
  					bindposes[i] = bindpose;
  				}	
  
  				spriteMesh.sharedMesh.Clear();
  				spriteMesh.sharedMesh.vertices = vertices;
  				spriteMesh.sharedMesh.uv = uvs;
  				spriteMesh.sharedMesh.triangles = indices.ToArray();
  				spriteMesh.sharedMesh.normals = normals;
  				spriteMesh.sharedMesh.boneWeights = boneWeights.ToArray();
  				spriteMesh.sharedMesh.bindposes = bindposes.ToArray();
  				spriteMesh.sharedMesh.RecalculateBounds();
  
  				RebuildBlendShapes(spriteMesh);
  			}
  		}
  
  		public static Vector3[] GetMeshVertices(SpriteMesh spriteMesh)
  		{
  			return GetMeshVertices(spriteMesh.sprite, LoadSpriteMeshData(spriteMesh));
  		}
  
  		public static Vector3[] GetMeshVertices(Sprite sprite, SpriteMeshData spriteMeshData)
  		{
  
gt: 			float pixelsPerUnit = GetSpritePixelsPerUnit(sprite);