예제 #1
0
        /// <summary>
        /// Combines as many <see cref="ITextureAtlasable"/> items as possible into an atlas.
        /// </summary>
        /// <param name="items">Collection of <see cref="ITextureAtlasable"/> items to add to the atlas.</param>
        /// <param name="width">Width of the atlas.</param>
        /// <param name="height">Height of the atlas.</param>
        /// <param name="breakOnAddFail">If true, the method will return instantly after failing to add an item.</param>
        /// <returns>Stack containing all items that were successfully added to the atlas. If the
        /// count of this return value equals the count of the <paramref name="items"/> collection,
        /// all items were successfully added to the atlas of the specified size.</returns>
        /// <exception cref="ArgumentException"><paramref name="items"/> is null.</exception>
        static Stack <AtlasTextureItem> CombineSingleTexture(ICollection <ITextureAtlasable> items, int width, int height, bool breakOnAddFail)
        {
            if (items == null)
            {
                const string errmsg = "items is null.";
                if (log.IsFatalEnabled)
                {
                    log.Fatal(errmsg);
                }
                throw new ArgumentException(errmsg, "items");
            }

            // Create the node stack for all set nodes
            var nodeStack = new Stack <AtlasTextureItem>(items.Count);

            // Set the positions
            var root = new AtlasTreeNode(new AtlasTextureItem(width, height));

            foreach (var ta in items)
            {
                var node = root.Insert(ta.SourceRect.Width + Padding * 2, ta.SourceRect.Height + Padding * 2, ta);
                if (node != null)
                {
                    // Assign the TextureAtlas and push the node onto the stack
                    nodeStack.Push(node.AtlasNode);
                }
                else if (breakOnAddFail)
                {
                    // Node didn't fit - return
                    return(nodeStack);
                }
            }

            return(nodeStack);
        }
예제 #2
0
        /// <summary>
        /// Inserts a <see cref="ITextureAtlasable"/> into the tree from this <see cref="AtlasTreeNode"/>.
        /// </summary>
        /// <param name="w">Width of the area to insert into.</param>
        /// <param name="h">Height of the area to insert into.</param>
        /// <param name="atlasItem">The <see cref="ITextureAtlasable"/> that inserted node is for.</param>
        /// <returns>The <see cref="AtlasTreeNode"/> containing the area the claimed, or null if no area of the
        /// required size could be found.</returns>
        public AtlasTreeNode Insert(int w, int h, ITextureAtlasable atlasItem)
        {
            if (!IsLeaf)
            {
                // Insert into children (left first then right)
                AtlasTreeNode ret = null;
                if (Left != null)
                {
                    ret = Left.Insert(w, h, atlasItem);
                }

                if (ret == null && Right != null)
                {
                    ret = Right.Insert(w, h, atlasItem);
                }

                if (ret != null)
                {
                    ret.AtlasNode.ITextureAtlasable = atlasItem;
                }

                return(ret);
            }
            else
            {
                // Check if it fits and not in use
                if (ITextureAtlasable != null || w > Rect.Width || h > Rect.Height)
                {
                    return(null);
                }

                // Perfect fit
                if (w == Rect.Width && h == Rect.Height)
                {
                    return(this);
                }

                // Not a perfect fit, split the node up into new nodes
                var diffW = Rect.Width - w;
                var diffH = Rect.Height - h;

                // Decide which way to split
                if (diffW > diffH)
                {
                    // Split vertically
                    Left  = new AtlasTreeNode(new Rectangle(Rect.Left, Rect.Top, w, Rect.Height));
                    Right = new AtlasTreeNode(new Rectangle(Rect.Left + w, Rect.Top, Rect.Width - w, Rect.Height));
                }
                else
                {
                    // Split horizontally
                    Left  = new AtlasTreeNode(new Rectangle(Rect.Left, Rect.Top, Rect.Width, h));
                    Right = new AtlasTreeNode(new Rectangle(Rect.Left, Rect.Top + h, Rect.Width, Rect.Height - h));
                }

                // Insert the rectangle first new child
                var node = Left.Insert(w, h, atlasItem);

                // If the insert is a perfect fit, drop the node from the tree to prevent checking it again
                if (diffW == 0 || diffH == 0)
                {
                    Left = null;
                }

                // If the node was created, set the atlas item
                if (node != null)
                {
                    node.AtlasNode.ITextureAtlasable = atlasItem;
                }

                return(node);
            }
        }
예제 #3
0
        /// <summary>
        /// Combines as many <see cref="ITextureAtlasable"/> items as possible into an atlas.
        /// </summary>
        /// <param name="items">Collection of <see cref="ITextureAtlasable"/> items to add to the atlas.</param>
        /// <param name="width">Width of the atlas.</param>
        /// <param name="height">Height of the atlas.</param>
        /// <param name="breakOnAddFail">If true, the method will return instantly after failing to add an item.</param>
        /// <returns>Stack containing all items that were successfully added to the atlas. If the
        /// count of this return value equals the count of the <paramref name="items"/> collection,
        /// all items were successfully added to the atlas of the specified size.</returns>
        /// <exception cref="ArgumentException"><paramref name="items"/> is null.</exception>
        static Stack<AtlasTextureItem> CombineSingleTexture(ICollection<ITextureAtlasable> items, int width, int height, bool breakOnAddFail)
        {
            if (items == null)
            {
                const string errmsg = "items is null.";
                if (log.IsFatalEnabled)
                    log.Fatal(errmsg);
                throw new ArgumentException(errmsg, "items");
            }

            // Create the node stack for all set nodes
            var nodeStack = new Stack<AtlasTextureItem>(items.Count);

            // Set the positions
            var root = new AtlasTreeNode(new AtlasTextureItem(width, height));
            foreach (var ta in items)
            {
                var node = root.Insert(ta.SourceRect.Width + Padding * 2, ta.SourceRect.Height + Padding * 2, ta);
                if (node != null)
                {
                    // Assign the TextureAtlas and push the node onto the stack
                    nodeStack.Push(node.AtlasNode);
                }
                else if (breakOnAddFail)
                {
                    // Node didn't fit - return
                    return nodeStack;
                }
            }

            return nodeStack;
        }
예제 #4
0
        /// <summary>
        /// Inserts a <see cref="ITextureAtlasable"/> into the tree from this <see cref="AtlasTreeNode"/>.
        /// </summary>
        /// <param name="w">Width of the area to insert into.</param>
        /// <param name="h">Height of the area to insert into.</param>
        /// <param name="atlasItem">The <see cref="ITextureAtlasable"/> that inserted node is for.</param>
        /// <returns>The <see cref="AtlasTreeNode"/> containing the area the claimed, or null if no area of the
        /// required size could be found.</returns>
        public AtlasTreeNode Insert(int w, int h, ITextureAtlasable atlasItem)
        {
            if (!IsLeaf)
            {
                // Insert into children (left first then right)
                AtlasTreeNode ret = null;
                if (Left != null)
                    ret = Left.Insert(w, h, atlasItem);

                if (ret == null && Right != null)
                    ret = Right.Insert(w, h, atlasItem);

                if (ret != null)
                    ret.AtlasNode.ITextureAtlasable = atlasItem;

                return ret;
            }
            else
            {
                // Check if it fits and not in use
                if (ITextureAtlasable != null || w > Rect.Width || h > Rect.Height)
                    return null;

                // Perfect fit
                if (w == Rect.Width && h == Rect.Height)
                    return this;

                // Not a perfect fit, split the node up into new nodes
                var diffW = Rect.Width - w;
                var diffH = Rect.Height - h;

                // Decide which way to split
                if (diffW > diffH)
                {
                    // Split vertically
                    Left = new AtlasTreeNode(new Rectangle(Rect.Left, Rect.Top, w, Rect.Height));
                    Right = new AtlasTreeNode(new Rectangle(Rect.Left + w, Rect.Top, Rect.Width - w, Rect.Height));
                }
                else
                {
                    // Split horizontally
                    Left = new AtlasTreeNode(new Rectangle(Rect.Left, Rect.Top, Rect.Width, h));
                    Right = new AtlasTreeNode(new Rectangle(Rect.Left, Rect.Top + h, Rect.Width, Rect.Height - h));
                }

                // Insert the rectangle first new child
                var node = Left.Insert(w, h, atlasItem);

                // If the insert is a perfect fit, drop the node from the tree to prevent checking it again
                if (diffW == 0 || diffH == 0)
                    Left = null;

                // If the node was created, set the atlas item
                if (node != null)
                    node.AtlasNode.ITextureAtlasable = atlasItem;

                return node;
            }
        }