Пример #1
0
		static void CreateVoxeland (bool infinite=true) 
		{
			GameObject go = new GameObject();
			go.name = "Voxeland";

			Voxeland voxeland = go.AddComponent<Voxeland>();
			voxeland.chunks = new ChunkGrid<Chunk>();
			voxeland.chunkSize = 30;
			Voxeland.instances.Add(voxeland);
			
			//adding empty layer 
			voxeland.landTypes = new LandTypeList();

			ArrayTools.Add(ref voxeland.landTypes.array, new BlockType()); 
			voxeland.landTypes.array[0].mainTex = TextureExtensions.ColorTexture(2,2,new Color(0.666f, 0.666f, 0.666f, 0.5f), linear:false);
			#if UNITY_2017_3_OR_NEWER
			voxeland.landTypes.array[0].bumpMap = TextureExtensions.ColorTexture(2,2,new Color(0.5f, 0.5f, 0.5f, 1f), linear:true);
			#else
			voxeland.landTypes.array[0].bumpMap = TextureExtensions.ColorTexture(2,2,new Color(0.5f, 0.5f, 0.5f, 0.5f), linear:true);
			#endif

			//voxeland.landTypes.mainTexArray = new Texture2DArray(1024, 1024, 1, TextureFormat.DXT5, true) { name = "Albedo Height Array" };
			//voxeland.landTypes.mainTexArray.SetTexture( TextureExtensions.ColorTexture(1024,1024,Color.gray), 0);
			//voxeland.landTypes.bumpMapArray = new Texture2DArray(1024, 1024, 1, TextureFormat.DXT5, true, linear:true) { name = "Normals Array" };
			//voxeland.landTypes.bumpMapArray.SetTexture( TextureExtensions.ColorTexture(1024,1024,new Color(0.5f,0.5f,0.5f,0.5f)), 0);

			voxeland.landTypes.selected = 0;

			//adding empty grass
			voxeland.grassTypes = new GrassTypeList();
			voxeland.grassTypes.selected = -1;

			//objects
			voxeland.objectsTypes = new ObjectTypeList();
			voxeland.objectsTypes.selected = -1;

			//data
			voxeland.data = ScriptableObject.CreateInstance<Data>(); 
			voxeland.data.areas = new ChunkGrid<Data.Area>();
			voxeland.data.areaSize = 512;

			//materials
			voxeland.material = Voxeland.GetDefaultLandMaterial();
			voxeland.farMaterial = Voxeland.GetDefaultFarMaterial();
			voxeland.grassMaterial = Voxeland.GetDefaultGrassMaterial();

			voxeland.landTypes.ApplyToMaterial(voxeland.material);
			voxeland.landTypes.ApplyToMaterial(voxeland.farMaterial, horizon:true);
			voxeland.grassTypes.ApplyToMaterial(voxeland.grassMaterial);

			if (voxeland.horizon != null) voxeland.horizon.meshRenderer.sharedMaterial = voxeland.farMaterial;
			
			//highlight
			if (voxeland.highlight == null) //could be created on de-prefab in onenable
			{
				voxeland.highlight = Highlight.Create(voxeland);
				voxeland.highlight.material = Voxeland.GetDefaultHighlightMaterial(); //new Material( Shader.Find("Voxeland/Highlight") );
			}

			//static and infinite
			if (infinite)
			{
				voxeland.playmodeSizeMode = Voxeland.SizeMode.DynamicInfinite;
				voxeland.editorSizeMode = Voxeland.SizeMode.DynamicInfinite;

				voxeland.saveMeshes = false;

				voxeland.horizon = Horizon.Create(voxeland);
			}
			else
			{
				voxeland.playmodeSizeMode = Voxeland.SizeMode.Static;
				voxeland.editorSizeMode = Voxeland.SizeMode.Static;

				voxeland.saveMeshes = true;  
			}

			//generators
			voxeland.data.generator.noiseGen.enabled = true;
			voxeland.data.generator.noiseGenB.enabled = false;
			voxeland.data.generator.noiseGenB.seed = 1234;
			voxeland.data.generator.noiseGenB.high = 0.1f;
			voxeland.data.generator.curveGen.enabled = true;
			voxeland.data.generator.blurGen.enabled = true;

			//registering undo
			Undo.RegisterCreatedObjectUndo (go, "Voxeland Create");
			EditorUtility.SetDirty(go);
		}
Пример #2
0
		public override void OnInspectorGUI ()
		{
			voxeland = (Voxeland)target;
			Voxeland.current = voxeland;

			//assigning voxeland to mapmagic window
			#if MAPMAGIC
			if (MapMagic.MapMagicWindow.instance != null && MapMagic.MapMagicWindow.instance.mapMagic != (MapMagic.IMapMagic)voxeland && voxeland.data != null && voxeland.data.generator != null && voxeland.data.generator.mapMagicGens != null)
				MapMagic.MapMagicWindow.Show(voxeland.data.generator.mapMagicGens, voxeland, forceOpen:false);
			#endif

			if (layout == null) layout = new Layout();
			layout.margin = 0; layout.rightMargin = 5;
			layout.field = Layout.GetInspectorRect();
			layout.cursor = new Rect();
			layout.undoObject = voxeland;
			layout.undoName =  "Voxeland settings change";
			layout.dragChange = true;
			layout.change = false;
			layout.delayed = true;

			if (voxeland.data == null) { layout.Par(30); layout.Label("Voxeland data is not assigned in Settings menu. No edit or rebuild allowed.", rect:layout.Inset(), helpbox:true); }

			#region Progress

				layout.Par();

				if (ThreadWorker.IsWorking("Voxeland"))
				{
					float calculatedSum; float completeSum; float totalSum;
					ThreadWorker.GetProgresByTag("VoxelandChunk", out totalSum, out calculatedSum, out completeSum);

					if (totalSum>10) 
					{
						Rect gaugeRect = layout.Inset(0.7f);
						layout.Gauge(0, "", gaugeRect);
						layout.Gauge(1, "", new Rect(gaugeRect.x, gaugeRect.y, gaugeRect.width * calculatedSum/totalSum, gaugeRect.height), disabled:true);
						layout.Gauge(1, "", new Rect(gaugeRect.x, gaugeRect.y, gaugeRect.width * completeSum/totalSum, gaugeRect.height));

					//	Rect cursor = layout.cursor;
				//		layout.Gauge(calculatedSum/totalSum, "", layout.Inset(0.7f), disabled:true);
					//	layout.cursor = cursor;
				//		layout.Gauge(calculatedSum/totalSum, "", layout.Inset(0.7f));
						//layout.Gauge(progress, "Progress: " + (int)completeSum + "(" + calculatedSum + ")" + "/" + (int)totalSum, layout.Inset(0.7f));
					//	layout.cursor = cursor;
						layout.Label("Progress: " + (int)completeSum + "(" + calculatedSum + ")" + "/" + (int)totalSum, gaugeRect);
					}
					else layout.Label("Progress: building", layout.Inset(0.7f));
					gaugeDisplayed = true;

					Repaint();
				}
				else 
				{
					layout.Label("Progress: complete", layout.Inset(0.7f));
					gaugeDisplayed = false;
				}

				if (layout.Button("Rebuild", layout.Inset(0.3f))) voxeland.Rebuild();

			#endregion

			layout.margin = 0; layout.rightMargin = 5;

			#region Brush
				layout.Par(8); 
				layout.Foldout(ref voxeland.guiBrush, "Brush");
				if (voxeland.guiBrush) 
				{
					Rect anchor = layout.lastRect;

					layout.Field(ref voxeland.brush.form, "Form");
					 voxeland.brush.extent = layout.Field(voxeland.brush.extent, "Extent", min:0, max: voxeland.brush.maxExtent, slider:true);
					layout.Toggle(ref voxeland.brush.round, "Round");
			
					layout.Par(5);
					if (voxeland.brush.form==Brush.Form.stamp)
					{
						 layout.Field(ref voxeland.brush.getStamp, "Get Stamp");
						if (voxeland.brush.getStamp)
						{
							layout.Par();
							layout.Label("Min:",rect:layout.Inset(0.25f));
							layout.Field(ref voxeland.brush.getStampMin.x, "X", rect:layout.Inset(0.25f));
							layout.Field(ref voxeland.brush.getStampMin.y, "Y", rect:layout.Inset(0.25f));
							layout.Field(ref voxeland.brush.getStampMin.z, "Z", rect:layout.Inset(0.25f));

							layout.Par();
							layout.Label("Max:",rect:layout.Inset(0.25f));
							layout.Field(ref voxeland.brush.getStampMax.x, "X", rect:layout.Inset(0.25f));
							layout.Field(ref voxeland.brush.getStampMax.y, "Y", rect:layout.Inset(0.25f));
							layout.Field(ref voxeland.brush.getStampMax.z, "Z", rect:layout.Inset(0.25f));
						}
					}

					layout.Par(5);
					layout.Field(ref voxeland.standardEditMode, "Standard Edit");
					layout.Field(ref voxeland.controlEditMode, "Control Mode");
					layout.Field(ref voxeland.shiftEditMode, "Shift Mode");
					layout.Field(ref voxeland.controlShiftEditMode, "Control+Shift Mode");

					layout.Par(5);
					layout.Toggle(ref voxeland.continuousPainting, "Continuous Painting");

					layout.Foreground(anchor);
					//if (voxeland.guiBrush) layout.Par(3);
				}

			#endregion

				
			#region Land Types
			layout.Par(8); 
			layout.Foldout(ref voxeland.guiBlocks, "Land Blocks");
			if (voxeland.guiBlocks) 
			{ 
				Rect anchor = layout.lastRect;
				layout.margin += 5; layout.rightMargin += 5;
				

				LandTypeList types = voxeland.landTypes;

				//blocks
				if (types.textureArrays  &&  types.mainTexArray != null  &&  types.bumpMapArray != null)
				{
					if (types.mainTexArrDec == null  ||  types.mainTexArrDec.texArr != types.mainTexArray) types.mainTexArrDec = new TextureArrayDecorator(types.mainTexArray);
					if (types.bumpTexArrDec == null  ||  types.bumpTexArrDec.texArr != types.bumpMapArray) types.bumpTexArrDec = new TextureArrayDecorator(types.bumpMapArray);

					int minCount = Mathf.Min(types.mainTexArray.depth, types.bumpMapArray.depth);
					if (types.array.Length != minCount) ArrayTools.Resize(ref types.array, minCount, createElement:num => new BlockType() { name="Land Block" });
				}

				layout.Par(4);
				for (int i=0; i<types.array.Length; i++)
				{
					/*#if RTP
					if (rtpMat) layout.DrawWithBackground(null, active:i==types.selected))
					else layout.DrawWithBackground(types.array[i].OnGUI, active:i==types.selected))

					if (layout.lastChange && !rtpMat) 
					{
						voxeland.landTypes.ApplyToMaterial(voxeland.material);
						voxeland.landTypes.ApplyToMaterial(voxeland.farMaterial);
					}
					#else*/
					
					layout.Layer(types, i);

					if (layout.lastChange) 
					{
						types.ApplyToMaterial(voxeland.material);
						types.ApplyToMaterial(voxeland.farMaterial, horizon:true);
					}

					//#endif
				}

				//drawing buttons
				layout.Par(3); layout.Par();
				layout.LayerButtons(types, types.array.Length, rect:layout.Inset(0.6f));
				layout.Inset(0.05f);
				layout.Field(ref types.changeBlockData, "Sync Data", rect:layout.Inset(0.35f), fieldSize:0.15f);
				layout.Par(5);

				//layout.AssetNewSaveField(ref voxeland.material, "Material", saveFilename:"LandMaterial", saveType:"mat", create:Voxeland.GetDefaultLandMaterial);

				//common (material)
				layout.Par(6); 
				layout.Par();
				layout.Foldout(ref voxeland.guiLandCommon, "General Material", rect:layout.Inset(), bold:false);
				if (voxeland.guiLandCommon) 
				{
					Rect internalAnchor = layout.lastRect;
					layout.change = false;

					layout.AssetNewSaveField(ref voxeland.material, "Material", saveFilename:"LandMaterial", saveType:"mat", create:Voxeland.GetDefaultLandMaterial);
					layout.Par(5);

					if (types.textureArrays)
						layout.Field(ref types.anisotropicFiltration, "Anisotropic Filtration", tooltip:"For TextureArray shader - enables/disables the anisotropic filtration in texture arrays created from blocks textures. Highly affects shader performance.");
					layout.Field(ref types.tile, "Tile");
					layout.Field(ref types.mips, "MipMap Factor");
					layout.Field(ref types.ambientOcclusion, "Ambient Occlusion");
					layout.Field(ref types.blendMapFactor, "Blend Map Factor");
					layout.Field(ref types.blendCrisp, "Blend Crispness");
					layout.Field(ref types.previewType, "Preview");

					if (layout.change)
					{
						types.ApplyToMaterial(voxeland.material);
						types.ApplyToMaterial(voxeland.farMaterial, horizon:true);
					}

					layout.Foreground(internalAnchor, layout.lastRect);
				}
				

				//texture arrays
				layout.Par(6); 
				layout.Foldout(ref voxeland.guiLandTexarr, "Texture Arrays", bold:false);
				if (voxeland.guiLandTexarr) 
				{
					Rect internalAnchor = layout.lastRect;

					layout.Toggle(ref types.textureArrays, "Use Texture Arrays");
					if (layout.lastChange)
					{
						//for (int i=0; i<types.array.Length; i++)
						//	types.array[i].icon = null;
					}

					if (types.textureArrays)
					{
						//if (voxeland.material==null || !voxeland.material.HasProperty("_MainTexArr"))
						//	{ layout.Par(30); layout.Label("Switch material to TextureArray shader in order to use texture arrays.", rect:layout.Inset(), helpbox:true); }

						layout.Par();
						layout.Field(ref types.mainTexArray, "Albedo", rect:layout.Inset(layout.field.width-25-layout.margin-layout.rightMargin));
						if (layout.lastChange) ChangeTextureArray(types.mainTexArray, ref types, isBump:false);
						layout.Inset(5);
						if (layout.Button("", rect:layout.Inset(20), icon:"DPLayout_New"))
						{
							Texture2DArray texArr = CreateTextureArrayAsset("MainTexArr", types, isBump:false);
							if (texArr != null) { types.mainTexArray = texArr; ChangeTextureArray(types.mainTexArray, ref types, isBump:false); }
						}

						layout.Par();
						layout.Field(ref types.bumpMapArray, "Normal", rect:layout.Inset(layout.field.width-25-layout.margin-layout.rightMargin));
						if (layout.lastChange) ChangeTextureArray(types.bumpMapArray, ref types, isBump:true);
						layout.Inset(5);
						if (layout.Button("", rect:layout.Inset(20), icon:"DPLayout_New"))
						{
							Texture2DArray texArr = CreateTextureArrayAsset("BumpMapArr", types, isBump:true);
							if (texArr != null) { types.bumpMapArray = texArr; ChangeTextureArray(types.bumpMapArray, ref types, isBump:true); }
						}

						if (types.bumpMapArray == null)
							{ layout.Par(30); layout.Label("A normal map is required for proper terrain lighing.", rect:layout.Inset(), helpbox:true); }

						layout.Par(0); layout.Inset();
					}
					//if (!types.textureArrays && voxeland.material!=null && voxeland.material.HasProperty("_MainTexArr"))
					//		{ layout.Par(30); layout.Label("Switch material to non-TextureArray (Voxeland/Land) shader in order to use the standard textures.", rect:layout.Inset(), helpbox:true); }
				
					layout.Foreground(internalAnchor, layout.lastRect);
				}

				//megasplat clusters (not yet implemented)
				/*#if __MEGASPLAT__
				layout.Par(6); 
				layout.Foldout(ref voxeland.guiLandMegaSplatClusters, "MegaSplat Clusters", bold:false);
				if (voxeland.guiLandMegaSplatClusters) 
				{
					Rect internalAnchor = layout.lastRect;

					layout.Toggle(ref types.megaClusters, "Use MegaSplat");
					if (layout.lastChange)
					{
						if (types.megaClusters) voxeland.channelEncoding = Voxeland.ChannelEncoding.MegaSplat;
						else voxeland.channelEncoding = Voxeland.ChannelEncoding.RTP;
					}

					if (types.megaClusters)
					{
						if (voxeland.material==null || !voxeland.material.HasProperty("_Diffuse") || !voxeland.material.HasProperty("_Normal"))
							{ layout.Par(30); layout.Label("Assign a proper MegaSplat mesh material.", rect:layout.Inset(), helpbox:true); }

						layout.Field(ref types.megaTexList);
						if (layout.lastChange) 
						{ 
							//if (types.megaTexList != null && types.array.Length != types.megaTexList.clusters.Length) 
							//	ArrayTools.Resize(ref types.array, types.megaTexList.clusters.Length, createElement:num => new BlockType() {name=types.megaTexList.clusters[num].name});
							types.array = new BlockType[0];
							if (types.megaTexList != null)
								ArrayTools.Resize(ref types.array, types.megaTexList.clusters.Length, createElement:num => new BlockType() {name=types.megaTexList.clusters[num].name});
						}
					}

					layout.Foreground(internalAnchor, layout.lastRect);
				}
				#endif*/
				

				//distant display
				layout.Par(6); 
				layout.Foldout(ref voxeland.guiLandFar, "Distant Tile", bold:false);
				if (voxeland.guiLandFar) 
				{
					Rect internalAnchor = layout.lastRect;
					layout.change = false;

					layout.Toggle(ref types.farEnabled, "Enabled");
					layout.Field(ref types.farTile, "Tile");
					layout.Field(ref types.farStart, "Start");
					layout.Field(ref types.farEnd, "End");

					if (layout.change)
					{
						types.ApplyToMaterial(voxeland.material);
						types.ApplyToMaterial(voxeland.farMaterial, horizon:true);
					}

					layout.Foreground(internalAnchor, layout.lastRect);
				}
				

				//horizon
				layout.Par(6); 
				layout.Foldout(ref voxeland.guiLandHorizon, "Horizon", bold:false);
				if (voxeland.guiLandHorizon) 
				{
					Rect internalAnchor = layout.lastRect;
					layout.change = false;

					layout.Field(ref types.horizonTile, "Tile");
					layout.Field(ref types.horizonBorderLower, "Border Lower");

					if (layout.change)
					{
						types.ApplyToMaterial(voxeland.material);
						types.ApplyToMaterial(voxeland.farMaterial, horizon:true);
					}

					layout.Foreground(internalAnchor, layout.lastRect);
				}
				
				layout.Par(5);

				
				layout.margin -= 5; layout.rightMargin -= 5;
				layout.Par(0,0,0); layout.Inset(1);
				layout.Foreground(anchor, layout.lastRect);
			}
			#endregion


			#region Object Types
			layout.Par(8); 
			layout.Foldout(ref voxeland.guiObjects, "Object Blocks");
			if (voxeland.guiObjects) 
			{ 
				Rect anchor = layout.lastRect;
				layout.margin += 5; layout.rightMargin += 5;

				ObjectTypeList types = voxeland.objectsTypes;

				layout.Par(0);
				for (int i=0; i<types.array.Length; i++)
					layout.Layer(types, i);

				layout.Par(3); layout.Par();
				layout.LayerButtons(types, types.array.Length, rect:layout.Inset(0.6f));
				layout.Inset(0.05f);
				layout.Field(ref types.changeBlockData, "Sync Data", rect:layout.Inset(0.35f), fieldSize:0.15f);

				layout.Par(10);
				layout.Toggle(ref voxeland.objectsPool.regardPrefabRotation, "Regard Prefab Rotation");
				layout.Toggle(ref voxeland.objectsPool.regardPrefabScale, "Regard Prefab Scale");
				layout.Toggle(ref voxeland.objectsPool.instantiateClones, "Instantiate Clones");

				layout.margin -= 5; layout.rightMargin -= 5;
				layout.Foreground(anchor);
			}
			#endregion


			#region Grass Types
			layout.Par(8); 
			layout.Foldout(ref voxeland.guiGrass, "Grass");
			if (voxeland.guiGrass) 
			{
				Rect anchor = layout.lastRect;
				layout.margin += 5; layout.rightMargin += 5;

				GrassTypeList types = voxeland.grassTypes;


				//layers
				layout.Par(4);
				for (int i=0; i<types.array.Length; i++)
				{
					layout.Layer(types, i);
					if (layout.lastChange) types.ApplyToMaterial(voxeland.grassMaterial);
				}

				//drawing buttons
				layout.Par(3); layout.Par();
				layout.LayerButtons(types, types.array.Length, rect:layout.Inset(0.6f));
				layout.Inset(0.05f);
				layout.Field(ref types.changeBlockData, "Sync Data", rect:layout.Inset(0.35f), fieldSize:0.15f);
				layout.Par(5);

				//common (material)
				layout.Par(6); 
				layout.Par();
				layout.Foldout(ref voxeland.guiGrassCommon, "Grass Material", rect:layout.Inset(), bold:false);
				if (voxeland.guiGrassCommon) 
				{
					Rect internalAnchor = layout.lastRect;
					layout.change = false;

					layout.AssetNewSaveField(ref voxeland.grassMaterial, "Material", saveFilename:"GrassMaterial", saveType:"mat", create:Voxeland.GetDefaultGrassMaterial);
					layout.Par(5);

					layout.Field(ref types.culling, "Culling");
					layout.Field(ref types.cutoff, "Alpha Ref");
					layout.Field(ref types.ambientPower, "Ambient");
					layout.Field(ref types.mipFactor, "Mip Factor");
					layout.Field(ref types.vanishAngle, "Vanish Angle");
					layout.Field(ref types.appearAngle, "Appear Angle");
					layout.Par(5); layout.Inset();

					if (layout.change)
						types.ApplyToMaterial(voxeland.grassMaterial);

					layout.Foreground(internalAnchor, layout.lastRect);
				}

				//atlas
				layout.Par(6); 
				layout.Par();
				layout.Foldout(ref voxeland.guiGrassAtlas, "Atlas", rect:layout.Inset(), bold:false);
				if (voxeland.guiGrassAtlas) 
				{
					Rect internalAnchor = layout.lastRect;
					layout.change = false;

					layout.Field(ref types.atlas, "Atlas Enabled");
					if (layout.lastChange && types.atlas)  //removing layer textures
						for (int i=0; i<types.array.Length; i++)
						{
//							types.array[i].mainTex = null;
//							types.array[i].bumpMap = null;
//							types.array[i].specSmoothMap = null;
//							types.array[i].sssVanishMap = null;
						}
					if (layout.lastChange && types.atlas)  //removing assigned atlas
					{
//						types.mainTex = null;
//						types.bumpMap = null;
//						types.specSmoothMap = null;
//						types.sssVanishMap = null;
					}

					if (types.atlas)
					{
						layout.Field(ref types.mainTex, "Albedo/Alpha");
						layout.Field(ref types.bumpMap, "Normal");
						layout.Field(ref types.specSmoothMap, "Spec/Gloss");
						layout.Field(ref types.sssVanishMap, "SSS");
						
					}

					if (layout.change)
						types.ApplyToMaterial(voxeland.grassMaterial);

					layout.Foreground(internalAnchor, layout.lastRect);
				}

				//SSS
				layout.Par(6); 
				layout.Par();
				layout.Foldout(ref voxeland.guiGrassSSS, "Translucency", rect:layout.Inset(), bold:false);
				if (voxeland.guiGrassSSS) 
				{
					Rect internalAnchor = layout.lastRect;
					layout.change = false;

					layout.Field(ref types.sss, "Value");
					layout.Field(ref types.saturation, "Saturation");
					layout.Field(ref types.sssDistance, "Distance");
					layout.Par(5); layout.Inset();

					if (layout.change)
						types.ApplyToMaterial(voxeland.grassMaterial);

					layout.Foreground(internalAnchor, layout.lastRect);
				}

				//Shake
				layout.Par(6); 
				layout.Par();
				layout.Foldout(ref voxeland.guiGrassShake, "Shake/Wind", rect:layout.Inset(), bold:false);
				if (voxeland.guiGrassShake) 
				{
					Rect internalAnchor = layout.lastRect;
					layout.change = false;

					layout.Field(ref types.shakingAmplitude, "Shake Amplitude");
					layout.Field(ref types.shakingFrequency, "Shake Frequency");

					layout.Field(ref types.windTex, "Wind Texture");
					layout.Field(ref types.windSize, "Wind Size");
					layout.Field(ref types.windSpeed, "Wind Speed");
					layout.Field(ref types.windStrength, "Wind Strength");

					if (layout.change)
						types.ApplyToMaterial(voxeland.grassMaterial);

					layout.Foreground(internalAnchor, layout.lastRect);
				}

				layout.Par(5); layout.Inset();
				layout.margin -= 5; layout.rightMargin -= 5;
				layout.Foreground(anchor);
			}
			#endregion


			#region Distances

			layout.Par(8); 
			layout.Foldout(ref voxeland.guiDistances, "Mode and Ranges");
			if (voxeland.guiDistances)
			{
				Rect anchor = layout.lastRect;

				layout.fieldSize = 0.4f;
				layout.Field(ref voxeland.editorSizeMode, "Editor Mode");
				layout.Field(ref voxeland.playmodeSizeMode, "Playmode Mode");
				
				layout.Par(5);
				if (voxeland.editorSizeMode!=Voxeland.SizeMode.DynamicInfinite || voxeland.playmodeSizeMode!=Voxeland.SizeMode.DynamicInfinite)
				{
					layout.Field(ref voxeland.terrainSize, "Terrain Size");
					voxeland.terrainSize = ((int)(voxeland.terrainSize/voxeland.chunkSize)) * voxeland.chunkSize;
				}

				bool prevChange = layout.change;
				layout.change = false;

				if (voxeland.editorSizeMode!=Voxeland.SizeMode.Static || voxeland.playmodeSizeMode!=Voxeland.SizeMode.Static)
				{
					layout.Par(5);
					layout.Label("Terrain Ranges:");
					if (voxeland.guiDistancesFullControl)
					{
						layout.fieldSize = 0.2f;
						voxeland.guiDistancesMax = layout.Field(voxeland.guiDistancesMax, "Max Distance", delayed:true);
						layout.fieldSize = 0.8f;
					
						layout.Par(5);
						layout.Label("Chunks");
						DrawRange("Create", ref voxeland.createRange, 0.01f, voxeland.guiDistancesMax, voxeland.guiDistancesMax);
						DrawRange("Remove", ref voxeland.removeRange, voxeland.createRange, voxeland.guiDistancesMax, voxeland.guiDistancesMax);

						layout.Par(5);
						layout.Label("Voxel Meshes");
						DrawRange("Low Detail", ref voxeland.voxelLoRange,	voxeland.voxelHiRange,	voxeland.createRange,	voxeland.guiDistancesMax);
						DrawRange("High Detail", ref voxeland.voxelHiRange,	0.01f,						voxeland.voxelLoRange,	voxeland.guiDistancesMax);
						DrawRange("Collision", ref voxeland.collisionRange,	0.01f,						voxeland.voxelLoRange,	voxeland.guiDistancesMax);
						DrawRange("Objects", ref voxeland.objectsRange,		0.01f,						voxeland.createRange,	voxeland.guiDistancesMax);
						DrawRange("Grass", ref voxeland.grassRange,			0.01f,						voxeland.voxelLoRange,	voxeland.guiDistancesMax);
						DrawRange("Remove", ref voxeland.voxelRemoveRange,	voxeland.voxelLoRange,	voxeland.createRange,	voxeland.guiDistancesMax);

						layout.Par(5);
						layout.Label("Sculpt Areas");
						DrawRange("Generate", ref voxeland.areaGenerateRange, 0.01f, voxeland.areaRemoveRange, voxeland.areaRemoveRange);
						DrawRange("Remove", ref voxeland.areaRemoveRange, voxeland.areaGenerateRange, voxeland.areaRemoveRange, voxeland.areaRemoveRange);
					}

					else 
					{
						layout.fieldSize = 0.8f;
					
						DrawRange("Voxel Mesh", ref voxeland.voxelLoRange,	0.01f,	300, 300);
						DrawRange("Objects", ref voxeland.objectsRange,		0.01f,	300, 300);

						layout.Par(5);
						DrawRange("Collision", ref voxeland.collisionRange,	0.01f,	voxeland.voxelLoRange,	voxeland.guiDistancesMax);
						DrawRange("Grass", ref voxeland.grassRange,			0.01f,	voxeland.voxelLoRange,	voxeland.guiDistancesMax);
						DrawRange("High Detail", ref voxeland.voxelHiRange,	0.01f,	voxeland.voxelLoRange,	voxeland.guiDistancesMax);

						voxeland.createRange = Mathf.Max(voxeland.voxelLoRange, voxeland.objectsRange);
						voxeland.removeRange = voxeland.createRange + voxeland.chunkSize*2+1;
						voxeland.voxelRemoveRange = voxeland.voxelLoRange + voxeland.chunkSize*2+1;

						voxeland.areaGenerateRange = voxeland.createRange + voxeland.data.areaSize;
						voxeland.areaRemoveRange = voxeland.areaGenerateRange + voxeland.data.areaSize*2;
					}

					layout.Toggle(ref voxeland.guiDistancesFullControl, "Advanced");
					layout.fieldSize = 0.5f;
				}

				if (layout.change) voxeland.ForceUpdate();
				layout.change = prevChange;

				layout.Foreground(anchor);
			}
			#endregion

			#region Settings

			layout.Par(8); 
			layout.Foldout(ref voxeland.guiSettings, "Settings");
			if (voxeland.guiSettings)
			{
				Rect anchor = layout.lastRect;

				layout.margin += 5; layout.rightMargin += 5;
				layout.fieldSize = 0.4f;

				//data label
				layout.Par(5);
				voxeland.data = layout.ScriptableAssetField(voxeland.data, construct:null, savePath:null, fieldSize:0.8f);

				//margins
				layout.Par(5);
				layout.Field(ref voxeland.meshMargin, "Mesh Margin");
				layout.Field(ref voxeland.ambientMargin, "Ambient Margin");
				layout.Field(ref voxeland.ambientFade, "Ambient Fade", min:0, max:1);
				layout.Field(ref voxeland.normalsSmooth, "Smooth Normals", min:0, max:5);
				layout.Field(ref voxeland.relaxStrength, "Relax Strength", min:0, max:3);
				layout.Field(ref voxeland.relaxIterations, "Relax Iterations", min:0, max:10);
				if (voxeland.relaxIterations > voxeland.meshMargin)
				{
					layout.Par(30);
					layout.Label("Consider using Mesh Margin value higher than Relax Iterations to avoid visible seams between chunks.", rect:layout.Inset(), helpbox:true);
				}
				layout.Field(ref voxeland.channelEncoding, "Mesh Channel Encoding");
				layout.Field(ref voxeland.useAmbient, "Use Ambient");
				layout.Field(ref voxeland.playmodeEdit, "Edit in Playmode");
				

				//threads
				layout.Par(5);
				layout.Field(ref ThreadWorker.multithreading, "Multithreading");

				if (ThreadWorker.multithreading)
				{
					layout.Par();
					layout.Field(ref ThreadWorker.maxThreads, "Max Threads", rect:layout.Inset(0.75f), fieldSize:0.2f, disabled:ThreadWorker.autoMaxThreads);
					layout.Toggle(ref ThreadWorker.autoMaxThreads, "Auto",rect:layout.Inset(0.25f));
				}
				else layout.Field(ref ThreadWorker.maxThreads, "Max Coroutines");
				 
				layout.Field(ref ThreadWorker.maxApplyTime, "Max Apply Time");

				//other
				layout.Par(5);
				layout.Field(ref voxeland.guiLockSelection, "Lock Selection");
				layout.Field(ref voxeland.guiHideWireframe, "Hide Frame");
				if (layout.lastChange) voxeland.transform.ToggleDisplayWireframe(!voxeland.guiHideWireframe);
				layout.Field(ref voxeland.hideColliderWire, "Hide Collider Wire");
				layout.Field(ref voxeland.brush.maxExtent, "Max Brush Size");
				if (voxeland.brush.maxExtent>8) { layout.Par(30); layout.Label("Large brush extent can slow down Blob Brush display", layout.Inset(), helpbox:true); }

				layout.Par(5);
				layout.Field(ref voxeland.saveMeshes, "Save Meshes with Scene");
				layout.Field(ref voxeland.saveNonpinnedAreas, "Save Non-pinned Areas");

				layout.Par(5);
				layout.Field(ref voxeland.chunkName, "Default Chunk Name");
				layout.Field(ref voxeland.copyLayersTags, "Copy Layers and Tags to Chunk");
				layout.Field(ref voxeland.copyComponents, "Copy Components to Chunk");

				//horizon
				layout.Par(10);
				layout.Par(0,padding:0); layout.Inset();
				Rect internalAnchor = layout.lastRect;
				bool useHorizon = layout.Toggle(voxeland.horizon!=null, "Horizon Mesh");
				if (useHorizon && voxeland.horizon==null) 
				{
					voxeland.horizon = Horizon.Create(voxeland); 
					voxeland.horizon.meshRenderer.sharedMaterial = voxeland.farMaterial;  
					
					voxeland.landTypes.ApplyToMaterial(voxeland.farMaterial, horizon:true);
				}

				if (!useHorizon && voxeland.horizon!=null) GameObject.DestroyImmediate(voxeland.horizon.gameObject);

				if (voxeland.horizon!=null)
				{
					voxeland.horizon.meshFilter.sharedMesh = layout.Field(voxeland.horizon.meshFilter.sharedMesh, "Mesh");
					layout.Field(ref voxeland.horizon.meshSize, "Mesh Bounding Box Size");
					layout.Field(ref voxeland.horizon.scale, "Scale");
					layout.Field(ref voxeland.horizon.textureResolutions, "Texture Resolution");
				}
				else
				{
					layout.Field<Mesh>(null, "Mesh", disabled:true);
					layout.Field(60, "Mesh Bounding Box Size", disabled:true);
					layout.Field(1, "Scale", disabled:true);
					layout.Field(512, "Texture Resolution", disabled:true);
				}
				layout.Foreground(internalAnchor);

				//floaty origin solution
				layout.Par(10);
				layout.Par(0,padding:0); layout.Inset();
				internalAnchor = layout.lastRect;
				layout.Toggle(ref voxeland.shift, "Shift World (Floating Point Solution)");
				layout.Field(ref voxeland.shiftThreshold, "Shift Threshold", disabled:!voxeland.shift);
				layout.Foreground(internalAnchor);

				//debug
				BuildTargetGroup buildGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
				string defineSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildGroup);
				
				bool debug = false;
				if (defineSymbols.Contains("WDEBUG;") || defineSymbols.EndsWith("WDEBUG")) debug = true;
				
				layout.Par(10);
				layout.Toggle(ref debug, "Debug (Requires re-compile)");
				if (layout.lastChange) 
				{
					if (debug)
					{
						defineSymbols += (defineSymbols.Length!=0? ";" : "") + "WDEBUG";
					}
					else
					{
						defineSymbols = defineSymbols.Replace("WDEBUG","");  
						defineSymbols = defineSymbols.Replace(";;", ";"); 
					}
					PlayerSettings.SetScriptingDefineSymbolsForGroup(buildGroup, defineSymbols);
				}

				layout.margin -= 5; layout.rightMargin -= 5;

				layout.Foreground(anchor);
			}

			#endregion

			#region Material
			layout.Par(8); 
			layout.Foldout(ref voxeland.guiMaterial, "Materials");
			if (voxeland.guiMaterial)
			{
				Rect anchor = layout.lastRect;
				layout.margin += 10;
				layout.fieldSize = 0.5f;

				layout.AssetNewSaveField(ref voxeland.material, "Land", saveFilename:"Land", saveType:"mat", create:Voxeland.GetDefaultLandMaterial);
				layout.AssetNewSaveField(ref voxeland.farMaterial, "Horizon", saveFilename:"Horizon", saveType:"mat", create:Voxeland.GetDefaultFarMaterial);
				layout.AssetNewSaveField(ref voxeland.grassMaterial, "Grass", saveFilename:"Grass.mat", saveType:"mat", create:Voxeland.GetDefaultGrassMaterial);
				if (voxeland.highlight!=null) layout.AssetNewSaveField(ref voxeland.highlight.material, "Highlight", saveFilename:"Highlight.mat", saveType:"mat", create:Voxeland.GetDefaultHighlightMaterial);
				else layout.Field<Material>(null, "Highlight", disabled:true);

				layout.margin -= 10;
				layout.Foreground(anchor);
				//if (voxeland.guiMaterial) layout.Par(3);
			}

			#endregion

			#region Generate
			layout.Par(8); 
			layout.Foldout(ref voxeland.guiGenerate, "Generate");
			if (voxeland.guiGenerate)
			{
				Rect anchor = layout.lastRect;
				layout.margin += 10;

				if (voxeland.data == null) layout.Label("No proper Voxeland data to generate");
				else
				{	
					Generator generator = voxeland.data.generator;
					bool change = layout.change;
					layout.change = false;
				
					layout.Field(ref generator.generatorType, "Generator Type");

					//gathering block names
					if (blockNames == null || blockNames.Length != voxeland.landTypes.array.Length+2) blockNames = new string[voxeland.landTypes.array.Length+2];
					for (int i=0; i<voxeland.landTypes.array.Length; i++)
						blockNames[i] = voxeland.landTypes.array[i].name;
					blockNames[blockNames.Length-1] = "Empty";

					if (objectNames == null || objectNames.Length != voxeland.objectsTypes.array.Length+2) objectNames = new string[voxeland.objectsTypes.array.Length+2];
					for (int i=0; i<voxeland.objectsTypes.array.Length; i++)
						objectNames[i] = voxeland.objectsTypes.array[i].name;
					objectNames[objectNames.Length-1] = "Empty";

					if (grassNames == null || grassNames.Length != voxeland.grassTypes.array.Length+2) grassNames = new string[voxeland.grassTypes.array.Length+2];
					for (int i=0; i<voxeland.grassTypes.array.Length; i++)
						grassNames[i] = voxeland.grassTypes.array[i].name;
					grassNames[grassNames.Length-1] = "Empty";


					layout.Par(10);
			
					if (generator.generatorType == Generator.GeneratorType.Planar)
					{
						generator.planarGen.OnGUI(layout, blockNames);
					}

					if (generator.generatorType == Generator.GeneratorType.Noise)
					{
						generator.noiseGen.OnGUI(layout, blockNames, "Noise");
						generator.curveGen.OnGUI(layout, blockNames);
						generator.slopeGen.OnGUI(layout, blockNames);
						generator.cavityGen.OnGUI(layout, blockNames);
						generator.blurGen.OnGUI(layout, blockNames);
						generator.stainsGen.OnGUI(layout, blockNames);
						generator.noiseGenB.OnGUI(layout, blockNames, "Bedrock (Noise)");
						generator.scatterGen.OnGUI(layout, objectNames, blockNames);

						//grass
						generator.grassGens.grassNames = grassNames;
						generator.grassGens.landNames = blockNames;

						layout.LayerButtons(generator.grassGens, generator.grassGens.gens.Length, "Grass Generators:", addBeforeSelected:true);

						layout.margin += 3; layout.rightMargin += 1; //right margin is 3 by default
						layout.Par(3);
						for (int num=0; num<generator.grassGens.gens.Length; num++)
							layout.Layer(generator.grassGens, num);
						layout.Par(3);
						layout.margin -= 3; layout.rightMargin -= 1;
					}

					else if (generator.generatorType == Generator.GeneratorType.MapMagic)
					{
						#if MAPMAGIC
						MapMagic.VoxelandOutput.voxeland = voxeland;
						MapMagic.VoxelandGrassOutput.voxeland = voxeland;
						MapMagic.VoxelandObjectsOutput.voxeland = voxeland;

						//data field
						layout.Par(5);
						layout.fieldSize = 0.7f;
						//generator.mapMagicGens = layout.ScriptableAssetField(generator.mapMagicGens, construct:MapMagic.GeneratorsAsset.DefaultVoxeland, savePath: null);
						generator.mapMagicGens = layout.ScriptableAssetField(generator.mapMagicGens, construct:MapMagic.Graph.DefaultVoxeland, savePath: null);
						if (layout.lastChange) 
							MapMagic.MapMagicWindow.Show(generator.mapMagicGens, voxeland, forceOpen:false, asBiome:false);
				
						//show editor button
						layout.Par(5);
						layout.Par(22);
						if (layout.Button("Show Editor", rect:layout.Inset(1f), disabled:generator.mapMagicGens==null))
							MapMagic.MapMagicWindow.Show(generator.mapMagicGens, voxeland, forceOpen:true);
					
						#else
						layout.Par(40);
						layout.Label("MapMagic World Generator does not seems to be installed. If you sure that you have it try restarting Unity to add it's define symbol.", rect:layout.Inset(), helpbox:true);
						#endif
					}

					else if (generator.generatorType == Generator.GeneratorType.Heightmap)
					{
						generator.standaloneHeightGen.OnGUI(layout, blockNames);
					}

					if (generator.generatorType != Generator.GeneratorType.Planar)
					{
						layout.Par(10);
				
						layout.Field(ref generator.seed, "Seed"); if (layout.lastChange) generator.change = true;
						#if MAPMAGIC
						if (layout.lastChange) voxeland.ClearResults();
						#endif
						layout.Field(ref generator.heightFactor, "Height"); if (layout.lastChange) generator.change = true;
						layout.Toggle(ref generator.saveResults, "Save Interim Results");
						layout.Toggle(ref generator.instantGenerate,"Instant Generate");
						//layout.Toggle(ref generator.forceGenerateChangedAreas, "Force Generate Changed Areas");
						layout.Toggle(ref generator.polish, "Polish");
						//layout.Toggle(ref generator.leaveDemoUntouched, "Leave Demo Untouched");
				
						layout.Par();
						layout.Toggle(ref generator.removeThinLayers, "Remove Thin Layers", rect:layout.Inset(0.8f));
						layout.Field(ref generator.minLayerThickness, rect:layout.Inset(0.2f));

						if (layout.change) voxeland.Refresh();
						layout.change = change;
					}

					layout.Par(5);

					string readyIcon = "Voxeland_Success"; int readyAnimFrames = 0;
					if (ThreadWorker.IsWorking("VoxelandGenerate")) { readyIcon = "Voxeland_Loading"; readyAnimFrames=12; Repaint(); }

					layout.Par(24);
					if (layout.Button("Generate", rect:layout.Inset(), icon:readyIcon, iconAnimFrames:readyAnimFrames)) 
						voxeland.Refresh();
					if (layout.Button("Force Re-Generate") && EditorUtility.DisplayDialog("Re-Generate", "This will remove all of the custom changes made in your DATA file. Are you sure you wish to continue?", "Re-Generate", "Cancel")) 
						voxeland.Refresh(force:true);
					
				}

				layout.margin -= 10;
				layout.Foreground(anchor);
			}
			#endregion

			#region About
			layout.Par(8); 
			layout.Foldout(ref voxeland.guiAbout, "About");
			if (voxeland.guiAbout)
			{
				Rect anchor = layout.lastRect;
				Rect savedCursor = layout.cursor;
				
				layout.margin = 20;
				layout.Par(100, padding:0);
				layout.Icon("VoxelandIcon", layout.Inset(50,padding:0));

				layout.cursor = savedCursor;
				layout.margin = 80;

				string versionName = Voxeland.version.ToString();
				versionName = versionName[0]+"."+versionName[1]+"."+versionName[2];
				layout.Label("Voxeland " + versionName);
				layout.Label("by Denis Pahunov");
				
				layout.Par(10);
				layout.Label(" - Wiki", url:"https://gitlab.com/denispahunov/voxeland/wikis/home");
				layout.Label(" - Forums", url:"https://forum.unity3d.com/threads/voxeland-voxel-terrain-tool.187741/");
				layout.Label(" - Issues / Ideas", url:"https://gitlab.com/denispahunov/voxeland/issues"); 

				/*layout.Par(10);
				layout.Label("Other Products:");

				layout.Par(5);
				layout.Label("MapMagic", url:"https://gitlab.com/denispahunov/voxeland/wikis/home");
				layout.Label("Node based infinite terrain generator");*/

				layout.Foreground(anchor);
			}
			#endregion

			Layout.SetInspectorRect(layout.field);
		}
Пример #3
0
 public void SwitchLayers(int num1, int num2)
 {
     ArrayTools.Switch(gens, num1, num2);
 }
Пример #4
0
 public void RemoveLayer(int num)
 {
     ArrayTools.RemoveAt(ref gens, num);
 }
Пример #5
0
 public void AddLayer(int num)
 {
     ArrayTools.Insert(ref gens, num, new GrassGenerator());
 }
Пример #6
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;

            #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);                                //TODO replace fn call
            }
            //order array
            if (order == null)
            {
                order = new int[count];
            }
            order = ArrayTools.Order(heightsInt, order: order, max: heights.count, stepsArray: stepsArray);


            /*if (order==null) order = new int[count];
             * for (int i=0; i<order.Length; i++) order[i] = i;
             * float[] refHeights = new float[heights.array.Length];
             * Array.Copy(heights.array, refHeights, heights.array.Length);
             * Array.Sort(refHeights, order);*/

            //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;
                //sedimentSum.array[pos] += sediments.array[pos] * 10;
                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;
                    }

                    //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;
                    }
                    //}

                    //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

            int seed = 12345;
            for (int j = heights.array.Length - 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
Пример #7
0
        public static void SetUserData(this UnityEditor.AssetImporter importer, string param, string[] data, bool reload = false)
        {
            char endline = '\n';             //';'

            string userData = importer.userData;

            string[] userDataSplit = userData.Split('\n', ';');

            //preparing new data line
            if (data == null)
            {
                data = new string[0];
            }
            string newDataString = param + ":" + data.ToStringMemberwise(separator: ",");

            //param line number (-1 if not found)
            int numInSplit = -1;

            for (int i = 0; i < userDataSplit.Length; i++)
            {
                if (userDataSplit[i].StartsWith(param + ":"))
                {
                    numInSplit = i;
                }
            }

            //erasing empty data
            if (numInSplit >= 0 && data.Length == 0)
            {
                ArrayTools.RemoveAt(ref userDataSplit, numInSplit);
            }

            //replacing line
            if (numInSplit >= 0 && data.Length != 0)
            {
                userDataSplit[numInSplit] = newDataString;
            }

            //adding new line
            if (numInSplit == -1 && data.Length != 0)
            {
                ArrayTools.Add(ref userDataSplit, newDataString);
            }

            //to string
            string newUserData = "";

            for (int i = 0; i < userDataSplit.Length; i++)
            {
                if (userDataSplit[i].Length == 0)
                {
                    continue;
                }
                newUserData += userDataSplit[i];
                if (i != userDataSplit.Length - 1)
                {
                    newUserData += endline;
                }
            }

            //writing
            if (newUserData != userData)
            {
                importer.userData = newUserData;

                UnityEditor.EditorUtility.SetDirty(importer);
                UnityEditor.AssetDatabase.WriteImportSettingsIfDirty(importer.assetPath);
                if (reload)
                {
                    UnityEditor.AssetDatabase.Refresh();
                }
            }
        }