1 /*
2  * Copyright (C) 2016-2017, by Laszlo Szeremi under the Boost license.
3  *
4  * Pixel Perfect Editor, graphics.outputScreen module
5  */
6 
7 module editor;
8 
9 import PixelPerfectEngine.graphics.outputScreen;
10 import PixelPerfectEngine.graphics.raster;
11 import PixelPerfectEngine.graphics.layers;
12 import PixelPerfectEngine.graphics.paletteMan;
13 import PixelPerfectEngine.extbmp.extbmp;
14 
15 import PixelPerfectEngine.graphics.bitmap;
16 import PixelPerfectEngine.graphics.draw;
17 //import collision;
18 import PixelPerfectEngine.system.inputHandler;
19 import PixelPerfectEngine.system.file;
20 import PixelPerfectEngine.system.etc;
21 import PixelPerfectEngine.system.config;
22 import PixelPerfectEngine.system.systemUtility;
23 import std.stdio;
24 import std.conv;
25 import core.stdc..string : memcpy;
26 //import derelict.sdl2.sdl;
27 import bindbc.sdl;
28 import PixelPerfectEngine.concrete.window;
29 import PixelPerfectEngine.concrete.eventChainSystem;
30 import PixelPerfectEngine.map.mapformat;
31 
32 //import converterdialog;
33 //import newLayerDialog;
34 import about;
35 import editorEvents;
36 public import layerlist;
37 public import materialList;
38 import document;
39 import rasterWindow;
40 import newTileLayer;
41 
42 public interface IEditor{
43 	public void onExit();
44 	public void newDocument();
45 	//public void newLayer();
46 	public void xmpToolkit();
47 	public void passActionEvent(Event e);
48 	public void createNewDocument(dstring name, int rX, int rY, int pal);
49 	//public void createNewLayer(string name, int type, int tX, int tY, int mX, int mY, int priority);
50 }
51 
52 public class NewDocumentDialog : Window{
53 	public IEditor ie;
54 	private TextBox[] textBoxes;
55 	public this(Coordinate size, dstring title){
56 		super(size, title);
57 	}
58 	public this(InputHandler inputhandler){
59 		this(Coordinate(10,10,220,150),"New Document"d);
60 
61 		Button[] buttons;
62 		Label[] labels;
63 		buttons ~= new Button("Ok", "ok", Coordinate(150,110,200,130));
64 
65 		labels ~= new Label("Name:","",Coordinate(5,20,80,39));
66 		labels ~= new Label("RasterX:","",Coordinate(5,40,80,59));
67 		labels ~= new Label("RasterY:","",Coordinate(5,60,80,79));
68 		labels ~= new Label("N. of colors:","",Coordinate(5,80,120,99));
69 		textBoxes ~= new TextBox("","name",Coordinate(81,20,200,39));
70 		textBoxes ~= new TextBox("","rX",Coordinate(121,40,200,59));
71 		textBoxes ~= new TextBox("","rY",Coordinate(121,60,200,79));
72 		textBoxes ~= new TextBox("","pal",Coordinate(121,80,200,99));
73 		addElement(buttons[0], EventProperties.MOUSE);
74 		foreach(WindowElement we; labels){
75 			addElement(we, EventProperties.MOUSE);
76 		}
77 		foreach(TextBox we; textBoxes){
78 			//we.addTextInputHandler(inputhandler);
79 			addElement(we, EventProperties.MOUSE);
80 		}
81 		buttons[0].onMouseLClickRel = &buttonOn_onMouseLClickRel;
82 	}
83 
84 	public void buttonOn_onMouseLClickRel(Event event){
85 		ie.createNewDocument(textBoxes[0].getText(), to!int(textBoxes[1].getText()), to!int(textBoxes[2].getText()), to!int(textBoxes[3].getText()));
86 
87 		parent.closeWindow(this);
88 	}
89 }
90 
91 public class EditorWindowHandler : WindowHandler, ElementContainer{
92 	private WindowElement[] elements, mouseC, keyboardC, scrollC;
93 	//private ListBox layerList, prop;
94 	//private ListBoxColumn[] propTL, propSL, propSLE;
95 	//private ListBoxColumn[] layerListE;
96 	public Label[] labels;
97 	private int[] propTLW, propSLW, propSLEW;
98 	public IEditor ie;
99 	//public bool layerList, materialList;
100 	public LayerList layerList;
101 	public MaterialList materialList;
102 
103 	//public InputHandler ih;
104 
105 	private BitmapDrawer output;
106 	public this(int sx, int sy, int rx, int ry,ISpriteLayer sl){
107 		super(sx,sy,rx,ry,sl);
108 		output = new BitmapDrawer(rx, ry);
109 		addBackground(output.output);
110 		propTLW = [40, 320];
111 		propSLW = [160, 320, 48, 64];
112 		propSLEW = [160, 320, 40, 56];
113 		WindowElement.popUpHandler = this;
114 		//openLayerList;
115 	}
116 	private void onLayerListClose(){
117 		layerList = null;
118 	}
119 	private void onMaterialListClose(){
120 		materialList = null;
121 	}
122 	public void clearArea(WindowElement sender){
123 
124 	}
125 	public void initGUI(){
126 		output.drawFilledRectangle(0, rasterX, 0, rasterY, 0x0005);
127 
128 		PopUpMenuElement[] menuElements;
129 		menuElements ~= new PopUpMenuElement("file", "FILE");
130 
131 		menuElements[0].setLength(7);
132 		menuElements[0][0] = new PopUpMenuElement("new", "New PPE map", "Ctrl + N");
133 		menuElements[0][1] = new PopUpMenuElement("newTemp", "New PPE map from template", "Ctrl + Shift + N");
134 		menuElements[0][2] = new PopUpMenuElement("load", "Load PPE map", "Ctrl + L");
135 		menuElements[0][3] = new PopUpMenuElement("save", "Save PPE map", "Ctrl + S");
136 		menuElements[0][4] = new PopUpMenuElement("saveAs", "Save PPE map as", "Ctrl + Shift + S");
137 		menuElements[0][5] = new PopUpMenuElement("saveTemp", "Save PPE map as template", "Ctrl + Shift + T");
138 		menuElements[0][6] = new PopUpMenuElement("exit", "Exit application", "Alt + F4");
139 
140 		menuElements ~= new PopUpMenuElement("edit", "EDIT");
141 
142 		menuElements[1].setLength(7);
143 		menuElements[1][0] = new PopUpMenuElement("undo", "Undo", "Ctrl + Z");
144 		menuElements[1][1] = new PopUpMenuElement("redo", "Redo", "Ctrl + Shift + Z");
145 		menuElements[1][2] = new PopUpMenuElement("copy", "Copy", "Ctrl + C");
146 		menuElements[1][3] = new PopUpMenuElement("cut", "Cut", "Ctrl + X");
147 		menuElements[1][4] = new PopUpMenuElement("paste", "Paste", "Ctrl + V");
148 		menuElements[1][5] = new PopUpMenuElement("editorSetup", "Editor Settings");
149 		menuElements[1][6] = new PopUpMenuElement("docSetup", "Document Settings");
150 
151 		menuElements ~= new PopUpMenuElement("view", "VIEW");
152 
153 		menuElements[2].setLength(2);
154 		menuElements[2][0] = new PopUpMenuElement("layerList", "Layers", "Alt + L");
155 		menuElements[2][1] = new PopUpMenuElement("materialList", "Materials", "Alt + M");
156 		//menuElements[2][2] = new PopUpMenuElement("layerTools", "Layer tools", "Alt + T");
157 
158 		menuElements ~= new PopUpMenuElement("layers", "LAYERS");
159 
160 		menuElements[3].setLength(4);
161 		menuElements[3][0] = new PopUpMenuElement("newLayer", "New layer", "Alt + N");
162 		menuElements[3][1] = new PopUpMenuElement("delLayer", "Delete layer", "Alt + Del");
163 		menuElements[3][2] = new PopUpMenuElement("impLayer", "Import layer", "Alt + Shift + I");
164 		menuElements[3][3] = new PopUpMenuElement("layerSrc", "Layer resources", "Alt + R");
165 
166 		menuElements ~= new PopUpMenuElement("tools", "TOOLS");
167 
168 		menuElements[4].setLength(2);
169 		menuElements[4][0] = new PopUpMenuElement("xmpTool", "XMP Toolkit", "Alt + X");
170 		menuElements[4][1] = new PopUpMenuElement("mapXMLEdit", "Edit map as XML", "Ctrl + Alt + X");
171 		//menuElements[4][2] = new PopUpMenuElement("bmfontimport", "Import BMFont File");
172 
173 		menuElements ~= new PopUpMenuElement("help", "HELP");
174 
175 		menuElements[5].setLength(2);
176 		menuElements[5][0] = new PopUpMenuElement("helpFile", "Content", "F1");
177 		menuElements[5][1] = new PopUpMenuElement("about", "About");
178 
179 
180 		MenuBar mb = new MenuBar("menubar",Coordinate(0,0,848,16),menuElements);
181 		addElement(mb, EventProperties.MOUSE);
182 		mb.onMouseLClickPre = &actionEvent;
183 		foreach(WindowElement we; labels){
184 			addElement(we, 0);
185 		}
186 		foreach(WindowElement we; elements){
187 			we.draw();
188 		}
189 	}
190 
191 	public override StyleSheet getStyleSheet(){
192 		return defaultStyle;
193 	}
194 
195 	public void addElement(WindowElement we, int eventProperties){
196 		elements ~= we;
197 		we.elementContainer = this;
198 		//we.al ~= this;
199 		if((eventProperties & EventProperties.KEYBOARD) == EventProperties.KEYBOARD){
200 			keyboardC ~= we;
201 		}
202 		if((eventProperties & EventProperties.MOUSE) == EventProperties.MOUSE){
203 			mouseC ~= we;
204 		}
205 		if((eventProperties & EventProperties.SCROLL) == EventProperties.SCROLL){
206 			scrollC ~= we;
207 		}
208 	}
209 	public void openLayerList() {
210 		if(!layerList){
211 			layerList = new LayerList(0, 16, &onLayerListClose);
212 			addWindow(layerList);
213 		}
214 	}
215 	public void openMaterialList() {
216 
217 		if(!materialList){
218 			materialList = new MaterialList(0, 16 + 213, &onMaterialListClose);
219 			//addWindow(new MaterialList(848 - 98, 16 + 213, &onMaterialListClose));
220 			addWindow(materialList);
221 		}
222 	}
223 	public void actionEvent(Event event){
224 		switch(event.source){
225 			case "exit":
226 				ie.onExit;
227 				break;
228 			case "new":
229 				ie.newDocument;
230 				break;
231 			case "xmpTool":
232 				ie.xmpToolkit();
233 				break;
234 			case "about":
235 				Window w = new AboutWindow();
236 				addWindow(w);
237 				w.relMove(30,30);
238 				break;
239 			case "layerList":
240 				openLayerList;
241 					//addWindow(new LayerList(848 - 98, 16, &onLayerListClose));
242 				//layerList = true;
243 				break;
244 			case "materialList":
245 				openMaterialList;
246 				//materialList = true;
247 				break;
248 			default:
249 				ie.passActionEvent(event);
250 				break;
251 		}
252 	}
253 
254 	public override void drawUpdate(WindowElement sender){
255 		output.insertBitmap(sender.getPosition().left,sender.getPosition().top,sender.output.output);
256 	}
257 
258 	override public void passMouseEvent(int x,int y,int state,ubyte button) {
259 		foreach(WindowElement e; mouseC){
260 			if(e.getPosition().left < x && e.getPosition().right > x && e.getPosition().top < y && e.getPosition().bottom > y){
261 				e.onClick(x - e.getPosition().left, y - e.getPosition().top, state, button);
262 				return;
263 			}
264 		}
265 	}
266 	public override void passScrollEvent(int wX, int wY, int x, int y){
267 		foreach(WindowElement e; scrollC){
268 			if(e.getPosition().left < wX && e.getPosition().right > wX && e.getPosition().top < wX && e.getPosition().bottom > wY){
269 
270 				e.onScroll(y, x, wX, wY);
271 
272 				return;
273 			}
274 		}
275 	}
276 	public Coordinate getAbsolutePosition(WindowElement sender){
277 		return sender.position;
278 	}
279 }
280 
281 public enum PlacementMode : uint{
282 	NULL		=	0,
283 	NORMAL		=	1,
284 	VOIDFILL	=	2,
285 	OVERWRITE	=	3,
286 
287 }
288 
289 public class Editor : InputListener, MouseListener, IEditor, SystemEventListener {
290 	public OutputScreen[] ow;
291 	public Raster rasters;
292 	public InputHandler input;
293 	public TileLayer[int] backgroundLayers;
294 	//public TileLayer8Bit[int] backgroundLayers8;
295 	//public TileLayer32Bit[int] backgroundLayers32;
296 	public Layer[int] layers;
297 	public wchar selectedTile;
298 	public BitmapAttrib selectedTileAttrib;
299 	public int selectedLayer;
300 	public SpriteLayer windowing;
301 	public SpriteLayer bitmapPreview;
302 	public bool onexit, exitDialog, newLayerDialog, mouseState, rasterRefresh;
303 	public Window test;
304 	public EditorWindowHandler wh;
305 	public EffectLayer selectionLayer;
306 	//public ForceFeedbackHandler ffb;
307 	private uint[5] framecounter;
308 	public char[40] windowTitle;
309 	public ConfigurationProfile configFile;
310 	private int mouseX, mouseY;
311 	private Coordinate selection, selectedTiles;
312 	public PlacementMode pm;
313 	public UndoableStack undoStack;
314 	public PaletteManager palman;
315 	public MapDocument[dstring] documents;
316 	public MapDocument selDoc;
317 
318 	public void mouseButtonEvent(Uint32 which, Uint32 timestamp, Uint32 windowID, Uint8 button, Uint8 state, Uint8 clicks, Sint32 x, Sint32 y){
319 
320 		setRasterRefresh;
321 	}
322 	public void mouseWheelEvent(uint type, uint timestamp, uint windowID, uint which, int x, int y, int wX, int wY){
323 		setRasterRefresh;
324 	}
325 	public void mouseMotionEvent(uint timestamp, uint windowID, uint which, uint state, int x, int y, int relX, int relY){
326 		setRasterRefresh;
327 	}
328 	public void keyPressed(string ID, Uint32 timestamp, Uint32 devicenumber, Uint32 devicetype){
329 		switch(ID){
330 			case "nextLayer":
331 				break;
332 			case "prevLayer":
333 				break;
334 			case "scrollUp":
335 				break;
336 			case "scrollDown":
337 				break;
338 			case "scrollLeft":
339 				break;
340 			case "scrollRight":
341 				break;
342 			case "quit":
343 				break;
344 			case "xmpTool":
345 				break;
346 			case "load":
347 				break;
348 			case "save":
349 				break;
350 			case "saveAs":
351 				break;
352 			default:
353 				break;
354 		}
355 	}
356 	public void keyReleased(string ID, Uint32 timestamp, Uint32 devicenumber, Uint32 devicetype){}
357 	public void passActionEvent(Event e){
358 		switch(e.source){
359 			case "saveas":
360 				FileDialog fd = new FileDialog("Save document as","docSave",&actionEvent,[FileDialog.FileAssociationDescriptor("PPE map file", ["*.xmf"])],".\\",true);
361 				wh.addWindow(fd);
362 				break;
363 			case "load":
364 				FileDialog fd = new FileDialog("Load document","docLoad",&actionEvent,[FileDialog.FileAssociationDescriptor("PPE map file", ["*.xmf"])],".\\",false);
365 				wh.addWindow(fd);
366 				break;
367 			case "newLayer":
368 				//NewLayerDialog nld = new NewLayerDialog(this);
369 				//wh.addWindow(nld);
370 				break;
371 			case "layerTools":
372 				//TileLayerEditor tle = new TileLayerEditor(this);
373 				//wh.addWindow(tle);
374 				break;
375 			default: break;
376 		}
377 	}
378 	/*public void actionEvent(string source, int type, int value, wstring message){
379 
380 
381 		if(source == "file"){
382 
383 		}
384 	}
385 	public void actionEvent(string source, string subSource, int type, int value, wstring message){
386 		switch(subSource){
387 			case "exitdialog":
388 				if(source == "Yes"){
389 					onexit = true;
390 				}
391 				break;
392 			default: break;
393 		}
394 	}*/
395 	public void actionEvent(Event event){
396 
397 		switch(event.subsource){
398 			case "exitdialog":
399 				if(event.source == "ok"){
400 					onexit = true;
401 				}
402 				break;
403 			case FileDialog.subsourceID:
404 				switch(event.source){
405 					case "docSave":
406 						break;
407 					case "docLoad":
408 						string path = event.path;
409 						path ~= event.filename;
410 						//document = new ExtendibleMap(path);
411 						break;
412 					default: break;
413 				}
414 				break;
415 			default:
416 				break;
417 		}
418 	}
419 	public void onQuit(){onExit();}
420 	public void controllerRemoved(uint ID){}
421 	public void controllerAdded(uint ID){}
422 	public void xmpToolkit(){
423 		//wh.addWindow(new ConverterDialog(input,bitmapPreview));
424 	}
425 	/*public void placeObject(int x, int y){
426 		if(backgroundLayers.get(selectedLayer, null) !is null){
427 			int sX = backgroundLayers[selectedLayer].getSX(), sY = backgroundLayers[selectedLayer].getSY();
428 			sX += x;
429 			sY += y;
430 			sX /= backgroundLayers[selectedLayer].getTileWidth();
431 			sY /= backgroundLayers[selectedLayer].getTileHeight();
432 			if(sX >= 0 && sY >= 0){
433 				backgroundLayers[selectedLayer].writeMapping(sX, sY, selectedTile);
434 			}
435 		}
436 	}*/
437 	public this(string[] args){
438 		pm = PlacementMode.OVERWRITE;
439 		ConfigurationProfile.setVaultPath("ZILtoid1991","PixelPerfectEditor");
440 		configFile = new ConfigurationProfile();
441 
442 		windowing = new SpriteLayer(LayerRenderingMode.COPY);
443 		bitmapPreview = new SpriteLayer();
444 
445 		wh = new EditorWindowHandler(1696,960,848,480,windowing);
446 		wh.ie = this;
447 
448 		//Initialize the Concrete framework
449 		INIT_CONCRETE(wh);
450 		//Initialize custom GUI elements
451 		{
452 			Bitmap8Bit[] customGUIElems = loadBitmapSheetFromFile!Bitmap8Bit("../system/concreteGUIE1.tga", 16, 16);
453 			WindowElement.styleSheet.setImage(customGUIElems[0], "menuButtonA");
454 			WindowElement.styleSheet.setImage(customGUIElems[1], "menuButtonB");
455 			WindowElement.styleSheet.setImage(customGUIElems[2], "fullSizeButtonA");
456 			WindowElement.styleSheet.setImage(customGUIElems[3], "fullSizeButtonB");
457 			WindowElement.styleSheet.setImage(customGUIElems[4], "smallSizeButtonA");
458 			WindowElement.styleSheet.setImage(customGUIElems[5], "smallSizeButtonB");
459 			WindowElement.styleSheet.setImage(customGUIElems[6], "newDocumentButtonA");
460 			WindowElement.styleSheet.setImage(customGUIElems[7], "newDocumentButtonB");
461 			WindowElement.styleSheet.setImage(customGUIElems[8], "saveDocumentButtonA");
462 			WindowElement.styleSheet.setImage(customGUIElems[9], "saveDocumentButtonB");
463 			WindowElement.styleSheet.setImage(customGUIElems[10], "loadDocumentButtonA");
464 			WindowElement.styleSheet.setImage(customGUIElems[11], "loadDocumentButtonB");
465 			WindowElement.styleSheet.setImage(customGUIElems[12], "settingsButtonA");
466 			WindowElement.styleSheet.setImage(customGUIElems[13], "settingsButtonB");
467 			WindowElement.styleSheet.setImage(customGUIElems[14], "blankButtonA");
468 			WindowElement.styleSheet.setImage(customGUIElems[15], "blankButtonB");
469 		}
470 		/+{
471 			Bitmap8Bit[] customGUIElems = loadBitmapSheetFromFile!Bitmap8Bit("../system/concreteGUIE2.tga");
472 			WindowElement.styleSheet.setImage(customGUIElems[0], "");
473 			WindowElement.styleSheet.setImage(customGUIElems[1], "");
474 			WindowElement.styleSheet.setImage(customGUIElems[2], "");
475 			WindowElement.styleSheet.setImage(customGUIElems[3], "");
476 			WindowElement.styleSheet.setImage(customGUIElems[4], "");
477 			WindowElement.styleSheet.setImage(customGUIElems[5], "");
478 			WindowElement.styleSheet.setImage(customGUIElems[6], "");
479 			WindowElement.styleSheet.setImage(customGUIElems[7], "");
480 			WindowElement.styleSheet.setImage(customGUIElems[8], "");
481 			WindowElement.styleSheet.setImage(customGUIElems[9], "");
482 			WindowElement.styleSheet.setImage(customGUIElems[10], "");
483 			WindowElement.styleSheet.setImage(customGUIElems[11], "");
484 			WindowElement.styleSheet.setImage(customGUIElems[12], "");
485 			WindowElement.styleSheet.setImage(customGUIElems[13], "");
486 			WindowElement.styleSheet.setImage(customGUIElems[14], "");
487 			WindowElement.styleSheet.setImage(customGUIElems[15], "");
488 		}+/
489 		{
490 			Bitmap8Bit[] customGUIElems = loadBitmapSheetFromFile!Bitmap8Bit("../system/concreteGUIE3.tga", 16, 16);
491 			WindowElement.styleSheet.setImage(customGUIElems[0], "trashButtonA");
492 			WindowElement.styleSheet.setImage(customGUIElems[1], "trashButtonB");
493 			WindowElement.styleSheet.setImage(customGUIElems[2], "visibilityButtonA");
494 			WindowElement.styleSheet.setImage(customGUIElems[3], "visibilityButtonB");
495 			WindowElement.styleSheet.setImage(customGUIElems[4], "newTileLayerButtonA");
496 			WindowElement.styleSheet.setImage(customGUIElems[5], "newTileLayerButtonB");
497 			WindowElement.styleSheet.setImage(customGUIElems[6], "newSpriteLayerButtonA");
498 			WindowElement.styleSheet.setImage(customGUIElems[7], "newSpriteLayerButtonB");
499 			WindowElement.styleSheet.setImage(customGUIElems[8], "newTransformableTileLayerButtonA");
500 			WindowElement.styleSheet.setImage(customGUIElems[9], "newTransformableTileLayerButtonB");
501 			WindowElement.styleSheet.setImage(customGUIElems[10], "importLayerDataButtonA");
502 			WindowElement.styleSheet.setImage(customGUIElems[11], "importLayerDataButtonB");
503 			WindowElement.styleSheet.setImage(customGUIElems[12], "importMaterialDataButtonA");
504 			WindowElement.styleSheet.setImage(customGUIElems[13], "importMaterialDataButtonB");
505 			WindowElement.styleSheet.setImage(customGUIElems[14], "paletteButtonA");
506 			WindowElement.styleSheet.setImage(customGUIElems[15], "paletteButtonB");
507 		}
508 
509 		wh.initGUI();
510 
511 		input = new InputHandler();
512 		input.ml ~= this;
513 		input.ml ~= wh;
514 		input.il ~= this;
515 		input.sel ~= this;
516 		input.kb ~= KeyBinding(0, SDL_SCANCODE_ESCAPE, 0, "sysesc", Devicetype.KEYBOARD);
517 		WindowElement.inputHandler = input;
518 		//wh.ih = input;
519 		//ffb = new ForceFeedbackHandler(input);
520 
521 		//OutputWindow.setScalingQuality("2");
522 		//OutputWindow.setDriver("software");
523 		ow ~= new OutputScreen("Pixel Perfect Editor", 1696, 960);
524 
525 		rasters = new Raster(848, 480, ow[0], 0);
526 		ow[0].setMainRaster(rasters);
527 		rasters.addLayer(windowing, 0);
528 		rasters.addLayer(bitmapPreview, 1);
529 		//ISSUE: Copying the palette from StyleSheet.defaultPaletteForGUI doesn't work
530 		//SOLUTION: Load the palette from a file
531 		rasters.palette = loadPaletteFromFile("../system/concreteGUIE1.tga");
532 		//rasters[0].addRefreshListener(ow[0],0);
533 		WindowElement.onDraw = &setRasterRefresh;
534 		PopUpElement.onDraw = &setRasterRefresh;
535 		Window.onDrawUpdate = &setRasterRefresh;
536 		wh.openLayerList;
537 		wh.openMaterialList;
538 	}
539 	/**
540 	 * Opens a window to aks the user for the data on the new tile layer
541 	 */
542 	public void initNewTileLayer(){
543 		wh.addWindow(new NewTileLayerDialog(this));
544 	}
545 	/**
546 	 * Creates a new tile layer with the given data.
547 	 *
548 	 * file: Optional field. If given, it specifies the external file for binary map data. If it specifies an already
549 	 * existing file, then that file will be loaded. If null, then the map data will be embedded as a BASE64 chunk.
550 	 * tmplt: Optional field. Specifies the initial tile source data from a map file alongside with the name of the layer
551 	 */
552 	public void newTileLayer(int tX, int tY, int mX, int mY, dstring name, string file, string tmplt, bool embed) {
553 		selDoc.events.addToTop(new CreateTileLayerEvent(selDoc, tX, tY, mX, mY, name, file, tmplt, embed));
554 	}
555 	public void setRasterRefresh(){
556 		rasterRefresh = true;
557 	}
558 	public void whereTheMagicHappens(){
559 		//rasters.refresh();
560 		while(!onexit){
561 			input.test();
562 
563 			rasters.refresh();
564 
565 		}
566 		configFile.store();
567 	}
568 	public void onExit(){
569 
570 		exitDialog=true;
571 		DefaultDialog dd = new DefaultDialog(Coordinate(10,10,220,75), "exitdialog","Exit application", ["Are you sure?"],
572 				["Yes","No","Pls save"],["ok","close","save"]);
573 
574 		dd.output = &actionEvent;
575 		wh.addWindow(dd);
576 
577 	}
578 	public void newDocument(){
579 		NewDocumentDialog ndd = new NewDocumentDialog(input);
580 		ndd.ie = this;
581 		wh.addWindow(ndd);
582 	}
583 	public void createNewDocument(dstring name, int rX, int rY, int pal){
584 		import std.utf : toUTF8;
585 		MapDocument md = new MapDocument(toUTF8(name), rX, rY);
586 		RasterWindow w = new RasterWindow(rX, rY, rasters.palette.ptr, name, md);
587 		md.outputWindow = w;
588 		wh.addWindow(w);
589 		documents[name] = md;
590 		selDoc = md;
591 	}
592 }