/// <summary>
    /// Draw the UI for this tool.
    /// </summary>

    void OnGUI()
    {
        bool             recalculate = false;
        bool             createHD    = false;
        bool             createSD    = false;
        List <Texture2D> textures    = null;

        NGUIEditorTools.SetLabelWidth(100f);

        GUILayout.Space(6f);

        GUILayout.Label("Select textures in insperctor. You can select files or whole directories.");
        currentHeuristic = (UITexturePacker.FreeRectChoiceHeuristic)EditorGUILayout.EnumPopup("Pack Heuristic", currentHeuristic);

        GUILayout.Space(30f);


        GUILayout.BeginHorizontal();
        GUILayout.Label("Best packed atlas size without compression");
        GUILayout.Label(packedSize.ToString());
        recalculate = GUILayout.Button("Recalculate");
        GUILayout.EndHorizontal();


        GUILayout.Space(30f);

        maxHDSize = EditorGUILayout.IntField("Max HD Size", maxHDSize);
        maxSDSize = EditorGUILayout.IntField("Max SD Size", maxSDSize);


        hDName = EditorGUILayout.TextField("HD Atlas Name", hDName);
        sDName = EditorGUILayout.TextField("SD Atlas Name", sDName);


        GUILayout.Space(30f);
        GUILayout.BeginHorizontal();
        createHD = GUILayout.Button("Create HD");
        createSD = GUILayout.Button("Create SD");
        GUILayout.EndHorizontal();


        if (recalculate && DisplayConfirmDialog())
        {
            textures = GetSelectedTextures();

            EditorUtility.DisplayProgressBar("Calculating size", "", 0.1f);

            try
            {
                packedSize = AtlasAdjustHelper.GetMinSize(textures.ToArray(), currentHeuristic);
            }
            catch (Exception e)
            {
                Debug.LogError("Exception \n" + e.Message);
                Debug.LogError("Stack trace: " + e.StackTrace);
            }

            EditorUtility.ClearProgressBar();
        }

        if (createHD && DisplayConfirmDialog())
        {
            textures = GetSelectedTextures();

            EditorUtility.DisplayProgressBar("Creating atlases", "HD", 0.1f);

            try
            {
                AtlasAdjustHelper.CreateUIAtlas(textures, hDName, maxHDSize > 0 ? maxHDSize : (int?)null, out packedSize, currentHeuristic);
            }
            catch (Exception e)
            {
                Debug.LogError("Exception \n" + e.Message);
                Debug.LogError("Stack trace: " + e.StackTrace);
            }

            EditorUtility.ClearProgressBar();
        }


        if (createSD && DisplayConfirmDialog())
        {
            textures = GetSelectedTextures();

            EditorUtility.DisplayProgressBar("Creating atlases", "SD", 0.1f);

            try
            {
                AtlasAdjustHelper.CreateUIAtlas(textures, sDName, maxSDSize > 0 ? maxSDSize : (int?)null, out packedSize, currentHeuristic);
            }
            catch (Exception e)
            {
                Debug.LogError("Exception \n" + e.Message);
                Debug.LogError("Stack trace: " + e.StackTrace);
            }

            EditorUtility.ClearProgressBar();
        }
    }
    public static int GetMinSize(Texture2D[] textures, UITexturePacker.FreeRectChoiceHeuristic heuristic)
    {
        int padding = 1;

        return(GetMinAtlasSize(textures, 4, ref padding, 4, heuristic));
    }
    private static Texture2D UpdateUIAtlas(UIAtlas atlas, List <Texture2D> textures, ref int?size, out int minSize, UITexturePacker.FreeRectChoiceHeuristic heuristic)
    {
        Debug.Log("***************** Updating atlas " + atlas.name + " - " + DateTime.Now);
        Rect[]    texRects;
        Texture2D newTexture = CreateTexture(textures.ToArray(), ref size, 1, out texRects, out minSize, heuristic);
        List <UIAtlasMaker.SpriteEntry> sprites = UIAtlasMaker.CreateSprites(textures.Cast <Texture>().ToList());

        for (int i = 0; i < sprites.Count; i++)
        {
            Rect rect = NGUIMath.ConvertToPixels(texRects[i], newTexture.width, newTexture.height, true);

            UIAtlasMaker.SpriteEntry se = sprites[i];
            se.x      = Mathf.RoundToInt(rect.x);
            se.y      = Mathf.RoundToInt(rect.y);
            se.width  = Mathf.RoundToInt(rect.width);
            se.height = Mathf.RoundToInt(rect.height);
        }

        // Replace the sprites within the atlas
        UIAtlasMaker.ReplaceSprites(atlas, sprites);

        // Release the temporary textures
        UIAtlasMaker.ReleaseSprites(sprites);

        return(newTexture);
    }
    private static bool CanPackTexturesInSize(Texture2D[] textures, int size, int padding, UITexturePacker.FreeRectChoiceHeuristic heuristic)
    {
        using (var packer = new UITexturePackerSpec(size, size, false))
        {
            for (int i = 0; i < textures.Length; i++)
            {
                Texture2D tex = textures[i];
                if (!tex)
                {
                    continue;
                }

                Rect rect = new Rect();

                int xPadding;
                int yPadding;

                for (xPadding = 1; xPadding >= 0; --xPadding)
                {
                    for (yPadding = 1; yPadding >= 0; --yPadding)
                    {
                        rect = packer.Insert(tex.width + (xPadding * padding), tex.height + (yPadding * padding), heuristic);
                        if (rect.width > 0 && rect.height > 0)
                        {
                            break;
                        }

                        // After having no padding if it still doesn't fit -- we can't pack all textures in this size.
                        else if (xPadding == 0 && yPadding == 0)
                        {
                            return(false);
                        }
                    }
                    if (rect.width > 0 && rect.height > 0)
                    {
                        break;
                    }
                }
            }
        }

        return(true);
    }
    private static int GetMinAtlasSize(Texture2D[] textures, int startSize, ref int padding, int nessSize, UITexturePacker.FreeRectChoiceHeuristic heuristic)
    {
        int startDiff = startSize / 2;
        int minDiff   = 0;

        int  size       = startSize;
        int  diff       = startDiff;
        bool?prevResult = null;

        while (true)
        {
            bool curResult = CanPackTexturesInSize(textures, size, (int)Math.Ceiling(padding * ((double)size / nessSize)), heuristic);

            if (prevResult.HasValue && curResult != prevResult)
            {
                if (diff / 2 <= minDiff)
                {
                    if (!curResult)
                    {
                        size += diff;
                    }

                    padding = (int)Math.Ceiling(padding * ((double)size / nessSize));

                    return(size);
                }

                diff /= 2;
            }

            if (curResult)
            {
                size -= diff;
            }
            else
            {
                size += diff;
            }

            prevResult = curResult;
        }
    }
    private static Texture2D CreateTexture(Texture2D[] textures, ref int?size, int padding, out Rect[] texRects, out int minAtlasSize, UITexturePacker.FreeRectChoiceHeuristic heuristic)
    {
        var result = new Texture2D(1, 1);

        minAtlasSize = GetMinAtlasSize(textures, size ?? 128, ref padding, size ?? 128, heuristic);
        Debug.Log("*************************** Min size = " + minAtlasSize + "  - " + DateTime.Now);
        NGUISettings.forceSquareAtlas = true;
        texRects = UITexturePackerSpec.PackTexturesSpec(result, textures, minAtlasSize, minAtlasSize, padding, minAtlasSize, heuristic);
        Debug.Log("*************************** texture packed - " + DateTime.Now);
        if (size == null)
        {
            int power = (int)Math.Round(Math.Log(minAtlasSize, 2));

            size = (int)Math.Pow(2, power);
        }
        if (size <= minAtlasSize)
        {
            TextureScale.Resize(result, size.Value, size.Value, InterpolationMode.HighQualityBicubic);
        }
        else
        {
            texRects = UITexturePackerSpec.PackTextures(result, textures, size.Value, size.Value, padding, size.Value);
        }

        return(result);
    }
    public static int CreateUIAtlas(List <Texture2D> images, string atlasName, int?size, out int minSize, UITexturePacker.FreeRectChoiceHeuristic heuristic)
    {
        string selectionFolder = NGUIEditorTools.GetSelectionFolder();

        if (string.IsNullOrEmpty(atlasName))
        {
            var lastIndexOf = selectionFolder.Substring(0, selectionFolder.Length - 1).LastIndexOf("/");
            atlasName = selectionFolder.Substring(lastIndexOf + 1, selectionFolder.Length - lastIndexOf - 2);
        }

        UIAtlas atlas;
        string  prefabPath = AssetDatabase.GetAllAssetPaths().FirstOrDefault(x => x.EndsWith("/" + atlasName + ".prefab"));

        if (prefabPath == null)
        {
            prefabPath = selectionFolder + atlasName + ".prefab";
            atlas      = CreateAtlas(atlasName);
        }
        else
        {
            Debug.Log("Update existing");
            atlas = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(UIAtlas)) as UIAtlas;
        }

        Texture2D newTexture = UpdateUIAtlas(atlas, images, ref size, out minSize, heuristic);
        var       texture    = SaveTexture(prefabPath, newTexture);

        atlas.spriteMaterial.mainTexture = texture;

        EditorUtility.SetDirty(atlas);

        // Update the prefab
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
        Debug.Log("***************** All done - " + DateTime.Now);
        return(size.Value);
    }
    /// <summary>
    /// Draw the UI for this tool.
    /// </summary>
    void OnGUI()
    {
        bool recalculate = false;
        bool createHD = false;
        bool createSD = false;
        List<Texture2D> textures = null;
        NGUIEditorTools.SetLabelWidth(100f);

        GUILayout.Space(6f);

        GUILayout.Label("Select textures in insperctor. You can select files or whole directories.");
        currentHeuristic = (UITexturePacker.FreeRectChoiceHeuristic)EditorGUILayout.EnumPopup("Pack Heuristic", currentHeuristic);

        GUILayout.Space(30f);

        GUILayout.BeginHorizontal();
        GUILayout.Label("Best packed atlas size without compression");
        GUILayout.Label(packedSize.ToString());
        recalculate = GUILayout.Button("Recalculate");
        GUILayout.EndHorizontal();

        GUILayout.Space(30f);

        maxHDSize = EditorGUILayout.IntField("Max HD Size", maxHDSize);
        maxSDSize = EditorGUILayout.IntField("Max SD Size", maxSDSize);

        hDName = EditorGUILayout.TextField("HD Atlas Name", hDName);
        sDName = EditorGUILayout.TextField("SD Atlas Name", sDName);

        GUILayout.Space(30f);
        GUILayout.BeginHorizontal();
        createHD = GUILayout.Button("Create HD");
        createSD = GUILayout.Button("Create SD");
        GUILayout.EndHorizontal();

        if (recalculate && DisplayConfirmDialog())
        {
            textures = GetSelectedTextures();

            EditorUtility.DisplayProgressBar("Calculating size", "", 0.1f);

            try
            {
                packedSize = AtlasAdjustHelper.GetMinSize(textures.ToArray(), currentHeuristic);
            }
            catch (Exception e)
            {
                Debug.LogError("Exception \n" + e.Message);
                Debug.LogError("Stack trace: " + e.StackTrace);
            }

            EditorUtility.ClearProgressBar();
        }

        if (createHD && DisplayConfirmDialog())
        {
            textures = GetSelectedTextures();

            EditorUtility.DisplayProgressBar("Creating atlases", "HD", 0.1f);

            try
            {
                AtlasAdjustHelper.CreateUIAtlas(textures, hDName, maxHDSize > 0 ? maxHDSize : (int?) null, out packedSize, currentHeuristic);
            }
            catch (Exception e)
            {
                Debug.LogError("Exception \n" + e.Message);
                Debug.LogError("Stack trace: " + e.StackTrace);
            }

            EditorUtility.ClearProgressBar();
        }

        if (createSD && DisplayConfirmDialog())
        {
            textures = GetSelectedTextures();

            EditorUtility.DisplayProgressBar("Creating atlases", "SD", 0.1f);

            try
            {
                AtlasAdjustHelper.CreateUIAtlas(textures, sDName, maxSDSize > 0 ? maxSDSize : (int?)null, out packedSize, currentHeuristic);
            }
            catch (Exception e)
            {
                Debug.LogError("Exception \n" + e.Message);
                Debug.LogError("Stack trace: " + e.StackTrace);
            }

            EditorUtility.ClearProgressBar();
        }
    }