private void OnGUI() {
			
			GUI.enabled = !EditorApplication.isCompiling;

			if (FlowSystemEditorWindow.defaultSkin == null) FlowSystemEditorWindow.defaultSkin = Resources.Load("UI.Windows/Flow/Styles/Skin" + (EditorGUIUtility.isProSkin == true ? "Dark" : "Light")) as GUISkin;
			
			if (this.guiDrawer == null) this.guiDrawer = new GUIDrawer(this);
			if (this.guiSplash == null) this.guiSplash = new FlowSplash(this);
			if (this.zoomDrawer == null) this.zoomDrawer = new EditorZoomArea();

			if (this.guiSplash.Draw() == false) {

				return;

			}

			//var draw = !FlowSceneView.IsActive();
			
			//if (draw == true) {
			
			this.contentRect = this.position;
			this.contentRect.x = 0f;
			this.contentRect.y = 0f;
			this.contentRect.width = 10000f;
			this.contentRect.height = 10000f;
			this.contentRect.height -= scrollSize;

			var hasData = FlowSystem.HasData();
			if (hasData == true) {

				var oldEnabled = GUI.enabled;
				GUI.enabled = FlowSystem.HasData() && GUI.enabled;
				this.DrawToolbar();
				GUI.enabled = oldEnabled;
				
				this.DrawSettings(TOOLBAR_HEIGHT);
				
				IEnumerable<FlowWindow> windows = null;
				IEnumerable<FlowWindow> containers = null;
				if (hasData == true) {
					
					windows = FlowSystem.GetWindows();
					containers = FlowSystem.GetContainers();
					
				}
				
				this.scrollRect = this.position;
				this.scrollRect.x = SETTINGS_WIDTH;
				this.scrollRect.y = TOOLBAR_HEIGHT;
				this.scrollRect.width -= SETTINGS_WIDTH;
				this.scrollRect.height -= TOOLBAR_HEIGHT;
				
				var scrollPos = FlowSystem.GetScrollPosition();
				if (scrollPos.x > 0f || scrollPos.y > 0f) scrollPos = -new Vector2(this.contentRect.width * 0.5f - this.scrollRect.width * 0.5f, this.contentRect.height * 0.5f - this.scrollRect.height * 0.5f);
				//FlowSystem.SetScrollPosition(GUI.BeginScrollView(this.scrollRect, scrollPos, this.contentRect));
				{

					//this.zoomDrawer.SetZoom(FlowSystem.GetZoom());
					//FlowSystem.SetScrollPosition(this.zoomDrawer.SetRect(this.scrollRect, scrollPos));
					//FlowSystem.SetZoom(this.zoomDrawer.GetZoom());
					//FlowSystem.SetScrollPosition(this.zoomDrawer.GetOrigin());

					this.zoomDrawer.SetZoom(FlowSystem.GetZoom());
					FlowSystem.SetScrollPosition(this.zoomDrawer.Begin(this.scrollRect, scrollPos, this.contentRect));
					FlowSystem.SetZoom(this.zoomDrawer.GetZoom());
					{

						this.DrawBackground();

						if (hasData == true && windows != null) {
							
							this.tempAttaches.Clear();
							foreach (var window in windows) {

								var attaches = window.attachItems;
								foreach (var attachItem in attaches) {

									var attachId = attachItem.targetId;

									var curWindow = FlowSystem.GetWindow(attachId);
									if (curWindow.IsContainer() == true &&
									    curWindow.IsFunction() == false) continue;
									
									//if (this.IsVisible(window) == false) continue;

									if (curWindow.IsFunction() == true &&
									    curWindow.IsContainer() == true) {
										
										if (curWindow.functionRootId == window.id) {
											
											// Find entrance window
											var rootWindow = FlowSystem.GetWindow(curWindow.functionRootId);
											if (rootWindow != null) {
												
												// Draw entrance point
												this.guiDrawer.DrawNodeCurve(new Vector3(curWindow.rect.x + 6f, curWindow.rect.y + curWindow.rect.height * 0.5f + 25f, -10f),
												                   			 new Vector3(rootWindow.rect.x + rootWindow.rect.width * 0.5f, rootWindow.rect.y + rootWindow.rect.height * 0.5f, -10f),
												                   			 Color.yellow);
												
											}
											
										}
										
										if (curWindow.functionExitId == window.id) {
											
											// Draw exit point
											var exitWindow = FlowSystem.GetWindow(curWindow.functionExitId);
											if (exitWindow != null) {
												
												// Draw entrance point
												this.guiDrawer.DrawNodeCurve(new Vector3(exitWindow.rect.x + exitWindow.rect.width * 0.5f, exitWindow.rect.y + exitWindow.rect.height * 0.5f, -10f),
												                   			 new Vector3(curWindow.rect.x + curWindow.rect.width - 6f, curWindow.rect.y + curWindow.rect.height * 0.5f + 25f, -10f),
												                  			 Color.green);
												
											}
											
										}
										
									} else {
										
										var doubleSided = FlowSystem.AlreadyAttached(attachId, window.id);
										if (this.tempAttaches.Contains(attachId) == true && doubleSided == true) continue;
										
										this.guiDrawer.DrawNodeCurve(window, curWindow, doubleSided);

										// Draw Transition Chooser
										this.DrawTransitionChooser(attachItem, window, curWindow, doubleSided);

									}
									
								}
								
								this.tempAttaches.Add(window.id);
								
							}
							
							var oldColor = GUI.backgroundColor;
							
							this.bringFront.Clear();
							
							var selectionMain = -1;
							var selected = FlowSystem.GetSelected();
							
							this.BeginWindows();
							
							var containerPadding = new Vector4(50f, 100f, 50f, 50f);
							foreach (var container in containers) {
								
								if (this.IsVisible(container) == false) continue;

								var backColor = container.randomColor;
								backColor.a = 0.3f;
								GUI.backgroundColor = backColor;
								
								var rootContainer = container.GetContainer();
								if (rootContainer != null) {
									
									// If container has other container
									
								}
								
								var attaches = container.attachItems;
								if (attaches.Count == 0) {
									
									container.rect.width = 200f;
									container.rect.height = 200f;
									
								} else {
									
									var minX = float.MaxValue;
									var minY = float.MaxValue;
									var maxX = float.MinValue;
									var maxY = float.MinValue;
									foreach (var attachItem in attaches) {

										var attachId = attachItem.targetId;
										var window = FlowSystem.GetWindow(attachId);
										
										minX = Mathf.Min(minX, window.rect.xMin);
										minY = Mathf.Min(minY, window.rect.yMin);
										maxX = Mathf.Max(maxX, window.rect.xMax);
										maxY = Mathf.Max(maxY, window.rect.yMax);
										
									}
									
									container.rect.xMin = minX - containerPadding.x;
									container.rect.yMin = minY - containerPadding.y;
									container.rect.xMax = maxX + containerPadding.z;
									container.rect.yMax = maxY + containerPadding.w;
									
								}
								
								var style = container.GetEditorStyle(false);
								
								var rect = GUI.Window(container.id, container.rect, this.DrawNodeContainer, container.title, style);
								this.BringBackOrFront(container, containers);
								
								if (selectionMain == -1 || selectionMain == container.id) {
									
									var isMoving = (rect != container.rect);
									var newRect = FlowSystem.Grid(rect);
									if (newRect != container.rect && isMoving == true) {
										
										if (selected.Count > 0 && selected.Contains(container.id) == false) {
											
											// nothing to do
											
										} else {
											
											var delta = new Vector2(newRect.x - container.rect.x, newRect.y - container.rect.y);
											if (delta != Vector2.zero) {
												
												selected.Clear();
												if (selected.Contains(container.id) == false) selected.Add(container.id);
												
												container.rect = newRect;
												
												FlowSystem.MoveContainerOrWindow(container.id, delta);
												
												selectionMain = container.id;
												
											}
											
										}
										
									}
									
								}
								
							}
							GUI.backgroundColor = oldColor;
							
							foreach (var window in windows) {

								if (this.IsVisible(window) == false) continue;

								var title = string.Empty;
								if (window.IsSmall() == true) {
									
									title = window.title;
									
								} else {
									
									var size = this.GetWindowSize(window);
									
									window.rect.width = size.x;
									window.rect.height = size.y;
									
								}
								
								var isSelected = selected.Contains(window.id) || (selected.Count == 0 && this.focusedGUIWindow == window.id);
								var style = window.GetEditorStyle(isSelected);
								
								var rect = GUI.Window(window.id, window.rect, this.DrawNodeWindow, title, style);
								GUI.BringWindowToFront(window.id);

								GUI.Window(-window.id, new Rect(rect.x, rect.y + rect.height, rect.width, this.GetTagsHeight(window)), (id) => {

									this.DrawTags(FlowSystem.GetWindow(-id), true);

								}, string.Empty, GUIStyle.none);
								GUI.BringWindowToFront(-window.id);

								var isMoving = (rect != window.rect);
								
								if (selectionMain == -1 || selectionMain == window.id) {
									
									var newRect = FlowSystem.Grid(rect);
									if (newRect != window.rect && isMoving == true) {
										
										// If selected contains
										if (selected.Count > 0 && selected.Contains(window.id) == false) {
											
											// nothing to do
											
										} else {
											
											var delta = new Vector2(newRect.x - window.rect.x, newRect.y - window.rect.y);
											if (delta != Vector2.zero) {
												
												window.rect = newRect;
												
												// Move all selected windows
												foreach (var selectedId in selected) {
													
													if (selectedId != window.id) {
														
														FlowSystem.GetWindow(selectedId).Move(delta);
														
													}
													
												}
												
												selectionMain = window.id;
												
											}
											
										}
										
									}
									
								}
								
							}
							
							this.EndWindows();
							
							var defaultColor = GUI.color;
							//var selectedColor = new Color(0.8f, 0.8f, 1f, 1f);
							
							if (selectionMain >= 0 && FlowSystem.GetWindow(selectionMain).IsContainer() == true) FlowSystem.ResetSelection();
							
							GUI.color = defaultColor;
							
							FlowSystem.Save();
							
						}
						
						if (FlowSystem.GetZoom() >= 0.3f) {

							if (FlowSystem.GetData() != null && FlowSystem.GetData().flowWindowWithLayout == true) {
								
								foreach (var window in windows) {

									if (this.IsVisible(window) == false) continue;

									var components = window.attachedComponents;
									for (int i = 0; i < components.Count; ++i) {
										
										var component = components[i];
										this.guiDrawer.DrawComponentCurve(window, ref component, FlowSystem.GetWindow (component.targetWindowId));
										components[i] = component;
										
									}
									
								}
								
							}

						}

					}
					this.zoomDrawer.End();

				}
				//GUI.EndScrollView();

				this.DrawWaitForConnection();
				this.DrawTagsPopup();
				this.HandleEvents(TOOLBAR_HEIGHT);
				
				GUI.enabled = true;
				
				if (this.scrollingMouseAnimation != null && this.scrollingMouseAnimation.isAnimating == true || this.scrollingMouse == true) this.DrawMinimap();
				
			}
			
		}
		public void ChangeFlowData() {

			this.guiSplash = null;
			FlowSystem.SetData(null);
			this.defaultWindows = null;
			this.tagsList = null;
			Flow.OnReset(this);

		}
		public override void Update() {
			
			if (FlowSystemEditorWindow.loading == true) {
				
				return;
				
			}
			
			if (FlowSystemEditorWindow.loaded == false) {
				
				FlowSystemEditorWindow.loading = true;
				
				EditorApplication.delayCall += () => {
					
					if (this.guiDrawer == null) this.guiDrawer = new GUIDrawer(this);
					if (this.guiSplash == null) this.guiSplash = new FlowSplash(this);

					// Cache
					ME.EditorUtilities.GetAssetsOfType<FlowData>();
					ME.EditorUtilities.GetPrefabsOfType<FlowWindowLayoutTemplate>();
					ME.EditorUtilities.GetPrefabsOfType<FlowLayoutWindowTypeTemplate>();
					ME.EditorUtilities.GetPrefabsOfType<WindowModule>(strongType: false);

					FlowSystemEditorWindow.loading = false;
					FlowSystemEditorWindow.loaded = true;
					
				};
				
				return;
				
			} else {
				
				CoreUtilities.LoadAddons();
				
			}
			
		}
		public void OpenFlowData(FlowData flowData) {
			
			if (this.guiSplash == null) this.guiSplash = new FlowSplash(this);
			this.guiSplash.cachedData = flowData;
			FlowSystem.SetData(flowData);
			
		}