Example #1
0
        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);
        }
Example #2
0
        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();
            }
        }