Browse Source

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.
tags/v0.1
Starbeamrainbowlabs 3 years ago
parent
commit
d19df5b1b9
4 changed files with 189 additions and 132 deletions
  1. 30
    131
      SpritePacker/Packer.cs
  2. 31
    1
      SpritePacker/Program.cs
  3. 127
    0
      SpritePacker/Sprite.cs
  4. 1
    0
      SpritePacker/SpritePacker.csproj

+ 30
- 131
SpritePacker/Packer.cs View File

@@ -32,7 +32,7 @@ namespace SpritePacker
32 32
 			foreach(Sprite cspr in sprites)
33 33
 			{
34 34
 				Point scanLines = Point.Empty;
35
-				Point nextScanLines = scanLines;
35
+				Point nextScanLines = new Point(int.MaxValue, int.MaxValue);
36 36
 				while(true)
37 37
 				{
38 38
 					if (!cspr.IntersectsWith(arrangedSprites))
@@ -55,12 +55,16 @@ namespace SpritePacker
55 55
 						List<Sprite> problems = cspr.GetIntersectors(arrangedSprites);
56 56
 						Sprite rightProblem = problems[0];
57 57
 						foreach (Sprite probSpr in problems)
58
+						{
58 59
 							if (probSpr.Area.Right > rightProblem.Area.Right)
59 60
 								rightProblem = probSpr;
61
+							if (probSpr.Area.Top < nextScanLines.Y)
62
+								nextScanLines.Y = probSpr.Area.Top + 1;
63
+						}
60 64
 
61 65
 						// Move up to the position furthest to the right
62 66
 						// NOTE: We may need to add one here.
63
-						cspr.Area.X = furthestRightPos + 1;
67
+						cspr.Area.X = rightProblem.Area.Right + 1;
64 68
 
65 69
 					}
66 70
 
@@ -81,9 +85,12 @@ namespace SpritePacker
81 85
 							List<Sprite> problems = cspr.GetIntersectors(arrangedSprites);
82 86
 							Sprite downProblem = problems[0];
83 87
 							foreach (Sprite probSpr in problems)
88
+							{
84 89
 								if (probSpr.Area.Bottom > downProblem.Area.Bottom)
85 90
 									downProblem = probSpr;
86
-
91
+								if (probSpr.Area.Left < nextScanLines.X)
92
+									nextScanLines.X = probSpr.Area.Left + 1;
93
+							}
87 94
 							// Move up to the position furthest downwards
88 95
 							cspr.Area.Y = downProblem.Area.Bottom + 1;
89 96
 						}
@@ -93,146 +100,38 @@ namespace SpritePacker
93 100
 					if (foundPosition)
94 101
 						break;
95 102
 
103
+					// Make sure that the next scan lines are sane
104
+					if (nextScanLines.X == int.MaxValue)
105
+						nextScanLines.X = scanLines.X;
106
+					if (nextScanLines.Y == int.MaxValue)
107
+						nextScanLines.Y = scanLines.Y;
96 108
 
97
-				}
98
-				if (cspr.IntersectsWith(arrangedSprites))
99
-				{
100
-					// We have a conflict! Let's move it to try and sort this out.
101
-					List<Sprite> problemSprites = cspr.GetIntersectors(arrangedSprites);
102
-					// Find the problem sprite closest to (0, 0)
103
-					Sprite mainProblem = problemSprites[0];
104
-					foreach (Sprite pSpr in problemSprites) {
105
-						if ((pSpr.Area.X < mainProblem.Area.X && pSpr.Area.Y <= mainProblem.Area.Y) ||
106
-						    (pSpr.Area.Y < mainProblem.Area.Y && pSpr.Area.X <= mainProblem.Area.X))
107
-							mainProblem = pSpr;
108
-					}
109
+					// If the next scan lines and the current scan lines are identical,
110
+					// then something is very wrong
111
+					if(nextScanLines.Equals(scanLines))
112
+						throw new Exception("Failed to find the next set of lines to scan!");
109 113
 
110
-					Point scanBox = new Point(mainProblem.Area.X, mainProblem.Area.Y);
111
-
112
-
113
-				}
114
-				else
115
-				{
116
-					arrangedSprites.Add(cspr);
114
+					// Move the scan lines up to the next nearest ones we've found
115
+					scanLines = nextScanLines;
116
+					nextScanLines = new Point(int.MaxValue, int.MaxValue);
117 117
 				}
118
-			}
119
-		}
120
-	}
121 118
 
122
-	public class Sprite 
123
-	{
124
-		private Rectangle area;
125
-		private string filename;
126
-
127
-		public Rectangle Area
128
-		{
129
-			get { return area; }
130
-			set { area = value; }
131
-		}
132
-		public string Filename
133
-		{
134
-			get { return filename; }
135
-			set { filename = value; }
136
-		}
137
-
138
-		public Sprite(string inFilename)
139
-		{
140
-			Filename = inFilename;
141
-			// TODO: Fill in the area automagically based on the given image
142
-			throw new NotImplementedException("Todo: Fill in the area automagically based on the given image");
143
-		}
144
-
145
-		public static int GetLargestSize(List<Sprite> sprList)
146
-		{
147
-			int largestSoFar = 0;
148
-			foreach(Sprite spr in sprList)
149
-			{
150
-				if (spr.Area.Width > largestSoFar)
151
-					largestSoFar = spr.Area.Width;
119
+				arrangedSprites.Add(cspr);
152 120
 			}
153
-		}
154 121
 
155
-		public List<Sprite> GetIntersectors(List<Sprite> spriteList)
156
-		{
157
-			List<Sprite> result = new List<Sprite>();
158
-			foreach(Sprite spr in spriteList)
159
-			{
160
-				if (spr.IntersectsWith(this))
161
-					result.Add(spr);
162
-			}
163
-			return result;
164
-		}
165
-		public List<Sprite> GetIntersectorsX(List<Sprite> spriteList)
166
-		{
167
-			List<Sprite> result = new List<Sprite>();
168
-			foreach(Sprite spr in spriteList)
169
-			{
170
-				if (spr.IntersectsWithX(this))
171
-					result.Add(spr);
172
-			}
173
-			return result;
174
-		}
175
-		public List<Sprite> GetIntersectorsY(List<Sprite> spriteList)
176
-		{
177
-			List<Sprite> result = new List<Sprite>();
178
-			foreach(Sprite spr in spriteList)
179
-			{
180
-				if (spr.IntersectsWithY(this))
181
-					result.Add(spr);
182
-			}
183
-			return result;
122
+			// We don't need to copy the list of arranged sprites across to the main list here
123
+			// because Sprite is a class and classes are passed by _reference_.
184 124
 		}
185 125
 
186
-		public bool IntersectsWith(List<Sprite> otherSprites)
187
-		{
188
-			foreach (Sprite spr in otherSprites)
189
-			{
190
-				if (IntersectsWith(spr))
191
-					return true;
192
-			}
193
-			return false;
194
-		}
195
-		public bool IntersectsWith(Sprite otherSprite)
126
+		public override string ToString()
196 127
 		{
197
-			return otherSprite.Area.IntersectsWith(Area);
198
-		}
128
+			string result = string.Format("SpritePacker:");
199 129
 
200
-		public bool IntersectsWithX(List<Sprite> otherSprites)
201
-		{
202
-			foreach (Sprite spr in otherSprites)
203
-			{
204
-				if (IntersectsWithX(spr))
205
-					return true;
206
-			}
207
-			return false;
208
-		}
209
-		public bool IntersectsWithY(List<Sprite> otherSprites)
210
-		{
211
-			foreach (Sprite spr in otherSprites)
212
-			{
213
-				if (IntersectsWithY(spr))
214
-					return true;
215
-			}
216
-			return false;
217
-		}
130
+			foreach (Sprite spr in sprites)
131
+				result += string.Format("\t{0}\n", spr);
218 132
 
219
-		public bool IntersectsWithX(Sprite otherSprite)
220
-		{
221
-			if(Area.Right > otherSprite.Area.X &&
222
-				Area.X < otherSprite.Area.Right)
223
-				return true;
224
-			else
225
-				return false;
226
-		}
227
-		public bool IntersectsWithY(Sprite otherSprite)
228
-		{
229
-			if(Area.Bottom > otherSprite.Area.Y &&
230
-				Area.Y < otherSprite.Area.Bottom)
231
-				return true;
232
-			else
233
-				return false;
133
+			return result;
234 134
 		}
235
-
236 135
 	}
237 136
 }
238 137
 

+ 31
- 1
SpritePacker/Program.cs View File

@@ -1,4 +1,7 @@
1 1
 using System;
2
+using System.Collections.Generic;
3
+using System.Windows.Markup;
4
+using System.IO;
2 5
 
3 6
 namespace SpritePacker
4 7
 {
@@ -6,7 +9,34 @@ namespace SpritePacker
6 9
 	{
7 10
 		public static void Main(string[] args)
8 11
 		{
9
-			Console.WriteLine("Hello World!");
12
+			List<string> values = new List<string>();
13
+			for(int i = 0; i < args.Length; i++)
14
+			{
15
+				switch(args[i])
16
+				{
17
+					case "--help":
18
+						Console.WriteLine("Help text coming soon!");
19
+						return;
20
+						break;
21
+					case "--version":
22
+						Console.WriteLine("Version text coming soon!");
23
+						break;
24
+					default:
25
+						values.Add(args[i]);
26
+						break;
27
+				}
28
+			}
29
+
30
+			Packer spritePacker = new Packer();
31
+			foreach(string filename in values)
32
+			{
33
+				if (File.Exists(filename))
34
+					spritePacker.Add(new Sprite(filename));
35
+				else
36
+					Console.Error.WriteLine("Warning: Ignoring non-existent file '{0}'.", filename);
37
+			}
38
+			spritePacker.Arrange();
39
+			Console.WriteLine(spritePacker.ToString());
10 40
 		}
11 41
 	}
12 42
 }

+ 127
- 0
SpritePacker/Sprite.cs View File

@@ -0,0 +1,127 @@
1
+using System;
2
+using System.Collections.Generic;
3
+using System.Drawing;
4
+
5
+namespace SpritePacker
6
+{
7
+	public class Sprite 
8
+	{
9
+		private Rectangle area;
10
+		private string filename;
11
+
12
+		public Rectangle Area
13
+		{
14
+			get { return area; }
15
+			set { area = value; }
16
+		}
17
+		public string Filename
18
+		{
19
+			get { return filename; }
20
+			set { filename = value; }
21
+		}
22
+
23
+		public Sprite(string inFilename)
24
+		{
25
+			Filename = inFilename;
26
+			// TODO: Fill in the area automagically based on the given image
27
+			throw new NotImplementedException("Todo: Fill in the area automagically based on the given image");
28
+		}
29
+
30
+		public static int GetLargestSize(List<Sprite> sprList)
31
+		{
32
+			int largestSoFar = 0;
33
+			foreach(Sprite spr in sprList)
34
+			{
35
+				if (spr.Area.Width > largestSoFar)
36
+					largestSoFar = spr.Area.Width;
37
+			}
38
+		}
39
+
40
+		public List<Sprite> GetIntersectors(List<Sprite> spriteList)
41
+		{
42
+			List<Sprite> result = new List<Sprite>();
43
+			foreach(Sprite spr in spriteList)
44
+			{
45
+				if (spr.IntersectsWith(this))
46
+					result.Add(spr);
47
+			}
48
+			return result;
49
+		}
50
+		public List<Sprite> GetIntersectorsX(List<Sprite> spriteList)
51
+		{
52
+			List<Sprite> result = new List<Sprite>();
53
+			foreach(Sprite spr in spriteList)
54
+			{
55
+				if (spr.IntersectsWithX(this))
56
+					result.Add(spr);
57
+			}
58
+			return result;
59
+		}
60
+		public List<Sprite> GetIntersectorsY(List<Sprite> spriteList)
61
+		{
62
+			List<Sprite> result = new List<Sprite>();
63
+			foreach(Sprite spr in spriteList)
64
+			{
65
+				if (spr.IntersectsWithY(this))
66
+					result.Add(spr);
67
+			}
68
+			return result;
69
+		}
70
+
71
+		public bool IntersectsWith(List<Sprite> otherSprites)
72
+		{
73
+			foreach (Sprite spr in otherSprites)
74
+			{
75
+				if (IntersectsWith(spr))
76
+					return true;
77
+			}
78
+			return false;
79
+		}
80
+		public bool IntersectsWith(Sprite otherSprite)
81
+		{
82
+			return otherSprite.Area.IntersectsWith(Area);
83
+		}
84
+
85
+		public bool IntersectsWithX(List<Sprite> otherSprites)
86
+		{
87
+			foreach (Sprite spr in otherSprites)
88
+			{
89
+				if (IntersectsWithX(spr))
90
+					return true;
91
+			}
92
+			return false;
93
+		}
94
+		public bool IntersectsWithY(List<Sprite> otherSprites)
95
+		{
96
+			foreach (Sprite spr in otherSprites)
97
+			{
98
+				if (IntersectsWithY(spr))
99
+					return true;
100
+			}
101
+			return false;
102
+		}
103
+
104
+		public bool IntersectsWithX(Sprite otherSprite)
105
+		{
106
+			if(Area.Right > otherSprite.Area.X &&
107
+				Area.X < otherSprite.Area.Right)
108
+				return true;
109
+			else
110
+				return false;
111
+		}
112
+		public bool IntersectsWithY(Sprite otherSprite)
113
+		{
114
+			if(Area.Bottom > otherSprite.Area.Y &&
115
+				Area.Y < otherSprite.Area.Bottom)
116
+				return true;
117
+			else
118
+				return false;
119
+		}
120
+
121
+		public override string ToString()
122
+		{
123
+			return string.Format("Sprite {0} at {1}", Filename, Area);
124
+		}
125
+	}
126
+}
127
+

+ 1
- 0
SpritePacker/SpritePacker.csproj View File

@@ -37,6 +37,7 @@
37 37
     <Compile Include="Program.cs" />
38 38
     <Compile Include="Properties\AssemblyInfo.cs" />
39 39
     <Compile Include="Packer.cs" />
40
+    <Compile Include="Sprite.cs" />
40 41
   </ItemGroup>
41 42
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
42 43
 </Project>

Loading…
Cancel
Save