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