public static Texture2D BuildAtlas(Texture2D atlasTexture, int tilePadding, int tileExtrude, Vector2 tileSize, Vector2 sliceOffset, Vector2 slicePadding) { int widthInTiles = Mathf.FloorToInt((atlasTexture.width - sliceOffset.x + slicePadding.x) / (tileSize.x + slicePadding.x)); //NOTE: "+ slicePadding.x" makes sure to count the last tile even if no padding pixels are added to the right int heightInTiles = Mathf.FloorToInt((atlasTexture.height - sliceOffset.y + +slicePadding.y) / (tileSize.y + slicePadding.y)); int padTileWidth = Mathf.RoundToInt(tileSize.x + tilePadding); int padTileHeight = Mathf.RoundToInt(tileSize.y + tilePadding); int width = widthInTiles * padTileWidth + tilePadding; int height = heightInTiles * padTileHeight + tilePadding; Texture2D output = new Texture2D(width, height, TextureFormat.ARGB32, false, false); output.filterMode = FilterMode.Point; output.SetPixels32(new Color32[width * height]); output.Apply(); List <Rect> rects = GenerateGridSpriteRectangles(atlasTexture, sliceOffset, tileSize, slicePadding); TilemapUtilsEditor.MakeTextureReadable(atlasTexture); int offset = tilePadding - tileExtrude; for (int ty = 0, idx = 0; ty < heightInTiles; ++ty) { for (int tx = 0; tx < widthInTiles; ++tx, ++idx) { Rect rect = rects[idx]; Color[] srcTileColors = atlasTexture.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height); int dstX = tx * padTileWidth + tilePadding - offset; int dstY = output.height - (ty + 1) * padTileHeight + offset;//- tilePadding; output.SetPixels(dstX, dstY, (int)rect.width, (int)rect.height, srcTileColors); //Extend border color to fill the padding area Color[] paddingColors; for (int p = 0; p < tileExtrude; ++p) { paddingColors = atlasTexture.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, 1); output.SetPixels(dstX, dstY - p - 1, (int)rect.width, 1, paddingColors); // bottom padding paddingColors = atlasTexture.GetPixels((int)rect.x, (int)rect.y + (int)rect.height - 1, (int)rect.width, 1); output.SetPixels(dstX, dstY + (int)rect.height + p, (int)rect.width, 1, paddingColors); // top padding paddingColors = atlasTexture.GetPixels((int)rect.x, (int)rect.y, 1, (int)rect.height); output.SetPixels(dstX - p - 1, dstY, 1, (int)rect.height, paddingColors); // left padding paddingColors = atlasTexture.GetPixels((int)rect.x + (int)rect.width - 1, (int)rect.y, 1, (int)rect.height); output.SetPixels(dstX + (int)rect.width + p, dstY, 1, (int)rect.height, paddingColors); // right padding } if (tileExtrude > 0) { paddingColors = Enumerable.Repeat(srcTileColors[0], tileExtrude * tileExtrude).ToArray(); output.SetPixels(dstX - tileExtrude, dstY - tileExtrude, tileExtrude, tileExtrude, paddingColors); // bottom-left corner paddingColors = Enumerable.Repeat(srcTileColors[(int)rect.width - 1], tileExtrude * tileExtrude).ToArray(); output.SetPixels(dstX + (int)rect.width, dstY - tileExtrude, tileExtrude, tileExtrude, paddingColors); // bottom-right corner paddingColors = Enumerable.Repeat(srcTileColors[srcTileColors.Length - (int)rect.width], tileExtrude * tileExtrude).ToArray(); output.SetPixels(dstX - tileExtrude, dstY + (int)rect.height, tileExtrude, tileExtrude, paddingColors); // top-left corner paddingColors = Enumerable.Repeat(srcTileColors[srcTileColors.Length - 1], tileExtrude * tileExtrude).ToArray(); output.SetPixels(dstX + (int)rect.width, dstY + (int)rect.height, tileExtrude, tileExtrude, paddingColors); // top-right corner } } } output.Apply(); return(output); }
public static Texture2D BuildAtlas(Texture2D atlasTexture, int tilePadding, int tileExtrude, Vector2 tileSize, int widthInTiles, int heightInTiles, List <Rect> rects) { int padTileWidth = Mathf.RoundToInt(tileSize.x + tilePadding); int padTileHeight = Mathf.RoundToInt(tileSize.y + tilePadding); int width = widthInTiles * padTileWidth + tilePadding; int height = heightInTiles * padTileHeight + tilePadding; Texture2D output = new Texture2D(width, height, TextureFormat.ARGB32, false, false); output.filterMode = FilterMode.Point; output.SetPixels32(new Color32[width * height]); output.Apply(); TilemapUtilsEditor.MakeTextureReadable(atlasTexture); int offset = tilePadding - tileExtrude; for (int ty = 0, idx = 0; ty < heightInTiles; ++ty) { for (int tx = 0; tx < widthInTiles; ++tx, ++idx) { Rect rect = rects[idx]; int rx = Mathf.RoundToInt(rect.x); int ry = Mathf.RoundToInt(rect.y); int rw = Mathf.RoundToInt(rect.width); int rh = Mathf.RoundToInt(rect.height); Color[] srcTileColors = atlasTexture.GetPixels(rx, ry, rw, rh); int dstX = tx * padTileWidth + tilePadding - offset; int dstY = output.height - (ty + 1) * padTileHeight + offset;//- tilePadding; output.SetPixels(dstX, dstY, rw, rh, srcTileColors); //Extend border color to fill the padding area Color[] paddingColors; for (int p = 0; p < tileExtrude; ++p) { paddingColors = atlasTexture.GetPixels(rx, ry, rw, 1); output.SetPixels(dstX, dstY - p - 1, rw, 1, paddingColors); // bottom padding paddingColors = atlasTexture.GetPixels(rx, ry + rh - 1, rw, 1); output.SetPixels(dstX, dstY + rh + p, rw, 1, paddingColors); // top padding paddingColors = atlasTexture.GetPixels(rx, ry, 1, rh); output.SetPixels(dstX - p - 1, dstY, 1, rh, paddingColors); // left padding paddingColors = atlasTexture.GetPixels(rx + rw - 1, ry, 1, rh); output.SetPixels(dstX + rw + p, dstY, 1, rh, paddingColors); // right padding } if (tileExtrude > 0) { paddingColors = Enumerable.Repeat(srcTileColors[0], tileExtrude * tileExtrude).ToArray(); output.SetPixels(dstX - tileExtrude, dstY - tileExtrude, tileExtrude, tileExtrude, paddingColors); // bottom-left corner paddingColors = Enumerable.Repeat(srcTileColors[rw - 1], tileExtrude * tileExtrude).ToArray(); output.SetPixels(dstX + rw, dstY - tileExtrude, tileExtrude, tileExtrude, paddingColors); // bottom-right corner paddingColors = Enumerable.Repeat(srcTileColors[srcTileColors.Length - rw], tileExtrude * tileExtrude).ToArray(); output.SetPixels(dstX - tileExtrude, dstY + rh, tileExtrude, tileExtrude, paddingColors); // top-left corner paddingColors = Enumerable.Repeat(srcTileColors[srcTileColors.Length - 1], tileExtrude * tileExtrude).ToArray(); output.SetPixels(dstX + rw, dstY + rh, tileExtrude, tileExtrude, paddingColors); // top-right corner } } } output.Apply(); return(output); }
void OnGUI() { m_serializedObject.Update(); m_scrollPos = EditorGUILayout.BeginScrollView(m_scrollPos, GUIStyle.none, GUI.skin.verticalScrollbar); { EditorGUILayout.Space(); EditorGUILayout.BeginVertical(EditorStyles.helpBox); { EditorGUILayout.LabelField("Atlas Texture:", EditorStyles.boldLabel); EditorGUI.indentLevel += 1; m_tileset = (Tileset)EditorGUILayout.ObjectField("Tileset (optional)", m_tileset, typeof(Tileset), false); if (!m_tileset) { if (GUILayout.Button("Create Tileset")) { m_tileset = TilesetEditor.CreateTileset(); } } // Read Data From Tileset if (m_tileset) { m_atlasTexture = m_tileset.AtlasTexture; } m_atlasTexture = (Texture2D)EditorGUILayout.ObjectField("Atlas texture", m_atlasTexture, typeof(Texture2D), false); EditorGUI.indentLevel -= 1; } EditorGUILayout.EndHorizontal(); //GUI.enabled = m_atlasTexture != null; EditorGUILayout.Space(); EditorGUILayout.BeginVertical(EditorStyles.helpBox); { EditorGUILayout.LabelField("Atlas Settings:", EditorStyles.boldLabel); EditorGUI.indentLevel += 1; EditorGUILayout.PropertyField(m_serializedObject.FindProperty("m_tileTextures"), true); if (GUILayout.Button("Sort by Name")) { m_tileTextures = m_tileTextures.Where(x => x != null).OrderBy(x => x.name).ToArray(); } m_padding = EditorGUILayout.IntField("Padding", m_padding); m_maxTextureSize = (eMaxTextureSize)EditorGUILayout.EnumPopup("Max. Texture Size", m_maxTextureSize); if (m_tileset && GUILayout.Button("Create Atlas & Update Tileset") || !m_tileset && GUILayout.Button("Create Atlas")) { if (!m_atlasTexture) { m_atlasTexture = new Texture2D((int)m_maxTextureSize, (int)m_maxTextureSize, TextureFormat.ARGB32, false); } foreach (Texture2D tileTexture in m_tileTextures) { TilemapUtilsEditor.MakeTextureReadable(tileTexture); } TilemapUtilsEditor.MakeTextureReadable(m_atlasTexture); Rect[] tileRects = m_atlasTexture.PackTextures(m_tileTextures, m_padding, (int)m_maxTextureSize, false); string atlasAssetPath = AssetDatabase.GetAssetPath(m_atlasTexture); if (string.IsNullOrEmpty(atlasAssetPath)) { atlasAssetPath = EditorUtility.SaveFilePanelInProject("Save atlas texture", m_tileset.name + "Atlas", "png", "Save the atlas texture"); } if (!string.IsNullOrEmpty(atlasAssetPath)) { File.WriteAllBytes(atlasAssetPath, m_atlasTexture.EncodeToPNG()); AssetDatabase.ImportAsset(atlasAssetPath, ImportAssetOptions.ForceSynchronousImport); TilesetEditor.OptimizeTextureImportSettings(m_atlasTexture); AssetDatabase.Refresh(); m_atlasTexture = AssetDatabase.LoadAssetAtPath <Texture2D>(atlasAssetPath); if (m_tileset && tileRects.Length > 0) { m_tileset.AtlasTexture = m_atlasTexture; m_tileset.TilePxSize = new Vector2(tileRects[0].size.x * m_atlasTexture.width, tileRects[0].size.y * m_atlasTexture.height); int idx; for (idx = 0; idx < tileRects.Length; ++idx) { Rect uv = tileRects[idx]; if (idx < m_tileset.Tiles.Count) { m_tileset.Tiles[idx].uv = uv; } else { m_tileset.Tiles.Add(new Tile() { uv = uv }); } } m_tileset.Tiles.RemoveRange(idx, m_tileset.Tiles.Count - idx); } } } EditorGUI.indentLevel -= 1; } EditorGUILayout.EndVertical(); const string sHelpInfo = "1. Create a tileset or drag a tileset into the Tileset field.\n" + "2. Drag the tile textures into the Tile Textures field.\n" + "3. Optionally sort by name the textures, to make sure the tile order will be the same if later you add new tile textures.\n" + "4. Press Create Atlas and Update Tileset"; EditorGUILayout.HelpBox(sHelpInfo, MessageType.Info); GUI.enabled = true; } EditorGUILayout.EndScrollView(); if (GUI.changed) { if (m_tileset) { EditorUtility.SetDirty(m_tileset); } m_serializedObject.ApplyModifiedProperties(); } }