From d19df5b1b98fab86605bd8458443a9ecea6846f5 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Tue, 17 May 2016 21:08:07 +0100 Subject: [PATCH] Finish implementing packer, and write simple interface. Unfortunately we will have to re-implement the Rectangle struct because we can't modify a value type apparently. --- SpritePacker/Packer.cs | 161 ++++++------------------------- SpritePacker/Program.cs | 32 +++++- SpritePacker/Sprite.cs | 127 ++++++++++++++++++++++++ SpritePacker/SpritePacker.csproj | 1 + 4 files changed, 189 insertions(+), 132 deletions(-) create mode 100644 SpritePacker/Sprite.cs diff --git a/SpritePacker/Packer.cs b/SpritePacker/Packer.cs index 9acce26..ba8b83e 100644 --- a/SpritePacker/Packer.cs +++ b/SpritePacker/Packer.cs @@ -32,7 +32,7 @@ namespace SpritePacker foreach(Sprite cspr in sprites) { Point scanLines = Point.Empty; - Point nextScanLines = scanLines; + Point nextScanLines = new Point(int.MaxValue, int.MaxValue); while(true) { if (!cspr.IntersectsWith(arrangedSprites)) @@ -55,12 +55,16 @@ namespace SpritePacker List problems = cspr.GetIntersectors(arrangedSprites); Sprite rightProblem = problems[0]; foreach (Sprite probSpr in problems) + { if (probSpr.Area.Right > rightProblem.Area.Right) rightProblem = probSpr; + if (probSpr.Area.Top < nextScanLines.Y) + nextScanLines.Y = probSpr.Area.Top + 1; + } // Move up to the position furthest to the right // NOTE: We may need to add one here. - cspr.Area.X = furthestRightPos + 1; + cspr.Area.X = rightProblem.Area.Right + 1; } @@ -81,9 +85,12 @@ namespace SpritePacker List problems = cspr.GetIntersectors(arrangedSprites); Sprite downProblem = problems[0]; foreach (Sprite probSpr in problems) + { if (probSpr.Area.Bottom > downProblem.Area.Bottom) downProblem = probSpr; - + if (probSpr.Area.Left < nextScanLines.X) + nextScanLines.X = probSpr.Area.Left + 1; + } // Move up to the position furthest downwards cspr.Area.Y = downProblem.Area.Bottom + 1; } @@ -93,146 +100,38 @@ namespace SpritePacker if (foundPosition) break; + // Make sure that the next scan lines are sane + if (nextScanLines.X == int.MaxValue) + nextScanLines.X = scanLines.X; + if (nextScanLines.Y == int.MaxValue) + nextScanLines.Y = scanLines.Y; + // If the next scan lines and the current scan lines are identical, + // then something is very wrong + if(nextScanLines.Equals(scanLines)) + throw new Exception("Failed to find the next set of lines to scan!"); + + // Move the scan lines up to the next nearest ones we've found + scanLines = nextScanLines; + nextScanLines = new Point(int.MaxValue, int.MaxValue); } - if (cspr.IntersectsWith(arrangedSprites)) - { - // We have a conflict! Let's move it to try and sort this out. - List problemSprites = cspr.GetIntersectors(arrangedSprites); - // Find the problem sprite closest to (0, 0) - Sprite mainProblem = problemSprites[0]; - foreach (Sprite pSpr in problemSprites) { - if ((pSpr.Area.X < mainProblem.Area.X && pSpr.Area.Y <= mainProblem.Area.Y) || - (pSpr.Area.Y < mainProblem.Area.Y && pSpr.Area.X <= mainProblem.Area.X)) - mainProblem = pSpr; - } - Point scanBox = new Point(mainProblem.Area.X, mainProblem.Area.Y); - - - } - else - { - arrangedSprites.Add(cspr); - } + arrangedSprites.Add(cspr); } - } - } - public class Sprite - { - private Rectangle area; - private string filename; - - public Rectangle Area - { - get { return area; } - set { area = value; } - } - public string Filename - { - get { return filename; } - set { filename = value; } + // We don't need to copy the list of arranged sprites across to the main list here + // because Sprite is a class and classes are passed by _reference_. } - public Sprite(string inFilename) + public override string ToString() { - Filename = inFilename; - // TODO: Fill in the area automagically based on the given image - throw new NotImplementedException("Todo: Fill in the area automagically based on the given image"); - } + string result = string.Format("SpritePacker:"); - public static int GetLargestSize(List sprList) - { - int largestSoFar = 0; - foreach(Sprite spr in sprList) - { - if (spr.Area.Width > largestSoFar) - largestSoFar = spr.Area.Width; - } - } + foreach (Sprite spr in sprites) + result += string.Format("\t{0}\n", spr); - public List GetIntersectors(List spriteList) - { - List result = new List(); - foreach(Sprite spr in spriteList) - { - if (spr.IntersectsWith(this)) - result.Add(spr); - } return result; } - public List GetIntersectorsX(List spriteList) - { - List result = new List(); - foreach(Sprite spr in spriteList) - { - if (spr.IntersectsWithX(this)) - result.Add(spr); - } - return result; - } - public List GetIntersectorsY(List spriteList) - { - List result = new List(); - foreach(Sprite spr in spriteList) - { - if (spr.IntersectsWithY(this)) - result.Add(spr); - } - return result; - } - - public bool IntersectsWith(List otherSprites) - { - foreach (Sprite spr in otherSprites) - { - if (IntersectsWith(spr)) - return true; - } - return false; - } - public bool IntersectsWith(Sprite otherSprite) - { - return otherSprite.Area.IntersectsWith(Area); - } - - public bool IntersectsWithX(List otherSprites) - { - foreach (Sprite spr in otherSprites) - { - if (IntersectsWithX(spr)) - return true; - } - return false; - } - public bool IntersectsWithY(List otherSprites) - { - foreach (Sprite spr in otherSprites) - { - if (IntersectsWithY(spr)) - return true; - } - return false; - } - - public bool IntersectsWithX(Sprite otherSprite) - { - if(Area.Right > otherSprite.Area.X && - Area.X < otherSprite.Area.Right) - return true; - else - return false; - } - public bool IntersectsWithY(Sprite otherSprite) - { - if(Area.Bottom > otherSprite.Area.Y && - Area.Y < otherSprite.Area.Bottom) - return true; - else - return false; - } - } } diff --git a/SpritePacker/Program.cs b/SpritePacker/Program.cs index 30fceac..39cdfcc 100644 --- a/SpritePacker/Program.cs +++ b/SpritePacker/Program.cs @@ -1,4 +1,7 @@ using System; +using System.Collections.Generic; +using System.Windows.Markup; +using System.IO; namespace SpritePacker { @@ -6,7 +9,34 @@ namespace SpritePacker { public static void Main(string[] args) { - Console.WriteLine("Hello World!"); + List values = new List(); + for(int i = 0; i < args.Length; i++) + { + switch(args[i]) + { + case "--help": + Console.WriteLine("Help text coming soon!"); + return; + break; + case "--version": + Console.WriteLine("Version text coming soon!"); + break; + default: + values.Add(args[i]); + break; + } + } + + Packer spritePacker = new Packer(); + foreach(string filename in values) + { + if (File.Exists(filename)) + spritePacker.Add(new Sprite(filename)); + else + Console.Error.WriteLine("Warning: Ignoring non-existent file '{0}'.", filename); + } + spritePacker.Arrange(); + Console.WriteLine(spritePacker.ToString()); } } } diff --git a/SpritePacker/Sprite.cs b/SpritePacker/Sprite.cs new file mode 100644 index 0000000..dd0a421 --- /dev/null +++ b/SpritePacker/Sprite.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Drawing; + +namespace SpritePacker +{ + public class Sprite + { + private Rectangle area; + private string filename; + + public Rectangle Area + { + get { return area; } + set { area = value; } + } + public string Filename + { + get { return filename; } + set { filename = value; } + } + + public Sprite(string inFilename) + { + Filename = inFilename; + // TODO: Fill in the area automagically based on the given image + throw new NotImplementedException("Todo: Fill in the area automagically based on the given image"); + } + + public static int GetLargestSize(List sprList) + { + int largestSoFar = 0; + foreach(Sprite spr in sprList) + { + if (spr.Area.Width > largestSoFar) + largestSoFar = spr.Area.Width; + } + } + + public List GetIntersectors(List spriteList) + { + List result = new List(); + foreach(Sprite spr in spriteList) + { + if (spr.IntersectsWith(this)) + result.Add(spr); + } + return result; + } + public List GetIntersectorsX(List spriteList) + { + List result = new List(); + foreach(Sprite spr in spriteList) + { + if (spr.IntersectsWithX(this)) + result.Add(spr); + } + return result; + } + public List GetIntersectorsY(List spriteList) + { + List result = new List(); + foreach(Sprite spr in spriteList) + { + if (spr.IntersectsWithY(this)) + result.Add(spr); + } + return result; + } + + public bool IntersectsWith(List otherSprites) + { + foreach (Sprite spr in otherSprites) + { + if (IntersectsWith(spr)) + return true; + } + return false; + } + public bool IntersectsWith(Sprite otherSprite) + { + return otherSprite.Area.IntersectsWith(Area); + } + + public bool IntersectsWithX(List otherSprites) + { + foreach (Sprite spr in otherSprites) + { + if (IntersectsWithX(spr)) + return true; + } + return false; + } + public bool IntersectsWithY(List otherSprites) + { + foreach (Sprite spr in otherSprites) + { + if (IntersectsWithY(spr)) + return true; + } + return false; + } + + public bool IntersectsWithX(Sprite otherSprite) + { + if(Area.Right > otherSprite.Area.X && + Area.X < otherSprite.Area.Right) + return true; + else + return false; + } + public bool IntersectsWithY(Sprite otherSprite) + { + if(Area.Bottom > otherSprite.Area.Y && + Area.Y < otherSprite.Area.Bottom) + return true; + else + return false; + } + + public override string ToString() + { + return string.Format("Sprite {0} at {1}", Filename, Area); + } + } +} + diff --git a/SpritePacker/SpritePacker.csproj b/SpritePacker/SpritePacker.csproj index 556c5ae..651a6e7 100644 --- a/SpritePacker/SpritePacker.csproj +++ b/SpritePacker/SpritePacker.csproj @@ -37,6 +37,7 @@ + \ No newline at end of file