X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=tools%2Ftilemanager%2FApplication.cs;h=deaf73b967a864a1fe80c73df71c9d711c68fce0;hb=2ad3ecbc14b77d373c796ad04d6389489666cc01;hp=280b72593a18c7c6b17b8521d7ba715524b47276;hpb=b263b994978e461dba8f41871fe72b514098ce21;p=supertux.git diff --git a/tools/tilemanager/Application.cs b/tools/tilemanager/Application.cs index 280b72593..deaf73b96 100644 --- a/tools/tilemanager/Application.cs +++ b/tools/tilemanager/Application.cs @@ -1,17 +1,20 @@ +// $Id$ using System; using System.IO; using System.Collections; using Gtk; using Gdk; -using Gnome; 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; @@ -20,21 +23,30 @@ public class Application { [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 Gnome.AppBar AppBar; - [Glade.Widget] - private Gtk.VBox MainLayout; + private Gtk.Entry IDEntry; [Glade.Widget] private Gtk.TreeView TileList; [Glade.Widget] @@ -42,6 +54,11 @@ public class Application { [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; @@ -57,9 +74,9 @@ public class Application { private string currentimage; private Gdk.Pixbuf pixbuf; - + public static int Main(string[] args) { - Program kit = new Program("tiler", "0.0.1", Modules.UI, args); + Gtk.Application.Init(); Application app = new Application(); @@ -67,7 +84,7 @@ public class Application { if(args.Length == 1) app.LoadTileSet(args[0]); - kit.Run(); + Gtk.Application.Run(); return 0; } @@ -75,39 +92,47 @@ public class Application { Glade.XML gxml = new Glade.XML(null, "tiler.glade", null, null); gxml.Autoconnect(this); - if(MainWindow == null || DrawingArea == null || AppBar == null) - throw new Exception("soem widgets not found"); + 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); - // libglade missed interactivity property :-/ - MainLayout.Remove(AppBar); - AppBar = new AppBar(true, true, PreferencesType.Always); - AppBar.UserResponse += new EventHandler(OnAppBarUserResponse); - MainLayout.PackStart(AppBar, false, false, 0); - AppBar.Show(); - - TileGroupComboBox.Entry.Activated - += new EventHandler (OnTileGroupComboBoxEntryActivated); - MainWindow.Show(); } - private void OnOpen(object o, EventArgs e) { - FileSelection selection = new FileSelection("Select TileSet"); - selection.OkButton.Clicked += new EventHandler(OnSelectTileSetOk); - selection.CancelButton.Clicked += new EventHandler(OnSelectImageCancel); - selection.Show(); - } - - private void OnSelectTileSetOk(object o, EventArgs e) { - FileSelection selection = ((FileSelection.FSButton) o).FileSelection; - string file = selection.Filename; - selection.Destroy(); - - LoadTileSet(file); + 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) { @@ -124,36 +149,49 @@ public class Application { SelectionChanged(); FillTileGroupComboBox(); FillTileList(); - } - private void OnImportImage(object o, EventArgs e) { - FileSelection selection = new FileSelection("Select ImageFile"); - selection.OkButton.Clicked += new EventHandler(OnSelectImageOk); - selection.CancelButton.Clicked += new EventHandler(OnSelectImageCancel); - selection.Show(); - } + 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"); - private void OnSelectImageCancel(object o, EventArgs args) { - FileSelection selection = ((FileSelection.FSButton) o).FileSelection; - selection.Destroy(); } - - private void OnSelectImageOk(object o, EventArgs args) { - FileSelection selection = ((FileSelection.FSButton) o).FileSelection; - string file = selection.Filename; - selection.Destroy(); - - ChangeImage(new FileInfo(file).Name); - + + 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 tile = new Tile(); tile.ID = startid + i; ImageRegion region = new ImageRegion(); region.ImageFile = currentimage; - region.Region = new System.Drawing.Rectangle(x*32, y*32, 32, 32); + 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( @@ -175,18 +213,18 @@ public class Application { } try { pixbuf = new Pixbuf(tilesetdir + "/" + file); - if(pixbuf.Width % 32 != 0 || pixbuf.Height % 32 != 0) + 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 / 32; - TilesY = pixbuf.Height / 32; + 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) @@ -195,8 +233,8 @@ public class Application { continue; ImageRegion region = (ImageRegion) tile.Images[0]; if(region.ImageFile == currentimage) { - int px = region.Region.X / 32; - int py = region.Region.Y / 32; + 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 " + @@ -205,77 +243,130 @@ public class Application { } if(Tiles[i] != null) { Console.WriteLine("Multiple tiles for region " + - px*32 + " , " + py*32); + px*TileSet.TILE_WIDTH + " , " + py*TileSet.TILE_HEIGHT); continue; } Tiles[i] = tile; } - } + } - /* DrawingArea.Allocation + /* DrawingArea.Allocation = new Gdk.Rectangle(0, 0, pixbuf.Width, pixbuf.Height);*/ DrawingArea.WidthRequest = pixbuf.Width; DrawingArea.HeightRequest = pixbuf.Height; DrawingArea.QueueResize(); } - private void OnSave(object o, EventArgs e) { - tileset.Write(tilesetfile); + 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); + } } - private void OnQuit(object o, EventArgs e) { + protected void OnQuit(object o, EventArgs e) { Gtk.Application.Quit(); } - private void OnAbout(object o, EventArgs e) { + protected void OnDeleteQuit(object o, DeleteEventArgs e) { + Gtk.Application.Quit(); } - private void OnRemapTiles(object o, EventArgs e) { - AppBar.SetPrompt("Start-ID:", true); + protected void OnAbout(object o, EventArgs e) { +// string[] authors = new string[]{ +// "", +// }; + + Gtk.AboutDialog dialog = new Gtk.AboutDialog(); +// dialog.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(); } - private void OnCreateTileGroup(object o, EventArgs e) { + protected void OnRemapTiles(object o, EventArgs e) { + if(Tiles == null) + return; + RemapDialog.Show(); } - private void OnRenameTileGroup(object o, EventArgs e) { + protected void OnRemapDialogCancel(object o, EventArgs e) { + RemapDialog.Hide(); } - private void OnAppBarUserResponse(object o, EventArgs e) { + protected void OnRemapDialogApply(object o, EventArgs e) { + RemapDialog.Hide(); try { - if(AppBar.Response == null || AppBar.Response == "" - || Tiles == null) - return; - + // remap tiles int id; try { - id = Int32.Parse(AppBar.Response); + id = RD_spinButton.ValueAsInt; } catch(Exception exception) { ShowException(exception); return; } - 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(); + RemapTiles(id); } finally { - AppBar.ClearPrompt(); + RD_spinButton.Value = 1; } } - private void OnDrawingAreaExpose(object o, ExposeEventArgs e) { + 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; @@ -286,7 +377,7 @@ public class Application { gc.RgbFgColor = new Color(0xff, 0, 0); foreach(Tile tile in Selection) { - System.Drawing.Rectangle rect + System.Drawing.Rectangle rect = ((ImageRegion) tile.Images[0]).Region; drawable.DrawRectangle(gc, false, rect.X, rect.Y, rect.Width, rect.Height); @@ -295,19 +386,19 @@ public class Application { e.RetVal = false; } - private void OnDrawingAreaButtonPress(object o, ButtonPressEventArgs e) { + 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/32 * TilesX + x/32; + int tile = y/TileSet.TILE_HEIGHT * TilesX + x/TileSet.TILE_WIDTH; if(tile < 0 || tile >= SelectionArray.Length) return; @@ -315,30 +406,42 @@ public class Application { SelectionArrayChanged(); } - private void OnDrawingAreaMotionNotify(object i, MotionNotifyEventArgs e) { + protected void OnDrawingAreaMotionNotify(object i, MotionNotifyEventArgs e) { if(!selecting) return; select((int) e.Event.X, (int) e.Event.Y); } - private void OnDrawingAreaButtonRelease(object o, ButtonPressEventArgs e) { + protected void OnDrawingAreaButtonRelease(object o, ButtonPressEventArgs e) { selecting = false; } - private void OnCheckButtonToggled(object sender, EventArgs e) { + protected void OnCheckButtonToggled(object sender, EventArgs e) { if(toggling) return; foreach(Tile tile in Selection) { if(sender == SolidCheckButton) - tile.Solid = SolidCheckButton.Active; + tile.SetAttribute(Attribute.SOLID, SolidCheckButton.Active); if(sender == UniSolidCheckButton) - tile.UniSolid = UniSolidCheckButton.Active; + tile.SetAttribute(Attribute.UNISOLID, UniSolidCheckButton.Active); if(sender == IceCheckButton) - tile.Ice = IceCheckButton.Active; + tile.SetAttribute(Attribute.ICE, IceCheckButton.Active); if(sender == WaterCheckButton) - tile.Water = WaterCheckButton.Active; + 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.Slope = SlopeCheckButton.Active; + 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) @@ -346,7 +449,7 @@ public class Application { } } - private void OnEntryChanged(object sender, EventArgs e) { + protected void OnEntryChanged(object sender, EventArgs e) { if(toggling) return; foreach(Tile tile in Selection) { @@ -357,7 +460,7 @@ public class Application { tile.Data = Int32.Parse(DataEntry.Text); if(sender == AnimFpsEntry) tile.AnimFps = Single.Parse(AnimFpsEntry.Text); - } catch(Exception exception) { + } catch(Exception) { // ignore parse errors for now... } } @@ -368,7 +471,7 @@ public class Application { 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... @@ -386,17 +489,23 @@ public class Application { string nextimage = ""; foreach(Tile tile in Selection) { if(first) { - SolidCheckButton.Active = tile.Solid; - UniSolidCheckButton.Active = tile.UniSolid; - IceCheckButton.Active = tile.Ice; - WaterCheckButton.Active = tile.Water; - SlopeCheckButton.Active = tile.Slope; + 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.Editable = true; + IDEntry.IsEditable = true; first = false; if(tile.Images.Count > 0) { @@ -404,11 +513,11 @@ public class Application { } } else { IDEntry.Text += "," + tile.ID.ToString(); - IDEntry.Editable = false; - if(tile.Images.Count > 0 + IDEntry.IsEditable = false; + if(tile.Images.Count > 0 && ((ImageRegion) tile.Images[0]).ImageFile != nextimage) { nextimage = ""; - pixbuf = null; + pixbuf = null; } } } @@ -433,7 +542,13 @@ public class Application { } } else { foreach(int id in selectedgroup.Tiles) { - Tile tile = (Tile) tileset.Tiles[id]; + 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; @@ -441,7 +556,7 @@ public class Application { store.AppendValues(new object[] { id.ToString() }); } } - + TileList.Model = store; TileList.Selection.Mode = SelectionMode.Multiple; } @@ -457,12 +572,12 @@ public class Application { //submenu.Add(new MenuItem(tilegroup)); } TileGroupComboBox.PopdownStrings = groups; - TileGroupComboBox.Entry.Editable = false; + TileGroupComboBox.Entry.IsEditable = false; //AddTileGroupMenu.Submenu = submenu; } - private void OnTileGroupComboBoxEntryActivated(object o, EventArgs args) { + protected void OnTileGroupComboBoxEntryActivated(object o, EventArgs args) { if(TileGroupComboBox.Entry.Text == "All") { selectedgroup = null; } else { @@ -476,10 +591,10 @@ public class Application { FillTileList(); } - private void OnTileListCursorChanged(object sender, EventArgs e) { + protected void OnTileListCursorChanged(object sender, EventArgs e) { TreeModel model; TreePath[] selectpaths = - TileList.Selection.GetSelectedRows(out model); + TileList.Selection.GetSelectedRows(out model); Selection.Clear(); foreach(TreePath path in selectpaths) {