상속: MonoBehaviour, ISpriteCollectionForceBuild
 public void DestroyColliderData(tk2dTileMap tileMap)
 {
     if (this.colliderMesh != null)
     {
         tileMap.DestroyMesh(this.colliderMesh);
     }
     if (((this.meshCollider != null) && (this.meshCollider.sharedMesh != null)) && (this.meshCollider.sharedMesh != this.colliderMesh))
     {
         tileMap.DestroyMesh(this.meshCollider.sharedMesh);
     }
     if (this.meshCollider != null)
     {
         tk2dUtil.DestroyImmediate(this.meshCollider);
     }
     this.meshCollider = null;
     this.colliderMesh = null;
     if (this.edgeColliders.Count > 0)
     {
         for (int i = 0; i < this.edgeColliders.Count; i++)
         {
             tk2dUtil.DestroyImmediate(this.edgeColliders[i]);
         }
         this.edgeColliders.Clear();
     }
 }
예제 #2
0
        ////////////////////////////////////////////////////////////////////////////////////////////////
        /// Static and helper functions
        ////////////////////////////////////////////////////////////////////////////////////////////////
        public static bool Import(tk2dTileMap tileMap, Format format)
        {
            var importer = new Importer();

            string ext = "";
            switch (format)
            {
                case Format.TMX:
                    if (!importer.CheckZlib()) return false;
                    ext = "tmx";
                break;
            }

            string path = EditorUtility.OpenFilePanel("Import tilemap", "", ext);
            if (path.Length == 0)
                return false;

            string message = "";
            switch (format)
            {
            case Format.TMX: message = importer.ImportTMX(path); break;
            }

            if (message.Length != 0)
            {
                EditorUtility.DisplayDialog("Tilemap failed to import", message, "Ok");
                return false;
            }

            importer.PopulateTilemap(tileMap);
            return true;
        }
        public static void Build(tk2dTileMap tileMap)
        {
            int numLayers = tileMap.Layers.Length;
            for (int layerId = 0; layerId < numLayers; ++layerId)
            {
                var layer = tileMap.Layers[layerId];
                if (layer.IsEmpty || !tileMap.data.Layers[layerId].generateCollider)
                    continue;

                for (int cellY = 0; cellY < layer.numRows; ++cellY)
                {
                    int baseY = cellY * layer.divY;
                    for (int cellX = 0; cellX < layer.numColumns; ++cellX)
                    {
                        int baseX = cellX * layer.divX;
                        var chunk = layer.GetChunk(cellX, cellY);

                        if (chunk.IsEmpty)
                            continue;

                        BuildForChunk(tileMap, chunk, baseX, baseY);
                    }
                }
            }
        }
예제 #4
0
        public Rect DrawBrush(tk2dTileMap tileMap, tk2dTileMapEditorBrush brush, float scale, bool forceUnitSpacing, int tilesPerRow)
        {
            var dictData = GetDictDataForBrush(brush, tilesPerRow);
            Mesh atlasViewMesh = dictData.mesh;
            Rect atlasViewRect = BrushToScreenRect(dictData.rect);

            float width = atlasViewRect.width * scale;
            float height = atlasViewRect.height * scale;

            float maxScreenWidth = Screen.width - 16;
            if (width > maxScreenWidth)
            {
                height = height * maxScreenWidth / width;
                width = maxScreenWidth;
            }

            Rect rect = GUILayoutUtility.GetRect(width, height, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false));
            scale = width / atlasViewRect.width;
            lastScale = scale;

            if (Event.current.type == EventType.Repaint)
            {
                tileMap.spriteCollection.materials[0].SetPass(0);
                Matrix4x4 mat = new Matrix4x4();
                var spriteDef = tileMap.spriteCollection.spriteDefinitions[0];
                mat.SetTRS(new Vector3(rect.x,
                                       rect.y + height, 0), Quaternion.identity, new Vector3(scale / spriteDef.texelSize.x, -scale / spriteDef.texelSize.y, 1));
                Graphics.DrawMeshNow(atlasViewMesh, mat * GUI.matrix);
            }

            return rect;
        }
		public static void Build(tk2dTileMap tileMap, bool forceBuild)
		{
			bool incremental = !forceBuild;
			int numLayers = tileMap.Layers.Length;
			for (int layerId = 0; layerId < numLayers; ++layerId)
			{
				var layer = tileMap.Layers[layerId];
				if (layer.IsEmpty || !tileMap.data.Layers[layerId].generateCollider)
					continue;
	
				for (int cellY = 0; cellY < layer.numRows; ++cellY)
				{
					int baseY = cellY * layer.divY;
					for (int cellX = 0; cellX < layer.numColumns; ++cellX)
					{
						int baseX = cellX * layer.divX;
						var chunk = layer.GetChunk(cellX, cellY);
						
						if (incremental && !chunk.Dirty)
							continue;
						
						if (chunk.IsEmpty)
							continue;
						
						BuildForChunk(tileMap, chunk, baseX, baseY);

						PhysicMaterial material = tileMap.data.Layers[layerId].physicMaterial;
						if (chunk.meshCollider != null) {
							chunk.meshCollider.sharedMaterial = material;
						}
					}
				}
			}
		}
예제 #6
0
        // Returns index of newly added layer
        public static int AddNewLayer(tk2dTileMap tileMap)
        {
            var existingLayers = tileMap.data.Layers;
            // find a unique hash
            bool duplicateHash = false;
            int hash;
            do
            {
                duplicateHash = false;
                hash = Random.Range(0, int.MaxValue);
                foreach (var layer in existingLayers)
                    if (layer.hash == hash)
                        duplicateHash = true;
            } while (duplicateHash == true);

            var newLayer = new tk2dRuntime.TileMap.LayerInfo();
            newLayer.name = "New Layer";
            newLayer.hash = hash;
            newLayer.z = 0.1f;
            tileMap.data.tileMapLayers.Add(newLayer);

            // remap tilemap
            tk2dRuntime.TileMap.BuilderUtil.InitDataStore(tileMap);

            return tileMap.data.NumLayers - 1;
        }
예제 #7
0
        public static void ResizeTileMap(tk2dTileMap tileMap, int width, int height, int partitionSizeX, int partitionSizeY)
        {
            int w = Mathf.Clamp(width, 1, MaxWidth);
            int h = Mathf.Clamp(height, 1, MaxHeight);

            tk2dRuntime.TileMap.BuilderUtil.InitDataStore(tileMap);

            // copy into new tilemap
            Layer[] layers = new Layer[tileMap.Layers.Length];
            for (int layerId = 0; layerId < tileMap.Layers.Length; ++layerId)
            {
                var srcLayer = tileMap.Layers[layerId];
                layers[layerId] = new Layer(srcLayer.hash, width, height, partitionSizeX, partitionSizeY);
                var destLayer = layers[layerId];

                if (srcLayer.IsEmpty)
                    continue;

                int hcopy = Mathf.Min(tileMap.height, h);
                int wcopy = Mathf.Min(tileMap.width, w);

                for (int y = 0; y < hcopy; ++y)
                {
                    for (int x = 0; x < wcopy; ++x)
                    {
                        destLayer.SetTile(x, y, srcLayer.GetTile(x, y));
                    }
                }

                destLayer.Optimize();
            }

            // copy new colors
            bool copyColors = (tileMap.ColorChannel != null && !tileMap.ColorChannel.IsEmpty);
            ColorChannel targetColors = new ColorChannel(width, height, partitionSizeX, partitionSizeY);
            if (copyColors)
            {
                int hcopy = Mathf.Min(tileMap.height, h) + 1;
                int wcopy = Mathf.Min(tileMap.width, w) + 1;
                for (int y = 0; y < hcopy; ++y)
                {
                    for (int x = 0; x < wcopy; ++x)
                    {
                        targetColors.SetColor(x, y, tileMap.ColorChannel.GetColor(x, y));
                    }
                }

                targetColors.Optimize();
            }

            tileMap.ColorChannel = targetColors;
            tileMap.Layers = layers;
            tileMap.width = w;
            tileMap.height = h;
            tileMap.partitionSizeX = partitionSizeX;
            tileMap.partitionSizeY = partitionSizeY;

            tk2dRuntime.TileMap.BuilderUtil.CleanRenderData(tileMap);
        }
		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);
			}
		}		
예제 #9
0
 public static void MoveLayer(tk2dTileMap tileMap, int layer, int direction)
 {
     tk2dRuntime.TileMap.BuilderUtil.CleanRenderData(tileMap);
     var tmp = tileMap.data.tileMapLayers[layer];
     tileMap.data.tileMapLayers[layer] = tileMap.data.tileMapLayers[layer + direction];
     tileMap.data.tileMapLayers[layer + direction] = tmp;
     tk2dRuntime.TileMap.BuilderUtil.InitDataStore(tileMap);
 }
예제 #10
0
		public void DestroyGameData(tk2dTileMap tileMap)
		{
			if (mesh != null) tileMap.DestroyMesh(mesh);
			if (gameObject != null) GameObject.DestroyImmediate(gameObject);
			gameObject = null;
			mesh = null;
			
			DestroyColliderData(tileMap);
		}
예제 #11
0
        public static void DeleteLayer(tk2dTileMap tileMap, int layerToDelete)
        {
            // Just in case
            if (tileMap.data.NumLayers <= 1)
                return;

            tk2dRuntime.TileMap.BuilderUtil.CleanRenderData(tileMap);
            tileMap.data.tileMapLayers.RemoveAt(layerToDelete);
            tk2dRuntime.TileMap.BuilderUtil.InitDataStore(tileMap);
        }
예제 #12
0
		public void DestroyColliderData(tk2dTileMap tileMap)
		{
			if (colliderMesh != null) 
				tileMap.DestroyMesh(colliderMesh);
			if (meshCollider != null && meshCollider.sharedMesh != null && meshCollider.sharedMesh != colliderMesh) 
				tileMap.DestroyMesh(meshCollider.sharedMesh);
			if (meshCollider != null) GameObject.DestroyImmediate(meshCollider);
			meshCollider = null;
			colliderMesh = null;
		}
 public static void Build(tk2dTileMap tileMap, bool editMode, bool forceBuild)
 {
     bool skipPrefabs = !editMode;
     bool flag2 = !forceBuild;
     int numLayers = tileMap.data.NumLayers;
     for (int i = 0; i < numLayers; i++)
     {
         Layer layer = tileMap.Layers[i];
         if (!layer.IsEmpty)
         {
             LayerInfo info = tileMap.data.Layers[i];
             bool useColor = !tileMap.ColorChannel.IsEmpty && tileMap.data.Layers[i].useColor;
             bool useSortingLayers = tileMap.data.useSortingLayers;
             for (int j = 0; j < layer.numRows; j++)
             {
                 int baseY = j * layer.divY;
                 for (int k = 0; k < layer.numColumns; k++)
                 {
                     int baseX = k * layer.divX;
                     SpriteChunk chunk = layer.GetChunk(k, j);
                     ColorChunk colorChunk = tileMap.ColorChannel.GetChunk(k, j);
                     bool flag5 = (colorChunk != null) && colorChunk.Dirty;
                     if ((!flag2 || flag5) || chunk.Dirty)
                     {
                         if (chunk.mesh != null)
                         {
                             chunk.mesh.Clear();
                         }
                         if (!chunk.IsEmpty)
                         {
                             if (editMode || (!editMode && !info.skipMeshGeneration))
                             {
                                 BuildForChunk(tileMap, chunk, colorChunk, useColor, skipPrefabs, baseX, baseY);
                                 if ((chunk.gameObject != null) && useSortingLayers)
                                 {
                                     Renderer renderer = chunk.gameObject.renderer;
                                     if (renderer != null)
                                     {
                                         renderer.sortingLayerName = info.sortingLayerName;
                                         renderer.sortingOrder = info.sortingOrder;
                                     }
                                 }
                             }
                             if (chunk.mesh != null)
                             {
                                 tileMap.TouchMesh(chunk.mesh);
                             }
                         }
                     }
                 }
             }
         }
     }
 }
		static GameObject GetExistingTilePrefabInstance(tk2dTileMap tileMap, int tileX, int tileY, int tileLayer) {
			int n = tileMap.GetTilePrefabsListCount();
			for (int i = 0; i < n; ++i) {
				int x, y, layer;
				GameObject instance;
				tileMap.GetTilePrefabsListItem(i, out x, out y, out layer, out instance);
				if (x == tileX && y == tileY && layer == tileLayer)
					return instance;
			}
			return null;
		}
예제 #15
0
 public void DestroyGameData(tk2dTileMap tilemap)
 {
     foreach (SpriteChunk chunk in this.spriteChannel.chunks)
     {
         if (chunk.HasGameData)
         {
             chunk.DestroyColliderData(tilemap);
             chunk.DestroyGameData(tilemap);
         }
     }
 }
예제 #16
0
        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);
            }
        }
예제 #17
0
    /* Farseer user data string to give to each box collider fixture. */
    //private string userData = "Environment"; // TODO: implement.
    /* Farseer user tag string to give to each box collider fixture. */
    //private string userTag = "Environment"; // TODO: implement.
    /* This is called first in the Unity execution order of events, adding new Farseer colliders
     * to the tilemap before the Farseer physics engine begins. */
    void Awake()
    {
        tilemap = GetComponent<tk2dTileMap>();
        spriteDefinitions = tilemap.SpriteCollectionInst.spriteDefinitions;

        tileWidth = tilemap.data.tileSize.x;
        tileHeight = tilemap.data.tileSize.y;

        maxTilesY = Mathf.Min(tilemap.partitionSizeY, tilemap.height);
        maxTilesX = Mathf.Min(tilemap.partitionSizeX, tilemap.width);

        GenerateColliders();
    }
예제 #18
0
 public static int FindOrCreateLayer(tk2dTileMap tileMap, string name)
 {
     int index = 0;
     foreach (var v in tileMap.data.Layers)
     {
         if (v.name == name)
             return index;
         ++index;
     }
     index = AddNewLayer(tileMap);
     tileMap.data.Layers[index].name = name;
     return index;
 }
예제 #19
0
    public tk2dTileMapSceneGUI(ITileMapEditorHost host, tk2dTileMap tileMap, tk2dTileMapEditorData editorData)
    {
        this.host = host;
        this.tileMap = tileMap;
        this.editorData = editorData;
        this.tileMapData = tileMap.data;

        // create default brush
        if (tileMap.spriteCollection && this.editorData)
        {
            this.editorData.InitBrushes(tileMap.spriteCollection);
            EditorUtility.SetDirty(this.editorData);
        }
    }
 public void DestroyGameData(tk2dTileMap tileMap)
 {
     if (this.mesh != null)
     {
         tileMap.DestroyMesh(this.mesh);
     }
     if (this.gameObject != null)
     {
         tk2dUtil.DestroyImmediate(this.gameObject);
     }
     this.gameObject = null;
     this.mesh = null;
     this.DestroyColliderData(tileMap);
 }
        /// Deletes all generated instances
        public static void CleanRenderData(tk2dTileMap tileMap)
        {
            if (tileMap.renderData == null)
                return;

            // To Do: Move all prefabs to the "Prefabs" object. (Then don't add to children list)

            // Build a list of all children
            // All children will appear after the parent
            int currentProcessedChild = 0;
            List<Transform> children = new List<Transform>();
            children.Add(tileMap.renderData.transform);
            while (currentProcessedChild < children.Count)
            {
                var thisChild = children[currentProcessedChild++];
                int childCount = thisChild.childCount;
                for (int i = 0; i < childCount; ++i)
                    children.Add(thisChild.GetChild(i));
            }
            currentProcessedChild = children.Count - 1;
            while (currentProcessedChild > 0) // skip very first as it is the root object
            {
                var go = children[currentProcessedChild--].gameObject;

                MeshFilter mf = go.GetComponent<MeshFilter>();
                if (mf != null)
                {
                    if (mf.sharedMesh != null && !EditorUtility.IsPersistent(mf.sharedMesh))
                    {
                        Mesh mesh = mf.sharedMesh;
                        mf.sharedMesh = null;
                        tileMap.DestroyMesh(mesh);
                    }
                }

                MeshCollider meshCollider = go.GetComponent<MeshCollider>();
                if (meshCollider)
                {
                    if (meshCollider.sharedMesh != null && !EditorUtility.IsPersistent(meshCollider.sharedMesh))
                    {
                        Mesh mesh = meshCollider.sharedMesh;
                        meshCollider.sharedMesh = null;
                        tileMap.DestroyMesh(mesh);
                    }
                }

                GameObject.DestroyImmediate(go);
            }
        }
예제 #22
0
        /// Spawns all prefabs for a given tilemap
        /// Expects populated chunks to have valid GameObjects
        public static void SpawnPrefabs(tk2dTileMap tileMap, bool forceBuild)
        {
            // Restart these lists that will be stored in the tileMap tilePrefabsList
            TilePrefabsX        = new List <int>();
            TilePrefabsY        = new List <int>();
            TilePrefabsLayer    = new List <int>();
            TilePrefabsInstance = new List <GameObject>();

            int[] prefabCounts = new int[tileMap.data.tilePrefabs.Length];

            int numLayers = tileMap.Layers.Length;

            for (int layerId = 0; layerId < numLayers; ++layerId)
            {
                var layer     = tileMap.Layers[layerId];
                var layerData = tileMap.data.Layers[layerId];

                // We skip offsetting the first one
                if (layer.IsEmpty || layerData.skipMeshGeneration)
                {
                    continue;
                }

                for (int cellY = 0; cellY < layer.numRows; ++cellY)
                {
                    int baseY = cellY * layer.divY;
                    for (int cellX = 0; cellX < layer.numColumns; ++cellX)
                    {
                        int baseX = cellX * layer.divX;
                        var chunk = layer.GetChunk(cellX, cellY);
                        if (chunk.IsEmpty)
                        {
                            continue;
                        }
                        if (!forceBuild && !chunk.Dirty)
                        {
                            continue;
                        }

                        SpawnPrefabsForChunk(tileMap, chunk, baseX, baseY, layerId, prefabCounts);
                    }
                }
            }

            tileMap.SetTilePrefabsList(TilePrefabsX, TilePrefabsY, TilePrefabsLayer, TilePrefabsInstance);
        }
예제 #23
0
 public static Vector3 ApplySpriteVertexTileFlags(tk2dTileMap tileMap, tk2dSpriteDefinition spriteDef, Vector3 pos, bool flipH, bool flipV, bool rot90)
 {
     float cx = tileMap.data.tileOrigin.x + 0.5f * tileMap.data.tileSize.x;
     float cy = tileMap.data.tileOrigin.y + 0.5f * tileMap.data.tileSize.y;
     float dx = pos.x - cx;
     float dy = pos.y - cy;
     if (rot90) {
         float tmp = dx;
         dx = dy;
         dy = -tmp;
     }
     if (flipH) dx *= -1.0f;
     if (flipV) dy *= -1.0f;
     pos.x = cx + dx;
     pos.y = cy + dy;
     return pos;
 }
예제 #24
0
 public void DestroyColliderData(tk2dTileMap tileMap)
 {
     if (colliderMesh != null)
     {
         tileMap.DestroyMesh(colliderMesh);
     }
     if (meshCollider != null && meshCollider.sharedMesh != null && meshCollider.sharedMesh != colliderMesh)
     {
         tileMap.DestroyMesh(meshCollider.sharedMesh);
     }
     if (meshCollider != null)
     {
         GameObject.DestroyImmediate(meshCollider);
     }
     meshCollider = null;
     colliderMesh = null;
 }
예제 #25
0
	static void Create()
	{
		tk2dSpriteCollectionData sprColl = null;
		if (sprColl == null)
		{
			// try to inherit from other TileMaps in scene
			tk2dTileMap sceneTileMaps = GameObject.FindObjectOfType(typeof(tk2dTileMap)) as tk2dTileMap;
			if (sceneTileMaps)
			{
				sprColl = sceneTileMaps.Editor__SpriteCollection;
			}
		}

		if (sprColl == null)
		{
			tk2dSpriteCollectionIndex[] spriteCollections = tk2dEditorUtility.GetOrCreateIndex().GetSpriteCollectionIndex();
			foreach (var v in spriteCollections)
			{
				if (v.managedSpriteCollection) continue; // don't wanna pick a managed one
				
				GameObject scgo = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(v.spriteCollectionDataGUID), typeof(GameObject)) as GameObject;
				var sc = scgo.GetComponent<tk2dSpriteCollectionData>();
				if (sc != null && sc.spriteDefinitions != null && sc.spriteDefinitions.Length > 0 && sc.allowMultipleAtlases == false)
				{
					sprColl = sc;
					break;
				}
			}

			if (sprColl == null)
			{
				EditorUtility.DisplayDialog("Create TileMap", "Unable to create sprite as no SpriteCollections have been found.", "Ok");
				return;
			}
		}

		GameObject go = tk2dEditorUtility.CreateGameObjectInScene("TileMap");
		go.transform.position = Vector3.zero;
		go.transform.rotation = Quaternion.identity;
		tk2dTileMap tileMap = go.AddComponent<tk2dTileMap>();
		tileMap.BeginEditMode();
	
		Selection.activeGameObject = go;
		Undo.RegisterCreatedObjectUndo(go, "Create TileMap");
	}
예제 #26
0
        public static void Build(tk2dTileMap tileMap, bool editMode, bool forceBuild)
        {
            bool skipPrefabs = editMode?false:true;
            bool incremental = !forceBuild;
            int numLayers = tileMap.data.NumLayers;

            for (int layerId = 0; layerId < numLayers; ++layerId)
            {
                var layer = tileMap.Layers[layerId];
                if (layer.IsEmpty)
                    continue;

                var layerData = tileMap.data.Layers[layerId];
                bool useColor = !tileMap.ColorChannel.IsEmpty && tileMap.data.Layers[layerId].useColor;

                for (int cellY = 0; cellY < layer.numRows; ++cellY)
                {
                    int baseY = cellY * layer.divY;
                    for (int cellX = 0; cellX < layer.numColumns; ++cellX)
                    {
                        int baseX = cellX * layer.divX;
                        var chunk = layer.GetChunk(cellX, cellY);

                        ColorChunk colorChunk = tileMap.ColorChannel.GetChunk(cellX, cellY);

                        bool colorChunkDirty = (colorChunk != null) && colorChunk.Dirty;
                        if (incremental && !colorChunkDirty && !chunk.Dirty)
                            continue;

                        if (chunk.mesh != null)
                            chunk.mesh.Clear();

                        if (chunk.IsEmpty)
                            continue;

                        if (editMode ||
                            (!editMode && !layerData.skipMeshGeneration))
                            BuildForChunk(tileMap, chunk, colorChunk, useColor, skipPrefabs, baseX, baseY);

                        if (chunk.mesh != null)
                            tileMap.TouchMesh(chunk.mesh);
                    }
                }
            }
        }
예제 #27
0
		/// Deletes all generated instances
		public static void CleanRenderData(tk2dTileMap tileMap)
		{
			if (tileMap.renderData == null)
				return;
			
			// Build a list of all children
			// All children will appear after the parent
			int currentProcessedChild = 0;
			List<Transform> children = new List<Transform>();
			children.Add(tileMap.renderData.transform);
			while (currentProcessedChild < children.Count)
			{
				var thisChild = children[currentProcessedChild++];
				int childCount = thisChild.GetChildCount();
				for (int i = 0; i < childCount; ++i)
					children.Add(thisChild.GetChild(i));
			}
			currentProcessedChild = children.Count - 1;
			while (currentProcessedChild > 0) // skip very first as it is the root object
			{
				var go = children[currentProcessedChild--].gameObject;
				
				MeshFilter mf = go.GetComponent<MeshFilter>();
				if (mf != null)
				{
					Mesh mesh = mf.sharedMesh;
					mf.sharedMesh = null;
					
					tileMap.DestroyMesh(mesh);
				}

				MeshCollider meshCollider = go.GetComponent<MeshCollider>();
				if (meshCollider)
				{
					Mesh mesh = meshCollider.sharedMesh;
					meshCollider.sharedMesh = null;
					
					tileMap.DestroyMesh(mesh);
				}
				
				GameObject.DestroyImmediate(go);
			}
			
			tileMap.buildKey++; // force a rebuild
		}
 void PopulateTilemap(tk2dTileMap tileMap)
 {
     tk2dEditor.TileMap.TileMapUtility.ResizeTileMap(tileMap, width, height, tileMap.partitionSizeX, tileMap.partitionSizeY);
     foreach (var layer in layers)
     {
         int index  = tk2dEditor.TileMap.TileMapUtility.FindOrCreateLayer(tileMap, layer.name);
         var target = tileMap.Layers[index];
         for (int y = 0; y < height; ++y)
         {
             for (int x = 0; x < width; ++x)
             {
                 int tile = (int)(layer.tiles[y * width + x] & ~(0xE0000000));                         // ignore flipping
                 target.SetTile(x, height - 1 - y, tile - 1);
             }
         }
         target.Optimize();
     }
 }
예제 #29
0
        /// Spawns all prefabs for a given chunk
        /// Expects the chunk to have a valid GameObject
        public static void SpawnPrefabsForChunk(tk2dTileMap tileMap, SpriteChunk chunk)
        {
            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;

            for (int y = 0; y < tileMap.partitionSizeY; ++y)
            {
                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, 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;
                        }
                    }
                }
            }
        }
예제 #30
0
    public void Init(Grid <int> layout, int variant)
    {
        Variant = variant;
        Layout  = layout;

        tileMap = GetComponent <tk2dTileMap>();
        tileMap.renderData.transform.localScale = new Vector3(0.5f, 0.5f, 1);
        Refresh();

        tileMap.renderData.transform.parent = transform;

        var collider = GetComponent <BoxCollider2D>();

        collider.size   *= tileMap.renderData.transform.localScale.x;
        collider.center *= tileMap.renderData.transform.localScale.x;

        Cursor = transform.FindChild("Selector").gameObject;
        Cursor.transform.localPosition = tileMap.data.tileSize * tileMap.renderData.transform.localScale.x;
    }
예제 #31
0
	public tk2dTileMapSceneGUI(ITileMapEditorHost host, tk2dTileMap tileMap, tk2dTileMapEditorData editorData)
	{
		this.host = host;
		this.tileMap = tileMap;
		this.editorData = editorData;
		this.tileMapData = tileMap.data;
		
		// create default brush
		if (tileMap.SpriteCollectionInst && this.editorData)
		{
			this.editorData.InitBrushes(tileMap.SpriteCollectionInst);
			EditorUtility.SetDirty(this.editorData);
		}

		scratchpadGUI = new tk2dScratchpadGUI(this, BrushRenderer, WorkingBrush);
		if (editorData != null) {
			scratchpadGUI.SetActiveScratchpads(editorData.scratchpads);
		}
	}
예제 #32
0
        private void ExpandRoom(PaydayDrillItem drillItem, RoomHandler r)
        {
            Dungeon dungeon = GameManager.Instance.Dungeon;

            AkSoundEngine.PostEvent("Play_OBJ_stone_crumble_01", GameManager.Instance.gameObject);
            tk2dTileMap          tk2dTileMap = null;
            HashSet <IntVector2> hashSet     = new HashSet <IntVector2>();

            for (int i = -5; i < r.area.dimensions.x + 5; i++)
            {
                for (int j = -5; j < r.area.dimensions.y + 5; j++)
                {
                    IntVector2 intVector = r.area.basePosition + new IntVector2(i, j);
                    CellData   cellData  = (!dungeon.data.CheckInBoundsAndValid(intVector)) ? null : dungeon.data[intVector];
                    if (cellData != null && cellData.type == CellType.WALL && cellData.HasTypeNeighbor(dungeon.data, CellType.FLOOR))
                    {
                        hashSet.Add(cellData.position);
                    }
                }
            }
            foreach (IntVector2 key in hashSet)
            {
                CellData cellData2 = dungeon.data[key];
                cellData2.breakable = true;
                cellData2.occlusionData.overrideOcclusion  = true;
                cellData2.occlusionData.cellOcclusionDirty = true;
                tk2dTileMap = dungeon.DestroyWallAtPosition(key.x, key.y, true);
                if (UnityEngine.Random.value < 0.25f)
                {
                    drillItem.VFXDustPoof.SpawnAtPosition(key.ToCenterVector3((float)key.y), 0f, null, null, null, null, false, null, null, false);
                }
                r.Cells.Add(cellData2.position);
                r.CellsWithoutExits.Add(cellData2.position);
                r.RawCells.Add(cellData2.position);
            }
            Pixelator.Instance.MarkOcclusionDirty();
            Pixelator.Instance.ProcessOcclusionChange(r.Epicenter, 1f, r, false);
            if (tk2dTileMap)
            {
                dungeon.RebuildTilemap(tk2dTileMap);
            }
        }
예제 #33
0
        public static void Build(tk2dTileMap tileMap, bool forceBuild)
        {
            bool incremental = !forceBuild;
            int  numLayers   = tileMap.Layers.Length;

            for (int layerId = 0; layerId < numLayers; ++layerId)
            {
                var layer = tileMap.Layers[layerId];
                if (layer.IsEmpty || !tileMap.data.Layers[layerId].generateCollider)
                {
                    continue;
                }

                for (int cellY = 0; cellY < layer.numRows; ++cellY)
                {
                    int baseY = cellY * layer.divY;
                    for (int cellX = 0; cellX < layer.numColumns; ++cellX)
                    {
                        int baseX = cellX * layer.divX;
                        var chunk = layer.GetChunk(cellX, cellY);

                        if (incremental && !chunk.Dirty)
                        {
                            continue;
                        }

                        if (chunk.IsEmpty)
                        {
                            continue;
                        }

                        BuildForChunk(tileMap, chunk, baseX, baseY);

                        PhysicMaterial material = tileMap.data.Layers[layerId].physicMaterial;
                        if (chunk.meshCollider != null)
                        {
                            chunk.meshCollider.sharedMaterial = material;
                        }
                    }
                }
            }
        }
예제 #34
0
    public tk2dTileMapSceneGUI(ITileMapEditorHost host, tk2dTileMap tileMap, tk2dTileMapEditorData editorData)
    {
        this.host        = host;
        this.tileMap     = tileMap;
        this.editorData  = editorData;
        this.tileMapData = tileMap.data;

        // create default brush
        if (tileMap.SpriteCollectionInst && this.editorData)
        {
            this.editorData.InitBrushes(tileMap.SpriteCollectionInst);
            EditorUtility.SetDirty(this.editorData);
        }

        scratchpadGUI = new tk2dScratchpadGUI(this, BrushRenderer, WorkingBrush);
        if (editorData != null)
        {
            scratchpadGUI.SetActiveScratchpads(editorData.scratchpads);
        }
    }
        public Rect DrawBrush(tk2dTileMap tileMap, tk2dTileMapEditorBrush brush, float scale, bool forceUnitSpacing, int tilesPerRow, Rect inRect)
        {
            var  dictData      = GetDictDataForBrush(brush, tilesPerRow);
            Mesh atlasViewMesh = dictData.mesh;
            Rect atlasViewRect = BrushToScreenRect(dictData.rect);

            Rect visibleRect = tk2dSpriteThumbnailCache.VisibleRect;

            visibleRect = inRect;
            Vector4 clipRegion = new Vector4(visibleRect.x, visibleRect.y, visibleRect.x + visibleRect.width, visibleRect.y + visibleRect.height);

            Material customMaterial = tk2dSpriteThumbnailCache.GetMaterial();

            customMaterial.SetColor("_Tint", Color.white);
            customMaterial.SetVector("_Clip", clipRegion);

            float width  = atlasViewRect.width * scale;
            float height = atlasViewRect.height * scale;

            Rect rect = GUILayoutUtility.GetRect(width, height, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true));

            scale     = width / atlasViewRect.width;
            lastScale = scale;

            if (Event.current.type == EventType.Repaint)
            {
                Matrix4x4 mat       = new Matrix4x4();
                var       spriteDef = tileMap.SpriteCollectionInst.spriteDefinitions[0];
                mat.SetTRS(new Vector3(rect.x,
                                       rect.y + height, 0), Quaternion.identity, new Vector3(scale / spriteDef.texelSize.x, -scale / spriteDef.texelSize.y, 1));

                for (int i = 0; i < dictData.materials.Length; ++i)
                {
                    customMaterial.mainTexture = dictData.materials[i].mainTexture;
                    customMaterial.SetPass(0);
                    Graphics.DrawMeshNow(atlasViewMesh, mat * GUI.matrix, i);
                }
            }

            return(rect);
        }
        /// Deletes all generated instances
        public static void CleanRenderData(tk2dTileMap tileMap)
        {
            if (tileMap.renderData == null)
            {
                return;
            }

            // Build a list of all children
            // All children will appear after the parent
            int currentProcessedChild = 0;
            List <Transform> children = new List <Transform>();

            children.Add(tileMap.renderData.transform);
            while (currentProcessedChild < children.Count)
            {
                var thisChild  = children[currentProcessedChild++];
                int childCount = thisChild.GetChildCount();
                for (int i = 0; i < childCount; ++i)
                {
                    children.Add(thisChild.GetChild(i));
                }
            }
            currentProcessedChild = children.Count - 1;
            while (currentProcessedChild > 0)             // skip very first as it is the root object
            {
                var go = children[currentProcessedChild--].gameObject;
                if (go.renderer)
                {
                    MeshFilter mf = go.GetComponent <MeshFilter>();
                    if (mf != null)
                    {
                        Mesh mesh = mf.sharedMesh;
                        GameObject.DestroyImmediate(mesh);
                        mf.sharedMesh = null;
                    }
                }
                GameObject.DestroyImmediate(go);
            }

            tileMap.buildKey++;             // force a rebuild
        }
예제 #37
0
		// Returns index of newly added layer
		public static int AddNewLayer(tk2dTileMap tileMap)
		{
			var existingLayers = tileMap.data.Layers;
			// find a unique hash
			bool duplicateHash = false;
			int hash;
			do
			{
				duplicateHash = false;
				hash = Random.Range(0, int.MaxValue);
				foreach (var layer in existingLayers) 
					if (layer.hash == hash) 
						duplicateHash = true;
			} while (duplicateHash == true);

			List<Object> objectsToUndo = new List<Object>();
			objectsToUndo.Add(tileMap);
			objectsToUndo.Add(tileMap.data);
			Undo.RegisterUndo(objectsToUndo.ToArray(), "Add layer");
			
			var newLayer = new tk2dRuntime.TileMap.LayerInfo();
			newLayer.name = "New Layer";
			newLayer.hash = hash;
			newLayer.z = 0.1f;
			tileMap.data.tileMapLayers.Add(newLayer);
			
			// remap tilemap
			tk2dRuntime.TileMap.BuilderUtil.InitDataStore(tileMap);

			GameObject layerGameObject = new GameObject(newLayer.name);
			layerGameObject.transform.parent = tileMap.renderData.transform;
			layerGameObject.transform.localPosition = Vector3.zero;
			layerGameObject.transform.localScale = Vector3.one;
			layerGameObject.transform.localRotation = Quaternion.identity;
			tileMap.Layers[tileMap.Layers.Length - 1].gameObject = layerGameObject;

			Undo.RegisterCreatedObjectUndo(layerGameObject, "Add layer");
			
			return tileMap.data.NumLayers - 1;
		}
        ////////////////////////////////////////////////////////////////////////////////////////////////
        /// Static and helper functions
        ////////////////////////////////////////////////////////////////////////////////////////////////

        public static bool Import(tk2dTileMap tileMap, Format format)
        {
            var importer = new Importer();

            string ext = "";

            switch (format)
            {
            case Format.TMX:
                if (!importer.CheckZlib())
                {
                    return(false);
                }
                ext = "tmx";
                break;
            }

            string path = EditorUtility.OpenFilePanel("Import tilemap", "", ext);

            if (path.Length == 0)
            {
                return(false);
            }

            string message = "";

            switch (format)
            {
            case Format.TMX: message = importer.ImportTMX(path); break;
            }

            if (message.Length != 0)
            {
                EditorUtility.DisplayDialog("Tilemap failed to import", message, "Ok");
                return(false);
            }

            importer.PopulateTilemap(tileMap);
            return(true);
        }
예제 #39
0
        void PopulateTilemap(tk2dTileMap tileMap)
        {
            int extraWidth = staggered ? 1 : 0;

            tk2dEditor.TileMap.TileMapUtility.ResizeTileMap(tileMap, width + extraWidth, height, tileMap.partitionSizeX, tileMap.partitionSizeY);

            if (staggered)
            {
                tileMap.data.sortMethod = tk2dTileMapData.SortMethod.TopLeft;
                tileMap.data.tileType   = tk2dTileMapData.TileType.Isometric;
            }

            foreach (var layer in layers)
            {
                int index  = tk2dEditor.TileMap.TileMapUtility.FindOrCreateLayer(tileMap, layer.name);
                var target = tileMap.Layers[index];

                int ww = width + extraWidth;
                for (int y = 0; y < height; ++y)
                {
                    for (int x = 0; x < ww; ++x)
                    {
                        target.SetTile(x, y, -1);
                    }
                }


                for (int y = 0; y < height; ++y)
                {
                    for (int x = 0; x < width; ++x)
                    {
                        int tile   = (int)(layer.tiles[y * width + x] & ~(0xE0000000));                       // ignore flipping
                        int offset = (staggered && ((y % 2) == 0)) ? 0 : 1;
                        target.SetTile(x + offset, height - 1 - y, tile - 1);
                    }
                }
                target.Optimize();
            }
        }
		public static void Build(tk2dTileMap tileMap, bool forceBuild)
		{
			bool incremental = !forceBuild;
			int numLayers = tileMap.Layers.Length;
			for (int layerId = 0; layerId < numLayers; ++layerId)
			{
				var layer = tileMap.Layers[layerId];
				if (layer.IsEmpty || !tileMap.data.Layers[layerId].generateCollider)
					continue;
	
				for (int cellY = 0; cellY < layer.numRows; ++cellY)
				{
					int baseY = cellY * layer.divY;
					for (int cellX = 0; cellX < layer.numColumns; ++cellX)
					{
						int baseX = cellX * layer.divX;
						var chunk = layer.GetChunk(cellX, cellY);
						
						if (incremental && !chunk.Dirty)
							continue;
						
						if (chunk.IsEmpty)
							continue;
						
						BuildForChunk(tileMap, chunk, baseX, baseY);

#if !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2)
						PhysicsMaterial2D material = tileMap.data.Layers[layerId].physicsMaterial2D;
						foreach (EdgeCollider2D ec in chunk.edgeColliders) {
							if (ec != null) {
								ec.sharedMaterial = material;
							}
						}
#endif
					}
				}
			}
		}
예제 #41
0
        private void ShrinkRoom(RoomHandler r)
        {
            Dungeon dungeon = GameManager.Instance.Dungeon;

            AkSoundEngine.PostEvent("Play_OBJ_stone_crumble_01", GameManager.Instance.gameObject);
            tk2dTileMap          tk2dTileMap = null;
            HashSet <IntVector2> hashSet     = new HashSet <IntVector2>();

            for (int i = -5; i < r.area.dimensions.x + 5; i++)
            {
                for (int j = -5; j < r.area.dimensions.y + 5; j++)
                {
                    IntVector2 intVector = r.area.basePosition + new IntVector2(i, j);
                    CellData   cellData  = (!dungeon.data.CheckInBoundsAndValid(intVector)) ? null : dungeon.data[intVector];
                    if (cellData != null && cellData.type != CellType.WALL && cellData.HasTypeNeighbor(dungeon.data, CellType.WALL))
                    {
                        hashSet.Add(cellData.position);
                    }
                }
            }
            foreach (IntVector2 key in hashSet)
            {
                CellData cellData2 = dungeon.data[key];
                cellData2.breakable = true;
                cellData2.occlusionData.overrideOcclusion  = true;
                cellData2.occlusionData.cellOcclusionDirty = true;
                tk2dTileMap = dungeon.ConstructWallAtPosition(key.x, key.y, true);
                r.Cells.Remove(cellData2.position);
                r.CellsWithoutExits.Remove(cellData2.position);
                r.RawCells.Remove(cellData2.position);
            }
            Pixelator.Instance.MarkOcclusionDirty();
            Pixelator.Instance.ProcessOcclusionChange(r.Epicenter, 1f, r, false);
            if (tk2dTileMap)
            {
                dungeon.RebuildTilemap(tk2dTileMap);
            }
        }
예제 #42
0
        public Rect DrawBrush(tk2dTileMap tileMap, tk2dTileMapEditorBrush brush, float scale, bool forceUnitSpacing, int tilesPerRow)
        {
            var  dictData      = GetDictDataForBrush(brush, tilesPerRow);
            Mesh atlasViewMesh = dictData.mesh;
            Rect atlasViewRect = BrushToScreenRect(dictData.rect);

            float width  = atlasViewRect.width * scale;
            float height = atlasViewRect.height * scale;

            float maxScreenWidth = Screen.width - 16;

            if (width > maxScreenWidth)
            {
                height = height * maxScreenWidth / width;
                width  = maxScreenWidth;
            }

            Rect rect = GUILayoutUtility.GetRect(width, height, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false));

            scale     = width / atlasViewRect.width;
            lastScale = scale;

            if (Event.current.type == EventType.Repaint)
            {
                Matrix4x4 mat       = new Matrix4x4();
                var       spriteDef = tileMap.SpriteCollectionInst.spriteDefinitions[0];
                mat.SetTRS(new Vector3(rect.x,
                                       rect.y + height, 0), Quaternion.identity, new Vector3(scale / spriteDef.texelSize.x, -scale / spriteDef.texelSize.y, 1));

                for (int i = 0; i < dictData.materials.Length; ++i)
                {
                    dictData.materials[i].SetPass(0);
                    Graphics.DrawMeshNow(atlasViewMesh, mat * GUI.matrix, i);
                }
            }

            return(rect);
        }
예제 #43
0
 //保存当前tilemap的数据为一个字符串,格式与CVS相同
 public string SaveTileMap(tk2dTileMap tk2dTM, int layerID)
 {
     try
     {
         string result = "";
         width  = tk2dTM.width;
         height = tk2dTM.height;
         //根据tilemap的宽度和高度初始化tileID数组
         tileID = new int[width, height];
         //从第一行开始,依次读取每一行,即row
         for (int y = 0; y < height; y++)
         {
             //从第一列开始,一次读取每一列,即column
             for (int x = 0; x < width; x++)
             {
                 //因为tk2dTileMap与Tiled的坐标系不同,y正好是相反的,所以从tk2dTileMap中取tileID时,y的值为height-1-y
                 tileID[x, y] = tk2dTM.GetTile(x, height - 1 - y, layerID);
                 //如果没有达到tilemap的宽度,则添加 "," 区分每一个tile
                 if (x != width - 1)
                 {
                     result += tileID[x, y].ToString() + ",";
                 }
                 //否则,一行完成后,进行换行
                 else
                 {
                     result += tileID[x, y].ToString() + "\r\n";
                 }
             }
         }
         return(result);
     }
     catch
     {
         //throw;
         return("");
     }
 }
 public static Vector3 ApplySpriteVertexTileFlags(tk2dTileMap tileMap, tk2dSpriteDefinition spriteDef, Vector3 pos, bool flipH, bool flipV, bool rot90)
 {
     float num = tileMap.data.tileOrigin.x + (0.5f * tileMap.data.tileSize.x);
     float num2 = tileMap.data.tileOrigin.y + (0.5f * tileMap.data.tileSize.y);
     float num3 = pos.x - num;
     float num4 = pos.y - num2;
     if (rot90)
     {
         float num5 = num3;
         num3 = num4;
         num4 = -num5;
     }
     if (flipH)
     {
         num3 *= -1f;
     }
     if (flipV)
     {
         num4 *= -1f;
     }
     pos.x = num + num3;
     pos.y = num2 + num4;
     return pos;
 }
예제 #45
0
        public static void DeleteLayer(tk2dTileMap tileMap, int layerToDelete)
        {
            // Just in case
            if (tileMap.data.NumLayers <= 1)
            {
                return;
            }

            // Find all objects that will be affected by this operation
            List <Object> objectsToUndo = new List <Object>();

            objectsToUndo.Add(tileMap);
            objectsToUndo.Add(tileMap.data);
            objectsToUndo.AddRange(CollectDeepHierarchy(tileMap.Layers[layerToDelete].gameObject));
            Undo.RegisterUndo(objectsToUndo.ToArray(), "Delete layer");

            tileMap.data.tileMapLayers.RemoveAt(layerToDelete);
            if (tileMap.Layers[layerToDelete].gameObject != null)
            {
                GameObject.DestroyImmediate(tileMap.Layers[layerToDelete].gameObject);
            }
            tk2dRuntime.TileMap.BuilderUtil.InitDataStore(tileMap);
            tileMap.ForceBuild();
        }
예제 #46
0
        public static void Build(tk2dTileMap tileMap, bool editMode, bool forceBuild)
        {
            bool skipPrefabs = editMode?false:true;
            bool incremental = !forceBuild;
            int  numLayers   = tileMap.data.NumLayers;

            for (int layerId = 0; layerId < numLayers; ++layerId)
            {
                var layer = tileMap.Layers[layerId];
                if (layer.IsEmpty)
                {
                    continue;
                }

                var  layerData = tileMap.data.Layers[layerId];
                bool useColor  = !tileMap.ColorChannel.IsEmpty && tileMap.data.Layers[layerId].useColor;
#if !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2)
                bool useSortingLayer = tileMap.data.useSortingLayers;
#endif

                for (int cellY = 0; cellY < layer.numRows; ++cellY)
                {
                    int baseY = cellY * layer.divY;
                    for (int cellX = 0; cellX < layer.numColumns; ++cellX)
                    {
                        int baseX = cellX * layer.divX;
                        var chunk = layer.GetChunk(cellX, cellY);

                        ColorChunk colorChunk = tileMap.ColorChannel.GetChunk(cellX, cellY);

                        bool colorChunkDirty = (colorChunk != null) && colorChunk.Dirty;
                        if (incremental && !colorChunkDirty && !chunk.Dirty)
                        {
                            continue;
                        }

                        if (chunk.mesh != null)
                        {
                            chunk.mesh.Clear();
                        }

                        if (chunk.IsEmpty)
                        {
                            continue;
                        }

                        if (editMode ||
                            (!editMode && !layerData.skipMeshGeneration))
                        {
                            BuildForChunk(tileMap, chunk, colorChunk, useColor, skipPrefabs, baseX, baseY);

#if !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2)
                            if (chunk.gameObject != null && useSortingLayer)
                            {
                                Renderer r = chunk.gameObject.GetComponent <Renderer>();
                                if (r != null)
                                {
                                    r.sortingLayerName = layerData.sortingLayerName;
                                    r.sortingOrder     = layerData.sortingOrder;
                                }
                            }
#endif
                        }

                        if (chunk.mesh != null)
                        {
                            tileMap.TouchMesh(chunk.mesh);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Moves the chunk's gameobject's children to the prefab root
        /// </summary>
        public static void HideTileMapPrefabs(tk2dTileMap tileMap)
        {
            if (tileMap.renderData == null)
            {
                // No Render Data to parent Prefab Root to
                return;
            }
            else
            {
                if (tileMap.PrefabsRoot == null)
                {
                    var go = tileMap.PrefabsRoot = new GameObject("Prefabs");
                    go.transform.parent        = tileMap.renderData.transform;
                    go.transform.localPosition = Vector3.zero;
                    go.transform.localRotation = Quaternion.identity;
                    go.transform.localScale    = Vector3.one;
                }
            }

            if (tileMap.Layers == null)
            {
                return;
            }

            int instListCount = tileMap.GetTilePrefabsListCount();

            bool[] instExists = new bool[instListCount];

            for (int i = 0; i < tileMap.Layers.Length; ++i)
            {
                var layer = tileMap.Layers[i];
                for (int j = 0; j < layer.spriteChannel.chunks.Length; ++j)
                {
                    var chunk = layer.spriteChannel.chunks[j];
                    if (chunk.gameObject == null)
                    {
                        continue;
                    }

                    var t          = chunk.gameObject.transform;
                    int childCount = t.childCount;
                    for (int k = 0; k < childCount; ++k)
                    {
                        GameObject go = t.GetChild(k).gameObject;
                        for (int q = 0; q < instListCount; ++q)
                        {
                            int        x, y, layerIdx;
                            GameObject instance;
                            tileMap.GetTilePrefabsListItem(q, out x, out y, out layerIdx, out instance);
                            if (instance == go)
                            {
                                instExists[q] = true;
                                break;
                            }
                        }
                    }
                }
            }

            List <int>        tileX     = new List <int>();
            List <int>        tileY     = new List <int>();
            List <int>        tileLayer = new List <int>();
            List <GameObject> tileInst  = new List <GameObject>();

            for (int i = 0; i < instListCount; ++i)
            {
                if (instExists[i])
                {
                    int        x, y, layerIdx;
                    GameObject instance;
                    tileMap.GetTilePrefabsListItem(i, out x, out y, out layerIdx, out instance);
                    tileX.Add(x);
                    tileY.Add(y);
                    tileLayer.Add(layerIdx);
                    tileInst.Add(instance);

                    instance.transform.parent = tileMap.PrefabsRoot.transform;
                }
            }
            tileMap.SetTilePrefabsList(tileX, tileY, tileLayer, tileInst);
        }
		// 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();
		}
 static Vector3 GetTilePosition(tk2dTileMap tileMap, int x, int y)
 {
     return(new Vector3(tileMap.data.tileSize.x * x, tileMap.data.tileSize.y * y, 0.0f));
 }
		/// 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);
						}
					}
				}
			}
		}
        // 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();
        }
        /// 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 (instance == null)
                        {
                                        #if UNITY_EDITOR && !(UNITY_3_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4)
                            instance = UnityEditor.PrefabUtility.InstantiatePrefab(prefab) as GameObject;
                                        #else
                            instance = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject;
                                        #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();
                            }

                            instance.transform.parent        = parent;
                            instance.transform.localPosition = pos;

                            // Add to tilePrefabs list
                            TilePrefabsX.Add(baseX + x);
                            TilePrefabsY.Add(baseY + y);
                            TilePrefabsLayer.Add(layer);
                            TilePrefabsInstance.Add(instance);
                        }
                    }
                }
            }
        }
예제 #53
0
    //private GameObject player1;

    // Use this for initialization
    void Start()
    {
        tilemap = GetComponent <tk2dTileMap>();
    }
예제 #54
0
        // 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, 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 <PolygonCollider2D>(chunk.gameObject);
                    }
                }
                // Create missing
                while (chunk.edgeColliders.Count < numEdges)
                {
                    chunk.edgeColliders.Add(tk2dUtil.AddComponent <PolygonCollider2D>(chunk.gameObject));
                }

                for (int i = 0; i < numEdges; ++i)
                {
                    chunk.edgeColliders[i].points = mergedEdges[i];
                }
            }
#endif
        }
예제 #56
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 <Vector2> meshUv2s     = 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);

            bool generateUv2 = tileMap.data.generateUv2;
            var  colorMode   = tileMap.data.colorMode;

            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 && colorChunk != null)
                        {
                            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)];

                            switch (colorMode)
                            {
                            case tk2dTileMapData.ColorMode.Interpolate:
                            {
                                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);
                                break;
                            }

                            case tk2dTileMapData.ColorMode.Solid:
                            {
                                meshColors.Add(tileColorx0y0);
                                break;
                            }
                            }
                        }
                        else
                        {
                            meshColors.Add(clearColor);
                        }

                        if (generateUv2)
                        {
                            if (sprite.normalizedUvs.Length == 0)
                            {
                                meshUv2s.Add(Vector2.zero);
                            }
                            else
                            {
                                meshUv2s.Add(sprite.normalizedUvs[v]);
                            }
                        }

                        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.Clear();

            chunk.mesh.vertices = meshVertices.ToArray();
            chunk.mesh.uv       = meshUvs.ToArray();
            if (generateUv2)
            {
                chunk.mesh.uv2 = meshUv2s.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;
        }
예제 #57
0
        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 (PolygonCollider2D 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);
            }
        }
        /// Creates render data for given tilemap
        public static void CreateRenderData(tk2dTileMap tileMap, bool editMode)
        {
            // Create render data
            if (tileMap.renderData == null)
            {
                tileMap.renderData = new GameObject(tileMap.name + " Render Data");
            }

            tileMap.renderData.transform.position = tileMap.transform.position;

            float accumulatedLayerZ = 0.0f;

            // Create all objects
            int layerId = 0;

            foreach (var layer in tileMap.Layers)
            {
                // We skip offsetting the first one
                float layerInfoZ = tileMap.data.Layers[layerId].z;
                if (layerId != 0)
                {
                    accumulatedLayerZ -= layerInfoZ;
                }

                if (layer.IsEmpty && layer.gameObject != null)
                {
                    GameObject.DestroyImmediate(layer.gameObject);
                    layer.gameObject = null;
                }
                else if (!layer.IsEmpty && layer.gameObject == null)
                {
                    var go = layer.gameObject = new GameObject("");
                    go.transform.parent = tileMap.renderData.transform;
                }

                int unityLayer = tileMap.data.Layers[layerId].unityLayer;

                if (layer.gameObject != null)
                {
#if UNITY_3_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 || UNITY_3_6 || UNITY_3_7 || UNITY_3_8 || UNITY_3_9
                    if (!editMode && layer.gameObject.active == false)
                    {
                        layer.gameObject.SetActiveRecursively(true);
                    }
#else
                    if (!editMode && layer.gameObject.activeSelf == false)
                    {
                        layer.gameObject.SetActive(true);
                    }
#endif

                    layer.gameObject.name = tileMap.data.Layers[layerId].name;
                    layer.gameObject.transform.localPosition = new Vector3(0, 0, tileMap.data.layersFixedZ ? (-layerInfoZ) : accumulatedLayerZ);
                    layer.gameObject.transform.localRotation = Quaternion.identity;
                    layer.gameObject.transform.localScale    = Vector3.one;
                    layer.gameObject.layer = unityLayer;
                }

                int x0, x1, dx;
                int y0, y1, dy;
                BuilderUtil.GetLoopOrder(tileMap.data.sortMethod,
                                         layer.numColumns, layer.numRows,
                                         out x0, out x1, out dx,
                                         out y0, out y1, out dy);

                float z = 0.0f;
                for (int y = y0; y != y1; y += dy)
                {
                    for (int x = x0; x != x1; x += dx)
                    {
                        var  chunk   = layer.GetChunk(x, y);
                        bool isEmpty = layer.IsEmpty || chunk.IsEmpty;
                        if (editMode)
                        {
                            isEmpty = false;
                        }

                        if (isEmpty && chunk.HasGameData)
                        {
                            chunk.DestroyGameData(tileMap);
                        }
                        else if (!isEmpty && chunk.gameObject == null)
                        {
                            string chunkName = "Chunk " + y.ToString() + " " + x.ToString();
                            var    go        = chunk.gameObject = new GameObject(chunkName);
                            go.transform.parent = layer.gameObject.transform;

                            // render mesh
                            MeshFilter meshFilter = go.AddComponent <MeshFilter>();
                            go.AddComponent <MeshRenderer>();
                            chunk.mesh      = new Mesh();
                            meshFilter.mesh = chunk.mesh;

                            // collider mesh
                            chunk.meshCollider            = go.AddComponent <MeshCollider>();
                            chunk.meshCollider.sharedMesh = null;
                            chunk.colliderMesh            = null;
                        }

                        if (chunk.gameObject != null)
                        {
                            Vector3 tilePosition = GetTilePosition(tileMap, x * tileMap.partitionSizeX, y * tileMap.partitionSizeY);
                            tilePosition.z += z;
                            chunk.gameObject.transform.localPosition = tilePosition;
                            chunk.gameObject.transform.localRotation = Quaternion.identity;
                            chunk.gameObject.transform.localScale    = Vector3.one;
                            chunk.gameObject.layer = unityLayer;

                            // We won't be generating collider data in edit mode, so clear everything
                            if (editMode)
                            {
                                if (chunk.colliderMesh)
                                {
                                    chunk.DestroyColliderData(tileMap);
                                }
                            }
                        }

                        z -= 0.000001f;
                    }
                }

                ++layerId;
            }
        }
예제 #59
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.SpriteCollectionInst.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);

            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     tile       = spriteIds[y * tileMap.partitionSizeX + x];
                    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)
                    {
                        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.SpriteCollectionInst.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;
        }
        /// Syncs layer data and makes sure data is valid
        public static bool InitDataStore(tk2dTileMap tileMap)
        {
            bool dataChanged = false;
            int  numLayers   = tileMap.data.NumLayers;

            if (tileMap.Layers == null)
            {
                tileMap.Layers = new Layer[numLayers];
                for (int i = 0; i < numLayers; ++i)
                {
                    tileMap.Layers[i] = new Layer(tileMap.data.Layers[i].hash, tileMap.width, tileMap.height, tileMap.partitionSizeX, tileMap.partitionSizeY);
                }
                dataChanged = true;
            }
            else
            {
                // link up layer hashes
                Layer[] newLayers = new Layer[numLayers];

                for (int i = 0; i < numLayers; ++i)
                {
                    var  layerInfo = tileMap.data.Layers[i];
                    bool found     = false;

                    // Find an existing layer with this hash
                    for (int j = 0; j < tileMap.Layers.Length; ++j)
                    {
                        if (tileMap.Layers[j].hash == layerInfo.hash)
                        {
                            newLayers[i] = tileMap.Layers[j];
                            found        = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        newLayers[i] = new Layer(layerInfo.hash, tileMap.width, tileMap.height, tileMap.partitionSizeX, tileMap.partitionSizeY);
                    }
                }

                // Identify if it has changed
                int numActiveLayers = 0;
                foreach (var layer in newLayers)
                {
                    if (!layer.IsEmpty)
                    {
                        numActiveLayers++;
                    }
                }

                int numPreviousActiveLayers = 0;
                foreach (var layer in tileMap.Layers)
                {
                    if (!layer.IsEmpty)
                    {
                        numPreviousActiveLayers++;
                    }
                }

                if (numActiveLayers != numPreviousActiveLayers)
                {
                    dataChanged = true;
                }

                tileMap.Layers = newLayers;
            }

            if (tileMap.ColorChannel == null)
            {
                tileMap.ColorChannel = new ColorChannel(tileMap.width, tileMap.height, tileMap.partitionSizeX, tileMap.partitionSizeY);
            }

            return(dataChanged);
        }