1 module converterdialog;
2 
3 import std.conv;
4 import std.stdio;
5 
6 import PixelPerfectEngine.concrete.window;
7 import PixelPerfectEngine.concrete.elements;
8 
9 import PixelPerfectEngine.map.mapload;
10 
11 import PixelPerfectEngine.system.etc;
12 import PixelPerfectEngine.system.inputHandler;
13 
14 import PixelPerfectEngine.graphics.bitmap;
15 import PixelPerfectEngine.graphics.layers;
16 
17 import PixelPerfectEngine.extbmp.extbmp;
18 
19 import converter;
20 /**
21  *Creates a window for converting external bitmaps for the engine's native format 
22  */
23 public class ConverterDialog : Window, ActionListener, SheetDialogListener{
24 	private ListBox imageList, fileList, animationList, frameList;
25 	private string[] filenames;
26 	private string importFileName,animationSelection;
27 	private Label[string] labels;
28 	private InputHandler inputHandler;
29 	public ExtendibleBitmap[] files;
30 	private ISpriteLayer32Bit viewer;
31 	private Bitmap32Bit preview;
32 	private int imageSelection, frameSelection;
33 
34 	private bool previewModeOn;
35 	ExtendibleBitmap selection;
36 	public this(InputHandler inputhandler, ISpriteLayer32Bit viewer, ExtendibleMap mh = null, ExtendibleBitmap[] documentFiles = null){
37 		this(Coordinate(0,0,640,480), "XMP Converter Toolkit");
38 		this.inputHandler = inputhandler;
39 		this.viewer = viewer;
40 		files = documentFiles;
41 		Button [] buttons;
42 		if(mh !is null){
43 			//filenames = mh.getAllFilenames();
44 			//fileList = new ListBox("fileList",Coordinate(4,20,204,101), [ListBoxColumn("Filename",filenames)], [256], 15);
45 		}else{
46 			labels["0x00"] = new Label("Path:", "", Coordinate(4,20,204,40));
47 			labels["path"] = new Label("n/a", "path", Coordinate(4,40,204,60));
48 		}
49 		buttons ~= new Button("New File","newfile", Coordinate(210,20,294,39));
50 		buttons ~= new Button("Load File","loadfile", Coordinate(210,40,294,59));
51 		buttons ~= new Button("Save File","savefile", Coordinate(210,60,294,79));
52 		//buttons ~= new Button("Rem File","removefile", Coordinate(210,60,294,79));
53 		imageList = new ListBox("imageList",Coordinate(4,104,204,304),[ListBoxColumn("BitmapID",[""]),ListBoxColumn("Bitdepth",[""]),ListBoxColumn("Format",[""]),ListBoxColumn("PalMode",[""])], [128,64,64,80], 15);
54 		buttons ~= new Button("Import New","inportnew", Coordinate(210,110,294,129));
55 		buttons ~= new Button("Imp Multi","inportmultiple", Coordinate(210,130,294,149));
56 		buttons ~= new Button("Export As","exportas", Coordinate(210,150,294,169));
57 		buttons ~= new Button("Remove","remove", Coordinate(210,170,294,189));
58 		buttons ~= new Button("Preview","preview", Coordinate(210,190,294,209));
59 		buttons ~= new Button("Imp Pal","paletteImport", Coordinate(210,210,294,229));
60 		animationList = new ListBox("animationList", Coordinate(300,20,500,120),[ListBoxColumn("AnimID",[""]),ListBoxColumn("Frames",[""])], [128,80], 15);
61 		buttons ~= new Button("New Anim","newAnim", Coordinate(506,20,590,39));
62 		buttons ~= new Button("Edit","animProp", Coordinate(506,40,590,59));
63 		//buttons ~= new Button("Save File","savefile", Coordinate(506,60,590,79));
64 		buttons ~= new Button("Rem Anim","removeAnim", Coordinate(506,60,590,79));
65 		frameList = new ListBox("frameList", Coordinate(300,122,500,304),[ListBoxColumn("Num",[""]),ListBoxColumn("ImageID",[""]),ListBoxColumn("Dur",[""])],[40,128,64], 15);
66 		buttons ~= new Button("Add Frame","addFrame", Coordinate(506,130,590,149));
67 		buttons ~= new Button("Edit","editFr", Coordinate(506,150,590,169));
68 		buttons ~= new Button("Remove","removeFr", Coordinate(506,170,590,189));
69 
70 		foreach(Button e; buttons){
71 			addElement(e, EventProperties.MOUSE);
72 			e.al ~= this;
73 		}
74 		foreach(WindowElement e; labels){
75 			addElement(e, EventProperties.MOUSE);
76 		}
77 		addElement(imageList, EventProperties.MOUSE);
78 		imageList.al ~= this;
79 		addElement(animationList, EventProperties.MOUSE);
80 		addElement(frameList, EventProperties.MOUSE);
81 	}
82 
83 	public this(Coordinate size, wstring title){
84 		super(size, title);
85 	}
86 	public void actionEvent(string source, int type, int value, wstring message){}
87 	public void actionEvent(string source, string subSource, int type, int value, wstring message){}
88 	public void actionEvent(Event event){
89 		//writeln(event.subsource);
90 		//writeln(event.source);
91 		switch(event.subsource){
92 			case "filedialog":
93 				switch(event.source){
94 					case "xmpfiledialog":
95 						ExtendibleBitmap newFile = new ExtendibleBitmap();
96 						string fileName = event.path ;
97 						fileName ~= '\\';
98 						fileName ~= event.filename;
99 						newFile.saveFile(fileName);
100 						if(files is null){
101 							selection = newFile;
102 							labels["path"].setText(to!wstring(fileName));
103 						}else{
104 							files ~= newFile;
105 							filenames ~= fileName;
106 							selection = newFile;
107 						}
108 
109 						break;
110 					case "xmpload":
111 						string fileName = event.path ;
112 						writeln(fileName);
113 						fileName ~= '\\';
114 						writeln(fileName);
115 						fileName ~= event.filename;
116 						writeln(fileName);
117 						ExtendibleBitmap newFile = new ExtendibleBitmap(fileName);
118 						if(files is null){
119 							selection = newFile;
120 							labels["path"].setText(to!wstring(fileName));
121 						}else{
122 							files ~= newFile;
123 							filenames ~= fileName;
124 							selection = newFile;
125 						}
126 						updateImageList();
127 						break;
128 					case "importfile":
129 						string fileName = event.path ;
130 						fileName ~= '\\';
131 						fileName ~= event.filename;
132 						importFileName = fileName;
133 						//Bitmap32Bit bmp = importBitmapFromFile(fileName);
134 						ImportDialog id = new ImportDialog(inputHandler);
135 						id.al ~= this;
136 						parent.addWindow(id);
137 						break;
138 					case "importmulti": 
139 						string fileName = event.path ;
140 						fileName ~= '\\';
141 						fileName ~= event.filename;
142 						importFileName = fileName;
143 						SpriteSheetDialog sd = new SpriteSheetDialog(this);
144 						parent.addWindow(sd);
145 						break;
146 					case "palettefile":
147 						string fileName = event.path ;
148 						fileName ~= '\\';
149 						fileName ~= event.filename;
150 						importFileName = fileName;
151 						TextInputDialog tid = new TextInputDialog(Coordinate(0,0,200,90),"palName","Import Palette","Palette ID:");
152 						tid.al ~= this;
153 						parent.addWindow(tid);
154 						break;
155 					default: break;
156 				}
157 				break;
158 			case "impDial":
159 				
160 				try{
161 					/*Bitmap32Bit bmp = import32BitBitmapFromFile(importFileName);
162 					 selection.addBitmap(cast(void[])bmp.getRawdata(),bmp.getX,bmp.getY,"32bit",to!string(event.text),"ARGB");
163 					 updateImageList();
164 					 previewModeOn = true;
165 					 //set sprite for preview mode
166 					 //writeln(preview);
167 					 viewer.addSprite(bmp, 0, 0, 0);*/
168 					string bitdepth;
169 					switch(event.value){
170 						case 0: bitdepth = "8bit"; break;
171 						case 1: bitdepth = "16bit"; break;
172 						case 2: bitdepth = "32bit"; break;
173 						default: bitdepth = "1bit"; break;
174 					}
175 					importDirectlyToXMP(importFileName,selection,new ImportData([to!string(event.text)],bitdepth,0,0,0));
176 
177 					}catch(Exception e){
178 						writeln(e);
179 					}
180 				break;
181 			case "TextInputDialog":
182 				switch(event.source){
183 					case "palName": 
184 						importPaletteDirectlyToXMP(importFileName,selection,to!string(event.text));
185 						break;
186 					default: break;
187 				}
188 				break;
189 			default:
190 				switch(event.source){
191 					case "newfile":
192 						// create new filedialog to save the new file to the given location
193 						FileDialog fileDialog = new FileDialog("Create new XMP file", "xmpfiledialog", this, ["*.xmp"], ".\\", true);
194 						parent.addWindow(fileDialog);
195 						break;
196 					case "loadfile":
197 						FileDialog fileDialog = new FileDialog("Load XMP file", "xmpload", this, ["*.xmp"], ".\\", false);
198 						parent.addWindow(fileDialog);
199 						break;
200 					case "savefile":
201 						selection.saveFile();
202 						break;
203 					case "preview":
204 						if(previewModeOn){
205 							previewModeOn = false;
206 							viewer.removeSprite(0);
207 						}else{
208 							previewModeOn = true;
209 							//set sprite for preview mode
210 							//writeln(preview);
211 							viewer.addSprite(preview, 0, 0, 0);
212 						}
213 						break;
214 					case "inportnew":
215 						FileDialog fileDialog = new FileDialog("Import PNG/TGA/BMP", "importfile", this, ["*.png","*.tga","*.bmp"], ".\\");
216 						parent.addWindow(fileDialog);
217 						break;
218 					case "inportmultiple":
219 						//parent.addWindow(new SpriteSheetDialog());
220 						FileDialog fileDialog = new FileDialog("Import PNG/TGA/BMP", "importmulti", this, ["*.png","*.tga","*.bmp"], ".\\");
221 						parent.addWindow(fileDialog);
222 						break;
223 					case "imageList":
224 						//if(!selection.isEmpty){
225 							imageSelection = event.value;
226 							//update image information
227 							//preview = new Bitmap32Bit(selection.getBitmap(imageSelection),selection.getXsize(imageSelection),selection.getYsize(imageSelection));
228 							//writeln(preview);
229 						preview = getBitmapPreview(selection,selection.bitmapID[imageSelection]);
230 						writeln(preview);
231 						//}
232 						break;
233 					case "paletteImport":
234 						FileDialog fileDialog = new FileDialog("Import Palette", "palettefile", this, ["*.png","*.tga","*.bmp"], ".\\");
235 						parent.addWindow(fileDialog);
236 						break;
237 					default: break;
238 				}
239 				break;
240 		}
241 	}
242 	public void SheetDialogEvent(string a, string b, int numFrom, int numOfDigits, int x, int y, int bitdepth, NumberingStyle ns){
243 		string bd;
244 		switch(bitdepth){
245 			case 0: bd="8bit"; break;
246 			case 1: bd="16bit"; break;
247 			case 2: bd="32bit"; break;
248 			default: bd="1bit"; break;
249 		}
250 		importDirectlyToXMP(importFileName,selection,new ImportData(new NamingConvention(a,b,ns,numFrom,numOfDigits),bd,x,y,0));
251 	}
252 
253 	private void updateFileList(){
254 
255 	}
256 	private void updateImageList(){
257 		wstring[] IDs = stringArrayConv(selection.getIDs());
258 		wstring[] bt = stringArrayConv(selection.bitdepth), form = stringArrayConv(selection.format), pm = stringArrayConv(selection.paletteMode);
259 
260 		imageList.updateColumns([ListBoxColumn("BitmapID",IDs),ListBoxColumn("Bitdepth",bt),ListBoxColumn("Format",form),ListBoxColumn("PalMode",pm)]);
261 	}
262 	private void updateAnimationList(){
263 		wstring[] IDs, frames;
264 		foreach(s; selection.animData.byKey){
265 			IDs ~= to!wstring(s);
266 			frames ~= to!wstring(selection.animData[s].ID.length);
267 		}
268 		animationList.updateColumns([ListBoxColumn("AnimID",IDs),ListBoxColumn("Frames",frames)]);
269 	}
270 	private void updateFrameList(){
271 		/*wstring[] num, IDs, dur;
272 		for(int i ; i < selection.animData[selection].bitmapID.length ; i++){
273 			num ~= to!wstring(i);
274 			ID ~= to!wstring(selection.animData[selection].bitmapID[i]);
275 			dur ~= to!wstring(selection.animData[selection].duration[i]);
276 		}
277 		[ListBoxColumn("Num",[""]),ListBoxColumn("ImageID",[""]),ListBoxColumn("Dur",[""])];*/
278 	}
279 
280 }
281 
282 interface SheetDialogListener{
283 	public void SheetDialogEvent(string a, string b, int numFrom, int numOfDigits, int x, int y, int bitdepth, NumberingStyle ns);
284 }
285 
286 public class SpriteSheetDialog : Window, ActionListener{
287 	private TextBox nameA, nameB, numFrom, gridX, gridY, nOfZeros;
288 	private RadioButtonGroup numberingConvention, bitDepthSetter;
289 	//private InputHandler inputHandler;
290 	public SheetDialogListener sdl;
291 	public this(SheetDialogListener sdl){
292 		this.sdl = sdl;
293 		this(Coordinate(0,0,230,340),"Sheet import settings");
294 		nameA = new TextBox("","nameA",Coordinate(120,20,220,40));
295 		addElement(nameA,EventProperties.MOUSE);
296 		addElement(new Label("NameA:","reversed",Coordinate(10,20,120,40)),EventProperties.MOUSE);
297 
298 		nameB = new TextBox("","nameB",Coordinate(120,50,220,70));
299 		addElement(nameB,EventProperties.MOUSE);
300 		addElement(new Label("NameB:","reversed",Coordinate(10,50,120,70)),EventProperties.MOUSE);
301 
302 		numFrom = new TextBox("","numFrom",Coordinate(120,80,220,100));
303 		addElement(numFrom,EventProperties.MOUSE);
304 		addElement(new Label("NumFrom:","reversed",Coordinate(10,80,120,100)),EventProperties.MOUSE);
305 
306 		gridX = new TextBox("","gridX",Coordinate(120,110,220,130));
307 		addElement(gridX,EventProperties.MOUSE);
308 		addElement(new Label("gridX:","reversed",Coordinate(10,110,120,130)),EventProperties.MOUSE);
309 
310 		gridY = new TextBox("","gridY",Coordinate(120,140,220,160));
311 		addElement(gridY,EventProperties.MOUSE);
312 		addElement(new Label("gridY:","reversed",Coordinate(10,140,120,160)),EventProperties.MOUSE);
313 
314 		nOfZeros = new TextBox("","nOfZeros",Coordinate(120,170,220,190));
315 		addElement(nOfZeros,EventProperties.MOUSE);
316 		addElement(new Label("NumOfZeros:","reversed",Coordinate(10,170,120,190)),EventProperties.MOUSE);
317 
318 		bitDepthSetter = new RadioButtonGroup("Bitdepth:","cmode",Coordinate(10,210,110,310),["8Bit","16Bit","32Bit","1Bit"],16,0);
319 		addElement(bitDepthSetter,EventProperties.MOUSE);
320 		numberingConvention = new RadioButtonGroup("numConv:","numConv",Coordinate(120,210,220,310),["Dec","Oct","Hex"],16,0);
321 		addElement(numberingConvention,EventProperties.MOUSE);
322 		Button ok = new Button("Ok","ok",Coordinate(160,315,220,335));
323 		addElement(ok,EventProperties.MOUSE);
324 		ok.al~=this;
325 	}
326 
327 	public this(Coordinate size, wstring title){
328 		super(size, title);
329 	}
330 	public void actionEvent(string source, int type, int value, wstring message){}
331 	public void actionEvent(string source, string subSource, int type, int value, wstring message){}
332 	public void actionEvent(Event event){
333 		if(event.source == "ok"){
334 			NumberingStyle ns;
335 			switch(numberingConvention.getValue){
336 				case 0: ns = NumberingStyle.DECIMAL; break;
337 				case 1: ns = NumberingStyle.OCTAL; break;
338 				case 2: ns = NumberingStyle.HEXADECIMAL; break;
339 				default: break;
340 			}
341 			sdl.SheetDialogEvent(to!string(nameA.getText),to!string(nameB.getText),to!int(numFrom.getText),to!int(nOfZeros.getText),to!int(gridX.getText),to!int(gridY.getText),bitDepthSetter.getValue,ns);
342 			parent.closeWindow(this);
343 		}
344 	}
345 }
346 
347 public class ImportDialog : Window, ActionListener{
348 	private TextBox name;
349 	private RadioButtonGroup bitdepthSetter;
350 	public ActionListener[] al;
351 	public this(InputHandler inputhandler){
352 		this(Coordinate(0,0,220,200), "Import settings");
353 		addElement(new Label("ID:","0000",Coordinate(10,20,80,40)), EventProperties.MOUSE);
354 		name = new TextBox("","name", Coordinate(100,20,210,40));
355 		//name.addTextInputHandler(inputhandler);
356 		bitdepthSetter = new RadioButtonGroup("Bitdepth:","cmode",Coordinate(20,50,200,150),["8Bit","16Bit","32Bit","1Bit"],16,0);
357 		Button b1 = new Button("Ok","ok",Coordinate(80,160,140,180));
358 		addElement(b1, EventProperties.MOUSE);
359 		b1.al ~= this;
360 		Button b2 = new Button("Cancel","cancel",Coordinate(150,160,210,180));
361 		addElement(b2, EventProperties.MOUSE);
362 		b2.al ~= this;
363 		addElement(bitdepthSetter, EventProperties.MOUSE);
364 		addElement(name, EventProperties.MOUSE);
365 	}
366 
367 	public this(Coordinate size, wstring title){
368 		super(size, title);
369 	}
370 	public void actionEvent(string source, int type, int value, wstring message){}
371 	public void actionEvent(string source, string subSource, int type, int value, wstring message){}
372 	public void actionEvent(Event event){
373 		//writeln(event.source);
374 		switch(event.source){
375 			case "ok": 
376 				foreach(a; al){
377 					a.actionEvent(new Event("impDial","impDial","","",name.getText,bitdepthSetter.getValue,-3));
378 
379 				}
380 				parent.closeWindow(this);
381 				break;
382 			case "cancel": parent.closeWindow(this); break;
383 			default: break;
384 		}
385 	}
386 }
387