/// <summary> /// Comparison function for sorting sprites in an <see cref="ITextureAtlasable"/> by size. /// </summary> /// <returns>A signed number indicating the relative values of this instance and value. /// Less than zero means this instance is less than value. Zero means this instance is equal to value. /// Greater than zero mean this instance is greater than value.</returns> /// <exception cref="ArgumentNullException"><paramref name="a" /> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException"><paramref name="b" /> is <c>null</c>.</exception> static int SizeCompare(ITextureAtlasable a, ITextureAtlasable b) { if (a == null) { if (log.IsFatalEnabled) { log.Fatal("argument a is null."); } throw new ArgumentNullException("a"); } if (b == null) { if (log.IsFatalEnabled) { log.Fatal("argument b is null."); } throw new ArgumentNullException("b"); } var aSize = a.SourceRect.Height * a.SourceRect.Width; var bSize = b.SourceRect.Height * b.SourceRect.Width; return(bSize.CompareTo(aSize)); }
/// <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); } }
/// <summary> /// Comparison function for sorting sprites in an <see cref="ITextureAtlasable"/> by size. /// </summary> /// <returns>A signed number indicating the relative values of this instance and value. /// Less than zero means this instance is less than value. Zero means this instance is equal to value. /// Greater than zero mean this instance is greater than value.</returns> /// <exception cref="ArgumentNullException"><paramref name="a" /> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException"><paramref name="b" /> is <c>null</c>.</exception> static int SizeCompare(ITextureAtlasable a, ITextureAtlasable b) { if (a == null) { if (log.IsFatalEnabled) log.Fatal("argument a is null."); throw new ArgumentNullException("a"); } if (b == null) { if (log.IsFatalEnabled) log.Fatal("argument b is null."); throw new ArgumentNullException("b"); } var aSize = a.SourceRect.Height * a.SourceRect.Width; var bSize = b.SourceRect.Height * b.SourceRect.Width; return bSize.CompareTo(aSize); }
/// <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; } }