public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY)
		{
			// Build local mesh
			Vector3[] localMeshVertices = new Vector3[0];
			int[] localMeshIndices = new int[0];
			BuildLocalMeshForChunk(tileMap, chunk, baseX, baseY, ref localMeshVertices, ref localMeshIndices);
			
			// only process when there are more than two triangles
			// avoids a lot of branches later
			if (localMeshIndices.Length > 6) 
			{
				// Remove duplicate verts
				localMeshVertices = WeldVertices(localMeshVertices, ref localMeshIndices);
				
				// Remove duplicate and back-to-back faces
				// Removes inside faces
				localMeshIndices = RemoveDuplicateFaces(localMeshIndices);
	
				// Merge coplanar faces
				// Optimize (remove unused vertices, reindex)
			}
	
#if !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2)
			foreach (EdgeCollider2D c2d in chunk.edgeColliders) {
				if (c2d != null) {
					tk2dUtil.DestroyImmediate(c2d);
				}
			}
			chunk.edgeColliders.Clear();
#endif

			if (localMeshVertices.Length > 0)
			{
				if (chunk.colliderMesh != null)
				{
					tk2dUtil.DestroyImmediate(chunk.colliderMesh);
					chunk.colliderMesh = null;
				}
				
				if (chunk.meshCollider == null)
				{
					chunk.meshCollider = chunk.gameObject.GetComponent<MeshCollider>();
					if (chunk.meshCollider == null)
						chunk.meshCollider = tk2dUtil.AddComponent<MeshCollider>(chunk.gameObject);
				}
				
				chunk.colliderMesh = tk2dUtil.CreateMesh();
				chunk.colliderMesh.vertices = localMeshVertices;
				chunk.colliderMesh.triangles = localMeshIndices;

				chunk.colliderMesh.RecalculateBounds();
				
				chunk.meshCollider.sharedMesh = chunk.colliderMesh;
			}
			else
			{
				chunk.DestroyColliderData(tileMap);
			}
		}		
 private void CreateChunk(SpriteChunk chunk)
 {
     if ((chunk.spriteIds == null) || (chunk.spriteIds.Length == 0))
     {
         chunk.spriteIds = new int[this.divX * this.divY];
         for (int i = 0; i < (this.divX * this.divY); i++)
         {
             chunk.spriteIds[i] = -1;
         }
     }
 }
        public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk)
        {
            // Build local mesh
            Vector3[] localMeshVertices = new Vector3[0];
            int[] localMeshIndices = new int[0];
            BuildLocalMeshForChunk(tileMap, chunk, ref localMeshVertices, ref localMeshIndices);

            // only process when there are more than two triangles
            // avoids a lot of branches later
            if (localMeshIndices.Length > 6)
            {
                // Remove duplicate verts
                localMeshVertices = WeldVertices(localMeshVertices, ref localMeshIndices);

                // Remove duplicate and back-to-back faces
                // Removes inside faces
                localMeshIndices = RemoveDuplicateFaces(localMeshIndices);

                // Merge coplanar faces
                // Optimize (remove unused vertices, reindex)
            }

            if (localMeshVertices.Length > 0)
            {
                if (chunk.colliderMesh != null)
                {
                    GameObject.DestroyImmediate(chunk.colliderMesh);
                    chunk.colliderMesh = null;
                }

                if (chunk.meshCollider == null)
                {
                    chunk.meshCollider = chunk.gameObject.GetComponent<MeshCollider>();
                    if (chunk.meshCollider == null)
                        chunk.meshCollider = chunk.gameObject.AddComponent<MeshCollider>();
                }

                chunk.colliderMesh = tileMap.GetOrCreateMesh();
                chunk.colliderMesh.vertices = localMeshVertices;
                chunk.colliderMesh.triangles = localMeshIndices;

                chunk.colliderMesh.RecalculateBounds();
                if (tileMap.serializeRenderData)
                    chunk.mesh.RecalculateNormals();

                chunk.meshCollider.sharedMesh = chunk.colliderMesh;
            }
            else
            {
                chunk.DestroyColliderData(tileMap);
            }
        }
Example #4
0
 void CreateChunk(SpriteChunk chunk)
 {
     if (chunk.spriteIds == null || chunk.spriteIds.Length == 0)
     {
         chunk.spriteIds = new int[divX * divY];
         for (int i = 0; i < divX * divY; ++i)
             chunk.spriteIds[i] = -1;
     }
 }
 public static void SpawnPrefabsForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, int layer, int[] prefabCounts)
 {
     int[] spriteIds = chunk.spriteIds;
     GameObject[] tilePrefabs = tileMap.data.tilePrefabs;
     Vector3 tileSize = tileMap.data.tileSize;
     Transform parent = chunk.gameObject.transform;
     float x = 0f;
     float y = 0f;
     tileMap.data.GetTileOffset(out x, out y);
     for (int i = 0; i < tileMap.partitionSizeY; i++)
     {
         float num4 = ((baseY + i) & 1) * x;
         for (int j = 0; j < tileMap.partitionSizeX; j++)
         {
             int tileFromRawTile = GetTileFromRawTile(spriteIds[(i * tileMap.partitionSizeX) + j]);
             if ((tileFromRawTile >= 0) && (tileFromRawTile < tilePrefabs.Length))
             {
                 UnityEngine.Object original = tilePrefabs[tileFromRawTile];
                 if (original != null)
                 {
                     prefabCounts[tileFromRawTile]++;
                     GameObject item = GetExistingTilePrefabInstance(tileMap, baseX + j, baseY + i, layer);
                     bool flag = item != null;
                     if (item == null)
                     {
                         item = UnityEngine.Object.Instantiate(original, Vector3.zero, Quaternion.identity) as GameObject;
                     }
                     if (item != null)
                     {
                         GameObject obj4 = original as GameObject;
                         Vector3 vector2 = new Vector3(tileSize.x * (j + num4), tileSize.y * i, 0f);
                         bool enablePrefabOffset = false;
                         TileInfo tileInfoForSprite = tileMap.data.GetTileInfoForSprite(tileFromRawTile);
                         if (tileInfoForSprite != null)
                         {
                             enablePrefabOffset = tileInfoForSprite.enablePrefabOffset;
                         }
                         if (enablePrefabOffset && (obj4 != null))
                         {
                             vector2 += obj4.transform.position;
                         }
                         if (!flag)
                         {
                             item.name = original.name + " " + prefabCounts[tileFromRawTile].ToString();
                         }
                         tk2dUtil.SetTransformParent(item.transform, parent);
                         item.transform.localPosition = vector2;
                         TilePrefabsX.Add(baseX + j);
                         TilePrefabsY.Add(baseY + i);
                         TilePrefabsLayer.Add(layer);
                         TilePrefabsInstance.Add(item);
                     }
                 }
             }
         }
     }
 }
    /* Creates Farseer Box Colliders for tiles in chunk and sets them as children of container. */
    void GenerateCollidersForChunk(SpriteChunk chunk, GameObject container)
    {
        int spriteCount = spriteDefinitions.Length;
        int[] chunkData = chunk.spriteIds;

        /* For every row in the chunk... */
        for (int y = 0; y < maxTilesY; ++y) {

            /* For every column in the chunk... */
            for (int x = 0; x < maxTilesX; ++x) {

                int spriteId = chunkData[y * tilemap.partitionSizeX + x];
                int spriteIdx = BuilderUtil.GetTileFromRawTile(spriteId);

                /* Handle if tile has no valid sprite. */
                if (spriteIdx < 0 || spriteIdx >= spriteCount) {
                    continue;
                }
                else if (tilemap.data.tilePrefabs[spriteIdx]) {
                    continue;
                }

                tk2dSpriteDefinition spriteData = spriteDefinitions[spriteIdx];

                /* If the tile is marked as User Defined, then add a box collider. */
                if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Unset) {

                    Vector3 newBoxColliderPosition = new Vector3(
                        chunk.gameObject.transform.position.x + x * tileWidth,
                        chunk.gameObject.transform.position.y + y * tileHeight,
                        chunk.gameObject.transform.position.z
                    );

                    GameObject newColliderObject;

                    if (roundedBoxColliders) {
                        newColliderObject = CreateRoundedBoxCollider(newBoxColliderPosition, "Rounded Box Collider " + x + " " + y);
                    }
                    else {
                        newColliderObject = CreateBoxCollider(newBoxColliderPosition, "Box Collider " + x + " " + y);
                    }

                    newColliderObject.transform.parent = container.transform;
                    newColliderObject.gameObject.AddComponent<FarseerFollowParent>();
                    newColliderObject.gameObject.AddComponent<FarseerEnableDisable>();
                }
            }
        }
    }
		public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY)
		{
#if !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2)
			////////////////////////////////////////////////////////////////////////////////////////
			// 1. Build local edge list
			////////////////////////////////////////////////////////////////////////////////////////
			Vector2[] localVerts = new Vector2[0];
			int[] localIndices = new int[0];
			List<Vector2[]> mergedEdges = new List<Vector2[]>();
			BuildLocalMeshForChunk(tileMap, chunk, baseX, baseY, ref localVerts, ref localIndices);

			////////////////////////////////////////////////////////////////////////////////////////
			// 2. Optimize
			////////////////////////////////////////////////////////////////////////////////////////
			if (localIndices.Length > 4) {
				// Remove duplicate verts, reindex
				localVerts = WeldVertices(localVerts, ref localIndices);
				// Remove duplicate and back-to-back edges
				// Removes inside edges
				localIndices = RemoveDuplicateEdges(localIndices);
			}

			////////////////////////////////////////////////////////////////////////////////////////
			// 3. Build and optimize an edge list
			////////////////////////////////////////////////////////////////////////////////////////
			mergedEdges = MergeEdges( localVerts, localIndices );

			////////////////////////////////////////////////////////////////////////////////////////
			// 4. Build the edge colliders
			////////////////////////////////////////////////////////////////////////////////////////

			if (chunk.meshCollider != null) {
				tk2dUtil.DestroyImmediate(chunk.meshCollider);
				chunk.meshCollider = null;
			}

			if (mergedEdges.Count == 0) {
				for (int i = 0; i < chunk.edgeColliders.Count; ++i) {
					if (chunk.edgeColliders[i] != null) {
						tk2dUtil.DestroyImmediate(chunk.edgeColliders[i]);
					}
				}
				chunk.edgeColliders.Clear();
			}
			else {
				int numEdges = mergedEdges.Count;

				// Destroy surplus
				for (int i = numEdges; i < chunk.edgeColliders.Count; ++i) {
					if (chunk.edgeColliders[i] != null) {
						tk2dUtil.DestroyImmediate(chunk.edgeColliders[i]);
					}
				}
				int numToRemove = chunk.edgeColliders.Count - numEdges;
				if (numToRemove > 0) {
					chunk.edgeColliders.RemoveRange(chunk.edgeColliders.Count - numToRemove, numToRemove);
				}

				// Make sure existing ones are not null
				for (int i = 0; i < chunk.edgeColliders.Count; ++i) {
					if (chunk.edgeColliders[i] == null) {
						chunk.edgeColliders[i] = tk2dUtil.AddComponent<EdgeCollider2D>(chunk.gameObject);
					}
				}
				// Create missing
				while (chunk.edgeColliders.Count < numEdges) {
					chunk.edgeColliders.Add( tk2dUtil.AddComponent<EdgeCollider2D>(chunk.gameObject) );
				}

				for (int i = 0; i < numEdges; ++i) {
					chunk.edgeColliders[i].points = mergedEdges[i];
				}
			}
#endif
		}		
        public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY)
        {
            // Build local mesh
            Vector3[] localMeshVertices = new Vector3[0];
            int[]     localMeshIndices  = new int[0];
            BuildLocalMeshForChunk(tileMap, chunk, baseX, baseY, ref localMeshVertices, ref localMeshIndices);

            // only process when there are more than two triangles
            // avoids a lot of branches later
            if (localMeshIndices.Length > 6)
            {
                // Remove duplicate verts
                localMeshVertices = WeldVertices(localMeshVertices, ref localMeshIndices);

                // Remove duplicate and back-to-back faces
                // Removes inside faces
                localMeshIndices = RemoveDuplicateFaces(localMeshIndices);

                // Merge coplanar faces
                // Optimize (remove unused vertices, reindex)
            }

#if !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2)
            foreach (EdgeCollider2D c2d in chunk.edgeColliders)
            {
                if (c2d != null)
                {
                    tk2dUtil.DestroyImmediate(c2d);
                }
            }
            chunk.edgeColliders.Clear();
#endif

            if (localMeshVertices.Length > 0)
            {
                if (chunk.colliderMesh != null)
                {
                    tk2dUtil.DestroyImmediate(chunk.colliderMesh);
                    chunk.colliderMesh = null;
                }

                if (chunk.meshCollider == null)
                {
                    chunk.meshCollider = chunk.gameObject.GetComponent <MeshCollider>();
                    if (chunk.meshCollider == null)
                    {
                        chunk.meshCollider = tk2dUtil.AddComponent <MeshCollider>(chunk.gameObject);
                    }
                }

                chunk.colliderMesh           = tk2dUtil.CreateMesh();
                chunk.colliderMesh.vertices  = localMeshVertices;
                chunk.colliderMesh.triangles = localMeshIndices;

                chunk.colliderMesh.RecalculateBounds();

                chunk.meshCollider.sharedMesh = chunk.colliderMesh;
            }
            else
            {
                chunk.DestroyColliderData(tileMap);
            }
        }
        // Builds an unoptimized mesh for this chunk
        static void BuildLocalMeshForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, ref Vector3[] vertices, ref int[] indices)
        {
            List<Vector3> vertexList = new List<Vector3>();
            List<int> indexList = new List<int>();

            int spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length;
            Vector3 tileSize = tileMap.data.tileSize;

            var tilePrefabs = tileMap.data.tilePrefabs;

            float xOffsetMult = 0.0f, yOffsetMult = 0.0f;
            tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult);

            var chunkData = chunk.spriteIds;
            for (int y = 0; y < tileMap.partitionSizeY; ++y)
            {
                float xOffset = ((baseY + y) & 1) * xOffsetMult;
                for (int x = 0; x < tileMap.partitionSizeX; ++x)
                {
                    int tile = chunkData[y * tileMap.partitionSizeX + x];
                    Vector3 currentPos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0);

                    if (tile < 0 || tile >= spriteCount)
                        continue;

                    if (tilePrefabs[tile])
                        continue;

                    var spriteData = tileMap.SpriteCollectionInst.spriteDefinitions[tile];
                    int baseVertexIndex = vertexList.Count;

                    if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Box)
                    {
                        Vector3 origin = spriteData.colliderVertices[0] + currentPos;
                        Vector3 extents = spriteData.colliderVertices[1];
                        Vector3 min = origin - extents;
                        Vector3 max = origin + extents;

                        vertexList.Add(new Vector3(min.x, min.y, min.z));
                        vertexList.Add(new Vector3(min.x, min.y, max.z));
                        vertexList.Add(new Vector3(max.x, min.y, min.z));
                        vertexList.Add(new Vector3(max.x, min.y, max.z));
                        vertexList.Add(new Vector3(min.x, max.y, min.z));
                        vertexList.Add(new Vector3(min.x, max.y, max.z));
                        vertexList.Add(new Vector3(max.x, max.y, min.z));
                        vertexList.Add(new Vector3(max.x, max.y, max.z));

            //						int[] indicesBack = { 0, 1, 2, 2, 1, 3, 6, 5, 4, 7, 5, 6, 3, 7, 6, 2, 3, 6, 4, 5, 1, 4, 1, 0 };
                        int[] indicesFwd = { 2, 1, 0, 3, 1, 2, 4, 5, 6, 6, 5, 7, 6, 7, 3, 6, 3, 2, 1, 5, 4, 0, 1, 4 };

                        var srcIndices = indicesFwd;
                        for (int i = 0; i < srcIndices.Length; ++i)
                        {
                            indexList.Add(baseVertexIndex + srcIndices[i]);
                        }
                    }
                    else if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Mesh)
                    {
                        for (int i = 0; i < spriteData.colliderVertices.Length; ++i)
                        {
                            Vector3 pos = spriteData.colliderVertices[i] + currentPos;
                            vertexList.Add(pos);
                        }

                        var srcIndices = spriteData.colliderIndicesFwd;
                        for (int i = 0; i < srcIndices.Length; ++i)
                        {
                            indexList.Add(baseVertexIndex + srcIndices[i]);
                        }
                    }
                }
            }

            vertices = vertexList.ToArray();
            indices = indexList.ToArray();
        }
        public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, ColorChunk colorChunk, bool useColor, bool skipPrefabs, int baseX, int baseY)
        {
            List <Vector3> meshVertices = new List <Vector3>();
            List <Color>   meshColors   = new List <Color>();
            List <Vector2> meshUvs      = new List <Vector2>();

            //List<int> meshIndices = new List<int>();

            int[]   spriteIds   = chunk.spriteIds;
            Vector3 tileSize    = tileMap.data.tileSize;
            int     spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length;

            Object[]             tilePrefabs = tileMap.data.tilePrefabs;
            tk2dSpriteDefinition firstSprite = tileMap.SpriteCollectionInst.FirstValidDefinition;
            bool buildNormals = (firstSprite != null && firstSprite.normals != null && firstSprite.normals.Length > 0);

            Color32 clearColor = (useColor && tileMap.ColorChannel != null)?tileMap.ColorChannel.clearColor:Color.white;

            // revert to no color mode (i.e. fill with clear color) when there isn't a color channel, or it is empty
            if (colorChunk == null || colorChunk.colors.Length == 0)
            {
                useColor = false;
            }

            int x0, x1, dx;
            int y0, y1, dy;

            BuilderUtil.GetLoopOrder(tileMap.data.sortMethod,
                                     tileMap.partitionSizeX, tileMap.partitionSizeY,
                                     out x0, out x1, out dx,
                                     out y0, out y1, out dy);

            float xOffsetMult = 0.0f, yOffsetMult = 0.0f;

            tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult);

            List <int>[] meshIndices = new List <int> [tileMap.SpriteCollectionInst.materials.Length];
            for (int j = 0; j < meshIndices.Length; ++j)
            {
                meshIndices[j] = new List <int>();
            }

            int colorChunkSize = tileMap.partitionSizeX + 1;

            for (int y = y0; y != y1; y += dy)
            {
                float xOffset = ((baseY + y) & 1) * xOffsetMult;
                for (int x = x0; x != x1; x += dx)
                {
                    int  spriteId = spriteIds[y * tileMap.partitionSizeX + x];
                    int  tile     = BuilderUtil.GetTileFromRawTile(spriteId);
                    bool flipH    = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX);
                    bool flipV    = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY);
                    bool rot90    = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90);

                    Vector3 currentPos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0);

                    if (tile < 0 || tile >= spriteCount)
                    {
                        continue;
                    }

                    if (skipPrefabs && tilePrefabs[tile])
                    {
                        continue;
                    }

                    var sprite = tileMap.SpriteCollectionInst.spriteDefinitions[tile];

                    int baseVertex = meshVertices.Count;
                    for (int v = 0; v < sprite.positions.Length; ++v)
                    {
                        Vector3 flippedPos = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, sprite, sprite.positions[v], flipH, flipV, rot90);

                        if (useColor)
                        {
                            Color tileColorx0y0 = colorChunk.colors[y * colorChunkSize + x];
                            Color tileColorx1y0 = colorChunk.colors[y * colorChunkSize + x + 1];
                            Color tileColorx0y1 = colorChunk.colors[(y + 1) * colorChunkSize + x];
                            Color tileColorx1y1 = colorChunk.colors[(y + 1) * colorChunkSize + (x + 1)];

                            Vector3 centeredSpriteVertex = flippedPos - sprite.untrimmedBoundsData[0];
                            Vector3 alignedSpriteVertex  = centeredSpriteVertex + tileMap.data.tileSize * 0.5f;
                            float   tileColorX           = Mathf.Clamp01(alignedSpriteVertex.x / tileMap.data.tileSize.x);
                            float   tileColorY           = Mathf.Clamp01(alignedSpriteVertex.y / tileMap.data.tileSize.y);

                            Color color = Color.Lerp(
                                Color.Lerp(tileColorx0y0, tileColorx1y0, tileColorX),
                                Color.Lerp(tileColorx0y1, tileColorx1y1, tileColorX),
                                tileColorY);
                            meshColors.Add(color);
                        }
                        else
                        {
                            meshColors.Add(clearColor);
                        }

                        meshVertices.Add(currentPos + flippedPos);
                        meshUvs.Add(sprite.uvs[v]);
                    }

                    bool reverseIndices = false;                     // flipped?
                    if (flipH)
                    {
                        reverseIndices = !reverseIndices;
                    }
                    if (flipV)
                    {
                        reverseIndices = !reverseIndices;
                    }

                    List <int> indices = meshIndices[sprite.materialId];
                    for (int i = 0; i < sprite.indices.Length; ++i)
                    {
                        int j = reverseIndices ? (sprite.indices.Length - 1 - i) : i;
                        indices.Add(baseVertex + sprite.indices[j]);
                    }
                }
            }

            if (chunk.mesh == null)
            {
                chunk.mesh = tk2dUtil.CreateMesh();
            }

            chunk.mesh.vertices = meshVertices.ToArray();
            chunk.mesh.uv       = meshUvs.ToArray();
            chunk.mesh.colors   = meshColors.ToArray();

            List <Material> materials    = new List <Material>();
            int             materialId   = 0;
            int             subMeshCount = 0;

            foreach (var indices in meshIndices)
            {
                if (indices.Count > 0)
                {
                    materials.Add(tileMap.SpriteCollectionInst.materialInsts[materialId]);
                    subMeshCount++;
                }
                materialId++;
            }
            if (subMeshCount > 0)
            {
                chunk.mesh.subMeshCount = subMeshCount;
                chunk.gameObject.GetComponent <Renderer>().materials = materials.ToArray();
                int subMeshId = 0;
                foreach (var indices in meshIndices)
                {
                    if (indices.Count > 0)
                    {
                        chunk.mesh.SetTriangles(indices.ToArray(), subMeshId);
                        subMeshId++;
                    }
                }
            }

            chunk.mesh.RecalculateBounds();
            if (buildNormals)
            {
                chunk.mesh.RecalculateNormals();
            }

            var meshFilter = chunk.gameObject.GetComponent <MeshFilter>();

            meshFilter.sharedMesh = chunk.mesh;
        }
 private void Optimize(SpriteChunk chunk)
 {
     bool flag = true;
     foreach (int num in chunk.spriteIds)
     {
         if (num != -1)
         {
             flag = false;
             break;
         }
     }
     if (flag)
     {
         chunk.spriteIds = new int[0];
     }
 }
        // Builds an unoptimized mesh for this chunk
        static void BuildLocalMeshForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, ref Vector2[] vertices, ref int[] indices)
        {
            List <Vector2> verts = new List <Vector2>();
            List <int>     inds  = new List <int>();

            Vector2[] boxPos         = new Vector2[4];     // used for box collider
            int[]     boxInds        = { 0, 1, 1, 2, 2, 3, 3, 0 };
            int[]     boxIndsFlipped = { 0, 3, 3, 2, 2, 1, 1, 0 };

            int     spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length;
            Vector2 tileSize    = new Vector3(tileMap.data.tileSize.x, tileMap.data.tileSize.y);

            var tilePrefabs = tileMap.data.tilePrefabs;

            float xOffsetMult = 0.0f, yOffsetMult = 0.0f;

            tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult);

            var chunkData = chunk.spriteIds;

            for (int y = 0; y < tileMap.partitionSizeY; ++y)
            {
                float xOffset = ((baseY + y) & 1) * xOffsetMult;
                for (int x = 0; x < tileMap.partitionSizeX; ++x)
                {
                    int     spriteId   = chunkData[y * tileMap.partitionSizeX + x];
                    int     spriteIdx  = BuilderUtil.GetTileFromRawTile(spriteId);
                    Vector2 currentPos = new Vector2(tileSize.x * (x + xOffset), tileSize.y * y);

                    if (spriteIdx < 0 || spriteIdx >= spriteCount)
                    {
                        continue;
                    }

                    if (tilePrefabs[spriteIdx])
                    {
                        continue;
                    }

                    bool flipH = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX);
                    bool flipV = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY);
                    bool rot90 = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90);

                    bool reverseIndices = false;
                    if (flipH)
                    {
                        reverseIndices = !reverseIndices;
                    }
                    if (flipV)
                    {
                        reverseIndices = !reverseIndices;
                    }

                    tk2dSpriteDefinition spriteData = tileMap.SpriteCollectionInst.spriteDefinitions[spriteIdx];
                    int baseVertexIndex             = verts.Count;

                    if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Box)
                    {
                        Vector3 origin  = spriteData.colliderVertices[0];
                        Vector3 extents = spriteData.colliderVertices[1];
                        Vector3 min     = origin - extents;
                        Vector3 max     = origin + extents;

                        boxPos[0] = new Vector2(min.x, min.y);
                        boxPos[1] = new Vector2(max.x, min.y);
                        boxPos[2] = new Vector2(max.x, max.y);
                        boxPos[3] = new Vector2(min.x, max.y);
                        for (int i = 0; i < 4; ++i)
                        {
                            verts.Add(BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, boxPos[i], flipH, flipV, rot90) + currentPos);
                        }

                        int[] boxIndices = reverseIndices ? boxIndsFlipped : boxInds;
                        for (int i = 0; i < 8; ++i)
                        {
                            inds.Add(baseVertexIndex + boxIndices[i]);
                        }
                    }
                    else if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Mesh)
                    {
                        foreach (tk2dCollider2DData dat in spriteData.edgeCollider2D)
                        {
                            baseVertexIndex = verts.Count;
                            foreach (Vector2 pos in dat.points)
                            {
                                verts.Add(BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, pos, flipH, flipV, rot90) + currentPos);
                            }
                            int numVerts = dat.points.Length;
                            if (reverseIndices)
                            {
                                for (int i = numVerts - 1; i > 0; --i)
                                {
                                    inds.Add(baseVertexIndex + i);
                                    inds.Add(baseVertexIndex + i - 1);
                                }
                            }
                            else
                            {
                                for (int i = 0; i < numVerts - 1; ++i)
                                {
                                    inds.Add(baseVertexIndex + i);
                                    inds.Add(baseVertexIndex + i + 1);
                                }
                            }
                        }
                        foreach (tk2dCollider2DData dat in spriteData.polygonCollider2D)
                        {
                            baseVertexIndex = verts.Count;
                            foreach (Vector2 pos in dat.points)
                            {
                                verts.Add(BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, pos, flipH, flipV, rot90) + currentPos);
                            }
                            int numVerts = dat.points.Length;
                            if (reverseIndices)
                            {
                                for (int i = numVerts; i > 0; --i)
                                {
                                    inds.Add(baseVertexIndex + (i % numVerts));
                                    inds.Add(baseVertexIndex + i - 1);
                                }
                            }
                            else
                            {
                                for (int i = 0; i < numVerts; ++i)
                                {
                                    inds.Add(baseVertexIndex + i);
                                    inds.Add(baseVertexIndex + (i + 1) % numVerts);
                                }
                            }
                        }
                    }
                }
            }

            vertices = verts.ToArray();
            indices  = inds.ToArray();
        }
        public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY)
        {
#if !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2)
            ////////////////////////////////////////////////////////////////////////////////////////
            // 1. Build local edge list
            ////////////////////////////////////////////////////////////////////////////////////////
            Vector2[]        localVerts   = new Vector2[0];
            int[]            localIndices = new int[0];
            List <Vector2[]> mergedEdges  = new List <Vector2[]>();
            BuildLocalMeshForChunk(tileMap, chunk, baseX, baseY, ref localVerts, ref localIndices);

            ////////////////////////////////////////////////////////////////////////////////////////
            // 2. Optimize
            ////////////////////////////////////////////////////////////////////////////////////////
            if (localIndices.Length > 4)
            {
                // Remove duplicate verts, reindex
                localVerts = WeldVertices(localVerts, ref localIndices);
                // Remove duplicate and back-to-back edges
                // Removes inside edges
                localIndices = RemoveDuplicateEdges(localIndices);
            }

            ////////////////////////////////////////////////////////////////////////////////////////
            // 3. Build and optimize an edge list
            ////////////////////////////////////////////////////////////////////////////////////////
            mergedEdges = MergeEdges(localVerts, localIndices);

            ////////////////////////////////////////////////////////////////////////////////////////
            // 4. Build the edge colliders
            ////////////////////////////////////////////////////////////////////////////////////////

            if (chunk.meshCollider != null)
            {
                tk2dUtil.DestroyImmediate(chunk.meshCollider);
                chunk.meshCollider = null;
            }

            if (mergedEdges.Count == 0)
            {
                for (int i = 0; i < chunk.edgeColliders.Count; ++i)
                {
                    if (chunk.edgeColliders[i] != null)
                    {
                        tk2dUtil.DestroyImmediate(chunk.edgeColliders[i]);
                    }
                }
                chunk.edgeColliders.Clear();
            }
            else
            {
                int numEdges = mergedEdges.Count;

                // Destroy surplus
                for (int i = numEdges; i < chunk.edgeColliders.Count; ++i)
                {
                    if (chunk.edgeColliders[i] != null)
                    {
                        tk2dUtil.DestroyImmediate(chunk.edgeColliders[i]);
                    }
                }
                int numToRemove = chunk.edgeColliders.Count - numEdges;
                if (numToRemove > 0)
                {
                    chunk.edgeColliders.RemoveRange(chunk.edgeColliders.Count - numToRemove, numToRemove);
                }

                // Make sure existing ones are not null
                for (int i = 0; i < chunk.edgeColliders.Count; ++i)
                {
                    if (chunk.edgeColliders[i] == null)
                    {
                        chunk.edgeColliders[i] = tk2dUtil.AddComponent <EdgeCollider2D>(chunk.gameObject);
                    }
                }
                // Create missing
                while (chunk.edgeColliders.Count < numEdges)
                {
                    chunk.edgeColliders.Add(tk2dUtil.AddComponent <EdgeCollider2D>(chunk.gameObject));
                }

                for (int i = 0; i < numEdges; ++i)
                {
                    chunk.edgeColliders[i].points = mergedEdges[i];
                }
            }
#endif
        }
Example #14
0
        /// Spawns all prefabs for a given chunk
        /// Expects the chunk to have a valid GameObject
        public static void SpawnPrefabsForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, int layer, int[] prefabCounts)
        {
            var     chunkData   = chunk.spriteIds;
            var     tilePrefabs = tileMap.data.tilePrefabs;
            Vector3 tileSize    = tileMap.data.tileSize;
            var     parent      = chunk.gameObject.transform;

            float xOffsetMult = 0.0f, yOffsetMult = 0.0f;

            tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult);

            for (int y = 0; y < tileMap.partitionSizeY; ++y)
            {
                float xOffset = ((baseY + y) & 1) * xOffsetMult;
                for (int x = 0; x < tileMap.partitionSizeX; ++x)
                {
                    int tile = GetTileFromRawTile(chunkData[y * tileMap.partitionSizeX + x]);
                    if (tile < 0 || tile >= tilePrefabs.Length)
                    {
                        continue;
                    }

                    Object prefab = tilePrefabs[tile];
                    if (prefab != null)
                    {
                        prefabCounts[tile]++;

                        GameObject instance      = GetExistingTilePrefabInstance(tileMap, baseX + x, baseY + y, layer);
                        bool       foundExisting = (instance != null);

                                        #if UNITY_EDITOR
                        if (instance != null)
                        {
                            if (UnityEditor.PrefabUtility.GetPrefabParent(instance) != prefab)
                            {
                                instance = null;
                            }
                        }
                                        #endif

                        if (instance == null)
                        {
                                        #if UNITY_EDITOR
                            instance = UnityEditor.PrefabUtility.InstantiatePrefab(prefab) as GameObject;
                                        #else
                            instance = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject;
                                        #endif

                                        #if UNITY_EDITOR && !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2)
                            if (!Application.isPlaying)
                            {
                                UnityEditor.Undo.RegisterCreatedObjectUndo(instance, "Instantiated Prefab");
                            }
                                        #endif
                        }

                        if (instance != null)
                        {
                            GameObject prefabGameObject = prefab as GameObject;

                            Vector3 pos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0);
                            bool    enablePrefabOffset = false;
                            var     tileInfo           = tileMap.data.GetTileInfoForSprite(tile);
                            if (tileInfo != null)
                            {
                                enablePrefabOffset = tileInfo.enablePrefabOffset;
                            }
                            if (enablePrefabOffset && prefabGameObject != null)
                            {
                                pos += prefabGameObject.transform.position;
                            }

                            if (!foundExisting)
                            {
                                instance.name = prefab.name + " " + prefabCounts[tile].ToString();
                            }

                            tk2dUtil.SetTransformParent(instance.transform, parent);
                            instance.transform.localPosition = pos;

                            // Add to tilePrefabs list
                            TilePrefabsX.Add(baseX + x);
                            TilePrefabsY.Add(baseY + y);
                            TilePrefabsLayer.Add(layer);
                            TilePrefabsInstance.Add(instance);
                        }
                    }
                }
            }
        }
        public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, ColorChunk colorChunk, bool useColor, bool skipPrefabs, int baseX, int baseY)
        {
            List <Vector3> meshVertices = new List <Vector3>();
            List <Color>   meshColors   = new List <Color>();
            List <Vector2> meshUvs      = new List <Vector2>();

            //List<int> meshIndices = new List<int>();

            int[]   spriteIds   = chunk.spriteIds;
            Vector3 tileSize    = tileMap.data.tileSize;
            int     spriteCount = tileMap.spriteCollection.spriteDefinitions.Length;

            Object[] tilePrefabs = tileMap.data.tilePrefabs;

            Color32 clearColor = (useColor && tileMap.ColorChannel != null)?tileMap.ColorChannel.clearColor:Color.white;

            // revert to no color mode (i.e. fill with clear color) when there isn't a color channel, or it is empty
            if (colorChunk == null || colorChunk.colors.Length == 0)
            {
                useColor = false;
            }

            int x0, x1, dx;
            int y0, y1, dy;

            BuilderUtil.GetLoopOrder(tileMap.data.sortMethod,
                                     tileMap.partitionSizeX, tileMap.partitionSizeY,
                                     out x0, out x1, out dx,
                                     out y0, out y1, out dy);

            List <int>[] meshIndices = new List <int> [tileMap.spriteCollection.materials.Length];
            for (int j = 0; j < meshIndices.Length; ++j)
            {
                meshIndices[j] = new List <int>();
            }

            int colorChunkSize = tileMap.partitionSizeX + 1;

            for (int y = y0; y != y1; y += dy)
            {
                for (int x = x0; x != x1; x += dx)
                {
                    int     tile       = spriteIds[y * tileMap.partitionSizeX + x];
                    Vector3 currentPos = new Vector3(tileSize.x * x, tileSize.y * y, 0);

                    if (tile < 0 || tile >= spriteCount)
                    {
                        continue;
                    }

                    if (skipPrefabs && tilePrefabs[tile])
                    {
                        continue;
                    }

                    var sprite = tileMap.spriteCollection.spriteDefinitions[tile];

                    int baseVertex = meshVertices.Count;
                    for (int v = 0; v < sprite.positions.Length; ++v)
                    {
                        if (useColor)
                        {
                            Color tileColorx0y0 = colorChunk.colors[y * colorChunkSize + x];
                            Color tileColorx1y0 = colorChunk.colors[y * colorChunkSize + x + 1];
                            Color tileColorx0y1 = colorChunk.colors[(y + 1) * colorChunkSize + x];
                            Color tileColorx1y1 = colorChunk.colors[(y + 1) * colorChunkSize + (x + 1)];

                            Vector3 centeredSpriteVertex = sprite.positions[v] - sprite.untrimmedBoundsData[0];
                            Vector3 alignedSpriteVertex  = centeredSpriteVertex + tileMap.data.tileSize * 0.5f;
                            float   tileColorX           = Mathf.Clamp01(alignedSpriteVertex.x / tileMap.data.tileSize.x);
                            float   tileColorY           = Mathf.Clamp01(alignedSpriteVertex.y / tileMap.data.tileSize.y);

                            Color color = Color.Lerp(
                                Color.Lerp(tileColorx0y0, tileColorx1y0, tileColorX),
                                Color.Lerp(tileColorx0y1, tileColorx1y1, tileColorX),
                                tileColorY);
                            meshColors.Add(color);
                        }
                        else
                        {
                            meshColors.Add(clearColor);
                        }

                        meshVertices.Add(currentPos + sprite.positions[v]);
                        meshUvs.Add(sprite.uvs[v]);
                    }

                    List <int> indices = meshIndices[sprite.materialId];
                    for (int i = 0; i < sprite.indices.Length; ++i)
                    {
                        indices.Add(baseVertex + sprite.indices[i]);
                    }
                }
            }

            chunk.mesh.vertices = meshVertices.ToArray();
            chunk.mesh.uv       = meshUvs.ToArray();
            chunk.mesh.colors   = meshColors.ToArray();

            List <Material> materials    = new List <Material>();
            int             materialId   = 0;
            int             subMeshCount = 0;

            foreach (var indices in meshIndices)
            {
                if (indices.Count > 0)
                {
                    materials.Add(tileMap.spriteCollection.materials[materialId]);
                    subMeshCount++;
                }
                materialId++;
            }
            if (subMeshCount > 0)
            {
                chunk.mesh.subMeshCount             = subMeshCount;
                chunk.gameObject.renderer.materials = materials.ToArray();
                int subMeshId = 0;
                foreach (var indices in meshIndices)
                {
                    if (indices.Count > 0)
                    {
                        chunk.mesh.SetTriangles(indices.ToArray(), subMeshId);
                        subMeshId++;
                    }
                }
            }

            chunk.mesh.RecalculateBounds();
        }
        // Builds an unoptimized mesh for this chunk
        static void BuildLocalMeshForChunk(tk2dTileMap tileMap, SpriteChunk chunk, ref Vector3[] vertices, ref int[] indices)
        {
            List <Vector3> vertexList = new List <Vector3>();
            List <int>     indexList  = new List <int>();

            int     spriteCount = tileMap.spriteCollection.spriteDefinitions.Length;
            Vector3 tileSize    = tileMap.data.tileSize;

            var tilePrefabs = tileMap.data.tilePrefabs;

            var chunkData = chunk.spriteIds;

            for (int y = 0; y < tileMap.partitionSizeY; ++y)
            {
                for (int x = 0; x < tileMap.partitionSizeX; ++x)
                {
                    int     tile       = chunkData[y * tileMap.partitionSizeX + x];
                    Vector3 currentPos = new Vector3(tileSize.x * x, tileSize.y * y, 0);

                    if (tile < 0 || tile >= spriteCount)
                    {
                        continue;
                    }

                    if (tilePrefabs[tile])
                    {
                        continue;
                    }

                    var spriteData      = tileMap.spriteCollection.spriteDefinitions[tile];
                    int baseVertexIndex = vertexList.Count;

                    if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Box)
                    {
                        Vector3 origin  = spriteData.colliderVertices[0] + currentPos;
                        Vector3 extents = spriteData.colliderVertices[1];
                        Vector3 min     = origin - extents;
                        Vector3 max     = origin + extents;

                        vertexList.Add(new Vector3(min.x, min.y, min.z));
                        vertexList.Add(new Vector3(min.x, min.y, max.z));
                        vertexList.Add(new Vector3(max.x, min.y, min.z));
                        vertexList.Add(new Vector3(max.x, min.y, max.z));
                        vertexList.Add(new Vector3(min.x, max.y, min.z));
                        vertexList.Add(new Vector3(min.x, max.y, max.z));
                        vertexList.Add(new Vector3(max.x, max.y, min.z));
                        vertexList.Add(new Vector3(max.x, max.y, max.z));

                        //						int[] indicesBack = { 0, 1, 2, 2, 1, 3, 6, 5, 4, 7, 5, 6, 3, 7, 6, 2, 3, 6, 4, 5, 1, 4, 1, 0 };
                        int[] indicesFwd = { 2, 1, 0, 3, 1, 2, 4, 5, 6, 6, 5, 7, 6, 7, 3, 6, 3, 2, 1, 5, 4, 0, 1, 4 };

                        var srcIndices = indicesFwd;
                        for (int i = 0; i < srcIndices.Length; ++i)
                        {
                            indexList.Add(baseVertexIndex + srcIndices[i]);
                        }
                    }
                    else if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Mesh)
                    {
                        for (int i = 0; i < spriteData.colliderVertices.Length; ++i)
                        {
                            Vector3 pos = spriteData.colliderVertices[i] + currentPos;
                            vertexList.Add(pos);
                        }

                        var srcIndices = spriteData.colliderIndicesFwd;
                        for (int i = 0; i < srcIndices.Length; ++i)
                        {
                            indexList.Add(baseVertexIndex + srcIndices[i]);
                        }
                    }
                }
            }

            vertices = vertexList.ToArray();
            indices  = indexList.ToArray();
        }
Example #17
0
 void Optimize(SpriteChunk chunk)
 {
     bool empty = true;
     foreach (var v in chunk.spriteIds)
     {
         if (v != -1)
         {
             empty = false;
             break;
         }
     }
     if (empty)
         chunk.spriteIds = new int[0];
 }
		/// Spawns all prefabs for a given chunk
		/// Expects the chunk to have a valid GameObject
		public static void SpawnPrefabsForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY)
		{
			var chunkData = chunk.spriteIds;
			var tilePrefabs = tileMap.data.tilePrefabs;
			Vector3 tileSize = tileMap.data.tileSize;
			int[] prefabCounts = new int[tilePrefabs.Length];
			var parent = chunk.gameObject.transform;
			
			float xOffsetMult = 0.0f, yOffsetMult = 0.0f;
			tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult);

			for (int y = 0; y < tileMap.partitionSizeY; ++y)
			{
				float xOffset = ((baseY + y) & 1) * xOffsetMult;
				for (int x = 0; x < tileMap.partitionSizeX; ++x)
				{
					int tile = chunkData[y * tileMap.partitionSizeX + x];
					if (tile < 0 || tile >= tilePrefabs.Length)
						continue;
					
					Vector3 currentPos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0);
					
					Object prefab = tilePrefabs[tile];
					if (prefab != null)
					{
						prefabCounts[tile]++;
						
#if UNITY_EDITOR && !(UNITY_3_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4)
						GameObject go = UnityEditor.PrefabUtility.InstantiatePrefab(prefab) as GameObject;
#else
						GameObject go = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject;
#endif
						if (go)
						{
							go.name = prefab.name + " " + prefabCounts[tile].ToString();
							// Position after transforming, as it is in local space
							go.transform.parent = parent;
							go.transform.localPosition = currentPos;
							go.transform.localRotation = Quaternion.identity;
							go.transform.localScale = Vector3.one;
						}
					}
				}
			}
		}
 public static unsafe void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, ColorChunk colorChunk, bool useColor, bool skipPrefabs, int baseX, int baseY)
 {
     int num2;
     int num3;
     int num4;
     int num5;
     int num6;
     int num7;
     List<Vector3> list = new List<Vector3>();
     List<Color> list2 = new List<Color>();
     List<Vector2> list3 = new List<Vector2>();
     int[] spriteIds = chunk.spriteIds;
     Vector3 tileSize = tileMap.data.tileSize;
     int length = tileMap.SpriteCollectionInst.spriteDefinitions.Length;
     UnityEngine.Object[] tilePrefabs = tileMap.data.tilePrefabs;
     tk2dSpriteDefinition firstValidDefinition = tileMap.SpriteCollectionInst.FirstValidDefinition;
     bool flag = ((firstValidDefinition != null) && (firstValidDefinition.normals != null)) && (firstValidDefinition.normals.Length > 0);
     Color32 color = (!useColor || (tileMap.ColorChannel == null)) ? Color.white : tileMap.ColorChannel.clearColor;
     if ((colorChunk == null) || (colorChunk.colors.Length == 0))
     {
         useColor = false;
     }
     BuilderUtil.GetLoopOrder(tileMap.data.sortMethod, tileMap.partitionSizeX, tileMap.partitionSizeY, out num2, out num3, out num4, out num5, out num6, out num7);
     float x = 0f;
     float y = 0f;
     tileMap.data.GetTileOffset(out x, out y);
     List<int>[] listArray = new List<int>[tileMap.SpriteCollectionInst.materials.Length];
     for (int i = 0; i < listArray.Length; i++)
     {
         listArray[i] = new List<int>();
     }
     int num11 = tileMap.partitionSizeX + 1;
     for (int j = num5; j != num6; j += num7)
     {
         float num13 = ((baseY + j) & 1) * x;
         for (int k = num2; k != num3; k += num4)
         {
             int rawTile = spriteIds[(j * tileMap.partitionSizeX) + k];
             int tileFromRawTile = BuilderUtil.GetTileFromRawTile(rawTile);
             bool flipH = BuilderUtil.IsRawTileFlagSet(rawTile, tk2dTileFlags.FlipX);
             bool flipV = BuilderUtil.IsRawTileFlagSet(rawTile, tk2dTileFlags.FlipY);
             bool flag4 = BuilderUtil.IsRawTileFlagSet(rawTile, tk2dTileFlags.Rot90);
             Vector3 vector2 = new Vector3(tileSize.x * (k + num13), tileSize.y * j, 0f);
             if (((tileFromRawTile >= 0) && (tileFromRawTile < length)) && (!skipPrefabs || (tilePrefabs[tileFromRawTile] == null)))
             {
                 tk2dSpriteDefinition spriteDef = tileMap.SpriteCollectionInst.spriteDefinitions[tileFromRawTile];
                 int count = list.Count;
                 for (int m = 0; m < spriteDef.positions.Length; m++)
                 {
                     Vector3 vector3 = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteDef, spriteDef.positions[m], flipH, flipV, flag4);
                     if (useColor)
                     {
                         Color a = *((Color*) &(colorChunk.colors[(j * num11) + k]));
                         Color b = *((Color*) &(colorChunk.colors[((j * num11) + k) + 1]));
                         Color color4 = *((Color*) &(colorChunk.colors[((j + 1) * num11) + k]));
                         Color color5 = *((Color*) &(colorChunk.colors[((j + 1) * num11) + (k + 1)]));
                         Vector3 vector4 = vector3 - spriteDef.untrimmedBoundsData[0];
                         Vector3 vector5 = vector4 + ((Vector3) (tileMap.data.tileSize * 0.5f));
                         float t = Mathf.Clamp01(vector5.x / tileMap.data.tileSize.x);
                         float num20 = Mathf.Clamp01(vector5.y / tileMap.data.tileSize.y);
                         Color item = Color.Lerp(Color.Lerp(a, b, t), Color.Lerp(color4, color5, t), num20);
                         list2.Add(item);
                     }
                     else
                     {
                         list2.Add((Color) color);
                     }
                     list.Add(vector2 + vector3);
                     list3.Add(spriteDef.uvs[m]);
                 }
                 bool flag5 = false;
                 if (flipH)
                 {
                     flag5 = !flag5;
                 }
                 if (flipV)
                 {
                     flag5 = !flag5;
                 }
                 List<int> list4 = listArray[spriteDef.materialId];
                 for (int n = 0; n < spriteDef.indices.Length; n++)
                 {
                     int num22 = !flag5 ? n : ((spriteDef.indices.Length - 1) - n);
                     list4.Add(count + spriteDef.indices[num22]);
                 }
             }
         }
     }
     if (chunk.mesh == null)
     {
         chunk.mesh = tk2dUtil.CreateMesh();
     }
     chunk.mesh.vertices = list.ToArray();
     chunk.mesh.uv = list3.ToArray();
     chunk.mesh.colors = list2.ToArray();
     List<Material> list5 = new List<Material>();
     int index = 0;
     int num24 = 0;
     foreach (List<int> list6 in listArray)
     {
         if (list6.Count > 0)
         {
             list5.Add(tileMap.SpriteCollectionInst.materialInsts[index]);
             num24++;
         }
         index++;
     }
     if (num24 > 0)
     {
         chunk.mesh.subMeshCount = num24;
         chunk.gameObject.renderer.materials = list5.ToArray();
         int submesh = 0;
         foreach (List<int> list7 in listArray)
         {
             if (list7.Count > 0)
             {
                 chunk.mesh.SetTriangles(list7.ToArray(), submesh);
                 submesh++;
             }
         }
     }
     chunk.mesh.RecalculateBounds();
     if (flag)
     {
         chunk.mesh.RecalculateNormals();
     }
     chunk.gameObject.GetComponent<MeshFilter>().sharedMesh = chunk.mesh;
 }
		// Builds an unoptimized mesh for this chunk
		static void BuildLocalMeshForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, ref Vector3[] vertices, ref int[] indices)
		{
			List<Vector3> vertexList = new List<Vector3>();
			List<int> indexList = new List<int>();
			
			int spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length;
			Vector3 tileSize = tileMap.data.tileSize;
			
			var tilePrefabs = tileMap.data.tilePrefabs;
			
			float xOffsetMult = 0.0f, yOffsetMult = 0.0f;
			tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult);

			var chunkData = chunk.spriteIds;
			for (int y = 0; y < tileMap.partitionSizeY; ++y)
			{
				float xOffset = ((baseY + y) & 1) * xOffsetMult;
				for (int x = 0; x < tileMap.partitionSizeX; ++x)
				{
					int spriteId = chunkData[y * tileMap.partitionSizeX + x];
					int spriteIdx = BuilderUtil.GetTileFromRawTile(spriteId);
					Vector3 currentPos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0);
	
					if (spriteIdx < 0 || spriteIdx >= spriteCount) 
						continue;
					
					if (tilePrefabs[spriteIdx])
						continue;

					bool flipH = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX);
					bool flipV = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY);
					bool rot90 = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90);

					bool reverseIndices = false;
					if (flipH) reverseIndices = !reverseIndices;
					if (flipV) reverseIndices = !reverseIndices;

					var spriteData = tileMap.SpriteCollectionInst.spriteDefinitions[spriteIdx];
					int baseVertexIndex = vertexList.Count;
					
					if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Box)
					{
						Vector3 origin = spriteData.colliderVertices[0];
						Vector3 extents = spriteData.colliderVertices[1];
						Vector3 min = origin - extents;
						Vector3 max = origin + extents;

						Vector3[] pos = new Vector3[8];
						pos[0] = new Vector3(min.x, min.y, min.z);
						pos[1] = new Vector3(min.x, min.y, max.z);
						pos[2] = new Vector3(max.x, min.y, min.z);
						pos[3] = new Vector3(max.x, min.y, max.z);
						pos[4] = new Vector3(min.x, max.y, min.z);
						pos[5] = new Vector3(min.x, max.y, max.z);
						pos[6] = new Vector3(max.x, max.y, min.z);
						pos[7] = new Vector3(max.x, max.y, max.z);
						for (int i = 0; i < 8; ++i) {
							Vector3 flippedPos = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, pos[i], flipH, flipV, rot90);
							vertexList.Add (flippedPos + currentPos);
						}
	
	//						int[] indicesBack = { 0, 1, 2, 2, 1, 3, 6, 5, 4, 7, 5, 6, 3, 7, 6, 2, 3, 6, 4, 5, 1, 4, 1, 0 };
						int[] indicesFwd = { 2, 1, 0, 3, 1, 2, 4, 5, 6, 6, 5, 7, 6, 7, 3, 6, 3, 2, 1, 5, 4, 0, 1, 4 };
						
						var srcIndices = indicesFwd;
						for (int i = 0; i < srcIndices.Length; ++i)
						{
							int j = reverseIndices ? (srcIndices.Length - 1 - i) : i;
							indexList.Add(baseVertexIndex + srcIndices[j]);
						}
					}
					else if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Mesh)
					{
						for (int i = 0; i < spriteData.colliderVertices.Length; ++i)
						{
							Vector3 flippedPos = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, spriteData.colliderVertices[i], flipH, flipV, rot90);
							vertexList.Add(flippedPos + currentPos);
						}
						
						var srcIndices = spriteData.colliderIndicesFwd;
						for (int i = 0; i < srcIndices.Length; ++i)
						{
							int j = reverseIndices ? (srcIndices.Length - 1 - i) : i;
							indexList.Add(baseVertexIndex + srcIndices[j]);
						}
					}
				}
			}
			
			vertices = vertexList.ToArray();
			indices = indexList.ToArray();
		}
		public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, ColorChunk colorChunk, bool useColor, bool skipPrefabs, int baseX, int baseY)
		{
			List<Vector3> meshVertices = new List<Vector3>();
			List<Color> meshColors = new List<Color>();
			List<Vector2> meshUvs = new List<Vector2>();
			//List<int> meshIndices = new List<int>();
			
			int[] spriteIds = chunk.spriteIds;
			Vector3 tileSize = tileMap.data.tileSize;
			int spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length;
			Object[] tilePrefabs = tileMap.data.tilePrefabs;
			tk2dSpriteDefinition firstSprite = tileMap.SpriteCollectionInst.FirstValidDefinition;
			bool buildNormals = (firstSprite != null && firstSprite.normals != null && firstSprite.normals.Length > 0);
			
			Color32 clearColor = (useColor && tileMap.ColorChannel != null)?tileMap.ColorChannel.clearColor:Color.white;
					
			// revert to no color mode (i.e. fill with clear color) when there isn't a color channel, or it is empty
			if (colorChunk == null || colorChunk.colors.Length == 0)
				useColor = false;
			
			int x0, x1, dx;
			int y0, y1, dy;
			BuilderUtil.GetLoopOrder(tileMap.data.sortMethod, 
				tileMap.partitionSizeX, tileMap.partitionSizeY, 
				out x0, out x1, out dx,
				out y0, out y1, out dy);
			
			float xOffsetMult = 0.0f, yOffsetMult = 0.0f;
			tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult);
			
			List<int>[] meshIndices = new List<int>[tileMap.SpriteCollectionInst.materials.Length];
			for (int j = 0; j < meshIndices.Length; ++j)
				meshIndices[j] = new List<int>();
			
			int colorChunkSize = tileMap.partitionSizeX + 1;
			for (int y = y0; y != y1; y += dy)
			{
				float xOffset = ((baseY + y) & 1) * xOffsetMult;
				for (int x = x0; x != x1; x += dx)
				{
					int spriteId = spriteIds[y * tileMap.partitionSizeX + x];
					int tile = BuilderUtil.GetTileFromRawTile(spriteId);
					bool flipH = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX);
					bool flipV = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY);
					bool rot90 = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90);

					Vector3 currentPos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0);
	
					if (tile < 0 || tile >= spriteCount) 
						continue;
					
					if (skipPrefabs && tilePrefabs[tile])
						continue;
					
					var sprite = tileMap.SpriteCollectionInst.spriteDefinitions[tile];
					
					int baseVertex = meshVertices.Count;
					for (int v = 0; v < sprite.positions.Length; ++v)
					{
						Vector3 flippedPos = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, sprite, sprite.positions[v], flipH, flipV, rot90);

						if (useColor)
						{
							Color tileColorx0y0 = colorChunk.colors[y * colorChunkSize + x];
							Color tileColorx1y0 = colorChunk.colors[y * colorChunkSize + x + 1];
							Color tileColorx0y1 = colorChunk.colors[(y + 1) * colorChunkSize + x];
							Color tileColorx1y1 = colorChunk.colors[(y + 1) * colorChunkSize + (x + 1)];
							
							Vector3 centeredSpriteVertex = flippedPos - sprite.untrimmedBoundsData[0];
							Vector3 alignedSpriteVertex = centeredSpriteVertex + tileMap.data.tileSize * 0.5f;
							float tileColorX = Mathf.Clamp01(alignedSpriteVertex.x / tileMap.data.tileSize.x);
							float tileColorY = Mathf.Clamp01(alignedSpriteVertex.y / tileMap.data.tileSize.y);
							
							Color color = Color.Lerp(
										  Color.Lerp(tileColorx0y0, tileColorx1y0, tileColorX),
										  Color.Lerp(tileColorx0y1, tileColorx1y1, tileColorX),
										  tileColorY);
							meshColors.Add(color);
						}
						else
						{
							meshColors.Add(clearColor);
						}

						meshVertices.Add(currentPos + flippedPos);
						meshUvs.Add(sprite.uvs[v]);
					}

					bool reverseIndices = false; // flipped?
					if (flipH) reverseIndices = !reverseIndices;
					if (flipV) reverseIndices = !reverseIndices;
					
					List<int> indices = meshIndices[sprite.materialId];
					for (int i = 0; i < sprite.indices.Length; ++i) {
						int j = reverseIndices ? (sprite.indices.Length - 1 - i) : i;
						indices.Add(baseVertex + sprite.indices[j]);
					}
					
				}
			}
			
			if (chunk.mesh == null)
				chunk.mesh = tk2dUtil.CreateMesh();

			chunk.mesh.vertices = meshVertices.ToArray();
			chunk.mesh.uv = meshUvs.ToArray();
			chunk.mesh.colors = meshColors.ToArray();

			List<Material> materials = new List<Material>();
			int materialId = 0;
			int subMeshCount = 0;
			foreach (var indices in meshIndices)
			{
				if (indices.Count > 0)
				{
					materials.Add(tileMap.SpriteCollectionInst.materialInsts[materialId]);
					subMeshCount++;
				}
				materialId++;
			}
			if (subMeshCount > 0)
			{
				chunk.mesh.subMeshCount = subMeshCount;
				chunk.gameObject.renderer.materials = materials.ToArray();
				int subMeshId = 0;
				foreach (var indices in meshIndices)
				{
					if (indices.Count > 0)
					{
						chunk.mesh.SetTriangles(indices.ToArray(), subMeshId);
						subMeshId++;
					}
				}
			}
			
			chunk.mesh.RecalculateBounds();
			if (buildNormals) {
				chunk.mesh.RecalculateNormals();
			}

			var meshFilter = chunk.gameObject.GetComponent<MeshFilter>();
			meshFilter.sharedMesh = chunk.mesh;
		}
Example #22
0
        public static void BuildPolygonCollidersForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY)
        {
            // Clear colliders
            EdgeCollider2D[] edgeColliders = chunk.gameObject.GetComponents <EdgeCollider2D>();
            foreach (var ec in edgeColliders)
            {
                tk2dUtil.DestroyImmediate(ec);
            }
            chunk.edgeColliders.Clear();

            PolygonCollider2D[] polyColliders = chunk.gameObject.GetComponents <PolygonCollider2D>();
            foreach (var pc in polyColliders)
            {
                tk2dUtil.DestroyImmediate(pc);
            }


            Vector2[] boxPos             = new Vector2[4]; // used for box collider
            List <List <Vector2> > paths = new List <List <Vector2> >();

            int     spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length;
            Vector2 tileSize    = new Vector3(tileMap.data.tileSize.x, tileMap.data.tileSize.y);

            var tilePrefabs = tileMap.data.tilePrefabs;

            float xOffsetMult = 0.0f, yOffsetMult = 0.0f;

            tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult);

            List <Vector2> cachedPoints = new List <Vector2>();

            var chunkData = chunk.spriteIds;

            for (int y = 0; y < tileMap.partitionSizeY; ++y)
            {
                float xOffset = ((baseY + y) & 1) * xOffsetMult;
                for (int x = 0; x < tileMap.partitionSizeX; ++x)
                {
                    int     spriteId   = chunkData[y * tileMap.partitionSizeX + x];
                    int     spriteIdx  = BuilderUtil.GetTileFromRawTile(spriteId);
                    Vector2 currentPos = new Vector2(tileSize.x * (x + xOffset), tileSize.y * y);

                    if (spriteIdx < 0 || spriteIdx >= spriteCount)
                    {
                        continue;
                    }

                    if (tilePrefabs[spriteIdx])
                    {
                        continue;
                    }

                    bool flipH = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX);
                    bool flipV = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY);
                    bool rot90 = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90);

                    bool reverseIndices = false;
                    if (flipH)
                    {
                        reverseIndices = !reverseIndices;
                    }
                    if (flipV)
                    {
                        reverseIndices = !reverseIndices;
                    }

                    tk2dSpriteDefinition spriteData = tileMap.SpriteCollectionInst.spriteDefinitions[spriteIdx];
                    if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Box)
                    {
                        Vector3 origin  = spriteData.colliderVertices[0];
                        Vector3 extents = spriteData.colliderVertices[1];
                        Vector3 min     = origin - extents;
                        Vector3 max     = origin + extents;

                        boxPos[0] = new Vector2(min.x, min.y);
                        boxPos[1] = new Vector2(max.x, min.y);
                        boxPos[2] = new Vector2(max.x, max.y);
                        boxPos[3] = new Vector2(min.x, max.y);

                        List <Vector2> thisList = new List <Vector2>();
                        int            start    = reverseIndices ? 3 : 0;
                        int            end      = reverseIndices ? -1 : 4;
                        int            inc      = reverseIndices ? -1 : 1;
                        for (int i = start; i != end; i += inc)
                        {
                            thisList.Add(BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, boxPos[i], flipH, flipV, rot90) + currentPos);
                        }

                        paths.Add(thisList);
                    }
                    else if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Mesh)
                    {
                        cachedPoints.Clear();
                        List <Vector2> points = new List <Vector2>();

                        foreach (tk2dCollider2DData dat in spriteData.polygonCollider2D)
                        {
                            foreach (Vector2 pos in dat.points)
                            {
                                cachedPoints.Add(BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, pos, flipH, flipV, rot90) + currentPos);
                            }
                            int numVerts = dat.points.Length;
                            if (reverseIndices)
                            {
                                for (int i = cachedPoints.Count - 1; i >= 0; --i)
                                {
                                    points.Add(cachedPoints[i]);
                                }
                            }
                            else
                            {
                                for (int i = 0; i < numVerts; ++i)
                                {
                                    points.Add(cachedPoints[i]);
                                }
                            }
                        }

                        paths.Add(points);
                    }
                }
            }

            int numPathsPerObject = 64;
            int startPath         = 0;
            int pathsRemaining    = paths.Count;

            while (pathsRemaining > 0)
            {
                int pathsThisRound = Mathf.Min(numPathsPerObject, pathsRemaining);

                PolygonCollider2D newPc = chunk.gameObject.AddComponent <PolygonCollider2D>();
                newPc.pathCount = pathsThisRound;
                for (int i = 0; i < pathsThisRound; ++i)
                {
                    newPc.SetPath(i, paths[startPath + i].ToArray());
                }

                startPath      += pathsThisRound;
                pathsRemaining -= pathsThisRound;
            }
        }
		/// Spawns all prefabs for a given chunk
		/// Expects the chunk to have a valid GameObject
		public static void SpawnPrefabsForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, int layer, int[] prefabCounts)
		{
			var chunkData = chunk.spriteIds;
			var tilePrefabs = tileMap.data.tilePrefabs;
			Vector3 tileSize = tileMap.data.tileSize;
			var parent = chunk.gameObject.transform;
			
			float xOffsetMult = 0.0f, yOffsetMult = 0.0f;
			tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult);

			for (int y = 0; y < tileMap.partitionSizeY; ++y)
			{
				float xOffset = ((baseY + y) & 1) * xOffsetMult;
				for (int x = 0; x < tileMap.partitionSizeX; ++x)
				{
					int tile = GetTileFromRawTile(chunkData[y * tileMap.partitionSizeX + x]);
					if (tile < 0 || tile >= tilePrefabs.Length)
						continue;

					Object prefab = tilePrefabs[tile];
					if (prefab != null)
					{
						prefabCounts[tile]++;

						GameObject instance = GetExistingTilePrefabInstance(tileMap, baseX + x, baseY + y, layer);
						bool foundExisting = (instance != null);

					#if UNITY_EDITOR
						if (instance != null) {
							if (UnityEditor.PrefabUtility.GetPrefabParent(instance) != prefab) {
								instance = null;
							}
						}
					#endif

						if (instance == null) {
					#if UNITY_EDITOR
							instance = UnityEditor.PrefabUtility.InstantiatePrefab(prefab) as GameObject;
					#else
							instance = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject;
					#endif

					#if UNITY_EDITOR && !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2)
							if (!Application.isPlaying) {
								UnityEditor.Undo.RegisterCreatedObjectUndo(instance, "Instantiated Prefab");
							}
					#endif
						}
						
						if (instance != null) {
							GameObject prefabGameObject = prefab as GameObject;

							Vector3 pos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0);
							bool enablePrefabOffset = false;
							var tileInfo = tileMap.data.GetTileInfoForSprite(tile);
							if (tileInfo != null)
								enablePrefabOffset = tileInfo.enablePrefabOffset;
							if (enablePrefabOffset && prefabGameObject != null)
								pos += prefabGameObject.transform.position;

							if (!foundExisting)
								instance.name = prefab.name + " " + prefabCounts[tile].ToString();

							tk2dUtil.SetTransformParent(instance.transform, parent);
							instance.transform.localPosition = pos;

							// Add to tilePrefabs list
							TilePrefabsX.Add(baseX + x);
							TilePrefabsY.Add(baseY + y);
							TilePrefabsLayer.Add(layer);
							TilePrefabsInstance.Add(instance);
						}
					}
				}
			}
		}
Example #24
0
        public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, ColorChunk colorChunk, bool useColor, bool skipPrefabs, int baseX, int baseY)
        {
            List<Vector3> meshVertices = new List<Vector3>();
            List<Color> meshColors = new List<Color>();
            List<Vector2> meshUvs = new List<Vector2>();
            //List<int> meshIndices = new List<int>();

            int[] spriteIds = chunk.spriteIds;
            Vector3 tileSize = tileMap.data.tileSize;
            int spriteCount = tileMap.spriteCollection.spriteDefinitions.Length;
            Object[] tilePrefabs = tileMap.data.tilePrefabs;

            Color32 clearColor = (useColor && tileMap.ColorChannel != null)?tileMap.ColorChannel.clearColor:Color.white;

            // revert to no color mode (i.e. fill with clear color) when there isn't a color channel, or it is empty
            if (colorChunk == null || colorChunk.colors.Length == 0)
                useColor = false;

            int x0, x1, dx;
            int y0, y1, dy;
            BuilderUtil.GetLoopOrder(tileMap.data.sortMethod,
                tileMap.partitionSizeX, tileMap.partitionSizeY,
                out x0, out x1, out dx,
                out y0, out y1, out dy);

            List<int>[] meshIndices = new List<int>[tileMap.spriteCollection.materials.Length];
            for (int j = 0; j < meshIndices.Length; ++j)
                meshIndices[j] = new List<int>();

            int colorChunkSize = tileMap.partitionSizeX + 1;
            for (int y = y0; y != y1; y += dy)
            {
                for (int x = x0; x != x1; x += dx)
                {
                    int tile = spriteIds[y * tileMap.partitionSizeX + x];
                    Vector3 currentPos = new Vector3(tileSize.x * x, tileSize.y * y, 0);

                    if (tile < 0 || tile >= spriteCount)
                        continue;

                    if (skipPrefabs && tilePrefabs[tile])
                        continue;

                    var sprite = tileMap.spriteCollection.spriteDefinitions[tile];

                    int baseVertex = meshVertices.Count;
                    for (int v = 0; v < sprite.positions.Length; ++v)
                    {
                        if (useColor)
                        {
                            Color tileColorx0y0 = colorChunk.colors[y * colorChunkSize + x];
                            Color tileColorx1y0 = colorChunk.colors[y * colorChunkSize + x + 1];
                            Color tileColorx0y1 = colorChunk.colors[(y + 1) * colorChunkSize + x];
                            Color tileColorx1y1 = colorChunk.colors[(y + 1) * colorChunkSize + (x + 1)];

                            Vector3 centeredSpriteVertex = sprite.positions[v] - sprite.untrimmedBoundsData[0];
                            Vector3 alignedSpriteVertex = centeredSpriteVertex + tileMap.data.tileSize * 0.5f;
                            float tileColorX = Mathf.Clamp01(alignedSpriteVertex.x / tileMap.data.tileSize.x);
                            float tileColorY = Mathf.Clamp01(alignedSpriteVertex.y / tileMap.data.tileSize.y);

                            Color color = Color.Lerp(
                                          Color.Lerp(tileColorx0y0, tileColorx1y0, tileColorX),
                                          Color.Lerp(tileColorx0y1, tileColorx1y1, tileColorX),
                                          tileColorY);
                            meshColors.Add(color);
                        }
                        else
                        {
                            meshColors.Add(clearColor);
                        }

                        meshVertices.Add(currentPos + sprite.positions[v]);
                        meshUvs.Add(sprite.uvs[v]);
                    }

                    List<int> indices = meshIndices[sprite.materialId];
                    for (int i = 0; i < sprite.indices.Length; ++i)
                        indices.Add(baseVertex + sprite.indices[i]);

                }
            }

            if (chunk.mesh == null)
                chunk.mesh = tileMap.GetOrCreateMesh();

            chunk.mesh.vertices = meshVertices.ToArray();
            chunk.mesh.uv = meshUvs.ToArray();
            chunk.mesh.colors = meshColors.ToArray();

            List<Material> materials = new List<Material>();
            int materialId = 0;
            int subMeshCount = 0;
            foreach (var indices in meshIndices)
            {
                if (indices.Count > 0)
                {
                    materials.Add(tileMap.spriteCollection.materials[materialId]);
                    subMeshCount++;
                }
                materialId++;
            }
            if (subMeshCount > 0)
            {
                chunk.mesh.subMeshCount = subMeshCount;
                chunk.gameObject.renderer.materials = materials.ToArray();
                int subMeshId = 0;
                foreach (var indices in meshIndices)
                {
                    if (indices.Count > 0)
                    {
                        chunk.mesh.SetTriangles(indices.ToArray(), subMeshId);
                        subMeshId++;
                    }
                }
            }

            chunk.mesh.RecalculateBounds();

            if (tileMap.serializeRenderData)
                chunk.mesh.RecalculateNormals();

            var meshFilter = chunk.gameObject.GetComponent<MeshFilter>();
            meshFilter.sharedMesh = chunk.mesh;
        }
		// Builds an unoptimized mesh for this chunk
		static void BuildLocalMeshForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, ref Vector2[] vertices, ref int[] indices)
		{
			List<Vector2> verts = new List<Vector2>();
			List<int> inds = new List<int>();
			Vector2[] boxPos = new Vector2[4]; // used for box collider
			int[] boxInds = { 0, 1, 1, 2, 2, 3, 3, 0 };
			int[] boxIndsFlipped = { 0, 3, 3, 2, 2, 1, 1, 0 };
			
			int spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length;
			Vector2 tileSize = new Vector3(tileMap.data.tileSize.x, tileMap.data.tileSize.y);
			
			var tilePrefabs = tileMap.data.tilePrefabs;
			
			float xOffsetMult = 0.0f, yOffsetMult = 0.0f;
			tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult);

			var chunkData = chunk.spriteIds;
			for (int y = 0; y < tileMap.partitionSizeY; ++y)
			{
				float xOffset = ((baseY + y) & 1) * xOffsetMult;
				for (int x = 0; x < tileMap.partitionSizeX; ++x)
				{
					int spriteId = chunkData[y * tileMap.partitionSizeX + x];
					int spriteIdx = BuilderUtil.GetTileFromRawTile(spriteId);
					Vector2 currentPos = new Vector2(tileSize.x * (x + xOffset), tileSize.y * y);
	
					if (spriteIdx < 0 || spriteIdx >= spriteCount) 
						continue;
					
					if (tilePrefabs[spriteIdx])
						continue;

					bool flipH = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX);
					bool flipV = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY);
					bool rot90 = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90);

					bool reverseIndices = false;
					if (flipH) reverseIndices = !reverseIndices;
					if (flipV) reverseIndices = !reverseIndices;

					tk2dSpriteDefinition spriteData = tileMap.SpriteCollectionInst.spriteDefinitions[spriteIdx];
					int baseVertexIndex = verts.Count;
					
					if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Box)
					{
						Vector3 origin = spriteData.colliderVertices[0];
						Vector3 extents = spriteData.colliderVertices[1];
						Vector3 min = origin - extents;
						Vector3 max = origin + extents;

						boxPos[0] = new Vector2(min.x, min.y);
						boxPos[1] = new Vector2(max.x, min.y);
						boxPos[2] = new Vector2(max.x, max.y);
						boxPos[3] = new Vector2(min.x, max.y);
						for (int i = 0; i < 4; ++i) {
							verts.Add( BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, boxPos[i], flipH, flipV, rot90) + currentPos );
						}

						int[] boxIndices = reverseIndices ? boxIndsFlipped : boxInds;
						for (int i = 0; i < 8; ++i) {
							inds.Add( baseVertexIndex + boxIndices[i] );
						}

					}
					else if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Mesh)
					{
						foreach (tk2dCollider2DData dat in spriteData.edgeCollider2D) {
							foreach (Vector2 pos in dat.points) {
								verts.Add( BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, pos, flipH, flipV, rot90) + currentPos );
							}
							int numVerts = dat.points.Length;
							if (reverseIndices) {
								for (int i = numVerts - 1; i > 0; --i) {
									inds.Add( baseVertexIndex + i );
									inds.Add( baseVertexIndex + i - 1 );
								}
							}
							else {
								for (int i = 0; i < numVerts - 1; ++i) {
									inds.Add(baseVertexIndex + i);
									inds.Add(baseVertexIndex + i + 1);
								}
							}
						}
						foreach (tk2dCollider2DData dat in spriteData.polygonCollider2D) {
							foreach (Vector2 pos in dat.points) {
								verts.Add( BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, pos, flipH, flipV, rot90) + currentPos );
							}
							int numVerts = dat.points.Length;
							if (reverseIndices) {
								for (int i = numVerts; i > 0; --i) {
									inds.Add( baseVertexIndex + (i % numVerts) );
									inds.Add( baseVertexIndex + i - 1 );
								}
							}
							else {
								for (int i = 0; i < numVerts; ++i) {
									inds.Add(baseVertexIndex + i);
									inds.Add(baseVertexIndex + (i + 1) % numVerts);
								}
							}
						}
					}
				}
			}
			
			vertices = verts.ToArray();
			indices = inds.ToArray();
		}
        // Builds an unoptimized mesh for this chunk
        static void BuildLocalMeshForChunk(tk2dTileMap tileMap, SpriteChunk chunk, int baseX, int baseY, ref Vector3[] vertices, ref int[] indices)
        {
            List <Vector3> vertexList = new List <Vector3>();
            List <int>     indexList  = new List <int>();

            int     spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length;
            Vector3 tileSize    = tileMap.data.tileSize;

            var tilePrefabs = tileMap.data.tilePrefabs;

            float xOffsetMult = 0.0f, yOffsetMult = 0.0f;

            tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult);

            var chunkData = chunk.spriteIds;

            for (int y = 0; y < tileMap.partitionSizeY; ++y)
            {
                float xOffset = ((baseY + y) & 1) * xOffsetMult;
                for (int x = 0; x < tileMap.partitionSizeX; ++x)
                {
                    int     spriteId   = chunkData[y * tileMap.partitionSizeX + x];
                    int     spriteIdx  = BuilderUtil.GetTileFromRawTile(spriteId);
                    Vector3 currentPos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0);

                    if (spriteIdx < 0 || spriteIdx >= spriteCount)
                    {
                        continue;
                    }

                    if (tilePrefabs[spriteIdx])
                    {
                        continue;
                    }

                    bool flipH = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX);
                    bool flipV = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY);
                    bool rot90 = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90);

                    bool reverseIndices = false;
                    if (flipH)
                    {
                        reverseIndices = !reverseIndices;
                    }
                    if (flipV)
                    {
                        reverseIndices = !reverseIndices;
                    }

                    var spriteData      = tileMap.SpriteCollectionInst.spriteDefinitions[spriteIdx];
                    int baseVertexIndex = vertexList.Count;

                    if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Box)
                    {
                        Vector3 origin  = spriteData.colliderVertices[0];
                        Vector3 extents = spriteData.colliderVertices[1];
                        Vector3 min     = origin - extents;
                        Vector3 max     = origin + extents;

                        Vector3[] pos = new Vector3[8];
                        pos[0] = new Vector3(min.x, min.y, min.z);
                        pos[1] = new Vector3(min.x, min.y, max.z);
                        pos[2] = new Vector3(max.x, min.y, min.z);
                        pos[3] = new Vector3(max.x, min.y, max.z);
                        pos[4] = new Vector3(min.x, max.y, min.z);
                        pos[5] = new Vector3(min.x, max.y, max.z);
                        pos[6] = new Vector3(max.x, max.y, min.z);
                        pos[7] = new Vector3(max.x, max.y, max.z);
                        for (int i = 0; i < 8; ++i)
                        {
                            Vector3 flippedPos = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, pos[i], flipH, flipV, rot90);
                            vertexList.Add(flippedPos + currentPos);
                        }

                        //						int[] indicesBack = { 0, 1, 2, 2, 1, 3, 6, 5, 4, 7, 5, 6, 3, 7, 6, 2, 3, 6, 4, 5, 1, 4, 1, 0 };
                        int[] indicesFwd = { 2, 1, 0, 3, 1, 2, 4, 5, 6, 6, 5, 7, 6, 7, 3, 6, 3, 2, 1, 5, 4, 0, 1, 4 };

                        var srcIndices = indicesFwd;
                        for (int i = 0; i < srcIndices.Length; ++i)
                        {
                            int j = reverseIndices ? (srcIndices.Length - 1 - i) : i;
                            indexList.Add(baseVertexIndex + srcIndices[j]);
                        }
                    }
                    else if (spriteData.colliderType == tk2dSpriteDefinition.ColliderType.Mesh)
                    {
                        for (int i = 0; i < spriteData.colliderVertices.Length; ++i)
                        {
                            Vector3 flippedPos = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, spriteData, spriteData.colliderVertices[i], flipH, flipV, rot90);
                            vertexList.Add(flippedPos + currentPos);
                        }

                        var srcIndices = spriteData.colliderIndicesFwd;
                        for (int i = 0; i < srcIndices.Length; ++i)
                        {
                            int j = reverseIndices ? (srcIndices.Length - 1 - i) : i;
                            indexList.Add(baseVertexIndex + srcIndices[j]);
                        }
                    }
                }
            }

            vertices = vertexList.ToArray();
            indices  = indexList.ToArray();
        }