123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618 |
- // $Id$
- using System;
- using System.IO;
- using System.Collections;
- using Gtk;
- using Gdk;
- using Glade;
- public class Application {
- [Glade.Widget]
- private Gtk.Window MainWindow;
- [Glade.Widget]
- private Gtk.CheckMenuItem useNewSyntax;
- [Glade.Widget]
- private Gtk.DrawingArea DrawingArea;
- [Glade.Widget]
- //Flags CheckButtons
- private Gtk.CheckButton SolidCheckButton;
- [Glade.Widget]
- private Gtk.CheckButton UniSolidCheckButton;
- [Glade.Widget]
- private Gtk.CheckButton IceCheckButton;
- [Glade.Widget]
- private Gtk.CheckButton WaterCheckButton;
- [Glade.Widget]
- private Gtk.CheckButton HurtsCheckButton;
- [Glade.Widget]
- private Gtk.CheckButton FireCheckButton;
- [Glade.Widget]
- private Gtk.CheckButton BrickCheckButton;
- [Glade.Widget]
- private Gtk.CheckButton CoinCheckButton;
- [Glade.Widget]
- private Gtk.CheckButton FullBoxCheckButton;
- [Glade.Widget]
- private Gtk.CheckButton SlopeCheckButton;
- [Glade.Widget]
- private Gtk.CheckButton GoalCheckButton;
- [Glade.Widget]
- private Gtk.CheckButton DontUseCheckButton;
- [Glade.Widget]
- private Gtk.CheckButton HiddenCheckButton;
- [Glade.Widget]
- private Gtk.Entry DataEntry;
- [Glade.Widget]
- private Gtk.Entry AnimFpsEntry;
- [Glade.Widget]
- private Gtk.Entry IDEntry;
- [Glade.Widget]
- private Gtk.TreeView TileList;
- [Glade.Widget]
- private Gtk.Combo TileGroupComboBox;
- [Glade.Widget]
- private Gtk.MenuItem AddTileGroupMenu;
- [Glade.Widget]
- private Gtk.Dialog RemapDialog;
- [Glade.Widget]
- private Gtk.SpinButton RD_spinButton;
- private string tilesetdir;
- private string tilesetfile;
- private TileSet tileset;
- private TileGroup selectedgroup;
- private Tile[] Tiles;
- private bool[] SelectionArray;
- private ArrayList Selection = new ArrayList();
- private int TilesX;
- private int TilesY;
- private bool toggling;
- private bool selecting;
- private string currentimage;
- private Gdk.Pixbuf pixbuf;
- public static int Main(string[] args) {
- Gtk.Application.Init();
- Application app = new Application();
- /* that's no proper commandlineparsing, but who'll notice... */
- if(args.Length == 1)
- app.LoadTileSet(args[0]);
- Gtk.Application.Run();
- return 0;
- }
- public Application() {
- Glade.XML gxml = new Glade.XML(null, "tiler.glade", null, null);
- gxml.Autoconnect(this);
- if(MainWindow == null || DrawingArea == null || RemapDialog == null)
- throw new Exception("some widgets not found");
- DrawingArea.AddEvents((int) Gdk.EventMask.ButtonPressMask);
- DrawingArea.AddEvents((int) Gdk.EventMask.ButtonReleaseMask);
- DrawingArea.AddEvents((int) Gdk.EventMask.ButtonMotionMask);
- MainWindow.Show();
- }
- protected void OnOpen(object o, EventArgs e) {
- FileChooserDialog fileChooser = new FileChooserDialog("Select TileSet", MainWindow, FileChooserAction.Open, new object[] {});
- fileChooser.AddButton(Gtk.Stock.Cancel, Gtk.ResponseType.Cancel);
- fileChooser.AddButton(Gtk.Stock.Ok, Gtk.ResponseType.Ok);
- fileChooser.DefaultResponse = Gtk.ResponseType.Ok;
- Gtk.FileFilter filter;
- filter = new Gtk.FileFilter();
- filter.Name = "Supertux tilesets";
- filter.AddPattern("*.strf");
- filter.AddPattern("*.stgt");
- fileChooser.AddFilter( filter );
- filter = new Gtk.FileFilter();
- filter.Name = "Supertux 0.1.x tilesets";
- filter.AddPattern("*.stgt");
- fileChooser.AddFilter( filter );
- filter = new Gtk.FileFilter();
- filter.Name = "Supertux 0.3.x tilesets";
- filter.AddPattern("*.strf");
- fileChooser.AddFilter( filter );
- Gtk.FileFilter all = new Gtk.FileFilter();
- all.Name = "All Files";
- all.AddPattern("*");
- fileChooser.AddFilter( all );
- int result = fileChooser.Run();
- fileChooser.Hide();
- if(result != (int) ResponseType.Ok)
- return;
- LoadTileSet(fileChooser.Filename);
- }
- private void LoadTileSet(string file) {
- try {
- tileset = new TileSet();
- tileset.Parse(file);
- tilesetfile = file;
- tilesetdir = new FileInfo(file).Directory.ToString();
- } catch(Exception exception) {
- ShowException(exception);
- }
- Selection.Clear();
- SelectionChanged();
- FillTileGroupComboBox();
- FillTileList();
- useNewSyntax.Active = tileset.IsNew;
- if (tileset.IsNew)
- Console.WriteLine("Warning: new syntax of 0.3.x files \"More tiles in one image\" isn't currently supported for WRITING");
- }
- protected void OnImportImage(object o, EventArgs e) {
- FileChooserDialog fileChooser = new FileChooserDialog("Select ImageFile", MainWindow, FileChooserAction.Open, new object[] {});
- fileChooser.AddButton(Gtk.Stock.Cancel, Gtk.ResponseType.Cancel);
- fileChooser.AddButton(Gtk.Stock.Ok, Gtk.ResponseType.Ok);
- fileChooser.DefaultResponse = Gtk.ResponseType.Ok;
- Gtk.FileFilter all = new Gtk.FileFilter();
- all.Name = "All Files";
- all.AddPattern("*");
- fileChooser.AddFilter( all );
- int result = fileChooser.Run();
- fileChooser.Hide();
- if(result != (int) ResponseType.Ok)
- return;
- string file = fileChooser.Filename;
- string trim = tilesetdir + "/";
- if (!file.StartsWith(trim)){
- Console.WriteLine(
- "Imported file must be located inside tileset directory");
- return;
- }
- ChangeImage(file.TrimStart(trim.ToCharArray()));
- int startid = tileset.Tiles.Count;
- for(int y = 0; y < TilesY; ++y) {
- for(int x = 0; x < TilesX; ++x) {
- int i = y*TilesX+x;
- Tile tile = new Tile();
- tile.ID = startid + i;
- ImageRegion region = new ImageRegion();
- region.ImageFile = currentimage;
- region.Region = new System.Drawing.Rectangle(x*TileSet.TILE_WIDTH, y*TileSet.TILE_HEIGHT, TileSet.TILE_WIDTH, TileSet.TILE_HEIGHT);
- tile.Images.Add(region);
- if(Tiles[i] != null) {
- Console.WriteLine(
- "Warning Tile in this region already existed...");
- }
- Tiles[i] = tile;
- tileset.Tiles.Add(tile);
- }
- }
- FillTileList();
- }
- private void ChangeImage(string file) {
- if(file == "") {
- currentimage = "";
- pixbuf = null;
- return;
- }
- try {
- pixbuf = new Pixbuf(tilesetdir + "/" + file);
- if(pixbuf.Width % TileSet.TILE_WIDTH != 0 || pixbuf.Height % TileSet.TILE_HEIGHT != 0)
- Console.WriteLine("Warning: Image Width or Height is not a multiple of 32");
- } catch(Exception e) {
- ShowException(e);
- return;
- }
- currentimage = new FileInfo(file).Name;
- TilesX = pixbuf.Width / TileSet.TILE_WIDTH;
- TilesY = pixbuf.Height / TileSet.TILE_HEIGHT;
- SelectionArray = new bool[TilesX * TilesY];
- Tiles = new Tile[TilesX * TilesY];
- // search tileset for tiles with matching image
- foreach(Tile tile in tileset.Tiles) {
- if(tile == null)
- continue;
- if(tile.Images.Count == 0)
- continue;
- ImageRegion region = (ImageRegion) tile.Images[0];
- if(region.ImageFile == currentimage) {
- int px = region.Region.X / TileSet.TILE_WIDTH;
- int py = region.Region.Y / TileSet.TILE_HEIGHT;
- int i = py*TilesX+px;
- if(i < 0 || i >= Tiles.Length) {
- Console.WriteLine("Invalid Imageregion at tile " +
- tile.ID);
- continue;
- }
- if(Tiles[i] != null) {
- Console.WriteLine("Multiple tiles for region " +
- px*TileSet.TILE_WIDTH + " , " + py*TileSet.TILE_HEIGHT);
- continue;
- }
- Tiles[i] = tile;
- }
- }
- /* DrawingArea.Allocation
- = new Gdk.Rectangle(0, 0, pixbuf.Width, pixbuf.Height);*/
- DrawingArea.WidthRequest = pixbuf.Width;
- DrawingArea.HeightRequest = pixbuf.Height;
- DrawingArea.QueueResize();
- }
- protected void OnSave(object o, EventArgs e) {
- if (tileset.IsNew && useNewSyntax.Active) {
- MessageDialog dialog = new MessageDialog(MainWindow, DialogFlags.Modal | DialogFlags.DestroyWithParent, MessageType.Error, ButtonsType.Ok,
- "Sorry, the file you are editing is too new and 0.3.x syntax is not supported yet.");
- dialog.Run();
- dialog.Destroy();
- } else {
- tileset.Write(tilesetfile);
- }
- }
- protected void OnQuit(object o, EventArgs e) {
- Gtk.Application.Quit();
- }
- protected void OnDeleteQuit(object o, DeleteEventArgs e) {
- Gtk.Application.Quit();
- }
- protected void OnAbout(object o, EventArgs e) {
- // string[] authors = new string[]{
- // "<autors?>",
- // };
- Gtk.AboutDialog dialog = new Gtk.AboutDialog();
- // dialog.Icon = <icon>;
- dialog.ProgramName = "SuperTux Tiler";
- dialog.Version = "0.0.3";
- dialog.Comments = "A tileset editor for SuperTux 0.1.x";
- // dialog.Authors = authors;
- dialog.Copyright = "Copyright (c) 2006 SuperTux Devel Team";
- dialog.License =
- "This program is free software; you can redistribute it and/or modify" + Environment.NewLine +
- "it under the terms of the GNU General Public License as published by" + Environment.NewLine +
- "the Free Software Foundation; either version 2 of the License, or" + Environment.NewLine +
- "(at your option) any later version." + Environment.NewLine +
- Environment.NewLine +
- "This program is distributed in the hope that it will be useful," + Environment.NewLine +
- "but WITHOUT ANY WARRANTY; without even the implied warranty of" + Environment.NewLine +
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" + Environment.NewLine +
- "GNU General Public License for more details." + Environment.NewLine +
- Environment.NewLine +
- "You should have received a copy of the GNU General Public License" + Environment.NewLine +
- "along with this program; if not, write to the Free Software Foundation, Inc.," + Environment.NewLine +
- "59 Temple Place, Suite 330, Boston, MA 02111-1307 USA" + Environment.NewLine;
- dialog.Website = "http://supertux.lethargik.org/";
- dialog.WebsiteLabel = "SuperTux on the Web";
- dialog.Run();
- dialog.Destroy();
- }
- protected void OnRemapTiles(object o, EventArgs e) {
- if(Tiles == null)
- return;
- RemapDialog.Show();
- }
- protected void OnRemapDialogCancel(object o, EventArgs e) {
- RemapDialog.Hide();
- }
- protected void OnRemapDialogApply(object o, EventArgs e) {
- RemapDialog.Hide();
- try {
- // remap tiles
- int id;
- try {
- id = RD_spinButton.ValueAsInt;
- } catch(Exception exception) {
- ShowException(exception);
- return;
- }
- RemapTiles(id);
- } finally {
- RD_spinButton.Value = 1;
- }
- }
- protected void OnCreateTileGroup(object o, EventArgs e) {
- }
- protected void OnRenameTileGroup(object o, EventArgs e) {
- }
- protected void RemapTiles(int startID) {
- if(Tiles == null)
- return;
- // remap tiles
- int id = startID;
- foreach(Tile tile in Selection) {
- if(tile.ID == -1)
- continue;
- int oldid = tile.ID;
- tile.ID = id++;
- // remap in all tilegroups...
- foreach(TileGroup tilegroup in tileset.TileGroups) {
- int idx = tilegroup.Tiles.IndexOf(oldid);
- if(idx >= 0) {
- tilegroup.Tiles[idx] = tile.ID;
- }
- }
- }
- FillTileList();
- SelectionChanged();
- }
- protected void OnDrawingAreaExpose(object o, ExposeEventArgs e) {
- if(pixbuf == null)
- return;
- Drawable drawable = e.Event.Window;
- Gdk.GC gc = new Gdk.GC(drawable);
- drawable.DrawPixbuf(gc, pixbuf, 0, 0, 0, 0,
- pixbuf.Width, pixbuf.Height, RgbDither.None, 0, 0);
- gc.RgbFgColor = new Color(0xff, 0, 0);
- foreach(Tile tile in Selection) {
- System.Drawing.Rectangle rect
- = ((ImageRegion) tile.Images[0]).Region;
- drawable.DrawRectangle(gc, false, rect.X, rect.Y, rect.Width,
- rect.Height);
- }
- e.RetVal = false;
- }
- protected void OnDrawingAreaButtonPress(object o, ButtonPressEventArgs e) {
- if(SelectionArray == null)
- return;
- selecting = true;
- for(int i = 0; i < SelectionArray.Length; ++i)
- SelectionArray[i] = false;
- select((int) e.Event.X, (int) e.Event.Y);
- }
- private void select(int x, int y) {
- int tile = y/TileSet.TILE_HEIGHT * TilesX + x/TileSet.TILE_WIDTH;
- if(tile < 0 || tile >= SelectionArray.Length)
- return;
- SelectionArray[tile] = true;
- SelectionArrayChanged();
- }
- protected void OnDrawingAreaMotionNotify(object i, MotionNotifyEventArgs e) {
- if(!selecting)
- return;
- select((int) e.Event.X, (int) e.Event.Y);
- }
- protected void OnDrawingAreaButtonRelease(object o, ButtonPressEventArgs e) {
- selecting = false;
- }
- protected void OnCheckButtonToggled(object sender, EventArgs e) {
- if(toggling)
- return;
- foreach(Tile tile in Selection) {
- if(sender == SolidCheckButton)
- tile.SetAttribute(Attribute.SOLID, SolidCheckButton.Active);
- if(sender == UniSolidCheckButton)
- tile.SetAttribute(Attribute.UNISOLID, UniSolidCheckButton.Active);
- if(sender == IceCheckButton)
- tile.SetAttribute(Attribute.ICE, IceCheckButton.Active);
- if(sender == WaterCheckButton)
- tile.SetAttribute(Attribute.WATER, WaterCheckButton.Active);
- if(sender == HurtsCheckButton)
- tile.SetAttribute(Attribute.HURTS, HurtsCheckButton.Active);
- if(sender == FireCheckButton)
- tile.SetAttribute(Attribute.FIRE, FireCheckButton.Active);
- if(sender == BrickCheckButton)
- tile.SetAttribute(Attribute.BRICK, BrickCheckButton.Active);
- if(sender == CoinCheckButton)
- tile.SetAttribute(Attribute.COIN, CoinCheckButton.Active);
- if(sender == FullBoxCheckButton)
- tile.SetAttribute(Attribute.FULLBOX, FullBoxCheckButton.Active);
- if(sender == SlopeCheckButton)
- tile.SetAttribute(Attribute.SLOPE, SlopeCheckButton.Active);
- if(sender == GoalCheckButton)
- tile.SetAttribute(Attribute.GOAL, GoalCheckButton.Active);
- if(sender == HiddenCheckButton)
- tile.Hidden = HiddenCheckButton.Active;
- if(sender == DontUseCheckButton)
- tile.ID = DontUseCheckButton.Active ? -1 : 0;
- }
- }
- protected void OnEntryChanged(object sender, EventArgs e) {
- if(toggling)
- return;
- foreach(Tile tile in Selection) {
- try {
- if(sender == IDEntry)
- tile.ID = Int32.Parse(IDEntry.Text);
- if(sender == DataEntry)
- tile.Data = Int32.Parse(DataEntry.Text);
- if(sender == AnimFpsEntry)
- tile.AnimFps = Single.Parse(AnimFpsEntry.Text);
- } catch(Exception) {
- // ignore parse errors for now...
- }
- }
- }
- private void SelectionArrayChanged() {
- Selection.Clear();
- for(int i = 0; i < SelectionArray.Length; ++i) {
- if(!SelectionArray[i])
- continue;
- if(Tiles[i] == null) {
- Console.WriteLine("Tile doesn't exist yet");
- // TODO ask user to create new tile...
- continue;
- }
- Selection.Add(Tiles[i]);
- }
- SelectionChanged();
- }
- private void SelectionChanged() {
- bool first = true;
- toggling = true;
- string nextimage = "";
- foreach(Tile tile in Selection) {
- if(first) {
- SolidCheckButton.Active = tile.HasAttribute(Attribute.SOLID);
- UniSolidCheckButton.Active = tile.HasAttribute(Attribute.UNISOLID);
- IceCheckButton.Active = tile.HasAttribute(Attribute.ICE);
- WaterCheckButton.Active = tile.HasAttribute(Attribute.WATER);
- HurtsCheckButton.Active = tile.HasAttribute(Attribute.HURTS);
- FireCheckButton.Active = tile.HasAttribute(Attribute.FIRE);
- BrickCheckButton.Active = tile.HasAttribute(Attribute.BRICK);
- CoinCheckButton.Active = tile.HasAttribute(Attribute.COIN);
- FullBoxCheckButton.Active = tile.HasAttribute(Attribute.FULLBOX);
- SlopeCheckButton.Active = tile.HasAttribute(Attribute.SLOPE);
- GoalCheckButton.Active = tile.HasAttribute(Attribute.GOAL);
- HiddenCheckButton.Active = tile.Hidden;
- DontUseCheckButton.Active = tile.ID == -1;
- DataEntry.Text = tile.Data.ToString();
- AnimFpsEntry.Text = tile.AnimFps.ToString();
- IDEntry.Text = tile.ID.ToString();
- IDEntry.IsEditable = true;
- first = false;
- if(tile.Images.Count > 0) {
- nextimage = ((ImageRegion) tile.Images[0]).ImageFile;
- }
- } else {
- IDEntry.Text += "," + tile.ID.ToString();
- IDEntry.IsEditable = false;
- if(tile.Images.Count > 0
- && ((ImageRegion) tile.Images[0]).ImageFile != nextimage) {
- nextimage = "";
- pixbuf = null;
- }
- }
- }
- if(nextimage != currentimage)
- ChangeImage(nextimage);
- toggling = false;
- DrawingArea.QueueDraw();
- }
- private void FillTileList() {
- TileList.HeadersVisible = true;
- if(TileList.Columns.Length == 0)
- TileList.AppendColumn("Tile", new CellRendererText(), "text", 0);
- ListStore store = new ListStore(typeof(string));
- if(selectedgroup == null) {
- foreach(Tile tile in tileset.Tiles) {
- if(tile == null)
- continue;
- store.AppendValues(new object[] { tile.ID.ToString() });
- }
- } else {
- foreach(int id in selectedgroup.Tiles) {
- Tile tile;
- if (id >= tileset.Tiles.Count){
- Console.WriteLine("Tile ID is above Tiles.Count: " + id.ToString());
- continue;
- } else {
- tile = (Tile) tileset.Tiles[id];
- }
- if(tile == null) {
- Console.WriteLine("tilegroup contains deleted tile");
- continue;
- }
- store.AppendValues(new object[] { id.ToString() });
- }
- }
- TileList.Model = store;
- TileList.Selection.Mode = SelectionMode.Multiple;
- }
- private void FillTileGroupComboBox() {
- string[] groups = new string[tileset.TileGroups.Count+1];
- groups[0] = "All";
- //Submenu submenu = new Submenu();
- for(int i = 0; i < tileset.TileGroups.Count; ++i) {
- String tilegroup = ((TileGroup) tileset.TileGroups[i]).Name;
- groups[i+1] = tilegroup;
- //submenu.Add(new MenuItem(tilegroup));
- }
- TileGroupComboBox.PopdownStrings = groups;
- TileGroupComboBox.Entry.IsEditable = false;
- //AddTileGroupMenu.Submenu = submenu;
- }
- protected void OnTileGroupComboBoxEntryActivated(object o, EventArgs args) {
- if(TileGroupComboBox.Entry.Text == "All") {
- selectedgroup = null;
- } else {
- foreach(TileGroup tilegroup in tileset.TileGroups) {
- if(tilegroup.Name == TileGroupComboBox.Entry.Text) {
- selectedgroup = tilegroup;
- break;
- }
- }
- }
- FillTileList();
- }
- protected void OnTileListCursorChanged(object sender, EventArgs e) {
- TreeModel model;
- TreePath[] selectpaths =
- TileList.Selection.GetSelectedRows(out model);
- Selection.Clear();
- foreach(TreePath path in selectpaths) {
- TreeIter iter;
- model.GetIter(out iter, path);
- int id = Int32.Parse(model.GetValue(iter, 0).ToString());
- Selection.Add(tileset.Tiles[id]);
- }
- SelectionChanged();
- }
- private void ShowException(Exception e) {
- MessageDialog dialog = new MessageDialog(MainWindow,
- DialogFlags.Modal | DialogFlags.DestroyWithParent,
- MessageType.Error, ButtonsType.Ok,
- e.Message);
- dialog.Run();
- dialog.Destroy();
- }
- }
|