// $Id$
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using Lisp;
public class TileGroup {
public string Name;
public ArrayList Tiles = new ArrayList();
public void Write(LispWriter writer) {
writer.StartList("tilegroup");
writer.Write("name", Name);
writer.Write("tiles", Tiles);
writer.EndList("tilegroup");
}
public void Parse(Lisp.Parser parser) {
int d = parser.Depth;
while(parser.Parse() && parser.Depth >= d) {
if(parser.Depth == d+1) {
if(parser.Type != Parser.LispType.SYMBOL)
throw new Exception("expected SYMBOL at supertux-tiles level, but got \"" + parser.StringValue + "\"");
string symbol = parser.SymbolValue;
parser.Parse();
switch(symbol) {
case "name":
Name = parser.StringValue;
break;
case "tiles":
do {
Tiles.Add(parser.IntegerValue);
} while(parser.Parse()
&& parser.Type == Parser.LispType.INTEGER);
break;
default:
Console.WriteLine("Unknown section " + symbol);
break;
}
}
}
}
}
public class TileSet {
public const int TILE_WIDTH = 32;
public const int TILE_HEIGHT = 32;
private bool isNew = false;
/// Whether version of tileset file is too new
public bool IsNew {
get {
return isNew;
}
}
public ArrayList Tiles = new ArrayList();
public ArrayList TileGroups = new ArrayList();
public void Write(string filename) {
FileStream fs = new FileStream(filename, FileMode.Create);
TextWriter tw = new StreamWriter(fs);
LispWriter writer = new LispWriter(tw);
writer.WriteComment("Generated by tiler");
writer.StartList("supertux-tiles");
foreach(TileGroup tilegroup in TileGroups) {
tilegroup.Write(writer);
}
foreach(Tile tile in Tiles) {
if(tile == null)
continue;
if(tile.ID >= 0)
tile.Write(writer);
}
writer.EndList("supertux-tiles");
tw.Close();
fs.Close();
}
public void Parse(string filename) {
FileStream fs = new FileStream(filename, FileMode.Open);
StreamReader stream = new StreamReader(fs);
Lisp.Parser parser = new Lisp.Parser(stream);
parser.Parse();
if(parser.Type != Parser.LispType.START_LIST)
throw new Exception("Expected START_LIST");
parser.Parse();
if(parser.Type != Parser.LispType.SYMBOL)
throw new Exception("Expected symbol");
if(parser.SymbolValue != "supertux-tiles")
throw new Exception("not a supertux tile files but " +
parser.SymbolValue);
ParseTiles(parser);
stream.Close();
fs.Close();
}
public void ParseTiles(Lisp.Parser parser) {
isNew = false;
int d = parser.Depth;
while(parser.Parse() && parser.Depth >= d) {
if(parser.Depth == d && parser.Type != Parser.LispType.START_LIST) {
Console.WriteLine("non-cons type in list...");
continue;
}
if(parser.Depth == d+1) {
if(parser.Type != Parser.LispType.SYMBOL) {
throw new Exception("Expected symbol in list element");
}
switch(parser.SymbolValue) {
case "properties":
SkipList(parser);
break;
case "tilegroup":
TileGroup tilegroup = new TileGroup();
tilegroup.Parse(parser);
TileGroups.Add(tilegroup);
break;
case "tile":
Tile tile = new Tile();
tile.Parse(parser);
while(tile.ID >= Tiles.Count)
Tiles.Add(null);
Tiles[tile.ID] = tile;
break;
case "tiles":
ParseMoreTiles(parser);
isNew = true;
break;
default:
throw new Exception("Unexpected listentry: " +
parser.SymbolValue);
}
}
}
}
public void ParseMoreTiles(Lisp.Parser parser)
{
int blockWidth = 0;
int blockHeight = 0;
List ids = new List();
List attributes = new List();
List datas = new List();
List imageNames = new List();
float animFps = 0;
int d = parser.Depth;
while(parser.Parse() && parser.Depth >= d) {
if(parser.Depth == d+1) {
if(parser.Type != Parser.LispType.SYMBOL)
throw new Exception("expected SYMBOL at supertux-tiles---tiles level, but got \"" + parser.StringValue + "\"");
string symbol = parser.SymbolValue;
parser.Parse();
switch(symbol) {
case "width":
blockWidth = parser.IntegerValue;
break;
case "height":
blockHeight = parser.IntegerValue;
break;
case "ids":
Parser.ParseIntList(parser, ids);
break;
case "attributes":
Parser.ParseIntList(parser, attributes);
break;
case "datas":
Parser.ParseIntList(parser, datas);
break;
case "anim-fps":
animFps = parser.FloatValue;
break;
case "image":
int subDepth = parser.Depth;
while(parser.Depth >= subDepth) {
imageNames.Add(parser.StringValue);
parser.Parse();
}
break;
default:
Console.WriteLine("Unknown tiles element " + symbol);
break;
}
}
}
if(ids.Count != blockWidth * blockHeight)
throw new ApplicationException("Must have width*height ids in tiles block, but found " + ids.Count.ToString());
if((attributes.Count != blockWidth * blockHeight) && attributes.Count > 0) //missing atributes == all-are-0-attributes
throw new ApplicationException("Must have width*height attributes in tiles block");
if((datas.Count != blockWidth * blockHeight) && datas.Count > 0) //missing DATAs == all-are-0-DATAs
throw new ApplicationException("Must have width*height DATAs in tiles block");
int id = 0;
for(int y = 0; y < blockHeight; ++y) {
for(int x = 0; x < blockWidth; ++x) {
if (ids[id] != 0) {
Tile tile = new Tile();
tile.Images = new ArrayList();
foreach (string str in imageNames)
{
ImageRegion region = new ImageRegion();
region.ImageFile = str;
region.Region.X = x * TILE_WIDTH;
region.Region.Y = y * TILE_HEIGHT;
region.Region.Width = TILE_WIDTH;
region.Region.Height = TILE_HEIGHT;
tile.Images.Add(region);
}
tile.ID = ids[id];
tile.Attributes = (attributes.Count > 0)?attributes[id]:0; //missing atributes == all-are-0-attributes
tile.Data = (datas.Count > 0)?datas[id]:0; //missing DATAs == all-are-0-DATAs
tile.AnimFps = animFps;
while(Tiles.Count <= tile.ID)
Tiles.Add(null);
Tiles[tile.ID] = tile;
}
id++;
}
}
}
private void SkipList(Lisp.Parser parser)
{
int d = parser.Depth;
while(parser.Parse() && parser.Depth >= d)
;
}
}