using System; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; using System.Linq; using System.Drawing; namespace SpritePacker { enum ProgramMode { Normal, DisplayHelpText, DisplayVersionText } enum OutputFormat { Text, CSV } class Program { public static string Version = Utilities.GetEmbeddedResourceContent("SpritePacker.Version.txt").Trim(); private static ProgramMode programMode = ProgramMode.Normal; private static string helpTextFilename = "SpritePacker.Resources.HelpText.txt"; private static string versionTextFilename = "SpritePacker.Resources.VersionText.txt"; private static string commitHashFilename = "SpritePacker.latest-commit-hash.txt"; private static SpritePacker spritePacker; private static OutputFormat outputFormat = OutputFormat.Text; private static string outputFilename = "spritesheet.png"; private static List values = new List(); private static string rawSourceLocations = null; public static bool Verbose = false; public static int Main(string[] args) { string commitHash = Utilities.GetEmbeddedResourceContent(commitHashFilename).Trim(); Version += "-" + commitHash.Substring(0, 7); for(int i = 0; i < args.Length; i++) { switch(args[i]) { case "--help": programMode = ProgramMode.DisplayHelpText; break; case "--version": programMode = ProgramMode.DisplayVersionText; break; case "--verbose": Verbose = true; break; case "--preset": string presetFilename = args[++i]; if (File.Exists(presetFilename)) rawSourceLocations = File.ReadAllText(presetFilename); else { Console.Error.WriteLine("Warning: Couldn't find the preset csv file at {0}", presetFilename); return 1; } break; case "--csv": outputFormat = OutputFormat.CSV; break; default: if(args[i].StartsWith("-")) { Console.Error.WriteLine("Error: Unrecognised flag '{0}'.", args[i]); return 1; } values.Add(args[i]); break; } } switch(programMode) { case ProgramMode.Normal: if (values.Count == 0) { Console.Error.WriteLine("Error: No filenames specified!"); return 1; } // Set the output filename to be equal to the first filename in the list outputFilename = values[0]; values.RemoveAt(0); RunNormal(); break; case ProgramMode.DisplayHelpText: case ProgramMode.DisplayVersionText: string textFileName = programMode == ProgramMode.DisplayHelpText ? helpTextFilename : versionTextFilename; string helpText = Utilities.GetEmbeddedResourceContent(textFileName); Dictionary templateValues = new Dictionary() { { "version", Version }, { "build-date", Utilities.GetProgramBuildDate().ToString("dd/MM/yyyy h:mmtt") }, { "commit-hash", commitHash.Substring(commitHash.Length - 7) }, { "commit-url", string.Format("https://git.starbeamrainbowlabs.com/sbrl/SpritePacker/commit/{0}", commitHash) } }; foreach (KeyValuePair replacePair in templateValues) helpText = helpText.Replace(string.Format("{{{0}}}", replacePair.Key), replacePair.Value); Console.WriteLine(helpText); break; } return 0; } public static void RunNormal() { spritePacker = new SpritePacker(Verbose); List sprites = new List(); addSprites(values, sprites); // Preset some locations if they were specified if (rawSourceLocations != null) { foreach (string[] line in parseCSV(rawSourceLocations).Skip(1)) { // Skip the header // index,filename,x,y,width,height Sprite currentSprite = sprites.Find((Sprite item) => item.Filename == line[1]); currentSprite.Area = new Rectangle( int.Parse(line[2]), int.Parse(line[3]), int.Parse(line[4]), int.Parse(line[5]) ); currentSprite.Placed = true; if(Verbose) Console.WriteLine("Pre-placing {0}", currentSprite); } } spritePacker.Add(sprites); spritePacker.Arrange(); spritePacker.Output(outputFilename); switch(outputFormat) { case OutputFormat.CSV: Console.WriteLine(spritePacker.GetSpritePositionsCSV().Trim()); break; case OutputFormat.Text: Console.WriteLine(spritePacker.ToString()); break; default: Console.Error.WriteLine("Error: Invalid output format!"); break; } } private static void addSprites(List filenames, List outputSpriteList) { foreach(string filename in filenames) { // Make sure that the file actually exists (we don't want the packer to throw a tantrum) if (File.Exists(filename)) { try { outputSpriteList.Add(new Sprite(filename)); } catch(Exception error) { Console.Error.WriteLine("Error reading {0}: {1}", filename, error.Message); } if ((File.GetAttributes(filename) & FileAttributes.Directory) == FileAttributes.Directory) { // This filename is a directory - recurse over all the files in the directory string[] dirFiles = Directory.GetFiles(filename); addSprites(new List(dirFiles), outputSpriteList); } } else { Console.Error.WriteLine("Warning: Ignoring non-existent file '{0}'.", filename); } } } private static IEnumerable parseCSV(string source) { return Regex.Split(source.Trim(), @"\r?\n").Select((string line) => line.Split(',')); } } }