Ejemplo n.º 1
0
		public void DrawPopup ()
		{
			//if (MapMagic.instance.guiGens == null) MapMagic.instance.guiGens = MapMagic.instance.gens;
			//GeneratorsAsset gens = MapMagic.instance.guiGens;
			//if (MapMagic.instance.guiGens != null) gens = MapMagic.instance.guiGens;
			
			Vector2 mousePos = gens.layout.ToInternal(Event.current.mousePosition);
				
			//finding something that was clicked
			Generator clickedGenerator = null;
			Group clickedGroup = null;
			Generator.Output clickedOutput = null;

			for (int i=0; i<gens.list.Length; i++) 
			{
				Generator gen = gens.list[i];
				if (gen.guiRect.Contains(mousePos))
				{
					if (!(gen is Group)) clickedGenerator = gens.list[i];
					else clickedGroup = gens.list[i] as Group;
				}
				
				foreach (Generator.Output output in gens.list[i].Outputs())
					if (output.guiRect.Contains(mousePos)) clickedOutput = output; 
			}
			if (clickedGenerator == null) clickedGenerator = clickedGroup;
			
			//create
			Dictionary<string, PopupMenu.MenuItem> itemsDict = new Dictionary<string, PopupMenu.MenuItem>();
			
			foreach (System.Type type in typeof(Generator).Subtypes())
			{
				if (System.Attribute.IsDefined(type, typeof(GeneratorMenuAttribute)))
				{
					GeneratorMenuAttribute attribute = System.Attribute.GetCustomAttribute(type, typeof(GeneratorMenuAttribute)) as GeneratorMenuAttribute;
					System.Type genType = type;

					if (attribute.disabled) continue;

					PopupMenu.MenuItem item = new PopupMenu.MenuItem(attribute.name, delegate () { CreateGenerator(genType, mousePos); });
					item.priority = attribute.priority;

					if (attribute.menu.Length != 0)
					{
						if (!itemsDict.ContainsKey(attribute.menu)) itemsDict.Add(attribute.menu, new PopupMenu.MenuItem(attribute.menu, subs:new PopupMenu.MenuItem[0]));
						ArrayTools.Add(ref itemsDict[attribute.menu].subItems, createElement:() => item);
					}
					else itemsDict.Add(attribute.name, item);
				}
			} 

			itemsDict["Map"].priority = 1;
			itemsDict["Objects"].priority = 2;
			itemsDict["Output"].priority = 3;
			itemsDict["Portal"].priority = 4;
			itemsDict["Group"].priority = 5;
			itemsDict["Biome"].priority = 6;
			itemsDict["Legacy"].priority = 7;

			PopupMenu.MenuItem[] createItems = new PopupMenu.MenuItem[itemsDict.Count];
			itemsDict.Values.CopyTo(createItems, 0);

			//create group
			//PopupMenu.MenuItem createGroupItem = new PopupMenu.MenuItem("Group",  delegate () { CreateGroup(mousePos); });
			//Extensions.ArrayAdd(ref createItems, createItems.Length-1, createGroupItem);

			//additional name
			/*string additionalName = "All";
			if (clickedGenerator != null) 
			{
				additionalName = "Generator";
				if (clickedGenerator is Group) additionalName = "Group";
			}*/

			//preview
			PopupMenu.MenuItem[] previewSubs = new PopupMenu.MenuItem[]
			{
				new PopupMenu.MenuItem("On Terrain", delegate() {PreviewOutput(clickedGenerator, clickedOutput, false);}, disabled:clickedOutput==null||clickedGenerator==null, priority:0), 
				new PopupMenu.MenuItem("In Window", delegate() {PreviewOutput(clickedGenerator, clickedOutput, true);}, disabled:clickedOutput==null||clickedGenerator==null, priority:1),
				new PopupMenu.MenuItem("Clear", delegate() {PreviewOutput(null, null, false);}, priority:2 )//, disabled:MapMagic.instance.previewOutput==null)
			};

			PopupMenu.MenuItem[] popupItems = new PopupMenu.MenuItem[]
			{
				new PopupMenu.MenuItem("Create", createItems, priority:0),
				new PopupMenu.MenuItem("Export",	delegate () { ExportGenerator(clickedGenerator, mousePos); }, priority:10),
				new PopupMenu.MenuItem("Import",	delegate () { ImportGenerator(mousePos); }, priority:20),
				new PopupMenu.MenuItem("Duplicate",	delegate () { DuplicateGenerator(clickedGenerator); }, priority:30),
				new PopupMenu.MenuItem("Update",	delegate () { UpdateGenerator(clickedGenerator); }, disabled:clickedGenerator==null || !CouldBeUpdated(clickedGenerator), priority:40),
				new PopupMenu.MenuItem("Remove",	delegate () { if (clickedGenerator!=null) DeleteGenerator(clickedGenerator); },	disabled:clickedGenerator==null, priority:50),
				new PopupMenu.MenuItem("Reset",		delegate () { if (clickedGenerator!=null) ResetGenerator(clickedGenerator); },	disabled:clickedGenerator==null, priority:60), 
				new PopupMenu.MenuItem("Preview", previewSubs, priority:70)
			};

			if (onDrawPopup != null)
				popupItems = onDrawPopup(popupItems, mousePos, gens, clickedGenerator, clickedGroup, clickedOutput);

			PopupMenu.DrawPopup(popupItems, Event.current.mousePosition, closeAllOther:true);
		}
Ejemplo n.º 2
0
			void UpdateGenerator (Generator gen)
			{
				if (!updateWarningShowed) 
				{
					if (EditorUtility.DisplayDialog("Warning", "Updating generator can break your graph. Make a backup before continue", "Go on, I've made a backup", "Cancel"))
						updateWarningShowed = true;
					else return;
				}
				
				Undo.RecordObject (gens, "MapMagic Update Generator"); 
				gens.setDirty = !gens.setDirty;

				//Generator[] copyGens = gens.SmartDuplicateGenerators(gen);

				System.Type type = gen.GetType();
				GeneratorMenuAttribute attribute = System.Attribute.GetCustomAttribute(type, typeof(GeneratorMenuAttribute)) as GeneratorMenuAttribute;

				//finding type to replace
				System.Type newType = null;
				if (attribute.updateType != null) newType = attribute.updateType;
				else
				{
					string name = attribute.name;
					name = name.Split(new string[] {" (Legacy"}, System.StringSplitOptions.None)[0];

					//iterating types starting from current version
					for (int v=MapMagic.version; v>=0; v--)
					{
						//newType = System.Type.GetType("MapMagic." + name + "Generator" + v.ToString()); //does not work
						newType = System.Reflection.Assembly.Load("Assembly-CSharp").GetType("MapMagic." + name + "Generator" + v.ToString());
						if (newType != null) break;
					}

					if (newType == null)
					for (int v=MapMagic.version; v>=0; v--)
					{
						newType = System.Reflection.Assembly.Load("Assembly-CSharp").GetType("MapMagic." + name + v.ToString()); //for generators that have no "Generator" in name
						if (newType != null) break;
					}
				}
				if (newType == null) { Debug.Log("Could not find a proper type to update"); return; }
				
				Generator newGen = System.Activator.CreateInstance(newType) as Generator;

				newGen.ReflectionCopyFrom(gen); 

				//changing links
				for (int g=0; g<gens.list.Length; g++)
					foreach (Generator.Input input in gens.list[g].Inputs())
						if (input != null && input.linkGen == gen) input.linkGen = newGen;

				//replacing in array
				int numInArray = ArrayTools.Find(gens.list, gen);
				gens.list[numInArray] = newGen;

				if (mapMagic != null)
				{
					mapMagic.ClearResults(gen); //copyGens
					mapMagic.Generate();
				}

				EditorUtility.SetDirty(gens);
			}
Ejemplo n.º 3
0
		private void OnGUI() { DrawWindow(); if (repaint) DrawWindow(); repaint = false; } //drawing window, or doing it twice if repaint is needed
		private void DrawWindow()
		{
			if (gens == null) return;

			//un-selecting field on drag
			#if !UNITY_EDITOR_LINUX
			if (Event.current.button != 0  &&  UnityEngine.GUI.GetNameOfFocusedControl() != "Temp") RemoveFocusOnControl();
			#endif

			//startingscript.layout
			
			if (gens.layout==null) 
				{ gens.layout = new Layout(); gens.layout.scroll = gens.guiScroll; gens.layout.zoom = gens.guiZoom; gens.layout.maxZoom = 1f; }
			gens.layout.Zoom(); gens.layout.Scroll(); //scrolling and zooming
			if (gens.layout.zoom < 0.0001f) gens.layout.zoom = 1;
			gens.layout.field = this.position;

			//zoomning with keyboard
			if (Event.current.type == EventType.KeyDown)
			{
				if (Event.current.keyCode==KeyCode.Equals && Event.current.alt) { gens.layout.zoom += gens.layout.zoomStep; if (gens.layout.zoom>1) gens.layout.zoom=1; Event.current.Use(); }
				if (Event.current.keyCode==KeyCode.Minus && Event.current.alt) { gens.layout.zoom -= gens.layout.zoomStep; Event.current.Use(); }
			}
			
			//unity 5.4 beta
			if (Event.current.type == EventType.Layout) return; 

			if (Event.current.type == EventType.MouseDrag) //skip all mouse drags (except when dragging text selection cursor in field)
			{
				if (!UnityEditor.EditorGUIUtility.editingTextField) return;
				if (UnityEngine.GUI.GetNameOfFocusedControl() == "Temp") return; 
			}

			//using middle mouse click events
			if (Event.current.button == 2) Event.current.Use();

			//undo
			Undo.undoRedoPerformed -= PerformUndo;
			Undo.undoRedoPerformed += PerformUndo;

			//setting title content
			titleContent = new GUIContent("Map Magic");
			titleContent.image =gens.layout.GetIcon("MapMagic_WindowIcon");

			//drawing background
			Vector2 windowZeroPos =gens.layout.ToInternal(Vector2.zero);
			windowZeroPos.x = ((int)(windowZeroPos.x/64f)) * 64; 
			windowZeroPos.y = ((int)(windowZeroPos.y/64f)) * 64; 

			Texture2D backTex = gens.layout.GetIcon("MapMagic_Background");
			Rect backRect = new Rect(windowZeroPos - new Vector2(64,64), position.size + new Vector2(127,127));
			UnityEditor.EditorGUI.DrawPreviewTexture(new Rect(0,0,position.width,position.height), backTex, null, ScaleMode.ScaleAndCrop);
			gens.layout.Icon(backTex, backRect, tile:true);

			//drawing test center
			//script.layout.Button("Zero", new Rect(-10,-10,20,20));

			//calculating visible area
			Rect visibleArea = gens.layout.ToInternal( new Rect(0,0,position.size.x,position.size.y) );
			if (forceAll) { visibleArea = new Rect(-200000,-200000,400000,400000); forceAll = false; }
			//visibleArea = new Rect(visibleArea.x+100, visibleArea.y+100, visibleArea.width-200, visibleArea.height-200);
			//layout.Label("Area", helpBox:true, rect:visibleArea);

			//checking if all generators are loaded, and none of them is null
			for (int i=gens.list.Length-1; i>=0; i--)
			{
				if (gens.list[i] == null) { ArrayTools.RemoveAt(ref gens.list, i); continue; }
				foreach (Generator.Input input in gens.list[i].Inputs()) 
				{
					if (input == null) continue;
					if (input.linkGen == null) input.Link(null, null);
				}
			}

			#region Drawing groups
				for(int i=0; i<gens.list.Length; i++)
				{
					if (!(gens.list[i] is Group)) continue;
					Group group = gens.list[i] as Group;

					//checking if this is withinscript.layout field
					if (group.guiRect.x > visibleArea.x+visibleArea.width || group.guiRect.y > visibleArea.y+visibleArea.height ||
						group.guiRect.x+group.guiRect.width < visibleArea.x || group.guiRect.y+group.guiRect.height < visibleArea.y) 
							if (group.guiRect.width > 0.001f && gens.layout.dragState != Layout.DragState.Drag) continue; //if guiRect initialized and not dragging

					//settingscript.layout data
					group.layout.field = group.guiRect;
					group.layout.scroll = gens.layout.scroll;
					group.layout.zoom = gens.layout.zoom;

					group.OnGUI(gens);

					group.guiRect = group.layout.field;
				}
			#endregion

			#region Drawing connections (before generators to make them display under nodes)

				foreach(Generator gen in gens.list)
				{
					foreach (Generator.Input input in gen.Inputs())
					{
						if (input==null || input.link == null) continue; //input could be null in layered generators
						if (gen is Portal)
						{ 
							Portal portal = (Portal)gen;
							if (!portal.drawInputConnection) continue;
						}
						gens.layout.Spline(input.link.guiConnectionPos, input.guiConnectionPos, color:GeneratorsAsset.CanConnect(input.link,input)? input.guiColor : Color.red);
					}
				}
			#endregion

			#region creating connections (after generators to make clicking in inout work)

			int dragIdCounter = gens.list.Length+1;
				foreach (Generator gen in gens.list)
					foreach (Generator.IGuiInout inout in gen.Inouts())
				{
					if (inout == null) continue;
					if (gens.layout.DragDrop(inout.guiRect, dragIdCounter))
					{
						//finding target
						Generator.IGuiInout target = null;
						foreach (Generator gen2 in gens.list)
							foreach (Generator.IGuiInout inout2 in gen2.Inouts())
								if (inout2.guiRect.Contains(gens.layout.dragPos)) target = inout2;

						//converting inout to Input (or Output) and target to Output (or Input)
						Generator.Input input = inout as Generator.Input;		if (input==null) input = target as Generator.Input;
						Generator.Output output = inout as Generator.Output;	if (output==null) output = target as Generator.Output;

						//connection validity test
						bool canConnect = input!=null && output!=null && GeneratorsAsset.CanConnect(output,input);

						//infinite loop test
						if (canConnect)
						{ 
							Generator outputGen = output.GetGenerator(gens.list);
							Generator inputGen = input.GetGenerator(gens.list);
							if (inputGen == outputGen || gens.CheckDependence(inputGen,outputGen)) canConnect = false;
						}

						//drag
						//if (script.layout.dragState==Layout.DragState.Drag) //commented out because will not be displayed on repaint otherwise
						//{
							if (input == null)gens.layout.Spline(output.guiConnectionPos,gens.layout.dragPos, color:Color.red);
							else if (output == null)gens.layout.Spline(gens.layout.dragPos, input.guiConnectionPos, color:Color.red);
							else gens.layout.Spline(output.guiConnectionPos, input.guiConnectionPos, color:canConnect? input.guiColor : Color.red);
						//}

						//release
						if (gens.layout.dragState==Layout.DragState.Released && input!=null) //on release. Do nothing if input not defined
						{
							Undo.RecordObject (gens, "MapMagic Connection"); 
							gens.setDirty = !gens.setDirty;

							input.Unlink();
							if (canConnect) input.Link(output, output.GetGenerator(gens.list));
							if (mapMagic!=null) 
							{
								mapMagic.ClearResults(gen);
								mapMagic.Generate();
							}

							EditorUtility.SetDirty(gens);
						}
					}
					dragIdCounter++;
				}
			#endregion

			#region Drawing generators

				for(int i=0; i<gens.list.Length; i++)
				{
					Generator gen = gens.list[i];
					if (gen is Group) continue; //skipping groups

					//checking if this generator is withinscript.layout field
					if (gen.guiRect.x > visibleArea.x+visibleArea.width || gen.guiRect.y > visibleArea.y+visibleArea.height ||
						gen.guiRect.x+gen.guiRect.width < visibleArea.x || gen.guiRect.y+gen.guiRect.height < visibleArea.y) 
							if (gen.guiRect.width > 0.001f && gens.layout.dragState != Layout.DragState.Drag) continue; //if guiRect initialized and not dragging

					if (gen.layout == null) gen.layout = new Layout();
					gen.layout.field = gen.guiRect;
					gen.layout.field.width = 160; //MapMagic.instance.guiGeneratorWidth;
				
					//gen.layout.OnBeforeChange -= RecordGeneratorUndo;
					//gen.layout.OnBeforeChange += RecordGeneratorUndo;
					gen.layout.undoObject = gens;
					gen.layout.undoName = "MapMagic Generators Change"; 
					gen.layout.dragChange = true;
					gen.layout.disabled = changeLock;

					//copyscript.layout params
					gen.layout.scroll = gens.layout.scroll;
					gen.layout.zoom = gens.layout.zoom;

					//drawing background
					gen.layout.Element("MapMagic_Window", gen.layout.field, new RectOffset(34,34,34,34), new RectOffset(33,33,33,33));

					//resetting layout
					gen.layout.field.height = 0;
					gen.layout.field.width =160;
					gen.layout.cursor = new Rect();
					gen.layout.change = false;
					gen.layout.margin = 1; gen.layout.rightMargin = 1;
					gen.layout.fieldSize = 0.4f;   
					
					//drawing header
					gen.DrawHeader (mapMagic, gens);
					if (gen is OutputGenerator && gen.layout.change && gen.enabled == false) //if just disabled output
						gensBiomeHierarchy[0].OnDisableGenerator(gen);

					//drawing parameters
					#if WDEBUG
					gen.OnGUI(gens);
					#else
					try { gen.OnGUI(gens); }
					catch (UnityException e) { Debug.LogError("Error drawing generator " + GetType() + "\n" + e);} 
					//should be system.exception but it causes ExitGUIException on opening curve/color/texture fields
					//it's so unity...
					//if something goes wrong but no error is displayed - you know where to find it
					#endif
					gen.layout.Par(3);

					//drawing debug generate time
					#if WDEBUG
					if (mapMagic!=null)
					{
						Rect timerRect = new Rect(gen.layout.field.x, gen.layout.field.y+gen.layout.field.height, 200, 20);
						string timeLabel = "g:" + gen.guiGenerateTime + "ms ";
						if (gen is OutputGenerator)
						{
							if (Generator.guiProcessTime.ContainsKey(gen.GetType())) timeLabel += " p:" + Generator.guiProcessTime[gen.GetType()] + "ms ";
							if (Generator.guiApplyTime.ContainsKey(gen.GetType())) timeLabel += " a:" + Generator.guiApplyTime[gen.GetType()] + "ms ";
						}
						gen.layout.Label(timeLabel, timerRect);
					}
					#endif

					//instant generate on params change
					if (gen.layout.change) 
					{
						if (mapMagic!=null) 
						{
							mapMagic.ClearResults(gen);
							mapMagic.Generate();
						}
						repaint=true; Repaint();

						EditorUtility.SetDirty(gens);
					}

					//drawing biome "edit" button. Rather hacky, but we have to call editor method when pressing "Edit"
					if (gen is Biome)
					{
						Biome biome = (Biome)gen;
						if (gen.layout.Button("Edit", disabled:biome.data==null)) 
						{
							MapMagicWindow.Show(biome.data, mapMagic, forceOpen:true,asBiome: true);
							Repaint();
							return; //cancel drawing this graph if biome was opened
						}
						gen.layout.Par(10);
					}

					//changing all of the output generators of the same type (in case this one was disabled to make refresh)
					if (gen.layout.change && !gen.enabled && gen is OutputGenerator)
					{
						foreach (GeneratorsAsset ga in gensBiomeHierarchy)
						foreach (OutputGenerator sameOut in ga.GeneratorsOfType<OutputGenerator>(onlyEnabled:true, checkBiomes:true))
							if (sameOut.GetType() == gen.GetType()) 
							{
								mapMagic.ClearResults(sameOut);
								mapMagic.Generate();
							}
					}

			
					if (gen.guiRect.width<1 && gen.guiRect.height<1) { repaint=true;  Repaint(); } //repainting if some of the generators rect is 0
					gen.guiRect = gen.layout.field;
				}
			#endregion

			#region Toolbar

				if (toolbarLayout==null) toolbarLayout = new Layout();
				toolbarLayout.margin = 0; toolbarLayout.rightMargin = 0;
				toolbarLayout.field.width = this.position.width;
				toolbarLayout.field.height = 18;
				toolbarLayout.cursor = new Rect();
				//toolbarLayout.window = this;
				toolbarLayout.Par(18, padding:0);

				EditorGUI.LabelField(toolbarLayout.field, "", EditorStyles.toolbarButton);

				if (mapMagic!=null  &&  mapMagic.ToString()!="null"  &&  !ReferenceEquals(mapMagic.gameObject,null)) //check game object in case it was deleted
				//mapMagic.ToString()!="null" - the only efficient delete check. Nor Equals neither ReferenceEquals are reliable. I <3 Unity!
				{
					//drawing state icon
					toolbarLayout.Inset(25);
					if (ThreadWorker.IsWorking("MapMagic")) { toolbarLayout.Icon("MapMagic_Loading", new Rect(5,0,16,16), animationFrames:12); Repaint(); }
					else toolbarLayout.Icon("MapMagic_Success", new Rect(5,0,16,16));
					//TODO: changed sign

					//mapmagic name
					Rect nameLabelRect = toolbarLayout.Inset(100); nameLabelRect.y+=1; //nameLabelRect.height-=4;
					EditorGUI.LabelField(nameLabelRect, mapMagic.gameObject.name, EditorStyles.miniLabel);

					//generate buttons
					if (GUI.Button(toolbarLayout.Inset(110,padding:0), "Generate Changed", EditorStyles.toolbarButton)) mapMagic.Generate(force:true);
					if (GUI.Button(toolbarLayout.Inset(110,padding:0), "Force Generate All", EditorStyles.toolbarButton)) 
					{ 
						mapMagic.ClearResults();  

						if (MapMagic.instance != null)
							foreach (Chunk chunk in MapMagic.instance.chunks.All())
								if (chunk.terrain != null) chunk.terrain.transform.RemoveChildren();
							
						mapMagic.Generate(force:true); 
					}

					//seed field
					toolbarLayout.Inset(10);
					Rect seedLabelRect = toolbarLayout.Inset(34); seedLabelRect.y+=1; seedLabelRect.height-=4;
					Rect seedFieldRect = toolbarLayout.Inset(64); seedFieldRect.y+=2; seedFieldRect.height-=4;
				}
				else
				{
					Rect nameLabelRect = toolbarLayout.Inset(300); nameLabelRect.y+=1; //nameLabelRect.height-=4;
					EditorGUI.LabelField(nameLabelRect, "External data '" + AssetDatabase.GetAssetPath(gens) + "'", EditorStyles.miniLabel); 
				}

				//right part
				toolbarLayout.Inset(toolbarLayout.field.width - toolbarLayout.cursor.x - 150 - 22,padding:0);

				//drawing exit biome button
				Rect biomeRect = toolbarLayout.Inset(80, padding:0);
				if (gensBiomeHierarchy.Count>1) 
				{
					if (toolbarLayout.Button("", biomeRect, icon:"MapMagic_ExitBiome", style:EditorStyles.toolbarButton)) 
					{
						gensBiomeHierarchy.RemoveAt(gensBiomeHierarchy.Count-1);
						Repaint();
						return;
					}

					toolbarLayout.Label("Exit Biome", new Rect(toolbarLayout.cursor.x-60, toolbarLayout.cursor.y+3, 60, toolbarLayout.cursor.height), fontSize:9);
				}

				//focus button 
				
			//	if (GUI.Button(script.toolbarLayout.Inset(100,padding:0), "Focus", EditorStyles.toolbarButton)) FocusOnGenerators();
				if (toolbarLayout.Button("", toolbarLayout.Inset(23,padding:0), icon:"MapMagic_Focus", style:EditorStyles.toolbarButton)) FocusOnGenerators();
				
				if (toolbarLayout.Button("", toolbarLayout.Inset(47,padding:0), icon:"MapMagic_Zoom", style:EditorStyles.toolbarButton)) gens.layout.zoom=1;
				toolbarLayout.Label((int)(gens.layout.zoom*100)+"%", new Rect(toolbarLayout.cursor.x-28, toolbarLayout.cursor.y+3, 28, toolbarLayout.cursor.height), fontSize:8);  
				
				toolbarLayout.Inset(3, margin:0);
				toolbarLayout.Label("",  toolbarLayout.Inset(22, margin:0), url:"https://gitlab.com/denispahunov/mapmagic/wikis/Editor%20Window", icon:"MapMagic_Help"); 

			#endregion

			#region Draging

				//dragging generators
				for(int i=gens.list.Length-1; i>=0; i--)
				{
					Generator gen = gens.list[i];
					if (gen is Group) continue;
					gen.layout.field = gen.guiRect;

					//dragging
					if (gens.layout.DragDrop(gen.layout.field, i)) 
					{
						if (gens.layout.dragState == Layout.DragState.Pressed) 
						{
							Undo.RecordObject (gens, "MapMagic Generators Drag");
							gens.setDirty = !gens.setDirty;
						}
						if (gens.layout.dragState == Layout.DragState.Drag || gens.layout.dragState == Layout.DragState.Released) 
						{ 
							//gen.Move(gens.layout.dragDelta,true);
							
							gen.layout.field.position += gens.layout.dragDelta;
							gen.guiRect = gens.layout.field;

							//moving inouts to remove lag
							foreach (Generator.IGuiInout inout in gen.Inouts()) 
								inout.guiRect = new Rect(inout.guiRect.position+gens.layout.dragDelta, inout.guiRect.size);

							//moving group
							if (gen is Group)
							{
								Group group = gen as Group;
								for (int g=0; g<group.generators.Count; g++) //group.generators[g].Move(delta,false);
								{
									group.generators[g].layout.field.position += gens.layout.dragDelta;
									group.generators[g].guiRect = gens.layout.field;

									foreach (Generator.IGuiInout inout in group.generators[g].Inouts())  //moving inouts to remove lag
										inout.guiRect = new Rect(inout.guiRect.position+gens.layout.dragDelta, inout.guiRect.size);
								}
							}

							repaint=true; Repaint(); 

							EditorUtility.SetDirty(gens);
						}
					}

					//saving all generator rects
					gen.guiRect = gen.layout.field;
				}

				//dragging groups
				for (int i=gens.list.Length-1; i>=0; i--)
				{
					//Generator gen = gens.list[i];
					Group group = gens.list[i] as Group;
					if (group == null) continue;
					group.layout.field = group.guiRect;

					//resizing
					group.layout.field =gens.layout.ResizeRect(group.layout.field, i+20000);

					//dragging
					if (gens.layout.DragDrop(group.layout.field, i)) 
					{
						if (gens.layout.dragState == Layout.DragState.Pressed) 
						{
							Undo.RecordObject (gens, "MapMagic Group Drag");
							gens.setDirty = !gens.setDirty;
							group.Populate(gens);
						}
						if (gens.layout.dragState == Layout.DragState.Drag || gens.layout.dragState == Layout.DragState.Released) 
						{ 
							//group.Move(gens.layout.dragDelta,true);
							
							group.layout.field.position += gens.layout.dragDelta;
							group.guiRect = gens.layout.field;

							for (int g=0; g<group.generators.Count; g++) //group.generators[g].Move(delta,false);
							{
								group.generators[g].layout.field.position += gens.layout.dragDelta;
								group.generators[g].guiRect.position += gens.layout.dragDelta; // = gens.layout.field;

					//			foreach (Generator.IGuiInout inout in group.generators[g].Inouts())  //moving inouts to remove lag
					//				inout.guiRect = new Rect(inout.guiRect.position+gens.layout.dragDelta, inout.guiRect.size);
							}

							repaint=true; Repaint(); 

							EditorUtility.SetDirty(gens);
						}
						if (gens.layout.dragState == Layout.DragState.Released && group != null) gens.SortGroups();
					}

					//saving all group rects
					group.guiRect = group.layout.field;
				}

			#endregion

			//right-click menus
			if (Event.current.type == EventType.ContextClick || (Event.current.type == EventType.MouseDown && Event.current.control)) DrawPopup();

			//debug center
			//EditorGUI.HelpBox(script.layout.ToLocal(new Rect(-25,-10,50,20)), "Zero", MessageType.None);

			//assigning portal popup action
			Portal.OnChooseEnter -= DrawPortalSelector; Portal.OnChooseEnter += DrawPortalSelector;

			//saving scroll and zoom
			gens.guiScroll = gens.layout.scroll; gens.guiZoom = gens.layout.zoom;  

			DrawDemoLock();

		}
Ejemplo n.º 4
0
        static public void ErosionIteration(Matrix heights, Matrix erosion, Matrix sedimentSum, CoordRect area = new CoordRect(),
                                            float erosionDurability = 0.9f, float erosionAmount = 1f, float sedimentAmount = 0.5f, int erosionFluidityIterations = 3, float ruffle = 0.1f,
                                            Matrix torrents         = null, Matrix sediments    = null, int[] stepsArray = null, int[] heightsInt = null, int[] order = null)
        {
            if (area.isZero)
            {
                area = heights.rect;
            }
            int count = heights.count;
            int seed  = 12345;

            #region Creating order array

            int steps = 1000000;

            //creating int-type copy of heights
            if (heightsInt == null)
            {
                heightsInt = new int[count];
            }
            for (int i = 0; i < heights.count; i++)
            {
                heightsInt[i] = (int)(Mathf.Clamp01(heights.array[i]) * steps);
            }

            //order array
            if (order == null)
            {
                order = new int[count];
            }
            order = ArrayTools.Order(heightsInt, order: order, max: heights.count, stepsArray: stepsArray);

            //setting out-of-area order num to negative
            for (int j = 0; j < heights.count; j++)
            {
                int   pos   = order[j];
                Coord coord = heights.rect.CoordByNum(pos);
                if (!area.CheckInRangeAndBounds(coord))
                {
                    order[j] = -1;
                }
            }

            #endregion

            #region Creating torrents

            if (torrents == null)
            {
                torrents = new Matrix(heights.rect);
            }
            torrents.ChangeRect(heights.rect);
            torrents.Fill(1f);                             //casting initial rain

            for (int j = count - 1; j >= 0; j--)
            {
                //finding column ordered by height
                int pos = order[j];
                if (pos < 0)
                {
                    continue;
                }

                /*
                 * MooreCross height = new MooreCross(heights, pos); //moore
                 * MooreCross torrent = new MooreCross(torrents, pos); //moore
                 * if (torrent.c > 2000000000) torrent.c = 2000000000;
                 *
                 * //creating torrents
                 * MooreCross delta = new MooreCross(height); //moore
                 * delta.SubtractInverse(height.c);
                 * delta.ClampPositive();
                 *
                 * delta.Percent(); //every side now determines a percent - how many water should go to it
                 * delta.Multiply(torrent.c);
                 * torrent.Add(delta);
                 */

                //getting height values
                float[] m = heights.array; int i = pos; int sizeX = heights.rect.size.x;
                float   h = m[i]; float hx = m[i - 1]; float hX = m[i + 1]; float hz = m[i - sizeX]; float hZ = m[i + sizeX];
                float   hxz = m[i - 1 - sizeX]; float hXz = m[i + 1 - sizeX]; float hxZ = m[i - 1 + sizeX]; float hXZ = m[i + 1 + sizeX];

                //creating delta
                float d = h - h; float dx = h - hx; float dX = h - hX; float dz = h - hz; float dZ = h - hZ;
                float dxz = h - hxz; float dXz = h - hXz; float dxZ = h - hxZ; float dXZ = h - hXZ;

                //ignoring negative delta values
                d   = d > 0? d : 0; dx = dx > 0? dx : 0; dX = dX > 0? dX : 0; dz = dz > 0? dz : 0; dZ = dZ > 0? dZ : 0;
                dxz = dxz > 0? dxz : 0; dXz = dXz > 0? dXz : 0; dxZ = dxZ > 0? dxZ : 0; dXZ = dXZ > 0? dXZ : 0;

                //finding percents
                float p = 0, px = 0, pX = 0, pz = 0, pZ = 0, pxz = 0, pXz = 0, pxZ = 0, pXZ = 0;
                float s = d + dx + dX + dz + dZ + dxz + dXz + dxZ + dXZ;
                if (s > 0.00001f)
                {
                    p = d / s; px = dx / s; pX = dX / s; pz = dz / s; pZ = dZ / s; pxz = dxz / s; pXz = dXz / s; pxZ = dxZ / s; pXZ = dXZ / s;
                }

                //getting central torrent (and clamping it)
                float t = torrents.array[i];
                if (t > 2000000000)
                {
                    t = 2000000000;
                }

                //spreading central torrent according percents delta. And adding to torrents array
                m                 = torrents.array;
                m[i]             += t * p; m[i - 1] += t * px; m[i + 1] += t * pX; m[i - sizeX] += t * pz; m[i + sizeX] += t * pZ;
                m[i - 1 - sizeX] += t * pxz; m[i + 1 - sizeX] += t * pXz; m[i - 1 + sizeX] += t * pxZ; m[i + 1 + sizeX] += t * pXZ;
            }
            #endregion

            #region Erosion

            if (sediments == null)
            {
                sediments = new Matrix(heights.rect);
            }
            else
            {
                sediments.ChangeRect(heights.rect);
            }
            sediments.Clear();

            for (int j = count - 1; j >= 0; j--)
            {
                //finding column ordered by height
                int pos = order[j];
                if (pos < 0)
                {
                    continue;
                }

                /*
                 * Cross height = new Cross(heights, pos);
                 * Cross torrent = new Cross(torrents, pos);
                 * Cross sediment = new Cross(sediments, pos);
                 *
                 * //erosion
                 * float erodeLine = (height.c + height.min)/2f; //halfway between current and maximum height
                 *
                 * if (height.c > erodeLine) //raising soil if column is higher than eroded column
                 * {
                 *      float raised = height.c - erodeLine;
                 *      raised = Mathf.Min(raised, raised*(torrent.c-1) * (1-erosionDurability));  //could not raise more soil than height-minHeight. //torrents always have 1 or more
                 *      raised *= erosionAmount;
                 *
                 *      heights.array[pos] -= raised; //raising soil
                 *      height.c -= raised;
                 *      sediments.array[pos] += raised * sedimentAmount; //and saving raised to sediment
                 *      sediment.c += raised * sedimentAmount;
                 *
                 *      if (paintErosion != null) paintErosion.array[pos] += raised * mapsFactor; //and writing to ref
                 * }
                 */

                //getting height values
                float[] m = heights.array; int i = pos; int sizeX = heights.rect.size.x;
                float   h = m[i]; float hx = m[i - 1]; float hX = m[i + 1]; float hz = m[i - sizeX]; float hZ = m[i + sizeX];

                //height minimum
                float h_min = h;
                if (hx < h_min)
                {
                    h_min = hx;
                }
                if (hX < h_min)
                {
                    h_min = hX;
                }
                if (hz < h_min)
                {
                    h_min = hz;
                }
                if (hZ < h_min)
                {
                    h_min = hZ;
                }

                //erosion line
                float erodeLine = (h + h_min) / 2f;                               //halfway between current and maximum height
                if (h < erodeLine)
                {
                    continue;
                }

                //raising soil
                float raised    = h - erodeLine;
                float maxRaised = raised * (torrents.array[pos] - 1) * (1 - erosionDurability);
                if (raised > maxRaised)
                {
                    raised = maxRaised;
                }
                raised *= erosionAmount;

                //saving arrays
                heights.array[pos]   -= raised;
                sediments.array[pos] += raised * sedimentAmount;
                if (erosion != null)
                {
                    erosion.array[pos] += raised;                                                  //and writing to ref
                }
            }
            #endregion

            #region Settling sediment

            for (int l = 0; l < erosionFluidityIterations; l++)
            {
                for (int j = count - 1; j >= 0; j--)
                {
                    //finding column ordered by height
                    int pos = order[j];
                    if (pos < 0)
                    {
                        continue;
                    }

                    /*
                     * Cross height = new Cross(heights, pos);
                     * Cross sediment = new Cross(sediments, pos);
                     * float sedimentSum = sediment.c+sediment.px+sediment.nx+sediment.pz+sediment.nz;
                     * if (sedimentSum < 0.00001f) continue;
                     *
                     * //finding columns that sediment will spread to
                     * Cross spread = new Cross(1,1,1,1,1); //actually it'a s bool-cross
                     *
                     * //from top to bottom
                     * foreach (int i in height.Sorted())
                     * {
                     *      //float curMaxLevel = (height*spread).max;
                     *      float curMaxLevel = 0;
                     *      if (spread.c > 0.1f && height.c > curMaxLevel) curMaxLevel = height.c;
                     *      if (spread.px > 0.1f && height.px > curMaxLevel) curMaxLevel = height.px;
                     *      if (spread.nx > 0.1f && height.nx > curMaxLevel) curMaxLevel = height.nx;
                     *      if (spread.pz > 0.1f && height.pz > curMaxLevel) curMaxLevel = height.pz;
                     *      if (spread.nz > 0.1f && height.nz > curMaxLevel) curMaxLevel = height.nz;
                     *
                     *      //sum of lack of heights to current max level  less  then total sediment
                     *      float lackSum = 0; //... + Mathf.Max(curMaxLevel-height.px, 0) + ...
                     *      if (curMaxLevel-height.c > 0) lackSum += curMaxLevel-height.c;
                     *      if (curMaxLevel-height.px > 0) lackSum += curMaxLevel-height.px;
                     *      if (curMaxLevel-height.pz > 0) lackSum += curMaxLevel-height.pz;
                     *      if (curMaxLevel-height.nx > 0) lackSum += curMaxLevel-height.nx;
                     *      if (curMaxLevel-height.nz > 0) lackSum += curMaxLevel-height.nz;
                     *
                     *      if (lackSum < sedimentSum) break;
                     *      spread[i] = 0;  //I find your lack of sediment disturbing!
                     *
                     *      //if ((lackSum < sedimentSum)) spread = new Cross(1,1,1,1,1);
                     *      //else spread = new Cross(0,0,0,0,0);
                     *
                     * }
                     *
                     * //find sediment-filled level
                     * float columnsRemain = spread.c+spread.px+spread.nx+spread.pz+spread.nz; //aka spread.sum;
                     * float filledLevel = 0;
                     * if (columnsRemain > 0.00001f) filledLevel = // ((height*spread).sum + sediment.sum)/columnsRemain
                     *      ((height.c*spread.c)+(height.px*spread.px)+(height.nx*spread.nx)+(height.pz*spread.pz)+(height.nz*spread.nz) + sedimentSum)/columnsRemain;
                     *
                     * //transfering sediment
                     * sediment = new Cross(
                     *      filledLevel-height.c>0 ? (filledLevel-height.c)*spread.c : 0,
                     *      filledLevel-height.px>0 ? (filledLevel-height.px)*spread.px : 0,
                     *      filledLevel-height.nx>0 ? (filledLevel-height.nx)*spread.nx : 0,
                     *      filledLevel-height.pz>0 ? (filledLevel-height.pz)*spread.pz : 0,
                     *      filledLevel-height.nz>0 ? (filledLevel-height.nz)*spread.nz : 0);
                     *
                     * sediment.ToMatrix(sediments, pos);
                     */


                    //getting height values
                    float[] m = heights.array; int sizeX = heights.rect.size.x;
                    float   h = m[pos]; float hx = m[pos - 1]; float hX = m[pos + 1]; float hz = m[pos - sizeX]; float hZ = m[pos + sizeX];

                    //getting sediment values
                    m = sediments.array;
                    float s = m[pos]; float sx = m[pos - 1]; float sX = m[pos + 1]; float sz = m[pos - sizeX]; float sZ = m[pos + sizeX];

                    //sediment sum
                    float sum = s + sx + sX + sz + sZ;
                    if (sum < 0.00001f)
                    {
                        continue;
                    }

                    //pouring sum to all cells
                    float sedimentFifth = sum / 5;
                    s = sedimentFifth; sx = sedimentFifth; sX = sedimentFifth; sz = sedimentFifth; sZ = sedimentFifth;

                    //levelling
                    //for (int i=0; i<2; i++)
                    //{
                    //x line
                    float avg = (h + s + sx + hx) / 2;
                    if (h + s > hx + sx)
                    {
                        float transfer = s + h - avg; if (transfer > s)
                        {
                            transfer = s;
                        }
                        s -= transfer; sx += transfer;
                    }
                    else
                    {
                        float transfer = sx + hx - avg; if (transfer > sx)
                        {
                            transfer = sx;
                        }
                        sx -= transfer; s += transfer;
                    }

                    avg = (hx + sx + sX + hX) / 2;
                    if (hx + sx > hX + sX)
                    {
                        float transfer = sx + hx - avg; if (transfer > sx)
                        {
                            transfer = sx;
                        }
                        sx -= transfer; sX += transfer;
                    }
                    else
                    {
                        float transfer = sX + hX - avg; if (transfer > sX)
                        {
                            transfer = sX;
                        }
                        sX -= transfer; sx += transfer;
                    }

                    avg = (h + s + sX + hX) / 2;
                    if (h + s > hX + sX)
                    {
                        float transfer = s + h - avg; if (transfer > s)
                        {
                            transfer = s;
                        }
                        s -= transfer; sX += transfer;
                    }
                    else
                    {
                        float transfer = sX + hX - avg; if (transfer > sX)
                        {
                            transfer = sX;
                        }
                        sX -= transfer; s += transfer;
                    }

                    //z line
                    avg = (h + s + sz + hz) / 2;
                    if (h + s > hz + sz)
                    {
                        float transfer = s + h - avg; if (transfer > s)
                        {
                            transfer = s;
                        }
                        s -= transfer; sz += transfer;
                    }
                    else
                    {
                        float transfer = sz + hz - avg; if (transfer > sz)
                        {
                            transfer = sz;
                        }
                        sz -= transfer; s += transfer;
                    }

                    avg = (hZ + sZ + sz + hz) / 2;
                    if (hZ + sZ > hz + sz)
                    {
                        float transfer = sZ + hZ - avg; if (transfer > sZ)
                        {
                            transfer = sZ;
                        }
                        sZ -= transfer; sz += transfer;
                    }
                    else
                    {
                        float transfer = sz + hz - avg; if (transfer > sz)
                        {
                            transfer = sz;
                        }
                        sz -= transfer; sZ += transfer;
                    }

                    avg = (h + s + sz + hz) / 2;
                    if (h + s > hz + sz)
                    {
                        float transfer = s + h - avg; if (transfer > s)
                        {
                            transfer = s;
                        }
                        s -= transfer; sz += transfer;
                    }
                    else
                    {
                        float transfer = sz + hz - avg; if (transfer > sz)
                        {
                            transfer = sz;
                        }
                        sz -= transfer; s += transfer;
                    }

                    //side pairs
                    avg = (hx + sx + sz + hz) / 2;
                    if (hx + sx > hz + sz)
                    {
                        float transfer = sx + hx - avg; if (transfer > sx)
                        {
                            transfer = sx;
                        }
                        sx -= transfer; sz += transfer;
                    }
                    else
                    {
                        float transfer = sz + hz - avg; if (transfer > sz)
                        {
                            transfer = sz;
                        }
                        sz -= transfer; sx += transfer;
                    }

                    avg = (hX + sX + sZ + hZ) / 2;
                    if (hX + sX > hZ + sZ)
                    {
                        float transfer = sX + hX - avg; if (transfer > sX)
                        {
                            transfer = sX;
                        }
                        sX -= transfer; sZ += transfer;
                    }
                    else
                    {
                        float transfer = sZ + hZ - avg; if (transfer > sZ)
                        {
                            transfer = sZ;
                        }
                        sZ -= transfer; sX += transfer;
                    }

                    avg = (hx + sx + sZ + hZ) / 2;
                    if (hx + sx > hZ + sZ)
                    {
                        float transfer = sx + hx - avg; if (transfer > sx)
                        {
                            transfer = sx;
                        }
                        sx -= transfer; sZ += transfer;
                    }
                    else
                    {
                        float transfer = sZ + hZ - avg; if (transfer > sZ)
                        {
                            transfer = sZ;
                        }
                        sZ -= transfer; sx += transfer;
                    }

                    avg = (hX + sX + sz + hz) / 2;
                    if (hX + sX > hz + sz)
                    {
                        float transfer = sX + hX - avg; if (transfer > sX)
                        {
                            transfer = sX;
                        }
                        sX -= transfer; sz += transfer;
                    }
                    else
                    {
                        float transfer = sz + hz - avg; if (transfer > sz)
                        {
                            transfer = sz;
                        }
                        sz -= transfer; sX += transfer;
                    }
                    //}

                    //additionally levelling

                    /*int sNum = 0; //number of cells with sediment
                     * float total = 0; //total height + sediment level
                     * if (s>0.001f) { sNum++; total+=h+s; }
                     * if (sx>0.001f) { sNum++; total+=hx+sx; }  if (sX>0.001f) { sNum++; total+=hX+sX; }
                     * if (sz>0.001f) { sNum++; total+=hz+sz; }  if (sZ>0.001f) { sNum++; total+=hZ+sZ; }
                     *
                     * float totalAvg = total / sNum;
                     * if (s>0.001f) s=totalAvg-h;
                     * if (sx>0.001f) sx=totalAvg-hx;   if (sX>0.001f) sX=totalAvg-hX;
                     * if (sz>0.001f) sz=totalAvg-hz;  if (sZ>0.001f) sZ=totalAvg-hZ;*/

                    //to matrix
                    m      = sediments.array;
                    m[pos] = s; m[pos - 1] = sx; m[pos + 1] = sX; m[pos - sizeX] = sz; m[pos + sizeX] = sZ;

                    if (sedimentSum != null)
                    {
                        m       = sedimentSum.array;
                        m[pos] += s; m[pos - 1] += sx; m[pos + 1] += sX; m[pos - sizeX] += sz; m[pos + sizeX] += sZ;
                    }
                }
            }
            #endregion

            #region Writing sediments back to height, adding smooth and ruffle

            for (int j = count - 1; j >= 0; j--)
            {
                //writing heights
                heights.array[j] += sediments.array[j];

                seed = 214013 * seed + 2531011;
                float random = ((seed >> 16) & 0x7FFF) / 32768f;

                int pos = order[j];
                if (pos < 0)
                {
                    continue;
                }

                float[] m = heights.array; int sizeX = heights.rect.size.x;
                float   h = m[pos]; float hx = m[pos - 1]; float hX = m[pos + 1]; float hz = m[pos - sizeX]; float hZ = m[pos + sizeX];

                //smoothing sediments a bit
                float s = sediments.array[pos];
                if (s > 0.0001f)
                {
                    float smooth = s / 2f; if (smooth > 0.75f)
                    {
                        smooth = 0.75f;
                    }
                    heights.array[pos] = h * (1 - smooth) + (hx + hX + hz + hZ) / 4f * smooth;
                }

                else
                {
                    float maxHeight = hx; if (hX > maxHeight)
                    {
                        maxHeight = hX;
                    }
                    if (hz > maxHeight)
                    {
                        maxHeight = hz;
                    }
                    if (hZ > maxHeight)
                    {
                        maxHeight = hZ;
                    }
                    float minHeight = hx; if (hX < minHeight)
                    {
                        minHeight = hX;
                    }
                    if (hz < minHeight)
                    {
                        minHeight = hz;
                    }
                    if (hZ < minHeight)
                    {
                        minHeight = hZ;
                    }
                    float randomHeight = random * (maxHeight - minHeight) + minHeight;
                    heights.array[pos] = heights.array[pos] * (1 - ruffle) + randomHeight * ruffle;
                }
                //Cross height = new Cross(heights, pos);
                //float maxAround = Mathf.Max(heights.array[pos-1], heights.array[pos+1], heights.array[pos-heights.rect.size.x], heights.array[pos+heights.rect.size.x]);
                //heights.array[pos] = Mathf.Min(heights.array[pos], maxAround);

                //heights.array[pos] = Mathf.Min(height.c, height.maxAround);
                //heights.array[pos] = Mathf.Min(height.c, height.avgAround)*0.5f + height.c*0.5f;

                //float maxHeight = height.maxAround;
                //float minHeight = height.minAround;
                //float randomHeight = random*(maxHeight-minHeight) + minHeight;
                //heights.array[pos] = heights.array[pos]*(1-ruffle) + randomHeight*ruffle;
            }
            #endregion
        }                //erosion iteration
Ejemplo n.º 5
0
        public void DeleteGenerator(Generator gen)
        {
            //removing generator from 'ready' and 'results' arrays
            ChangeGenerator(gen);

            //manually resetting all dependent generators ready stae
            for (int g = 0; g < list.Length; g++)
            {
                if (list[g].IsDependentFrom(gen))
                {
                    ChangeGenerator(list[g]);
                }
            }

            //clearing if it is output gen
            //if (gen is IOutput)
            //	foreach (MapMagic.Chunk chunk in MapMagic.instance.terrains.Objects())
            //		(gen as IOutput).Clear(chunk);

            //removing group members if it is group
                        #if UNITY_EDITOR
            if (gen is Group &&
                UnityEditor.EditorUtility.DisplayDialog("Remove Containing Generators", "Do you want to remove a contaning generators as well?", "Remove Generators", "Remove Group Only"))
            {
                Group group = gen as Group;
                group.Populate();
                for (int g = group.generators.Count - 1; g >= 0; g--)
                {
                    MapMagic.instance.gens.DeleteGenerator(group.generators[g]);
                }
            }
                        #endif

            //unlinking and removing it's reference in inputs and outputs
            //for (int g=0; g<list.Length; g++)
            //	foreach (Generator.Input input in list[g].Inputs())
            //		if (input.linkGen == gen) input.Unlink();
            UnlinkGenerator(gen);

            //removing from output generators list
            //if (gen is IOutput)
            //	Extensions.ArrayRemove(ref outputs, gen);

            //removing from array
            ArrayTools.Remove(ref list, gen);

            //if it is preview - applying splats
            if (gen is PreviewOutput)
            {
                SplatOutput splatOut = GetGenerator <SplatOutput>();
                if (splatOut != null)
                {
                    ChangeGenerator(splatOut);
                }
                else
                {
                    foreach (MapMagic.Chunk chunk in MapMagic.instance.terrains.Objects())
                    {
                        chunk.ClearSplats();
                    }
                }
            }
        }
Ejemplo n.º 6
0
		private void OnGUI() { DrawWindow(); if (repaint) DrawWindow(); repaint = false; } //drawing window, or doing it twice if repaint is needed
		private void DrawWindow()
		{
			if (MapMagic.instance == null) MapMagic.instance = FindObjectOfType<MapMagic>();
			MapMagic script = MapMagic.instance;
			if (script==null) return;
			if (MapMagic.instance.guiGens == null) MapMagic.instance.guiGens = MapMagic.instance.gens;
			GeneratorsAsset gens = MapMagic.instance.guiGens;
			//if (script.guiGens != null) gens = script.guiGens;
			//if (script.gens==null) script.gens = ScriptableObject.CreateInstance<GeneratorsAsset>();

			//un-selecting field on drag
			if (Event.current.button != 0) UnityEditor.EditorGUI.FocusTextInControl("");

			//startingscript.layout
			
			if (script.layout==null) 
				{ script.layout = new Layout(); script.layout.scroll = script.guiScroll; script.layout.zoom = script.guiZoom; script.layout.maxZoom = 1f; }
			script.layout.Zoom(); script.layout.Scroll(); //scrolling and zooming
			script.layout.field = this.position;
			
			//unity 5.4 beta
			if (Event.current.type == EventType.MouseDrag || Event.current.type == EventType.layout) return; 

			if (script.guiDebug) Profiler.BeginSample("Redraw Window");

			//using middle mouse click events
			if (Event.current.button == 2) Event.current.Use();

			//undo
			Undo.undoRedoPerformed -= PerformUndo;
			Undo.undoRedoPerformed += PerformUndo;

			//setting title content
			titleContent = new GUIContent("Map Magic");
			titleContent.image =script.layout.GetIcon("MapMagic_WindowIcon");

			//drawing background
			Vector2 windowZeroPos =script.layout.ToInternal(Vector2.zero);
			windowZeroPos.x = ((int)(windowZeroPos.x/64f)) * 64; 
			windowZeroPos.y = ((int)(windowZeroPos.y/64f)) * 64; 
			script.layout.Icon( 
				"MapMagic_Background",
				new Rect(windowZeroPos - new Vector2(64,64), 
				position.size + new Vector2(128,128)), 
				tile:true);

			//drawing test center
			//script.layout.Button("Zero", new Rect(-10,-10,20,20));

			//calculating visible area
			Rect visibleArea = script.layout.ToInternal( new Rect(0,0,position.size.x,position.size.y) );
			if (forceAll) { visibleArea = new Rect(-200000,-200000,400000,400000); forceAll = false; }
			//visibleArea = new Rect(visibleArea.x+100, visibleArea.y+100, visibleArea.width-200, visibleArea.height-200);
			//layout.Label("Area", helpBox:true, rect:visibleArea);

			//checking if all generators are loaded, and none of them is null
			for (int i=gens.list.Length-1; i>=0; i--)
			{
				if (gens.list[i] == null) { ArrayTools.RemoveAt(ref gens.list, i); continue; }
				foreach (Generator.Input input in gens.list[i].Inputs()) 
				{
					if (input == null) continue;
					if (input.linkGen == null) input.Link(null, null);
				}
			}

			#region Drawing groups
			if (script.guiDebug) Profiler.BeginSample("Drawing Groups");

				for(int i=0; i<gens.list.Length; i++)
				{
					if (!(gens.list[i] is Group)) continue;
					Group group = gens.list[i] as Group;

					//checking if this is withinscript.layout field
					if (group.guiRect.x > visibleArea.x+visibleArea.width || group.guiRect.y > visibleArea.y+visibleArea.height ||
						group.guiRect.x+group.guiRect.width < visibleArea.x || group.guiRect.y+group.guiRect.height < visibleArea.y) 
							if (group.guiRect.width > 0.001f &&script.layout.dragState != Layout.DragState.Drag) continue; //if guiRect initialized and not dragging

					//settingscript.layout data
					group.layout.field = group.guiRect;
					group.layout.scroll =script.layout.scroll;
					group.layout.zoom =script.layout.zoom;

					group.OnGUI();

					group.guiRect = group.layout.field;
				}
			
			if (script.guiDebug) Profiler.EndSample();
			#endregion

			#region Drawing connections (before generators to make them display under nodes)
			if (script.guiDebug) Profiler.BeginSample("Drawing Connections");

				foreach(Generator gen in gens.list)
				{
					foreach (Generator.Input input in gen.Inputs())
					{
						if (input==null || input.link == null) continue; //input could be null in layered generators
						if (gen is Portal)
						{ 
							Portal portal = (Portal)gen;
							if (!portal.drawInputConnection) continue;
						}
						script.layout.Spline(input.link.guiConnectionPos, input.guiConnectionPos, color:Generator.CanConnect(input.link,input)? input.guiColor : Color.red);
					}
				}

			if (script.guiDebug) Profiler.EndSample();
			#endregion

			#region creating connections (after generators to make clicking in inout work)
			if (script.guiDebug) Profiler.BeginSample("Creating Connections");

			int dragIdCounter = gens.list.Length+1;
				foreach (Generator gen in gens.list)
					foreach (Generator.IGuiInout inout in gen.Inouts())
				{
					if (inout == null) continue;
					if (script.layout.DragDrop(inout.guiRect, dragIdCounter))
					{
						//finding target
						Generator.IGuiInout target = null;
						foreach (Generator gen2 in gens.list)
							foreach (Generator.IGuiInout inout2 in gen2.Inouts())
								if (inout2.guiRect.Contains(script.layout.dragPos)) target = inout2;

						//converting inout to Input (or Output) and target to Output (or Input)
						Generator.Input input = inout as Generator.Input;		if (input==null) input = target as Generator.Input;
						Generator.Output output = inout as Generator.Output;	if (output==null) output = target as Generator.Output;

						//connection validity test
						bool canConnect = input!=null && output!=null && Generator.CanConnect(output,input);

						//infinite loop test
						if (canConnect)
						{ 
							Generator outputGen = output.GetGenerator(gens.list);
							Generator inputGen = input.GetGenerator(gens.list);
							if (inputGen == outputGen || outputGen.IsDependentFrom(inputGen)) canConnect = false;
						}

						//drag
						//if (script.layout.dragState==Layout.DragState.Drag) //commented out because will not be displayed on repaint otherwise
						//{
							if (input == null)script.layout.Spline(output.guiConnectionPos,script.layout.dragPos, color:Color.red);
							else if (output == null)script.layout.Spline(script.layout.dragPos, input.guiConnectionPos, color:Color.red);
							else script.layout.Spline(output.guiConnectionPos, input.guiConnectionPos, color:canConnect? input.guiColor : Color.red);
						//}

						//release
						if (script.layout.dragState==Layout.DragState.Released && input!=null) //on release. Do nothing if input not defined
						{
							Undo.RecordObject (gens, "MapMagic Connection"); 
							gens.setDirty = !gens.setDirty;

							input.Unlink();
							if (canConnect) input.Link(output, output.GetGenerator(gens.list));
							gens.ChangeGenerator(gen);

							EditorUtility.SetDirty(gens);
						}
					}
					dragIdCounter++;
				}

			if (script.guiDebug) Profiler.EndSample();
			#endregion

			#region Drawing generators
			if (script.guiDebug) Profiler.BeginSample("Drawing Generators");

				for(int i=0; i<gens.list.Length; i++)
				{
					Generator gen = gens.list[i];
					if (gen is Group) continue; //skipping groups

					//checking if this generator is withinscript.layout field
					if (gen.guiRect.x > visibleArea.x+visibleArea.width || gen.guiRect.y > visibleArea.y+visibleArea.height ||
						gen.guiRect.x+gen.guiRect.width < visibleArea.x || gen.guiRect.y+gen.guiRect.height < visibleArea.y) 
							if (gen.guiRect.width > 0.001f &&script.layout.dragState != Layout.DragState.Drag) continue; //if guiRect initialized and not dragging

					if (gen.layout == null) gen.layout = new Layout();
					gen.layout.field = gen.guiRect;
					gen.layout.field.width = MapMagic.instance.guiGeneratorWidth;
				
					//gen.layout.OnBeforeChange -= RecordGeneratorUndo;
					//gen.layout.OnBeforeChange += RecordGeneratorUndo;
					gen.layout.undoObject = gens;
					gen.layout.undoName = "MapMagic Generators Change"; 
					gen.layout.dragChange = true;
					gen.layout.disabled = locked;

					//copyscript.layout params
					gen.layout.scroll =script.layout.scroll;
					gen.layout.zoom =script.layout.zoom;

					//drawing
					if (script.guiDebug) Profiler.BeginSample("Generator GUI");
					gen.OnGUIBase();
					if (script.guiDebug) Profiler.EndSample();

					//instant generate on params change
					if (gen.layout.change) 
					{
						gens.ChangeGenerator(gen);
						repaint=true; Repaint();

						EditorUtility.SetDirty(gens);
						
					}
			
					if (gen.guiRect.width<1 && gen.guiRect.height<1) { repaint=true;  Repaint(); } //repainting if some of the generators rect is 0
					gen.guiRect = gen.layout.field;
				}

			if (script.guiDebug) Profiler.EndSample();
			#endregion

			#region Toolbar
			if (script.guiDebug) Profiler.BeginSample("Toolbar");

				if (script.toolbarLayout==null) script.toolbarLayout = new Layout();
				script.toolbarLayout.margin = 0; script.toolbarLayout.rightMargin = 0;
				script.toolbarLayout.field.width = this.position.width;
				script.toolbarLayout.field.height = 18;
				script.toolbarLayout.cursor = new Rect();
				//script.toolbarLayout.window = this;
				script.toolbarLayout.Par(18, padding:0);

				EditorGUI.LabelField(script.toolbarLayout.field, "", EditorStyles.toolbarButton);

				//drawing state icon
				script.toolbarLayout.Inset(25);
				if (!MapMagic.instance.terrains.complete) { script.toolbarLayout.Icon("MapMagic_Loading", new Rect(5,0,16,16), animationFrames:12); Repaint(); }
				else script.toolbarLayout.Icon("MapMagic_Success", new Rect(5,0,16,16));
				//TODO: changed sign

				//generate buttons
				if (GUI.Button(script.toolbarLayout.Inset(120,padding:0), "Generate Changed", EditorStyles.toolbarButton) && MapMagic.instance.enabled) MapMagic.instance.Generate();
				if (GUI.Button(script.toolbarLayout.Inset(120,padding:0), "Force Generate All", EditorStyles.toolbarButton) && MapMagic.instance.enabled) MapMagic.instance.ForceGenerate();

				//seed field
				script.toolbarLayout.Inset(10);
				Rect seedLabelRect = script.toolbarLayout.Inset(34); seedLabelRect.y+=1; seedLabelRect.height-=4;
				Rect seedFieldRect = script.toolbarLayout.Inset(64); seedFieldRect.y+=2; seedFieldRect.height-=4;
				EditorGUI.LabelField(seedLabelRect, "Seed:", EditorStyles.miniLabel);
				int newSeed = EditorGUI.IntField(seedFieldRect, MapMagic.instance.seed, EditorStyles.toolbarTextField);
				if (newSeed != MapMagic.instance.seed) { MapMagic.instance.seed = newSeed; if (MapMagic.instance.instantGenerate) MapMagic.instance.ForceGenerate(); }

				//right part
				script.toolbarLayout.Inset(script.toolbarLayout.field.width - script.toolbarLayout.cursor.x - 150,padding:0);

				//drawing exit biome button
				Rect biomeRect = script.toolbarLayout.Inset(80, padding:0);
				if (MapMagic.instance.guiGens != null && MapMagic.instance.guiGens != MapMagic.instance.gens) 
				{
					if (script.toolbarLayout.Button("", biomeRect, icon:"MapMagic_ExitBiome", style:EditorStyles.toolbarButton)) MapMagic.instance.guiGens = null;
					script.toolbarLayout.Label("Exit Biome", new Rect(script.toolbarLayout.cursor.x-60, script.toolbarLayout.cursor.y+3, 60, script.toolbarLayout.cursor.height), fontSize:9);
				}

				//focus button
				
			//	if (GUI.Button(script.toolbarLayout.Inset(100,padding:0), "Focus", EditorStyles.toolbarButton)) FocusOnGenerators();
				if (script.toolbarLayout.Button("", script.toolbarLayout.Inset(23,padding:0), icon:"MapMagic_Focus", style:EditorStyles.toolbarButton)) FocusOnGenerators();
				if (script.toolbarLayout.Button("", script.toolbarLayout.Inset(60,padding:0), icon:"MapMagic_Zoom", style:EditorStyles.toolbarButton))script.layout.zoom=1;
				script.toolbarLayout.Label((int)(script.layout.zoom*100)+"%", new Rect(script.toolbarLayout.cursor.x-42, script.toolbarLayout.cursor.y+3, 42, script.toolbarLayout.cursor.height), fontSize:8);

			if (script.guiDebug) Profiler.EndSample();
			#endregion

			#region Draging
			if (script.guiDebug) Profiler.BeginSample("Dragging");

				//dragging generators
				for(int i=gens.list.Length-1; i>=0; i--)
				{
					Generator gen = gens.list[i];
					if (gen is Group) continue;
					gen.layout.field = gen.guiRect;

					//dragging
					if (script.layout.DragDrop(gen.layout.field, i)) 
					{
						if (script.layout.dragState == Layout.DragState.Pressed) 
						{
							Undo.RecordObject (gens, "MapMagic Generators Drag");
							gens.setDirty = !gens.setDirty;
						}
						if (script.layout.dragState == Layout.DragState.Drag ||script.layout.dragState == Layout.DragState.Released) 
						{ 
							//moving inout rects to remove lag
							//foreach (Generator.IGuiInout inout in gen.Inouts())
							//	inout.guiRect = new Rect(inout.guiRect.position+layout.dragDelta, inout.guiRect.size);
							gen.Move(script.layout.dragDelta,true);
							repaint=true; Repaint(); 

							EditorUtility.SetDirty(gens);
						}
					}

					//saving all generator rects
					gen.guiRect = gen.layout.field;
				}

				//dragging groups
				for (int i=gens.list.Length-1; i>=0; i--)
				{
					//Generator gen = gens.list[i];
					Group group = gens.list[i] as Group;
					if (group == null) continue;
					group.layout.field = group.guiRect;

					//resizing
					group.layout.field =script.layout.ResizeRect(group.layout.field, i+20000);

					//dragging
					if (script.layout.DragDrop(group.layout.field, i)) 
					{
						if (script.layout.dragState == Layout.DragState.Pressed) 
						{
							Undo.RecordObject (gens, "MapMagic Group Drag");
							gens.setDirty = !gens.setDirty;
							group.Populate(gens);
						}
						if (script.layout.dragState == Layout.DragState.Drag ||script.layout.dragState == Layout.DragState.Released) 
						{ 
							group.Move(script.layout.dragDelta,true);
							repaint=true; Repaint(); 

							EditorUtility.SetDirty(gens);
						}
						if (script.layout.dragState == Layout.DragState.Released && group != null) gens.SortGroups();
					}

					//saving all group rects
					group.guiRect = group.layout.field;
				}

			if (script.guiDebug) Profiler.EndSample();
			#endregion

			//right-click menus
			if (Event.current.type == EventType.MouseDown && Event.current.button == 1) DrawPopup();

			//debug center
			//EditorGUI.HelpBox(script.layout.ToLocal(new Rect(-25,-10,50,20)), "Zero", MessageType.None);

			//assigning portal popup action
			Portal.OnChooseEnter -= DrawPortalSelector; Portal.OnChooseEnter += DrawPortalSelector;

			//saving scroll and zoom
			script.guiScroll =script.layout.scroll; script.guiZoom =script.layout.zoom;  

			//producing synthetic lag to test performance
			//for (int i=0; i<10; i++) Debug.LogWarning("Lag");

			//drawing lock warning
			if (locked)
			{
				script.toolbarLayout.Label("", rect: new Rect(4,20,300,155), helpbox:true);
				script.toolbarLayout.Label("You are using the demo version of Map Magic. " + 
					"It should be used for evaluation purposes only and has a save limitation: although the node graph could be saved, " + 
					"it could not be edited after the load. " +
					"You can get a fully functional version at the Asset Store or reset your graph to proceed editing:", 
					rect: new Rect(4,20,300,155), helpbox:true);
				if (script.toolbarLayout.Button("Get MapMagic at the Asset Store", rect: new Rect(20,120, 260, 22))) Application.OpenURL("https://www.assetstore.unity3d.com/en/#!/content/56762"); 
				if (script.toolbarLayout.Button("Reset node graph", rect: new Rect(20,145, 260, 18))) 
				{ 
					MapMagic.instance.gens = ScriptableObject.CreateInstance<GeneratorsAsset>(); 
					gens = MapMagic.instance.gens;
					MapMagic.instance.guiGens = gens;
					gens.OnBeforeSerialize(); 
				}
			}

			if (script.guiDebug) Profiler.EndSample();
		}
        public void DeleteGenerator(Generator gen)
        {
            //removing generator from 'ready' and 'results' arrays
            ChangeGenerator(gen);

            //manually resetting all dependent generators ready stae
            for (int g = 0; g < list.Length; g++)
            {
                if (list[g].IsDependentFrom(gen))
                {
                    ChangeGenerator(list[g]);
                }
            }

            //clearing if it is output gen
            //if (gen is IOutput)
            //	foreach (Chunk chunk in MapMagic.instance.terrains.Objects())
            //		(gen as IOutput).Clear(chunk);

            //removing group members if it is group
                        #if UNITY_EDITOR
            if (gen is Group)
            {
                int dialogResult = UnityEditor.EditorUtility.DisplayDialogComplex("Remove Containing Generators", "Do you want to remove a contaning generators as well?", "Remove Generators", "Remove Group Only", "Cancel");
                if (dialogResult == 2)
                {
                    return;                          //cancel
                }
                if (dialogResult == 0)               //generators
                {
                    Group group = gen as Group;
                    group.Populate(this);
                    for (int g = group.generators.Count - 1; g >= 0; g--)
                    {
                        DeleteGenerator(group.generators[g]);
                    }
                }
            }
                        #endif

            //unlinking and removing it's reference in inputs and outputs
            //for (int g=0; g<list.Length; g++)
            //	foreach (Generator.Input input in list[g].Inputs())
            //		if (input.linkGen == gen) input.Unlink();
            UnlinkGenerator(gen);

            //removing from output generators list
            //if (gen is IOutput)
            //	Extensions.ArrayRemove(ref outputs, gen);

            //removing from array
            ArrayTools.Remove(ref list, gen);

            //removing from preview
            if (MapMagic.instance.previewGenerator == gen)
            {
                MapMagic.instance.previewGenerator = null; MapMagic.instance.previewOutput = null;
            }

            //force regenerate if it was an output
            if (gen is Generator.IOutput)
            {
                MapMagic.instance.ForceGenerate();
            }
        }
Ejemplo n.º 8
0
		public void DrawPopup ()
		{
			Vector2 mousePos = layout.ToInternal(Event.current.mousePosition);
				
			//finding something that was clicked
			Generator clickedGenerator = null;
			for (int i=0; i<MapMagic.instance.gens.list.Length; i++) 
			{
				Generator gen = MapMagic.instance.gens.list[i];
				if (gen.guiRect.Contains(mousePos) && !(gen is Group)) clickedGenerator = MapMagic.instance.gens.list[i];
			}

			Group clickedGroup = null;
			for (int i=0; i<MapMagic.instance.gens.list.Length; i++) 
			{
				Generator gen = MapMagic.instance.gens.list[i];
				if (gen.guiRect.Contains(mousePos) && gen is Group) clickedGroup = MapMagic.instance.gens.list[i] as Group;
			}

			if (clickedGenerator == null) clickedGenerator = clickedGroup;
			
			Generator.Output clickedOutput = null;
			for (int i=0; i<MapMagic.instance.gens.list.Length; i++) 
				foreach (Generator.Output output in MapMagic.instance.gens.list[i].Outputs())
					if (output.guiRect.Contains(mousePos)) clickedOutput = output;

			//create
			Dictionary<string, PopupMenu.MenuItem> itemsDict = new Dictionary<string, PopupMenu.MenuItem>();
			
			List<System.Type> allGeneratorTypes = typeof(Generator).GetAllChildTypes();
			for (int i=0; i<allGeneratorTypes.Count; i++)
			{
				if (System.Attribute.IsDefined(allGeneratorTypes[i], typeof(GeneratorMenuAttribute)))
				{
					GeneratorMenuAttribute attribute = System.Attribute.GetCustomAttribute(allGeneratorTypes[i], typeof(GeneratorMenuAttribute)) as GeneratorMenuAttribute;
					System.Type genType = allGeneratorTypes[i];

					if (attribute.disabled) continue;

					PopupMenu.MenuItem item = new PopupMenu.MenuItem(attribute.name, delegate () { CreateGenerator(genType, mousePos); });
					item.priority = attribute.priority;

					if (attribute.menu.Length != 0)
					{
						if (!itemsDict.ContainsKey(attribute.menu)) itemsDict.Add(attribute.menu, new PopupMenu.MenuItem(attribute.menu, subs:new PopupMenu.MenuItem[0]));
						ArrayTools.Add(ref itemsDict[attribute.menu].subItems, item);
					}
					else itemsDict.Add(attribute.name, item);
				}
			} 
			PopupMenu.MenuItem[] createItems = new PopupMenu.MenuItem[itemsDict.Count];
			itemsDict.Values.CopyTo(createItems, 0);

			//create group
			//PopupMenu.MenuItem createGroupItem = new PopupMenu.MenuItem("Group",  delegate () { CreateGroup(mousePos); });
			//Extensions.ArrayAdd(ref createItems, createItems.Length-1, createGroupItem);

			//additional name
			string additionalName = "All";
			if (clickedGenerator != null) 
			{
				additionalName = "Generator";
				if (clickedGenerator is Group) additionalName = "Group";
			}

			//preview
			PopupMenu.MenuItem[] previewSubs = new PopupMenu.MenuItem[]
			{
				new PopupMenu.MenuItem("On Terrain", delegate() {PreviewOutput(clickedGenerator, clickedOutput, false);}, disabled:clickedOutput==null||clickedGenerator==null), 
				new PopupMenu.MenuItem("In Window", delegate() {PreviewOutput(clickedGenerator, clickedOutput, true);}, disabled:clickedOutput==null||clickedGenerator==null),
				new PopupMenu.MenuItem("Clear", delegate() {PreviewOutput(null, null, false);}, disabled:MapMagic.instance.gens.GetGenerator<PreviewOutput>()==null)
			};

			PopupMenu.MenuItem[] popupItems = new PopupMenu.MenuItem[]
			{
				new PopupMenu.MenuItem("Create", createItems),
				new PopupMenu.MenuItem("Save " + additionalName,	delegate () { SaveGenerator(clickedGenerator, mousePos); }),
				new PopupMenu.MenuItem("Load",						delegate () { LoadGenerator(mousePos); }),
				new PopupMenu.MenuItem("Duplicate",					delegate () { DuplicateGenerator(clickedGenerator); }),
				new PopupMenu.MenuItem("Remove",	delegate () { if (clickedGenerator!=null) DeleteGenerator(clickedGenerator); },	disabled:(clickedGenerator==null)),
				new PopupMenu.MenuItem("Reset",						delegate () { if (clickedGenerator!=null) ResetGenerator(clickedGenerator); },	disabled:clickedGenerator==null), 
				new PopupMenu.MenuItem("Preview", previewSubs)
			};

			PopupMenu.DrawPopup(popupItems, Event.current.mousePosition, closeAllOther:true);
		}