context: using UnityEngine;
  using System.Collections;
  using System.Collections.Generic;
  using System.Xml;
  using System.Xml.Serialization;
  
  [AddComponentMenu("2D/Tile Info")]
  public class TileInfo : MonoBehaviour {
  
  	public enum CollisionType {
  		None, Full, SlopeUpRight, SlopeUpLeft, Platform
  	};
  
  	public enum AutoTileEdgeMode {
  		None, LinkToEdge, Wrap
  	};
  
  	public enum AutoTileType {
  		Normal, IsometricWall
  	};
  
  	public class TilePolygonPoints {
  		public bool isKnown;
  		public Vector2[] points;
  	}
  	[HideInInspector]
  	[System.NonSerialized]
  	public TilePolygonPoints[,] knownTilePoints;
  
  	[HideInInspector]
  	/// <summary>
  	/// List of the tiles in a 1D array in the format [ local y * mapWidth + local x ].
  	/// To get the index of a tile from a world position use WorldPointToMapIndex
  	/// </summary>
  	public Tile[] tiles;
  	[HideInInspector]
  	public int mapWidth;
  	[HideInInspector]
  	public int mapHeight;
  	//	[HideInInspector]
  	//	public int _numberOfTiles;
  	//
  	//	public int numberOfTiles {
  	//		get {
  	//			return _numberOfTiles;
  	//		}
  	//	}
  
  	//[HideInInspector]
  	//public List<Vector2> tileIndex = new List<Vector2>();
  //	[HideInInspector]
  	public int tileSize;
  //	[HideInInspector]
  	public int spacing;
  //	[HideInInspector]
  	public int offsetX;
  //	[HideInInspector]
  	public int offsetY;
  	[HideInInspector]
  	public float zoomFactor = 1;
  	[HideInInspector]
  	public CollisionType[] collisions;
  	//[HideInInspector]
  	//public Vector3 positionAtLastEdit;
  	[HideInInspector]
  	public int numberOfAutotiles;
  	[HideInInspector]
  	public List<string> autoTileNames = new List<string>();
  	[HideInInspector]
  	public List<int> autoTileLinkMask = new List<int>();
  	[HideInInspector]
  	public List<Tile> autoTileData = new List<Tile>();
  	[HideInInspector]
  	public List<bool> showAutoTile = new List<bool>();
  	[HideInInspector]
  	public List<AutoTileEdgeMode> autoTileEdgeMode = new List<AutoTileEdgeMode>();
  	[HideInInspector]
  	public List<AutoTileType>autoTileType = new List<AutoTileType>();
  	[HideInInspector] public bool pixelColliders;
  
  	public TileInfo upLayer;
  	public TileInfo downLayer;
  	public TileInfo leftLayer;
  	public TileInfo rightLayer;
  	[Space(10)]
  	public TileInfo upRightLayer;
  	public TileInfo upLeftLayer;
  	public TileInfo downRightLayer;
  	public TileInfo downLeftLayer;
  
  	//settings
  	[HideInInspector]
  	public bool update3DWalls = false;
  	[HideInInspector]
  	public float depthOf3DWalls = 10;
  	[HideInInspector]
  	public bool update2DColliders = false;
  
  	[HideInInspector]
  	public bool mapHasChanged = false;
  
  	Vector2 _nonTransparentUV = new Vector2( -1, -1 );
  
  	public Vector2 nonTransparentUV {
  		get {
  
  			if( _nonTransparentUV == new Vector2( -1, -1 ) ) {
  				if( meshRenderer == null || meshRenderer.sharedMaterial == null || meshRenderer.sharedMaterial.mainTexture == null )
  					return Vector2.zero;
  
  				Texture2D tex = (Texture2D)meshRenderer.sharedMaterial.mainTexture;
  				for( int x = 0; x < tex.width; x++ ) {
  					for( int y = 0; y < tex.height; y++ ) {
  						if( tex.GetPixel( x, y ).a == 1 ) {
  							_nonTransparentUV = new Vector2( (float)x / (float)tex.width, (float)y / (float)tex.height );
  							return _nonTransparentUV;
  						}
  					}
  				}
  			}
  			return _nonTransparentUV;
  		}
  	}
  
  	PolygonCollider2D _mainCollider;
  
  	public PolygonCollider2D mainCollider {
  		get {
  			if( _mainCollider == null ) {
  				PolygonCollider2D[] allColliders = GetComponents<PolygonCollider2D>();
  				foreach( PolygonCollider2D col in allColliders ) {
  					if( !col.usedByEffector )
  						_mainCollider = col;
  				}
  				if( _mainCollider == null )
  					_mainCollider = gameObject.AddComponent<PolygonCollider2D>();
  			}
  			return _mainCollider;
  		}
  	}
  
  	PolygonCollider2D _platformCollider;
  
  	public PolygonCollider2D platformCollider {
  		get {
  			if( _platformCollider == null ) {
  				PolygonCollider2D[] allColliders = GetComponents<PolygonCollider2D>();
  				foreach( PolygonCollider2D col in allColliders ) {
  					if( col.usedByEffector )
  						_platformCollider = col;
  				}
  				if( _platformCollider == null ) {
  					_platformCollider = gameObject.AddComponent<PolygonCollider2D>();
  					_platformCollider.usedByEffector = true;
  					if( GetComponent<PlatformEffector2D>() == null )
  						gameObject.AddComponent<PlatformEffector2D>();
  				}
  			}
  			return _platformCollider;
  		}
  	}
  
  	MeshRenderer _meshRenderer;
  
  	public MeshRenderer meshRenderer {
  		get {
  			if( _meshRenderer == null )
  				_meshRenderer = GetComponent<MeshRenderer>();
  			return _meshRenderer;
  		}
  	}
  
  	public static TileInfo[] _allMaps;
  	public static TileInfo[] allMaps {
  		get {
  			if( _allMaps == null )
  				_allMaps = FindObjectsOfType<TileInfo>();
  			return _allMaps;
  		}
  	}
  
  	public static TileInfo GetMapAtWorldPos ( Vector2 worldPos ) {
  		foreach( TileInfo map in allMaps ) {
  			if( map.WorldPointToMapIndex( worldPos ) != -1 )
  				return map;
  		}
  		return null;
  	}
  
  	public static TileInfo[] GetMapsAtWorldPos ( Vector2 worldPos ) {
  		List<TileInfo> result = new List<TileInfo>();
  		foreach( TileInfo map in allMaps ) {
  			if( map.WorldPointToMapIndex( worldPos ) != -1 )
  				result.Add( map );
  		}
  		return result.ToArray();
  	}
  
  	public static bool CollisionAtWorldPos ( Vector2 worldPos ) {
  		TileInfo[] maps = GetMapsAtWorldPos( worldPos );
  		foreach( TileInfo map in maps ) {
  			if( map.tiles[map.WorldPointToMapIndex(worldPos)].GetCollisionType( map ) != CollisionType.None )
  				return true;
  		}
  		return false;
  	}
  
  	public static CollisionType CollisionTypeAtWorldPos ( Vector2 worldPos ) {
  		TileInfo[] maps = GetMapsAtWorldPos( worldPos );
  		CollisionType result = CollisionType.None;
  		foreach( TileInfo map in maps ) {
  			CollisionType tempResult = map.tiles[map.WorldPointToMapIndex(worldPos)].GetCollisionType( map );
  			if( tempResult != CollisionType.None && result != CollisionType.Full )
  				result = tempResult;
  		}
  		return result;
  	}
  
  	void AddWall ( Vector2 p1, Vector2 p2, List<Vector3> vertices, List<Vector2> uv, List<int> triangles ) {
  		vertices.Add( new Vector3( p1.x, p1.y, depthOf3DWalls ) );
  		vertices.Add( new Vector3( p1.x, p1.y, 0 ) );
  		vertices.Add( new Vector3( p2.x, p2.y, 0 ) );
  		vertices.Add( new Vector3( p2.x, p2.y, depthOf3DWalls ) );
  
  		uv.Add( nonTransparentUV );
  		uv.Add( nonTransparentUV );
  		uv.Add( nonTransparentUV );
  		uv.Add( nonTransparentUV );
  
  		triangles.Add( vertices.Count - 4 );
  		triangles.Add( vertices.Count - 3 );
  		triangles.Add( vertices.Count - 1 );
  		triangles.Add( vertices.Count - 1 );
  		triangles.Add( vertices.Count - 3 );
  		triangles.Add( vertices.Count - 2 );
  	}
  
  	void OnEnable () {
  		if( GetComponent<MeshFilter>().sharedMesh == null ) {
  			mapHasChanged = true;
  			UpdateVisualMesh( true );
  		}
  	}
  
  	public struct Collider2DEdgeConnection {
  		public int index;
  		public bool toP1;
  		public Collider2DEdgeConnection ( int index, bool toP1 ) {
  			this.index = index;
  			this.toP1 = toP1;
  		}
  	}
  
  	public struct Collider2DEdge {
  		public Vector2 p1;
  		public Vector2 p2;
  		public List<Collider2DEdgeConnection> p1Connections;
  		public List<Collider2DEdgeConnection> p2Connections;
  		public bool processed;
  		public Collider2DEdge ( Vector2 p1, Vector2 p2 ) {
  			this.p1 = p1;
  			this.p2 = p2;
  			this.p1Connections = new List<Collider2DEdgeConnection>();
  			this.p2Connections = new List<Collider2DEdgeConnection>();
  			this.processed = false;
  		}
  	}
  	bool Approximately( Vector2 v1, Vector2 v2 ) {
  		float tolerance = 0.05f * zoomFactor;
  		return ( v1.x > v2.x - tolerance && v1.x < v2.x + tolerance && v1.y > v2.y - tolerance && v1.y < v2.y + tolerance );
  	}
  
  	void AddEdge( List<Collider2DEdge> edges, Vector2 p1, Vector2 p2 ) {
  		int index = edges.Count;
  		Collider2DEdge thisEdge = new Collider2DEdge( p1, p2 );
  		for (int i = 0; i < index; i++) {
  			if( Approximately( edges[i].p1, p1 ) ) {
  				edges[i].p1Connections.Add( new Collider2DEdgeConnection( index, true ) );
  				thisEdge.p1Connections.Add( new Collider2DEdgeConnection( i, true ) );
  			}
  			else if( Approximately( edges[i].p1, p2 ) ) {
  				edges[i].p1Connections.Add( new Collider2DEdgeConnection( index, false ) );
  				thisEdge.p2Connections.Add( new Collider2DEdgeConnection( i, true ) );
  			}
  			else if( Approximately( edges[i].p2, p1 ) ) {
  				edges[i].p2Connections.Add( new Collider2DEdgeConnection( index, true ) );
  				thisEdge.p1Connections.Add( new Collider2DEdgeConnection( i, false ) );
  			}
  			else if( Approximately( edges[i].p2, p2 ) ) {
  				edges[i].p2Connections.Add( new Collider2DEdgeConnection( index, false ) );
  				thisEdge.p2Connections.Add( new Collider2DEdgeConnection( i, false ) );
  			}
  		}
  		edges.Add( thisEdge );
  	}
  
  	void RemoveEdgeConnections( List<Collider2DEdge> edges, int index ) {
  //		if( isP2End ) {
  			for( int i = 0; i < edges[index].p2Connections.Count; i++ ) {
  				int j = edges[index].p2Connections[i].index;
  				if( edges[index].p2Connections[i].toP1 ) {
  					for( int k = 0; k < edges[j].p1Connections.Count; k++ ) {
  						if( edges[j].p1Connections[k].index == index ) {
  							edges[j].p1Connections.RemoveAt( k );
  							break;
  						}
  					}
  				}
  				else {
  					for( int k = 0; k < edges[j].p2Connections.Count; k++ ) {
  						if( edges[j].p2Connections[k].index == index ) {
  							edges[j].p2Connections.RemoveAt( k );
  							break;
  						}
  					}
  				}
  			}
  //		}
  //		else {
  			for( int i = 0; i < edges[index].p1Connections.Count; i++ ) {
  				int j = edges[index].p1Connections[i].index;
  				if( edges[index].p1Connections[i].toP1 ) {
  					for( int k = 0; k < edges[j].p1Connections.Count; k++ ) {
  						if( edges[j].p1Connections[k].index == index ) {
  							edges[j].p1Connections.RemoveAt( k );
  							break;
  						}
  					}
  				}
  				else {
  					for( int k = 0; k < edges[j].p2Connections.Count; k++ ) {
  						if( edges[j].p2Connections[k].index == index ) {
  							edges[j].p2Connections.RemoveAt( k );
  							break;
  						}
  					}
  				}
  			}
  //		}
  	}
  
  	void PolygoniseEdges ( List<Vector2[]> polygons, List<Collider2DEdge> edges ) {
  		if( edges.Count == 0 )
  			return;
  
gt: 		List<Vector2> currentPolygon = new List<Vector2>();