internal static bool rebuildAtlas( dfAtlas atlas )
    {
        try
        {

            EditorUtility.DisplayProgressBar( "Rebuilding Texture Atlas", "Processing changes to the texture atlas...", 0 );

            var sprites = atlas.Items
                .Where( i => i != null && !i.deleted )
                .Select( i => new { source = i, texture = getTexture( i.textureGUID ) } )
                .Where( i => i.texture != null )
                .OrderByDescending( i => i.texture.width * i.texture.height )
                .ToList();

            var textures = sprites.Select( i => i.texture ).ToList();

            var oldAtlasTexture = atlas.Material.mainTexture;
            var texturePath = AssetDatabase.GetAssetPath( oldAtlasTexture );

            var padding = EditorPrefs.GetInt( "DaikonForge.AtlasDefaultPadding", 2 );

            var newAtlasTexture = new Texture2D( 0, 0, TextureFormat.RGBA32, false );
            var newRects = newAtlasTexture.PackTextures2( textures.ToArray(), padding, dfTextureAtlasInspector.MaxAtlasSize, dfTextureAtlasInspector.ForceSquare );

            byte[] bytes = newAtlasTexture.EncodeToPNG();
            System.IO.File.WriteAllBytes( texturePath, bytes );
            bytes = null;
            DestroyImmediate( newAtlasTexture );

            setAtlasTextureSettings( texturePath, false );

            // Fix up the new sprite locations
            for( int i = 0; i < sprites.Count; i++ )
            {
                sprites[ i ].source.region = newRects[ i ];
                sprites[ i ].source.sizeInPixels = new Vector2( textures[ i ].width, textures[ i ].height );
                sprites[ i ].source.texture = null;
            }

            // Remove any deleted sprites
            atlas.Items.RemoveAll( i => i.deleted );

            // Re-sort the Items collection
            atlas.Items.Sort();
            atlas.RebuildIndexes();

            EditorUtility.SetDirty( atlas );
            EditorUtility.SetDirty( atlas.Material );

            dfGUIManager.RefreshAll( true );

            return true;

        }
        catch( Exception err )
        {

            Debug.LogError( err.ToString(), atlas );
            EditorUtility.DisplayDialog( "Error Rebuilding Texture Atlas", err.Message, "OK" );

            return false;

        }
        finally
        {
            EditorUtility.ClearProgressBar();
        }
    }
    public static void CreateAtlasFromSelection()
    {
        try
        {

            EditorUtility.DisplayProgressBar( "Creating Texture Atlas", "Adding selected textures to the Texture Atlas", 0 );

            var selection = Selection
                .GetFiltered( typeof( Texture2D ), SelectionMode.Assets )
                .Cast<Texture2D>()
                .Where( t => isReadable( t ) )
                .OrderByDescending( t => t.width * t.height )
                .ToArray();

            if( selection.Length == 0 )
            {
                EditorUtility.DisplayDialog( "Create Texture Atlas", "Either no textures selected or none of the selected textures has Read/Write enabled", "OK" );
                return;
            }

            var saveFolder = Path.GetDirectoryName( AssetDatabase.GetAssetPath( selection[ 0 ] ) );
            var prefabPath = EditorUtility.SaveFilePanel( "Create Texture Atlas", saveFolder, "Texture Atlas", "prefab" );
            if( string.IsNullOrEmpty( prefabPath ) )
                return;

            prefabPath = prefabPath.MakeRelativePath();

            var padding = EditorPrefs.GetInt( "DaikonForge.AtlasDefaultPadding", 2 );

            var texture = new Texture2D( 1, 1, TextureFormat.ARGB32, false );
            var rects = texture.PackTextures2( selection, padding, dfTextureAtlasInspector.MaxAtlasSize, dfTextureAtlasInspector.ForceSquare );

            var texturePath = Path.ChangeExtension( prefabPath, "png" );
            byte[] bytes = texture.EncodeToPNG();
            System.IO.File.WriteAllBytes( texturePath, bytes );
            bytes = null;
            DestroyImmediate( texture );

            setAtlasTextureSettings( texturePath, true );

            texture = AssetDatabase.LoadAssetAtPath( texturePath, typeof( Texture2D ) ) as Texture2D;
            if( texture == null )
                Debug.LogError( "Failed to find texture at " + texturePath );

            var sprites = new List<dfAtlas.ItemInfo>();
            for( int i = 0; i < rects.Length; i++ )
            {

                var pixelCoords = rects[ i ];
                var size = new Vector2( selection[ i ].width, selection[ i ].height );

                var spritePath = AssetDatabase.GetAssetPath( selection[ i ] );
                var guid = AssetDatabase.AssetPathToGUID( spritePath );

                var item = new dfAtlas.ItemInfo()
                {
                    name = selection[ i ].name,
                    region = pixelCoords,
                    rotated = false,
                    textureGUID = guid,
                    sizeInPixels = size
                };

                sprites.Add( item );

            }

            sprites.Sort();

            var shader = Shader.Find( "Daikon Forge/Default UI Shader" );
            var atlasMaterial = new Material( shader );
            atlasMaterial.mainTexture = texture;
            AssetDatabase.CreateAsset( atlasMaterial, Path.ChangeExtension( texturePath, "mat" ) );

            var go = new GameObject() { name = Path.GetFileNameWithoutExtension( prefabPath ) };
            var atlas = go.AddComponent<dfAtlas>();
            atlas.Material = atlasMaterial;
            atlas.AddItems( sprites );

            var prefab = PrefabUtility.CreateEmptyPrefab( prefabPath );
            prefab.name = atlas.name;
            PrefabUtility.ReplacePrefab( go, prefab );

            DestroyImmediate( go );
            AssetDatabase.Refresh();

            #region Delay execution of object selection to work around a Unity issue

            // Declared with null value to eliminate "uninitialized variable"
            // compiler error in lambda below.
            EditorApplication.CallbackFunction callback = null;

            callback = () =>
            {
                EditorUtility.FocusProjectWindow();
                go = AssetDatabase.LoadMainAssetAtPath( prefabPath ) as GameObject;
                Selection.objects = new Object[] { go };
                EditorGUIUtility.PingObject( go );
                Debug.Log( "Texture Atlas prefab created at " + prefabPath, prefab );
                EditorApplication.delayCall -= callback;
            };

            EditorApplication.delayCall += callback;

            #endregion

        }
        catch( Exception err )
        {
            Debug.LogError( err.ToString() );
            EditorUtility.DisplayDialog( "Error Creating Texture Atlas", err.Message, "OK" );
        }
        finally
        {
            EditorUtility.ClearProgressBar();
        }
    }