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, wstring 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!wstring(e.classinfo.toString()), to!wstring(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!wstring(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!wstring(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 /+public void sheetDialogEvent(string a, string b, int numFrom, int numOfDigits, int x, int y, int bitdepth, NumberingStyle ns){ 289 string bd; 290 switch(bitdepth){ 291 case 0: bd="8bit"; break; 292 case 1: bd="16bit"; break; 293 case 2: bd="32bit"; break; 294 default: bd="1bit"; break; 295 } 296 importDirectlyToXMP(importFileName,selection,new ImportData(new NamingConvention(a,b,ns,numFrom,numOfDigits),bd,x,y,0)); 297 }+/ 298 299 private void updateFileList(){ 300 301 } 302 private void updateImageList(){ 303 //wstring[] IDs = stringArrayConv(selection.bitmapID); 304 //wstring[] bt = stringArrayConv(selection.bitdepth), form = stringArrayConv(selection.format), pm = stringArrayConv(selection.paletteMode); 305 ListBoxItem[] items; 306 for(int i; i < selection.bitmapID.length; i++){ 307 items ~= new ListBoxItem([to!wstring(selection.bitmapID[i]),to!wstring(selection.bitdepth[i]),to!wstring(selection.format[i]),to!wstring(selection.paletteMode[i]), 308 to!wstring(selection.getXsize(i)),to!wstring(selection.getYsize(i))]); 309 } 310 //imageList.updateColumns([ListBoxColumn("BitmapID",IDs),ListBoxColumn("Bitdepth",bt),ListBoxColumn("Format",form),ListBoxColumn("PalMode",pm)]); 311 imageList.updateColumns(items); 312 imageList.draw(); 313 } 314 private void updateAnimationList(){ 315 //wstring[] IDs, frames; 316 ListBoxItem[] items; 317 foreach(s; selection.animData.byKey){ 318 items ~= new ListBoxItem([to!wstring(s), to!wstring(selection.animData[s].ID.length)]); 319 } 320 animationList.updateColumns(items); 321 animationList.draw(); 322 } 323 private void updateFrameList(){ 324 //wstring[] num, IDs, dur; 325 ListBoxItem[] items; 326 for(int i ; i < selection.animData[animationSelection].ID.length ; i++){ 327 items ~= new ListBoxItem([to!wstring(i), to!wstring(selection.animData[animationSelection].ID[i]), to!wstring(selection.animData[animationSelection].duration[i])]); 328 } 329 frameList.updateColumns(items); 330 frameList.draw(); 331 } 332 333 } 334 335 interface SheetDialogListener{ 336 public void SheetDialogEvent(string a, string b, int numFrom, int numOfDigits, int x, int y, int bitdepth, NumberingStyle ns); 337 } 338 339 /+public class SpriteSheetDialog : Window, ActionListener{ 340 private TextBox nameA, nameB, numFrom, gridX, gridY, nOfZeros; 341 private RadioButtonGroup numberingConvention, bitDepthSetter; 342 //private InputHandler inputHandler; 343 public SheetDialogListener sdl; 344 public this(SheetDialogListener sdl){ 345 this.sdl = sdl; 346 this(Coordinate(0,0,230,340),"Sheet import settings"); 347 nameA = new TextBox("","nameA",Coordinate(120,20,220,40)); 348 addElement(nameA,EventProperties.MOUSE); 349 addElement(new Label("NameA:","reversed",Coordinate(10,20,120,40)),EventProperties.MOUSE); 350 351 nameB = new TextBox("","nameB",Coordinate(120,50,220,70)); 352 addElement(nameB,EventProperties.MOUSE); 353 addElement(new Label("NameB:","reversed",Coordinate(10,50,120,70)),EventProperties.MOUSE); 354 355 numFrom = new TextBox("","numFrom",Coordinate(120,80,220,100)); 356 addElement(numFrom,EventProperties.MOUSE); 357 addElement(new Label("NumFrom:","reversed",Coordinate(10,80,120,100)),EventProperties.MOUSE); 358 359 gridX = new TextBox("","gridX",Coordinate(120,110,220,130)); 360 addElement(gridX,EventProperties.MOUSE); 361 addElement(new Label("gridX:","reversed",Coordinate(10,110,120,130)),EventProperties.MOUSE); 362 363 gridY = new TextBox("","gridY",Coordinate(120,140,220,160)); 364 addElement(gridY,EventProperties.MOUSE); 365 addElement(new Label("gridY:","reversed",Coordinate(10,140,120,160)),EventProperties.MOUSE); 366 367 nOfZeros = new TextBox("","nOfZeros",Coordinate(120,170,220,190)); 368 addElement(nOfZeros,EventProperties.MOUSE); 369 addElement(new Label("NumOfZeros:","reversed",Coordinate(10,170,120,190)),EventProperties.MOUSE); 370 371 bitDepthSetter = new RadioButtonGroup("Bitdepth:","cmode",Coordinate(10,210,110,310),["8Bit","16Bit","32Bit","1Bit"],16,0); 372 addElement(bitDepthSetter,EventProperties.MOUSE); 373 numberingConvention = new RadioButtonGroup("numConv:","numConv",Coordinate(120,210,220,310),["Dec","Oct","Hex"],16,0); 374 addElement(numberingConvention,EventProperties.MOUSE); 375 Button ok = new Button("Ok","ok",Coordinate(160,315,220,335)); 376 addElement(ok,EventProperties.MOUSE); 377 ok.al~=this; 378 } 379 380 public this(Coordinate size, wstring title){ 381 super(size, title); 382 } 383 public void actionEvent(string source, int type, int value, wstring message){} 384 public void actionEvent(string source, string subSource, int type, int value, wstring message){} 385 public void actionEvent(Event event){ 386 if(event.source == "ok"){ 387 NumberingStyle ns; 388 switch(numberingConvention.getValue){ 389 case 0: ns = NumberingStyle.DECIMAL; break; 390 case 1: ns = NumberingStyle.OCTAL; break; 391 case 2: ns = NumberingStyle.HEXADECIMAL; break; 392 default: break; 393 } 394 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); 395 parent.closeWindow(this); 396 } 397 } 398 }+/ 399 400 /+public class ImportDialog : Window, ActionListener{ 401 private TextBox name; 402 private RadioButtonGroup bitdepthSetter; 403 public ActionListener[] al; 404 public this(InputHandler inputhandler){ 405 this(Coordinate(0,0,220,200), "Import settings"); 406 addElement(new Label("ID:","0000",Coordinate(10,20,80,40)), EventProperties.MOUSE); 407 name = new TextBox("","name", Coordinate(100,20,210,40)); 408 //name.addTextInputHandler(inputhandler); 409 bitdepthSetter = new RadioButtonGroup("Bitdepth:","cmode",Coordinate(20,50,200,150),["8Bit","16Bit","32Bit","1Bit"],16,0); 410 Button b1 = new Button("Ok","ok",Coordinate(80,160,140,180)); 411 addElement(b1, EventProperties.MOUSE); 412 b1.al ~= this; 413 Button b2 = new Button("Cancel","cancel",Coordinate(150,160,210,180)); 414 addElement(b2, EventProperties.MOUSE); 415 b2.al ~= this; 416 addElement(bitdepthSetter, EventProperties.MOUSE); 417 addElement(name, EventProperties.MOUSE); 418 } 419 420 public this(Coordinate size, wstring title){ 421 super(size, title); 422 } 423 public void actionEvent(string source, int type, int value, wstring message){} 424 public void actionEvent(string source, string subSource, int type, int value, wstring message){} 425 public void actionEvent(Event event){ 426 //writeln(event.source); 427 switch(event.source){ 428 case "ok": 429 foreach(a; al){ 430 a.actionEvent(new Event("impDial","impDial","","",name.getText,bitdepthSetter.getValue,-3)); 431 432 } 433 parent.closeWindow(this); 434 break; 435 case "cancel": parent.closeWindow(this); break; 436 default: break; 437 } 438 } 439 }+/ 440 441 public class PreviewWindow : Window{ 442 Bitmap32Bit previewImage; 443 ISpriteLayer spriteLayer; 444 ConverterDialog cd; 445 public this(Bitmap32Bit previewImage, ISpriteLayer spriteLayer, ConverterDialog cd){ 446 Coordinate size = Coordinate(0,0,previewImage.width > 78 ? previewImage.width + 2 : 80, previewImage.height + 18); 447 super(size, "Preview"); 448 spriteLayer.addSprite(previewImage, -1, 2, 18, BitmapAttrib(false,false)); 449 this.spriteLayer = spriteLayer; 450 this.cd = cd; 451 } 452 453 public deprecated void actionEvent(Event event) { 454 455 } 456 457 override public void move(int x,int y) { 458 spriteLayer.moveSprite(-1,x+2,y+18); 459 super.move(x,y); 460 } 461 override public void relMove(int x,int y) { 462 spriteLayer.relMoveSprite(-1,x,y); 463 super.relMove(x,y); 464 } 465 override public void close() { 466 spriteLayer.removeSprite(-1); 467 cd.previewModeOn = false; 468 super.close; 469 } 470 471 } 472