Example #1
0
        public override void Generate(Chunk chunk, Biome biome = null)
        {
            //return on stop/disable
            if (chunk.stop || !enabled)
            {
                return;
            }

            InstanceRandom rnd = new InstanceRandom(MapMagic.instance.seed + seed /* + chunk.coord.x*1000 + chunk.coord.z*/);

            // Calculate the total weight of all layers
            float sumOfWeights = 0f;

            for (int i = 0; i < layers.Length; i++)
            {
                sumOfWeights += layers[i].weight;
            }

            // Pick a random value less than the total weight
            float rouletteSelection = rnd.Random(0, sumOfWeights);

            // Loop through the layers, keeping a running sum of weights
            // The layer that contains the chosen rouletteWeight gets sent the input
            // All other layers get sent the default matrix
            float prevRunningWeight = 0f;
            float nextRunningWeight = 0f;

            for (int i = 0; i < layers.Length; i++)
            {
                nextRunningWeight = prevRunningWeight + layers[i].weight;
                if (prevRunningWeight < rouletteSelection && nextRunningWeight > rouletteSelection)
                {
                    layers[i].output.SetObject(chunk, (Matrix)input.GetObject(chunk));
                }
                else
                {
                    layers[i].output.SetObject(chunk, chunk.defaultMatrix);
                }
                prevRunningWeight = nextRunningWeight;
            }
        }
        public override void Generate(Chunk chunk, Biome biome = null)
        {
            SpatialHash spatialHash = chunk.defaultSpatialHash;

            if (!enabled)
            {
                output.SetObject(chunk, spatialHash); return;
            }
            if (chunk.stop)
            {
                return;
            }

            // Note that spacing is specified in terms of the resolution of the terrain.
            // The *world spacing* will be equal to the spacing specified here / the terrain size * terrain resolution
            for (float z = zOffset; z < spatialHash.size; z += zSpacing)
            {
                for (float x = xOffset; x < spatialHash.size; x += xSpacing)
                {
                    Vector2 candidate = new Vector2((spatialHash.offset.x + x), (spatialHash.offset.y + z));
                    spatialHash.Add(candidate, 0, 0, 1); //adding only if some suitable candidate found
                    if (xSpacing == 0)
                    {
                        break;
                    }
                }
                if (zSpacing == 0)
                {
                    break;
                }
            }

            if (chunk.stop)
            {
                return;
            }
            output.SetObject(chunk, spatialHash);
        }
Example #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();

		}
        public override void Generate(Chunk chunk, Biome biome = null)
        {
            //getting inputs
            SpatialHash minuend    = (SpatialHash)minuendIn.GetObject(chunk);
            SpatialHash subtrahend = (SpatialHash)subtrahendIn.GetObject(chunk);

            //return on stop/disable/null input
            if (chunk.stop || minuend == null)
            {
                return;
            }
            if (!enabled || subtrahend == null || subtrahend.Count == 0)
            {
                minuendOut.SetObject(chunk, minuend); return;
            }

            //preparing output
            SpatialHash result = new SpatialHash(minuend.offset, minuend.size, minuend.resolution);

            //transforming distance to map-space
            float dist = distance / MapMagic.instance.terrainSize * MapMagic.instance.resolution;

            //finding maximum seek distance
            float maxObjSize = 0;

            foreach (SpatialObject obj in subtrahend.AllObjs())
            {
                if (obj.size > maxObjSize)
                {
                    maxObjSize = obj.size;
                }
            }
            maxObjSize = maxObjSize / MapMagic.instance.terrainSize * MapMagic.instance.resolution;             //transforming to map-space
            float maxDist = dist * (1 - sizeFactor) + dist * maxObjSize * sizeFactor;

            foreach (SpatialObject obj in minuend.AllObjs())
            {
                bool inRange = false;

                foreach (SpatialObject closeObj in subtrahend.ObjsInRange(obj.pos, maxDist))
                {
                    float minDist = (obj.pos - closeObj.pos).magnitude;
                    if (minDist < dist * (1 - sizeFactor) + dist * closeObj.size * sizeFactor)
                    {
                        inRange = true; break;
                    }
                }

                if (!inRange)
                {
                    result.Add(obj);
                }

                //SpatialObject closestObj = subtrahend.Closest(obj.pos,false);
                //float minDist = (obj.pos - closestObj.pos).magnitude;

                //if (minDist > dist*(1-sizeFactor) + dist*closestObj.size*sizeFactor) result.Add(obj);
            }

            //setting output
            if (chunk.stop)
            {
                return;
            }
            minuendOut.SetObject(chunk, result);
        }
        public override void Generate(Chunk chunk, Biome biome = null)
        {
            //getting inputs
            SpatialHash objects = (SpatialHash)objectsIn.GetObject(chunk);
            Matrix      src     = (Matrix)canvasIn.GetObject(chunk);

            //return on stop/disable/null input
            if (chunk.stop || objects == null)
            {
                return;
            }
            if (!enabled)
            {
                output.SetObject(chunk, src); return;
            }

            //preparing output
            Matrix dst;

            if (src != null)
            {
                dst = src.Copy(null);
            }
            else
            {
                dst = chunk.defaultMatrix;
            }

            //finding maximum radius
            float maxRadius = radius;

            if (sizeFactor > 0.00001f)
            {
                float maxObjSize = 0;
                foreach (SpatialObject obj in objects.AllObjs())
                {
                    if (obj.size > maxObjSize)
                    {
                        maxObjSize = obj.size;
                    }
                }
                maxObjSize = maxObjSize / MapMagic.instance.terrainSize * MapMagic.instance.resolution;                 //transforming to map-space
                maxRadius  = radius * (1 - sizeFactor) + radius * maxObjSize * sizeFactor;
            }

            //preparing procedural matrices
            Matrix noiseMatrix   = new Matrix(new CoordRect(0, 0, maxRadius * 2 + 2, maxRadius * 2 + 2));
            Matrix percentMatrix = new Matrix(new CoordRect(0, 0, maxRadius * 2 + 2, maxRadius * 2 + 2));

            foreach (SpatialObject obj in objects.AllObjs())
            {
                //finding current radius
                float curRadius = radius * (1 - sizeFactor) + radius * obj.size * sizeFactor;
                curRadius = curRadius / MapMagic.instance.terrainSize * MapMagic.instance.resolution;                 //transforming to map-space

                //resizing procedural matrices
                CoordRect matrixSize = new CoordRect(0, 0, curRadius * 2 + 2, curRadius * 2 + 2);
                noiseMatrix.ChangeRect(matrixSize);
                percentMatrix.ChangeRect(matrixSize);

                //apply stamp
                noiseMatrix.rect.offset   = new Coord((int)(obj.pos.x - curRadius - 1), (int)(obj.pos.y - curRadius - 1));
                percentMatrix.rect.offset = new Coord((int)(obj.pos.x - curRadius - 1), (int)(obj.pos.y - curRadius - 1));

                CoordRect intersection = CoordRect.Intersect(noiseMatrix.rect, dst.rect);
                Coord     min = intersection.Min; Coord max = intersection.Max;
                for (int x = min.x; x < max.x; x++)
                {
                    for (int z = min.z; z < max.z; z++)
                    {
                        float dist    = Mathf.Sqrt((x - obj.pos.x + 0.5f) * (x - obj.pos.x + 0.5f) + (z - obj.pos.y + 0.5f) * (z - obj.pos.y + 0.5f));
                        float percent = 1f - dist / curRadius;
                        if (percent < 0 || dist > curRadius)
                        {
                            percent = 0;
                        }

                        percentMatrix[x, z] = percent;
                    }
                }

                //adjusting value by curve
                Curve c = new Curve(curve);
                for (int i = 0; i < percentMatrix.array.Length; i++)
                {
                    percentMatrix.array[i] = c.Evaluate(percentMatrix.array[i]);
                }

                //adding some noise
                if (useNoise)
                {
                    NoiseGenerator.Noise(noiseMatrix, noiseSize, 0.5f, offset: Vector2.zero);

                    for (int x = min.x; x < max.x; x++)
                    {
                        for (int z = min.z; z < max.z; z++)
                        {
                            float val = percentMatrix[x, z];
                            if (val < 0.0001f)
                            {
                                continue;
                            }

                            float noise = noiseMatrix[x, z];
                            if (val < 0.5f)
                            {
                                noise *= val * 2;
                            }
                            else
                            {
                                noise = 1 - (1 - noise) * (1 - val) * 2;
                            }

                            percentMatrix[x, z] = noise * noiseAmount + val * (1 - noiseAmount);
                        }
                    }
                }

                //applying matrices
                for (int x = min.x; x < max.x; x++)
                {
                    for (int z = min.z; z < max.z; z++)
                    {
                        //float distSq = (x-obj.pos.x)*(x-obj.pos.x) + (z-obj.pos.y)*(z-obj.pos.y);
                        //if (distSq > radius*radius) continue;

                        float percent = percentMatrix[x, z];
                        dst[x, z] = (maxHeight? 1:obj.height) * percent + dst[x, z] * (1 - percent);
                    }
                }
            }

            Matrix mask = (Matrix)maskIn.GetObject(chunk);

            if (mask != null)
            {
                Matrix.Mask(src, dst, mask);
            }
            if (safeBorders != 0)
            {
                Matrix.SafeBorders(src, dst, safeBorders);
            }

            //setting output
            if (chunk.stop)
            {
                return;
            }
            output.SetObject(chunk, dst);
        }
        public override void Generate(Chunk chunk, Biome biome = null)
        {
            Matrix matrix = (Matrix)input.GetObject(chunk); if (matrix != null)

            {
                matrix = matrix.Copy(null);
            }

            if (matrix == null)
            {
                matrix = chunk.defaultMatrix;
            }
            Matrix mask = (Matrix)maskIn.GetObject(chunk);

            if (chunk.stop)
            {
                return;
            }
            if (!enabled || intensity == 0 || cellCount == 0)
            {
                output.SetObject(chunk, matrix); return;
            }

            //NoiseGenerator.Noise(matrix,200,0.5f,Vector2.zero);
            //matrix.Multiply(amount);

            InstanceRandom random = new InstanceRandom(MapMagic.instance.seed + seed);

            //creating point matrix
            float             cellSize = 1f * matrix.rect.size.x / cellCount;
            Matrix2 <Vector3> points   = new Matrix2 <Vector3>(new CoordRect(0, 0, cellCount + 2, cellCount + 2));

            points.rect.offset = new Coord(-1, -1);

            Coord matrixSpaceOffset = new Coord((int)(matrix.rect.offset.x / cellSize), (int)(matrix.rect.offset.z / cellSize));

            //scattering points
            for (int x = -1; x < points.rect.size.x - 1; x++)
            {
                for (int z = -1; z < points.rect.size.z - 1; z++)
                {
                    Vector3 randomPoint = new Vector3(x + random.CoordinateRandom(x + matrixSpaceOffset.x, z + matrixSpaceOffset.z), 0, z + random.NextCoordinateRandom());
                    Vector3 centerPoint = new Vector3(x + 0.5f, 0, z + 0.5f);
                    Vector3 point       = randomPoint * (1 - uniformity) + centerPoint * uniformity;
                    point        = point * cellSize + new Vector3(matrix.rect.offset.x, 0, matrix.rect.offset.z);
                    point.y      = random.NextCoordinateRandom();
                    points[x, z] = point;
                }
            }

            Coord min = matrix.rect.Min; Coord max = matrix.rect.Max;

            for (int x = min.x; x < max.x; x++)
            {
                for (int z = min.z; z < max.z; z++)
                {
                    //finding current cell
                    Coord cell = new Coord((int)((x - matrix.rect.offset.x) / cellSize), (int)((z - matrix.rect.offset.z) / cellSize));

                    //finding min dist
                    float minDist = 200000000; float secondMinDist = 200000000;
                    float minHeight = 0;             //float secondMinHeight = 0;
                    for (int ix = -1; ix <= 1; ix++)
                    {
                        for (int iz = -1; iz <= 1; iz++)
                        {
                            Coord nearCell = new Coord(cell.x + ix, cell.z + iz);
                            //if (!points.rect.CheckInRange(nearCell)) continue; //no need to perform test as points have 1-cell border around matrix

                            Vector3 point = points[nearCell];
                            float   dist  = (x - point.x) * (x - point.x) + (z - point.z) * (z - point.z);
                            if (dist < minDist)
                            {
                                secondMinDist = minDist; minDist = dist;
                                minHeight     = point.y;
                            }
                            else if (dist < secondMinDist)
                            {
                                secondMinDist = dist;
                            }
                        }
                    }

                    float val = 0;
                    switch (blendType)
                    {
                    case BlendType.flat: val = minHeight; break;

                    case BlendType.closest: val = minDist / (MapMagic.instance.resolution * 16); break;

                    case BlendType.secondClosest: val = secondMinDist / (MapMagic.instance.resolution * 16); break;

                    case BlendType.cellular: val = (secondMinDist - minDist) / (MapMagic.instance.resolution * 16); break;

                    case BlendType.organic: val = (secondMinDist + minDist) / 2 / (MapMagic.instance.resolution * 16); break;
                    }
                    if (mask == null)
                    {
                        matrix[x, z] += val * intensity;
                    }
                    else
                    {
                        matrix[x, z] += val * intensity * mask[x, z];
                    }
                }
            }

            if (chunk.stop)
            {
                return;                         //do not write object is generating is stopped
            }
            output.SetObject(chunk, matrix);
        }
        public float uniformity = 0.1f;         //aka candidatesNum/100

        public override void Generate(Chunk chunk, Biome biome = null)
        {
            Matrix      probMatrix  = (Matrix)probability.GetObject(chunk);
            SpatialHash spatialHash = chunk.defaultSpatialHash;

            if (!enabled)
            {
                output.SetObject(chunk, spatialHash); return;
            }
            if (chunk.stop)
            {
                return;
            }

            InstanceRandom rnd = new InstanceRandom(MapMagic.instance.seed + seed + chunk.coord.x * 1000 + chunk.coord.z);

            //Rect terrainRect = terrain.coord.ToRect(terrain.size);
            //terrainRect.position += Vector2.one; terrainRect.size-=Vector2.one*2;

            //SpatialHash spatialHash = new SpatialHash(terrain.coord.ToVector2(terrain.size), terrain.size, 16);


            //float square = terrainRect.width * terrainRect.height;
            //float count = square*(density/1000000); //number of items per terrain

            //positioned scatter

            /*float sideCount = Mathf.Sqrt(count);
             * float step = spatialHash.size / sideCount;
             *
             * //int uniformity = 100;
             * //Random.seed = 12345;
             * for (float x=spatialHash.offset.x+step/2; x<spatialHash.offset.x+spatialHash.size-step/2; x+=step)
             *      for (float y=spatialHash.offset.y+step/2; y<spatialHash.offset.y+spatialHash.size-step/2; y+=step)
             * {
             *      Vector2 offset = new Vector2(((Random.value*2-1)*uniformity), ((Random.value*2-1)*uniformity));
             *      Vector2 point = new Vector2(x,y) + offset;
             *      if (point.x > spatialHash.size) point.x -= spatialHash.size; if (point.x < 0) point.x += spatialHash.size;
             *      if (point.y > spatialHash.size) point.y -= spatialHash.size; if (point.y < 0) point.y += spatialHash.size;
             *      spatialHash.Add(point, 0,0,0);
             * }*/

            //realRandom algorithm
            int candidatesNum = (int)(uniformity * 100);

            for (int i = 0; i < count; i++)
            {
                Vector2 bestCandidate = Vector3.zero;
                float   bestDist      = 0;

                for (int c = 0; c < candidatesNum; c++)
                {
                    Vector2 candidate = new Vector2((spatialHash.offset.x + 1) + (rnd.Random() * (spatialHash.size - 2.01f)), (spatialHash.offset.y + 1) + (rnd.Random() * (spatialHash.size - 2.01f)));

                    //checking if candidate available here according to probability map
                    if (probMatrix != null && probMatrix[candidate] < rnd.Random() + 0.0001f)
                    {
                        continue;
                    }

                    //checking if candidate is the furthest one
                    float dist = spatialHash.MinDist(candidate);
                    if (dist > bestDist)
                    {
                        bestDist = dist; bestCandidate = candidate;
                    }
                }

                if (bestDist > 0.001f)
                {
                    spatialHash.Add(bestCandidate, 0, 0, 1);                                  //adding only if some suitable candidate found
                }
            }

            if (chunk.stop)
            {
                return;
            }
            output.SetObject(chunk, spatialHash);
        }
        public override void Generate(Chunk chunk, Biome biome = null)
        {
            if (!enabled || chunk.stop)
            {
                return;
            }

            CoordRect scaledRect = new CoordRect(
                (int)(offset.x * MapMagic.instance.resolution / MapMagic.instance.terrainSize),
                (int)(offset.y * MapMagic.instance.resolution / MapMagic.instance.terrainSize),
                (int)(MapMagic.instance.resolution * scale),
                (int)(MapMagic.instance.resolution * scale));
            Matrix stampMatrix = new Matrix(scaledRect);

            float gradientStep = 1f / stampMatrix.rect.size.x;
            Coord center = scaledRect.Center;
            float radius = stampMatrix.rect.size.x / 2f;
            Coord min = stampMatrix.rect.Min; Coord max = stampMatrix.rect.Max;

            switch (type)
            {
            case FormType.GradientX:
                for (int x = min.x; x < max.x; x++)
                {
                    for (int z = min.z; z < max.z; z++)
                    {
                        stampMatrix[x, z] = x * gradientStep;
                    }
                }
                break;

            case FormType.GradientZ:
                for (int x = min.x; x < max.x; x++)
                {
                    for (int z = min.z; z < max.z; z++)
                    {
                        stampMatrix[x, z] = z * gradientStep;
                    }
                }
                break;

            case FormType.Pyramid:
                for (int x = min.x; x < max.x; x++)
                {
                    for (int z = min.z; z < max.z; z++)
                    {
                        float valX = x * gradientStep; if (valX > 1 - valX)
                        {
                            valX = 1 - valX;
                        }
                        float valZ = z * gradientStep; if (valZ > 1 - valZ)
                        {
                            valZ = 1 - valZ;
                        }
                        stampMatrix[x, z] = valX < valZ? valX * 2 : valZ * 2;
                    }
                }
                break;

            case FormType.Cone:
                for (int x = min.x; x < max.x; x++)
                {
                    for (int z = min.z; z < max.z; z++)
                    {
                        float val = 1 - (Coord.Distance(new Coord(x, z), center) / radius);
                        if (val < 0)
                        {
                            val = 0;
                        }
                        stampMatrix[x, z] = val;
                    }
                }
                break;
            }

            Matrix matrix = chunk.defaultMatrix;

            matrix.Replicate(stampMatrix, tile: tile);
            matrix.Multiply(intensity);


            //if (tile) textureMatrix.FromTextureTiled(texture);
            //else textureMatrix.FromTexture(texture);

            //if (!Mathf.Approximately(scale,1)) textureMatrix = textureMatrix.Resize(matrix.rect, result:matrix);
            if (chunk.stop)
            {
                return;
            }
            output.SetObject(chunk, matrix);
        }
Example #9
0
 public virtual void Generate(Chunk chunk, Biome biome = null)
 {
 }
Example #10
0
			//generating
			public void ThreadFn ()
			{	
				if (locked) return;
				
				lock (locker) while (true)
				{
					stop=false;  //in case it was restarted
					start = false; 
					clear = false;
					apply.Clear();

					//clearing debug timers to know what generators were processed
					MapMagic.instance.guiDebugProcessTimes.Clear(); 
					MapMagic.instance.guiDebugApplyTimes.Clear();

					try 
					{
						

						#region Generating Main graph first
							
							//calculating the list of changed outputs
							List<Generator> changedOutputs = new List<Generator>();
							foreach (Generator outGen in MapMagic.instance.gens.OutputGenerators(onlyEnabled:true, checkBiomes:false))
							{
								outGen.CheckClearRecursive(this);
								if (!ready.Contains(outGen)) changedOutputs.Add(outGen);
							}

							//preview (checking it twice - here and in the fn end)
							if (MapMagic.instance.previewGenerator!=null && MapMagic.instance.previewOutput!=null)
								MapMagic.instance.previewGenerator.CheckClearRecursive(this);

							//types of objects that were changed (for process)
							HashSet<System.Type> changedTypes = new HashSet<Type>();
							for (int i=0; i<changedOutputs.Count; i++) 
							{
								changedTypes.Add(changedOutputs[i].GetType());
								
								//adding all of the biome outgens to processing list
								if (changedOutputs[i] is Biome)
								{
									Biome biome = (Biome)changedOutputs[i];
									if (biome.data == null) continue;
									foreach (Generator outGen in biome.data.OutputGenerators(onlyEnabled:true, checkBiomes:false))
										changedTypes.Add(outGen.GetType());
								}
							}

							//generating
							for (int i=0; i<changedOutputs.Count; i++) 
							{
								changedOutputs[i].GenerateWithPriors(this);
								if (stop) return;
							}

						#endregion

						#region Generating Biomes

							//calculating the list of changed outputs
							changedOutputs.Clear();
							foreach (Biome biome in MapMagic.instance.gens.GeneratorsOfType<Biome>(onlyEnabled:true, checkBiomes:false))
							{
								if (biome.data==null) continue;
								if (biome.mask.linkGen==null) continue;

								Matrix biomeMask = (Matrix)biome.mask.GetObject(this);
								if (biomeMask==null || biomeMask.IsEmpty()) continue;

								foreach (Generator outGen in biome.data.OutputGenerators(onlyEnabled:true, checkBiomes:false))
								{
									outGen.CheckClearRecursive(this);
									if (!ready.Contains(outGen)) changedOutputs.Add(outGen);
								}
							}

							//adding changed types
							for (int i=0; i<changedOutputs.Count; i++) 
								changedTypes.Add(changedOutputs[i].GetType());

							//generating
							for (int i=0; i<changedOutputs.Count; i++) 
							{
								changedOutputs[i].GenerateWithPriors(this);
								if (stop) return;
							}

						#endregion

						#region Preview

							if (MapMagic.instance.previewGenerator!=null && MapMagic.instance.previewOutput!=null)
							{
								MapMagic.instance.previewGenerator.CheckClearRecursive(this);
								MapMagic.instance.previewGenerator.GenerateWithPriors(this);
								if (stop) return;

								//if (results.ContainsKey(MapMagic.instance.previewOutput)) previewObject = results[MapMagic.instance.previewOutput];  
								//else previewObject = defaultMatrix;
							}

						#endregion

						
						/*//checking and resetting ready state recursive
						foreach (Generator outGen in MapMagic.instance.gens.OutputGenerators(onlyEnabled:true, checkBiomes:true)) //for outputs (including biomes)
							outGen.CheckClearRecursive(this);
						if (MapMagic.instance.previewOutput != null) MapMagic.instance.previewGenerator.CheckClearRecursive(this); //for preview

						//types of objects that were changed (for process)
						HashSet<System.Type> changedTypes = new HashSet<Type>();
						foreach (Generator outGen in MapMagic.instance.gens.OutputGenerators(onlyEnabled:true, checkBiomes:true)) 
							if (!ready.Contains(outGen)) 
								changedTypes.Add(outGen.GetType());

						//resseting all biome output if it has changed
						foreach (Biome biome in MapMagic.instance.gens.GeneratorsOfType<Biome>(onlyEnabled:true, checkBiomes:true))
							if (!ready.Contains(biome) && biome.data!=null && biome.mask.linkGen!=null)
							{
								foreach (Generator outGen in biome.data.OutputGenerators(onlyEnabled:true, checkBiomes:false))
									changedTypes.Add(outGen.GetType());
							}

						//generating main
						foreach (Generator outGen in MapMagic.instance.gens.OutputGenerators(onlyEnabled:true, checkBiomes:true)) //generating outputs
							if (!ready.Contains(outGen)) 
								outGen.GenerateWithPriors(this);

						if (MapMagic.instance.previewOutput != null) //generating preview
						{
							MapMagic.instance.previewGenerator.GenerateWithPriors(this);
							if (!stop) 
							{
								if (results.ContainsKey(MapMagic.instance.previewOutput)) previewObject = results[MapMagic.instance.previewOutput];
								else previewObject = defaultMatrix;
							}
						}*/

						//resetting objects if height changed (to floor them)
						if (changedTypes.Contains(typeof(HeightOutput))) { changedTypes.Add(typeof(TreesOutput)); changedTypes.Add(typeof(ObjectOutput)); }

						//finalizing (processing)
						if (changedTypes.Contains(typeof(HeightOutput))) HeightOutput.Process(this); //typeof(HeightOutput).GetMethod("Process", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static).Invoke(null,new object[] {this});
						if (changedTypes.Contains(typeof(SplatOutput))) SplatOutput.Process(this);
						if (changedTypes.Contains(typeof(ObjectOutput))) ObjectOutput.Process(this);
						if (changedTypes.Contains(typeof(TreesOutput))) TreesOutput.Process(this);
						if (changedTypes.Contains(typeof(GrassOutput))) GrassOutput.Process(this);
						if (changedTypes.Contains(typeof(RTPOutput))) RTPOutput.Process(this);
					}

					catch (System.Exception e) { Debug.LogError("Generate Thread Error:\n" + e); }

					//if (!stop) Thread.Sleep(2000);
					//exiting thread - only if it should not be restared
					if (!start) { queuedApply=true; break; }
				}
			}
        public float uniformity = 0.1f;         //aka candidatesNum/100

        public override void Generate(Chunk chunk, Biome biome = null)
        {
            Matrix      probMatrix  = (Matrix)probability.GetObject(chunk);
            SpatialHash spatialHash = chunk.defaultSpatialHash;

            if (!enabled)
            {
                output.SetObject(chunk, spatialHash); return;
            }
            if (chunk.stop)
            {
                return;
            }

            // If the bounds of this chunk don't contain the specified zValue then return the
            // default spatialHash
            if (spatialHash.offset.y > zValue || spatialHash.offset.y + spatialHash.size <= zValue)
            {
                output.SetObject(chunk, spatialHash);
                return;
            }

            InstanceRandom rnd = new InstanceRandom(MapMagic.instance.seed + seed + chunk.coord.x * 1000 + chunk.coord.z);

            int candidatesNum = (int)(uniformity * 100);

            for (int i = 0; i < count; i++)
            {
                Vector2 bestCandidate = Vector3.zero;
                float   bestDist      = 0;

                for (int c = 0; c < candidatesNum; c++)
                {
                    Vector2 candidate = new Vector2((spatialHash.offset.x + 1) + (rnd.Random() * (spatialHash.size - 2.01f)), zValue);

                    //checking if candidate available here according to probability map
                    if (probMatrix != null && probMatrix[candidate] < rnd.Random())
                    {
                        continue;
                    }

                    //checking if candidate is the furthest one
                    float dist = spatialHash.MinDist(candidate);
                    if (dist > bestDist)
                    {
                        bestDist = dist; bestCandidate = candidate;
                    }
                }

                if (bestDist > 0.001f)
                {
                    spatialHash.Add(bestCandidate, 0, 0, 1); //adding only if some suitable candidate found
                }
            }

            if (chunk.stop)
            {
                return;
            }
            output.SetObject(chunk, spatialHash);
        }