TileSet.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /**
  2. * From supertux/tools/tilemanager
  3. */
  4. using System;
  5. using System.IO;
  6. using System.Collections;
  7. using System.Collections.Generic;
  8. using Lisp;
  9. using System.Drawing;
  10. public class TileGroup {
  11. public string Name;
  12. public ArrayList Tiles = new ArrayList();
  13. public void Write(LispWriter writer) {
  14. writer.StartList("tilegroup");
  15. writer.Write("name", Name);
  16. writer.Write("tiles", Tiles);
  17. writer.EndList("tilegroup");
  18. }
  19. public void Parse(Lisp.Parser parser) {
  20. int d = parser.Depth;
  21. while (parser.Parse() && parser.Depth >= d) {
  22. if (parser.Depth == d + 1) {
  23. if (parser.Type != Parser.LispType.SYMBOL)
  24. throw new Exception("expected SYMBOL");
  25. string symbol = parser.SymbolValue;
  26. parser.Parse();
  27. switch (symbol) {
  28. case "name":
  29. Name = parser.StringValue;
  30. break;
  31. case "tiles":
  32. do {
  33. Tiles.Add(parser.IntegerValue);
  34. } while (parser.Parse()
  35. && parser.Type == Parser.LispType.INTEGER);
  36. break;
  37. default:
  38. Console.WriteLine("Unknown section " + symbol);
  39. break;
  40. }
  41. }
  42. }
  43. }
  44. public override string ToString() {
  45. return Name;
  46. }
  47. }
  48. public class TileSet {
  49. public ArrayList Tiles = new ArrayList();
  50. public ArrayList TileGroups = new ArrayList();
  51. public void Write(string filename) {
  52. FileStream fs = new FileStream(filename, FileMode.Create);
  53. TextWriter tw = new StreamWriter(fs);
  54. LispWriter writer = new LispWriter(tw);
  55. writer.WriteComment("Generated by tiler");
  56. writer.StartList("supertux-tiles");
  57. foreach(TileGroup tilegroup in TileGroups) {
  58. tilegroup.Write(writer);
  59. }
  60. foreach(Tile tile in Tiles) {
  61. if(tile == null)
  62. continue;
  63. if(tile.ID >= 0)
  64. tile.Write(writer);
  65. }
  66. writer.EndList("supertux-tiles");
  67. tw.Close();
  68. fs.Close();
  69. }
  70. public void Parse(string filename) {
  71. FileStream fs = new FileStream(filename, FileMode.Open);
  72. StreamReader stream = new StreamReader(fs);
  73. Lisp.Parser parser = new Lisp.Parser(stream);
  74. parser.Parse();
  75. if(parser.Type != Parser.LispType.START_LIST)
  76. throw new Exception("Expected START_LIST");
  77. parser.Parse();
  78. if(parser.Type != Parser.LispType.SYMBOL)
  79. throw new Exception("Expected symbol");
  80. if(parser.SymbolValue != "supertux-tiles")
  81. throw new Exception("not a supertux tile files but " +
  82. parser.SymbolValue);
  83. ParseTiles(parser);
  84. stream.Close();
  85. fs.Close();
  86. }
  87. public void ParseTiles(Lisp.Parser parser) {
  88. int d = parser.Depth;
  89. while(parser.Parse() && parser.Depth >= d) {
  90. if(parser.Depth == d && parser.Type != Parser.LispType.START_LIST) {
  91. Console.WriteLine("non-cons type in list...");
  92. continue;
  93. }
  94. if(parser.Depth == d+1) {
  95. if(parser.Type != Parser.LispType.SYMBOL) {
  96. throw new Exception("Expected symbol in list element");
  97. }
  98. switch(parser.SymbolValue) {
  99. case "properties":
  100. SkipList(parser);
  101. break;
  102. case "tilegroup":
  103. TileGroup tilegroup = new TileGroup();
  104. tilegroup.Parse(parser);
  105. TileGroups.Add(tilegroup);
  106. break;
  107. case "tile":
  108. Tile tile = new Tile();
  109. tile.Parse(parser);
  110. while(tile.ID >= Tiles.Count)
  111. Tiles.Add(null);
  112. Tiles[tile.ID] = tile;
  113. break;
  114. case "tiles":
  115. parseTilesList(parser);
  116. break;
  117. default:
  118. throw new Exception("Unexpected listentry: " +
  119. parser.SymbolValue);
  120. }
  121. }
  122. }
  123. }
  124. private void parseTilesList(Parser parser) {
  125. int width = 0;
  126. int height = 0;
  127. string image = null;
  128. List<int> ids = null;
  129. int d = parser.Depth;
  130. while (parser.Parse() && parser.Depth >= d) {
  131. if (parser.Depth == d + 1) {
  132. if (parser.Type != Parser.LispType.SYMBOL)
  133. throw new Exception("expected SYMBOL");
  134. string symbol = parser.SymbolValue;
  135. parser.Parse();
  136. switch (symbol) {
  137. case "width":
  138. width = parser.IntegerValue;
  139. break;
  140. case "height":
  141. height = parser.IntegerValue;
  142. break;
  143. case "ids":
  144. ids = parseIdList(parser);
  145. break;
  146. case "attributes":
  147. SkipList(parser);
  148. break;
  149. case "image":
  150. image = parser.StringValue;
  151. break;
  152. default:
  153. throw new ArgumentException("Unexpected \"" + symbol + "\" in list \"tiles\"");
  154. }
  155. }
  156. }
  157. if (width < 1) throw new ArgumentException("Read \"tiles\" list without \"width\"");
  158. if (height < 1) throw new ArgumentException("Read \"tiles\" list without \"height\"");
  159. if (image == null) throw new ArgumentException("Read \"tiles\" list without \"image\"");
  160. if (ids.Count < width * height) throw new ArgumentException("Read \"tiles\" list with to few \"ids\"");
  161. for (int y = 0; y < height; y++) {
  162. for (int x = 0; x < width; x++) {
  163. Tile tile = new Tile();
  164. tile.ID = ids[y*width+x];
  165. ImageRegion ir = new ImageRegion();
  166. ir.ImageFile = image;
  167. ir.Region = Rectangle.Empty;
  168. ir.RelativeRegion = new RectangleF((float)x / width, (float)y / width, 1.0F / width, 1.0F / height);
  169. tile.Images.Add(ir);
  170. while (tile.ID >= Tiles.Count) Tiles.Add(null);
  171. Tiles[tile.ID] = tile;
  172. }
  173. }
  174. }
  175. private List<int> parseIdList(Parser parser) {
  176. List<int> ids = new List<int>();
  177. if (parser.Type == Parser.LispType.END_LIST) return ids;
  178. int d = parser.Depth;
  179. do {
  180. if (parser.Type != Parser.LispType.INTEGER) throw new Exception("unexpected lisp data: " + parser.Type);
  181. ids.Add(parser.IntegerValue);
  182. } while (parser.Parse() && parser.Depth >= d);
  183. return ids;
  184. }
  185. private void SkipList(Lisp.Parser parser) {
  186. int d = parser.Depth;
  187. while(parser.Parse() && parser.Depth >= d)
  188. ;
  189. }
  190. }