Example #1
0
 /// <summary>
 /// Initializes a new instance of <see cref="BitmapBinPacker"/>.
 /// </summary>
 public BitmapBinPacker()
 {
     Bitmap      = null;
     Disposed    = false;
     Size        = Size.Empty;
     SourceFiles = new List <string>().AsReadOnly();
     RootNode    = null;
 }
Example #2
0
 /// <summary>
 /// Initializes a new instance of the BinPackerNode class with specified
 /// parameters.
 /// </summary>
 /// <param name="bounds">The bounding box of the node.</param>
 /// <param name="leftChild">The node's "left-hand" child node.</param>
 /// <param name="rightChild">The node's "right-hand" child node.</param>
 /// <param name="leafName">The name of the node.</param>
 internal BinPackerNode(
     Rectangle bounds,
     BinPackerNode leftChild,
     BinPackerNode rightChild,
     string leafName
     )
 {
     Bounds     = bounds;
     LeftChild  = leftChild;
     RightChild = rightChild;
     LeafName   = leafName;
 }
Example #3
0
        /// <summary>
        /// Attempts to insert a new node as a child of this node.
        /// </summary>
        /// <param name="node">The node to insert.</param>
        /// <param name="rect">The bounding box rectangle of the node.</param>
        /// <returns>The inserted node.</returns>
        public BinPackerNode Insert(BinPackerNode node, Rectangle rect)
        {
            if (node.LeafName == null && node.LeftChild != null && node.RightChild != null)
            {
                BinPackerNode newNode = null;

                newNode = Insert(node.LeftChild, rect);

                if (newNode == null)
                {
                    newNode = Insert(node.RightChild, rect);
                }

                return(newNode);
            }
            else
            {
                if (node.LeafName != null)
                {
                    return(null);
                }

                if (node.Bounds.Width == rect.Width && node.Bounds.Height == rect.Height)
                {
                    return(node);
                }

                if (node.Bounds.Width < rect.Width || node.Bounds.Height < rect.Height)
                {
                    return(null);
                }

                node.LeftChild  = new BinPackerNode();
                node.RightChild = new BinPackerNode();

                int deltaWidth  = node.Bounds.Width - rect.Width;
                int deltaHeight = node.Bounds.Height - rect.Height;

                if (deltaWidth > deltaHeight)
                {
                    node.LeftChild.Bounds  = new Rectangle(node.Bounds.X, node.Bounds.Y, rect.Width, node.Bounds.Height);
                    node.RightChild.Bounds = new Rectangle(node.Bounds.X + rect.Width, node.Bounds.Y, node.Bounds.Width - rect.Width, node.Bounds.Height);
                }
                else
                {
                    node.LeftChild.Bounds  = new Rectangle(node.Bounds.X, node.Bounds.Y, node.Bounds.Width, rect.Height);
                    node.RightChild.Bounds = new Rectangle(node.Bounds.X, node.Bounds.Y + rect.Height, node.Bounds.Width, node.Bounds.Height - rect.Height);
                }

                return(Insert(node.LeftChild, rect));
            }
        }
Example #4
0
        /// <summary>
        /// Maps sprite information to the specified list recursively.
        /// </summary>
        /// <param name="currentNode">
        /// The current node to discover sprites from; if this is to be the first
        /// iteration, this should be the root node.
        /// </param>
        /// <param name="list">
        /// A reference to the <see cref="List{SpriteInfo}"/> collection into which all
        /// sprite information will be inserted.
        /// </param>
        private void DiscoverSprites(
            BinPackerNode currentNode,
            ref List <SpriteInfo> list
            )
        {
            if (currentNode.LeftChild != null)
            {
                DiscoverSprites(currentNode.LeftChild, ref list);
            }

            if (currentNode.RightChild != null)
            {
                DiscoverSprites(currentNode.RightChild, ref list);
            }

            if (currentNode.LeafName != null)
            {
                list.Add(new SpriteInfo(currentNode.LeafName, currentNode.Bounds));
            }
        }
Example #5
0
        /// <summary>
        /// Refreshes the generated atlas <see cref="Bitmap"/>.
        /// </summary>
        public void Refresh()
        {
            AssertNotDisposed();

            // Get ourselves a clean Bitmap
            //
            var newBitmap = new Bitmap(Size.Width, Size.Height);

            // Prepare our root node
            //
            RootNode = new BinPackerNode(
                new Rectangle(0, 0, Size.Width, Size.Height),
                null,
                null,
                null
                );

            // Now do the actual bin packing
            //
            var result = BinPackerError.None;
            var ex     = new Exception("Unknown error occurred.");

            using (var g = Graphics.FromImage(newBitmap))
            {
                foreach (string filePath in SourceFiles)
                {
                    Bitmap        sprite;
                    string        spriteName = Path.GetFileNameWithoutExtension(filePath);
                    BinPackerNode node;

                    if (!File.Exists(filePath))
                    {
                        result = BinPackerError.MissingFile;
                        ex     = new FileNotFoundException(
                            "Failed to find a source file.",
                            filePath
                            );

                        break;
                    }

                    try
                    {
                        sprite = (Bitmap)Bitmap.FromFile(filePath);
                    }
                    catch (Exception anyEx)
                    {
                        result = BinPackerError.UnreadableFile;
                        ex     = anyEx;

                        break;
                    }

                    node = RootNode.Insert(
                        RootNode,
                        new Rectangle(Point.Empty, sprite.Size)
                        );

                    if (node != null)
                    {
                        g.DrawImage(sprite, node.Bounds);
                        node.LeafName = spriteName;
                        sprite.Dispose();
                    }
                    else
                    {
                        result = BinPackerError.OutOfRoom;
                        ex     = new InvalidOperationException(
                            "There is not enough room in the atlas to contain all of the sprites."
                            );
                        sprite.Dispose();

                        break;
                    }
                }
            }

            if (result != BinPackerError.None)
            {
                throw ex;
            }

            Bitmap?.Dispose();
            Bitmap = newBitmap;
        }