1 /**
2 Copyright: Copyright (c) 2015-2016 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 
7 module gui;
8 
9 import std.algorithm;
10 import std.array;
11 import std.experimental.logger;
12 import std.format;
13 import std.process;
14 import std.range;
15 import std.stdio;
16 import std..string : format, fromStringz;
17 import std.typecons : Flag, Yes, No;
18 
19 import voxelman.math;
20 import derelict.glfw3.glfw3;
21 import derelict.imgui.imgui;
22 import derelict.opengl3.gl3;
23 import anchovy.glfwwindow;
24 import voxelman.imgui_glfw;
25 import voxelman.utils.libloader;
26 import voxelman.utils.textformatter;
27 import voxelman.utils.linebuffer;
28 
29 import launcher;
30 
31 
32 struct ItemList(T)
33 {
34 	T[]* items;
35 	size_t currentItem;
36 	bool hasSelected() @property {
37 		return currentItem < (*items).length;
38 	}
39 	T selected() @property {
40 		if (currentItem < (*items).length)
41 			return (*items)[currentItem];
42 		else if ((*items).length > 0)
43 			return (*items)[$-1];
44 		else
45 			return T.init;
46 	}
47 
48 	void update() {
49 		if (currentItem >= (*items).length)
50 			currentItem = (*items).length-1;
51 		if ((*items).length == 0)
52 			currentItem = 0;
53 	}
54 
55 	ref T opIndex(size_t i) {
56 		return (*items)[i];
57 	}
58 }
59 
60 struct LauncherGui
61 {
62 	bool show_test_window = true;
63 	bool show_another_window = false;
64 	float[3] clear_color = [0.3f, 0.4f, 0.6f];
65 	bool isRunning = true;
66 	ImguiState igState;
67 	GlfwWindow window;
68 
69 	Launcher launcher;
70 
71 	string pluginFolder = `./plugins`;
72 	string pluginPackFolder = `./pluginpacks`;
73 	string toolFolder = `./tools`;
74 	ItemList!(PluginInfo*) plugins;
75 
76 	void init()
77 	{
78 		import std.datetime : SysTime;
79 		import std.concurrency : Tid;
80 		class ConciseLogger : FileLogger {
81 			this(File file, const LogLevel lv = LogLevel.info) @safe {
82 				super(file, lv);
83 			}
84 
85 			override protected void beginLogMsg(string file, int line, string funcName,
86 				string prettyFuncName, string moduleName, LogLevel logLevel,
87 				Tid threadId, SysTime timestamp, Logger logger)
88 				@safe {}
89 		}
90 		//auto file = File(filename, "w");
91 		auto logger = new MultiLogger;
92 		//logger.insertLogger("fileLogger", new FileLogger(file));
93 		logger.insertLogger("stdoutLogger", new ConciseLogger(stdout));
94 		sharedLog = logger;
95 
96 		launcher.init();
97 
98 		playMenu.init(&launcher);
99 		codeMenu.init(&launcher);
100 		refresh();
101 
102 		window = new GlfwWindow();
103 		window.init(ivec2(820, 600), "Voxelman launcher");
104 		igState.init(window.handle);
105 		window.keyPressed.connect(&igState.onKeyPressed);
106 		window.keyReleased.connect(&igState.onKeyReleased);
107 		window.charEntered.connect(&igState.charCallback);
108 		window.mousePressed.connect(&igState.onMousePressed);
109 		window.mouseReleased.connect(&igState.onMouseReleased);
110 		window.wheelScrolled.connect((dvec2 s) => igState.scrollCallback(s.y));
111 
112 		if (window is null)
113 			isRunning = false;
114 
115 		setStyle();
116 	}
117 
118 	void run()
119 	{
120 		DerelictGL3.load();
121 		loadLib(DerelictGLFW3, "", "glfw3");
122 		loadLib(DerelictImgui, "", "cimgui");
123 
124 		init();
125 
126 		while(isRunning)
127 		{
128 			if (glfwWindowShouldClose(window.handle) && !launcher.anyProcessesRunning)
129 				isRunning = false;
130 			else
131 				glfwSetWindowShouldClose(window.handle, false);
132 			update();
133 			render();
134 		}
135 
136 		close();
137 	}
138 
139 	void refresh()
140 	{
141 		launcher.setRootPath(pluginFolder, pluginPackFolder, toolFolder);
142 		launcher.refresh();
143 		plugins.items = &launcher.plugins;
144 		playMenu.refresh();
145 		codeMenu.refresh();
146 	}
147 
148 	void update()
149 	{
150 		launcher.update();
151 		window.processEvents();
152 		igState.newFrame();
153 		doGui();
154 
155 		import core.thread;
156 		Thread.sleep(15.msecs);
157 	}
158 
159 	void render()
160 	{
161 		ImGuiIO* io = igGetIO();
162 		glViewport(0, 0, cast(int)io.DisplaySize.x, cast(int)io.DisplaySize.y);
163 		glClearColor(clear_color[0], clear_color[1], clear_color[2], 0);
164 		glClear(GL_COLOR_BUFFER_BIT);
165 		igState.render();
166 		glfwSwapBuffers(window.handle);
167 	}
168 
169 	void close()
170 	{
171 		window.releaseWindow;
172 		igState.shutdown();
173 		glfwTerminate();
174 	}
175 
176 	void doGui()
177 	{
178 		//igPushStyleVar(ImGuiStyleVar_FrameRounding, 0f);
179 		//igGetStyle().FrameRounding = 0.0f;
180 		igSetNextWindowPos(ImVec2(0,0));
181 		igSetNextWindowSize(igGetIO().DisplaySize);
182 		if (igBegin("Main", null, mainWindowFlags))
183 		{
184 			drawMainMenu();
185 			igSameLine();
186 			drawMenuContent();
187 
188 			igEnd();
189 		}
190 		//igPopStyleVar();
191 		//igShowTestWindow(null);
192 	}
193 
194 	enum SelectedMenu
195 	{
196 		play,
197 		code,
198 		conf
199 	}
200 
201 	SelectedMenu selectedMenu;
202 	PlayMenu playMenu;
203 	CodeMenu codeMenu;
204 
205 	void drawMainMenu()
206 	{
207 		igBeginGroup();
208 
209 		menuEntry("Play", SelectedMenu.play);
210 		menuEntry("Code", SelectedMenu.code);
211 		menuEntry("Conf", SelectedMenu.conf);
212 
213 		//if (igButton("Refresh"))
214 		//	refresh();
215 		igSpacing();
216 		if (igButton("Exit"))
217 			isRunning = false;
218 		igEndGroup();
219 	}
220 
221 	void menuEntry(string text, SelectedMenu select)
222 	{
223 		ImGuiStyle* style = igGetStyle();
224 		const ImVec4 color       = style.Colors[ImGuiCol_Button];
225 		const ImVec4 colorActive = style.Colors[ImGuiCol_ButtonActive];
226 		const ImVec4 colorHover  = style.Colors[ImGuiCol_ButtonHovered];
227 
228 		if (selectedMenu == select)
229 		{
230 			style.Colors[ImGuiCol_Button]        = colorActive;
231 			style.Colors[ImGuiCol_ButtonActive]  = colorActive;
232 			style.Colors[ImGuiCol_ButtonHovered] = colorActive;
233 		}
234 		else
235 		{
236 			style.Colors[ImGuiCol_Button]        = color;
237 			style.Colors[ImGuiCol_ButtonActive]  = colorActive;
238 			style.Colors[ImGuiCol_ButtonHovered] = colorHover;
239 		}
240 
241 		if (igButton(text.ptr)) selectedMenu = select;
242 
243 		style.Colors[ImGuiCol_Button] =         color;
244 		style.Colors[ImGuiCol_ButtonActive] =   colorActive;
245 		style.Colors[ImGuiCol_ButtonHovered] =  colorHover;
246 	}
247 
248 	void drawMenuContent()
249 	{
250 		final switch(selectedMenu) with(SelectedMenu)
251 		{
252 			case play:
253 				playMenu.draw();
254 				break;
255 			case code:
256 				codeMenu.draw();
257 				break;
258 			case conf:
259 				break;
260 		}
261 	}
262 }
263 
264 struct PlayMenu
265 {
266 	enum SelectedMenu
267 	{
268 		worlds,
269 		connect,
270 		newGame,
271 	}
272 	Launcher* launcher;
273 	SelectedMenu selectedMenu;
274 	ItemList!(PluginPack*) pluginPacks;
275 	ItemList!(ServerInfo*) servers;
276 	ItemList!(SaveInfo*) saves;
277 	AddServerDialog addServerDlg;
278 	NewSaveDialog newSaveDlg;
279 
280 	void init(Launcher* launcher)
281 	{
282 		this.launcher = launcher;
283 		addServerDlg.launcher = launcher;
284 		newSaveDlg.launcher = launcher;
285 	}
286 
287 	void refresh()
288 	{
289 		pluginPacks.items = &launcher.pluginPacks;
290 		servers.items = &launcher.servers;
291 		saves.items = &launcher.saves;
292 	}
293 
294 	void draw()
295 	{
296 		pluginPacks.update();
297 		servers.update();
298 		saves.update();
299 		igBeginGroup();
300 
301 		if (igButton("Worlds##Play"))
302 			selectedMenu = SelectedMenu.worlds;
303 		igSameLine();
304 		if (igButton("Connect##Play"))
305 			selectedMenu = SelectedMenu.connect;
306 		//if (igButton("New##Play"))
307 		//	selectedMenu = SelectedMenu.newGame;
308 		//igSameLine();
309 
310 		final switch(selectedMenu)
311 		{
312 			case SelectedMenu.worlds:
313 				drawWorlds(); break;
314 			case SelectedMenu.connect:
315 				drawConnect(); break;
316 			case SelectedMenu.newGame:
317 				drawNewGame(); break;
318 		}
319 
320 		igEndGroup();
321 	}
322 
323 	void drawNewGame()
324 	{
325 		string pluginpack = "default";
326 		if (auto pack = pluginPacks.selected)
327 			pluginpack = pack.id;
328 
329 		// ------------------------ PACKAGES -----------------------------------
330 		igBeginChild("packs", ImVec2(100, -igGetItemsLineHeightWithSpacing()), true);
331 			foreach(int i, pluginPack; *pluginPacks.items)
332 			{
333 				igPushIdInt(cast(int)i);
334 				immutable bool itemSelected = (i == pluginPacks.currentItem);
335 
336 				if (igSelectable(pluginPack.id.ptr, itemSelected))
337 					pluginPacks.currentItem = i;
338 
339 				igPopId();
340 			}
341 		igEndChild();
342 
343 		igSameLine();
344 
345 		// ------------------------ PLUGINS ------------------------------------
346 		if (pluginPacks.hasSelected)
347 		{
348 			igBeginChild("pack's plugins", ImVec2(220, -igGetItemsLineHeightWithSpacing()), true);
349 				foreach(int i, plugin; pluginPacks.selected.plugins)
350 				{
351 					igPushIdInt(cast(int)i);
352 					igTextUnformatted(plugin.id.ptr, plugin.id.ptr+plugin.id.length);
353 					igPopId();
354 				}
355 			igEndChild();
356 		}
357 	}
358 
359 	void drawConnect()
360 	{
361 		igBeginChild("Servers", ImVec2(400, -igGetItemsLineHeightWithSpacing()), true);
362 			foreach(int i, server; *servers.items)
363 			{
364 				igPushIdInt(cast(int)i);
365 				immutable bool itemSelected = (i == servers.currentItem);
366 
367 				if (igSelectable(server.name.ptr, itemSelected))
368 					servers.currentItem = i;
369 				igPopId();
370 			}
371 		igEndChild();
372 
373 		if (addServerDlg.show())
374 		{
375 			refresh();
376 		}
377 
378 		if (servers.hasSelected)
379 		{
380 			igSameLine();
381 			if (igButton("Remove##Servers"))
382 				launcher.removeServer(servers.currentItem);
383 			igSameLine();
384 			if (igButton("Connect"))
385 			{
386 				launcher.connect(servers.selected, pluginPacks.selected);
387 			}
388 		}
389 	}
390 
391 	void drawWorlds()
392 	{
393 		enum tableWidth = 300;
394 		igBeginChild("Saves", ImVec2(tableWidth, -igGetItemsLineHeightWithSpacing()), true);
395 		igColumns(2);
396 		igSetColumnOffset(1, tableWidth - 90);
397 			foreach(int i, save; *saves.items)
398 			{
399 				igPushIdInt(cast(int)i);
400 				immutable bool itemSelected = (i == saves.currentItem);
401 
402 				if (igSelectable(save.name.ptr, itemSelected, ImGuiSelectableFlags_SpanAllColumns))
403 					saves.currentItem = i;
404 				igNextColumn();
405 				igTextUnformatted(save.displaySize.ptr, save.displaySize.ptr+save.displaySize.length);
406 				igNextColumn();
407 				igPopId();
408 			}
409 		igColumns(1);
410 		igEndChild();
411 
412 		size_t newSaveIndex;
413 		if (newSaveDlg.show(newSaveIndex)) {
414 			refresh();
415 			saves.currentItem = newSaveIndex;
416 		}
417 		igSameLine();
418 
419 		if (saves.hasSelected)
420 		{
421 			if (igButton("Delete##Saves"))
422 				igOpenPopup("Confirm");
423 			if (igBeginPopupModal("Confirm", null, ImGuiWindowFlags_AlwaysAutoResize))
424 			{
425 				if (igButton("Delete##Confirm"))
426 				{
427 					launcher.deleteSave(saves.currentItem);
428 					refresh();
429 					igCloseCurrentPopup();
430 				}
431 				igSameLine();
432 				if (igButton("Cancel##Confirm"))
433 					igCloseCurrentPopup();
434 				igEndPopup();
435 			}
436 		}
437 
438 		igSameLine();
439 		if (igButton("Refresh##Saves")) {
440 			launcher.refreshSaves();
441 			refresh();
442 		}
443 
444 		if (saves.hasSelected)
445 		{
446 			igSameLine();
447 			igSetCursorPosX(tableWidth - 50);
448 			if (igButton("Server##Saves"))
449 			{
450 				launcher.startServer(pluginPacks.selected, saves.selected);
451 			}
452 			igSameLine();
453 			igSetCursorPosX(tableWidth + 10);
454 			if (igButton("Start##Saves"))
455 			{
456 				launcher.startCombined(pluginPacks.selected, saves.selected);
457 			}
458 		}
459 	}
460 }
461 
462 struct NewSaveDialog
463 {
464 	char[128] saveInputBuffer;
465 	Launcher* launcher;
466 
467 	bool show(out size_t newSaveIndex)
468 	{
469 		bool result;
470 		if (igButton("New"))
471 			igOpenPopup("New world");
472 		if (igBeginPopupModal("New world", null, ImGuiWindowFlags_AlwaysAutoResize))
473 		{
474 			bool entered;
475 			if (igInputText("World name", saveInputBuffer.ptr, saveInputBuffer.length, ImGuiInputTextFlags_EnterReturnsTrue))
476 			{
477 				entered = true;
478 			}
479 
480 			if (igButton("Create") || entered)
481 			{
482 				newSaveIndex = launcher.createSave(saveInputBuffer.fromCString);
483 				resetFields();
484 
485 				igCloseCurrentPopup();
486 				result = true;
487 			}
488 			igSameLine();
489 			if (igButton("Cancel"))
490 				igCloseCurrentPopup();
491 
492 			igEndPopup();
493 		}
494 		return result;
495 	}
496 
497 	void resetFields()
498 	{
499 		saveInputBuffer[] = '\0';
500 	}
501 }
502 
503 struct AddServerDialog
504 {
505 	char[128] serverInputBuffer;
506 	char[16] ipAddress;
507 	int port = DEFAULT_PORT;
508 	Launcher* launcher;
509 
510 	bool show()
511 	{
512 		if (igButton("Add"))
513 			igOpenPopup("add");
514 		if (igBeginPopupModal("add", null, ImGuiWindowFlags_AlwaysAutoResize))
515 		{
516 			igInputText("Server name", serverInputBuffer.ptr, serverInputBuffer.length);
517 			igInputText("IP/port", ipAddress.ptr, ipAddress.length, ImGuiInputTextFlags_CharsDecimal);
518 			igSameLine();
519 			igInputInt("##port", &port);
520 			port = clamp(port, 0, ushort.max);
521 
522 			if (igButton("Add"))
523 			{
524 				launcher.addServer(ServerInfo(
525 					serverInputBuffer.fromCString(),
526 					ipAddress.fromCString(),
527 					cast(ushort)port));
528 				resetFields();
529 
530 				igCloseCurrentPopup();
531 				return true;
532 			}
533 			igSameLine();
534 			if (igButton("Cancel"))
535 				igCloseCurrentPopup();
536 
537 			igEndPopup();
538 		}
539 		return false;
540 	}
541 
542 	void resetFields()
543 	{
544 		Launcher* l = launcher;
545 		this = AddServerDialog();
546 		launcher = l;
547 	}
548 }
549 
550 import std.traits : Parameters;
551 auto withWidth(float width, alias func)(auto ref Parameters!func args)
552 {
553 	scope(exit) igPopItemWidth();
554 	igPushItemWidth(width);
555 	return func(args);
556 }
557 
558 extern (C)
559 bool itemGetter(T)(void* itemList, int idx, const(char)** out_text)
560 {
561 	auto il = cast(T*)itemList;
562 	*out_text = (*il.items)[idx].guiName.ptr;
563 	return true;
564 }
565 
566 struct CodeMenu
567 {
568 	Launcher* launcher;
569 	ItemList!(PluginPack*) pluginPacks;
570 	ItemList!(SaveInfo*) saves;
571 
572 	void init(Launcher* launcher)
573 	{
574 		this.launcher = launcher;
575 	}
576 
577 	void refresh()
578 	{
579 		pluginPacks.items = &launcher.pluginPacks;
580 		saves.items = &launcher.saves;
581 	}
582 
583 	void draw()
584 	{
585 		igBeginGroup();
586 		withWidth!(150, igCombo3)(
587 			"Pack",
588 			cast(int*)&pluginPacks.currentItem,
589 			&itemGetter!(ItemList!(PluginPack*)), &pluginPacks,
590 			cast(int)pluginPacks.items.length, -1);
591 		igSameLine();
592 		withWidth!(150, igCombo3)(
593 			"Save",
594 			cast(int*)&saves.currentItem,
595 			&itemGetter!(ItemList!(SaveInfo*)), &saves,
596 			cast(int)saves.items.length, -1);
597 		igSameLine();
598 		startButtons(launcher, pluginPacks.selected, saves.selected);
599 
600 		float areaHeight = igGetWindowHeight() - igGetCursorPosY() - 10;
601 
602 		enum minItemHeight = 160;
603 		size_t numJobs = launcher.jobs.length;
604 		float itemHeight = (numJobs) ? areaHeight / numJobs : minItemHeight;
605 		if (itemHeight < minItemHeight) itemHeight = minItemHeight;
606 		foreach(job; launcher.jobs) drawJobLog(job, itemHeight);
607 
608 		igEndGroup();
609 	}
610 }
611 
612 void startButtons(Launcher* launcher, PluginPack* pack, SaveInfo* save)
613 {
614 	static JobParams params;
615 	if (pack) params.runParameters["pack"] = pack.id;
616 	if (save) params.runParameters["world_name"] = save.name;
617 
618 	params.appType = AppType.client;
619 	if (igButton("Client")) launcher.createJob(params); igSameLine();
620 
621 	params.appType = AppType.server;
622 	if (igButton("Server")) launcher.createJob(params); igSameLine();
623 
624 	params.appType = AppType.combined;
625 	if (igButton("Combined")) launcher.createJob(params);
626 }
627 
628 void jobParams(JobParams* params)
629 {
630 	igCheckbox("nodeps", cast(bool*)&params.nodeps); igSameLine();
631 	igCheckbox("force", cast(bool*)&params.force); igSameLine();
632 	igCheckbox("x64", cast(bool*)&params.arch64); igSameLine();
633 	//igCheckbox("release", cast(bool*)&params.release); igSameLine();
634 
635 	withWidth!(60, igCombo2)("##buildType", cast(int*)&params.buildType, buildTypeUiSelectionString.ptr, 4); igSameLine();
636 	withWidth!(40, igCombo2)("##compiler", cast(int*)&params.compiler, compilerUiSelectionString.ptr, 2);
637 }
638 
639 void drawJobLog(J)(J* job, float height)
640 {
641 	igPushIdPtr(job);
642 	assert(job.title.ptr);
643 	auto state = jobStateString(job);
644 	auto textPtrs = makeFormattedTextPtrs("%s %s\0", state, job.title);
645 
646 	igBeginChildEx(igGetIdPtr(job), ImVec2(0, height), true, ImGuiWindowFlags_HorizontalScrollbar);
647 		igTextUnformatted(textPtrs.start, textPtrs.end-1);
648 		igSameLine();
649 		jobParams(&job.params);
650 		igSameLine();
651 		drawActionButtons(job);
652 		if (job.command)
653 		{
654 			igPushItemWidth(-1);
655 			igInputText("", cast(char*)job.command.ptr, job.command.length, ImGuiInputTextFlags_ReadOnly);
656 			igPopItemWidth();
657 		}
658 		job.messageWindow.draw();
659 	igEndChild();
660 
661 	igPopId();
662 }
663 
664 void drawActionButtons(J)(J* job)
665 {
666 	if (igButton("Clear")) job.messageWindow.lineBuffer.clear();
667 	if (!job.isRunning && !job.needsRestart) {
668 		igSameLine();
669 		if (igButton("Close")) job.needsClose = true;
670 		igSameLine();
671 
672 		int jobType = int.max;
673 		if (igButton(" Run ")) jobType = JobType.run; igSameLine();
674 		if (igButton("Build")) jobType = JobType.compile; igSameLine();
675 		if (igButton(" B&R ")) jobType = JobType.compileAndRun;
676 		if (jobType != int.max)
677 		{
678 			job.needsRestart = true;
679 			job.params.jobType = cast(JobType)jobType;
680 		}
681 	} else {
682 		igSameLine();
683 		if (igButton("Stop")) job.sendCommand("stop");
684 	}
685 }
686 
687 void setStyle()
688 {
689 	ImGuiStyle* style = igGetStyle();
690 	style.Colors[ImGuiCol_Text]                  = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
691 	style.Colors[ImGuiCol_WindowBg]              = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
692 	style.Colors[ImGuiCol_Border]                = ImVec4(0.00f, 0.00f, 0.20f, 0.65f);
693 	style.Colors[ImGuiCol_BorderShadow]          = ImVec4(0.00f, 0.00f, 0.00f, 0.12f);
694 	style.Colors[ImGuiCol_FrameBg]               = ImVec4(0.80f, 0.80f, 0.80f, 0.39f);
695 	style.Colors[ImGuiCol_MenuBarBg]             = ImVec4(1.00f, 1.00f, 1.00f, 0.80f);
696 	style.Colors[ImGuiCol_ScrollbarBg]           = ImVec4(0.47f, 0.47f, 0.47f, 0.00f);
697 	style.Colors[ImGuiCol_ScrollbarGrab]         = ImVec4(0.55f, 0.55f, 0.55f, 1.00f);
698 	style.Colors[ImGuiCol_ScrollbarGrabHovered]  = ImVec4(0.55f, 0.55f, 0.55f, 1.00f);
699 	style.Colors[ImGuiCol_ScrollbarGrabActive]   = ImVec4(0.55f, 0.55f, 0.55f, 1.00f);
700 	style.Colors[ImGuiCol_ComboBg]               = ImVec4(0.80f, 0.80f, 0.80f, 1.00f);
701 	style.Colors[ImGuiCol_CheckMark]             = ImVec4(0.36f, 0.40f, 0.71f, 0.60f);
702 	style.Colors[ImGuiCol_SliderGrab]            = ImVec4(0.52f, 0.56f, 1.00f, 0.60f);
703 	style.Colors[ImGuiCol_SliderGrabActive]      = ImVec4(0.36f, 0.40f, 0.71f, 0.60f);
704 	style.Colors[ImGuiCol_Button]                = ImVec4(0.52f, 0.56f, 1.00f, 0.60f);
705 	style.Colors[ImGuiCol_ButtonHovered]         = ImVec4(0.43f, 0.46f, 0.82f, 0.60f);
706 	style.Colors[ImGuiCol_ButtonActive]          = ImVec4(0.37f, 0.40f, 0.71f, 0.60f);
707 	style.Colors[ImGuiCol_TooltipBg]             = ImVec4(0.86f, 0.86f, 0.86f, 0.90f);
708 	//style.Colors[ImGuiCol_ModalWindowDarkening]  = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
709 	style.WindowFillAlphaDefault = 1.0f;
710 }
711 
712 enum mainWindowFlags = ImGuiWindowFlags_NoTitleBar |
713 	ImGuiWindowFlags_NoResize |
714 	ImGuiWindowFlags_NoMove |
715 	ImGuiWindowFlags_NoCollapse |
716 	ImGuiWindowFlags_NoSavedSettings;
717 	//ImGuiWindowFlags_MenuBar;