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); }
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); }
public virtual void Generate(Chunk chunk, Biome biome = null) { }
//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); }