Exemple #1
0
			public override void OnCreate (Chunk chunk, Coord coord)
			{
				//creating gameobject
				GameObject go = new GameObject();
				go.name = "Terrain " + coord.x + "," + coord.z;
				go.transform.parent = MapMagic.instance.transform;
				go.transform.localPosition = coord.ToVector3(MapMagic.instance.terrainSize);

				//creating terrain
				chunk.terrain = go.AddComponent<Terrain>();
				TerrainCollider terrainCollider = go.AddComponent<TerrainCollider>();

				TerrainData terrainData = new TerrainData();
				chunk.terrain.terrainData = terrainData;
				terrainCollider.terrainData = terrainData;
				terrainData.size = new Vector3(MapMagic.instance.terrainSize, MapMagic.instance.terrainHeight, MapMagic.instance.terrainSize);

				//chunk settings
				chunk.coord = coord;
				chunk.SetSettings();
				chunk.clear = true;
				//if (!instance.isEditor || instance.instantGenerate) { chunk.start = true; }

				MapMagic.CallRepaintWindow(); //if (MapMagic.instance.isEditor) if (RepaintWindow != null) RepaintWindow();
			}
		public static void ShowEditor ()
		{
			//GeneratorsAsset gens = FindObjectOfType<GeneratorsAsset>();
			MapMagic mm = FindObjectOfType<MapMagic>();
			GeneratorsAsset gens = mm!=null? mm.gens : null;
			MapMagicWindow.Show(gens, mm, forceOpen:true);
		}
Exemple #3
0
        public void OnEnable()
        {
            #if UNITY_EDITOR
            //adding delegates
            UnityEditor.EditorApplication.update -= Update;

            if (isEditor)
                UnityEditor.EditorApplication.update += Update;
            #endif

            //finding singleton instance
            instance = FindObjectOfType<MapMagic>();

            //checking terrains consistency
            if (chunks != null)
            foreach (Chunk chunk in chunks.All())
                if (chunk.terrain == null) chunks.Remove(chunk.coord);

            //changing seed on playmode start
            if (changeSeed && Extensions.isPlaying)
            {
                seed = (int)(System.DateTime.Now.Ticks % 1000000);
                ClearResults();
                Generate(force:true);
            }

            if (previewShader == null) previewShader = Shader.Find("MapMagic/TerrainPreview");
        }
Exemple #4
0
    public override void OnJoinedRoom()
    {
        Invoke("SpawnPlayer", 0.1f);
        MapMagic.MapMagic mm = Resources.FindObjectsOfTypeAll <MapMagic.MapMagic>()[0] as MapMagic.MapMagic;
        Debug.Log(PhotonNetwork.CurrentRoom.CustomProperties.ToStringFull());
        PhotonNetwork.CurrentRoom.CustomProperties.TryGetValue("seed", out object result);

        mm.seed = (int)result;
        mm.ClearResults();
        GameObject tempCameraGO = new GameObject("Temp Camera");

        tempCamera = tempCameraGO.AddComponent <Camera>();
        tempCamera.transform.position = new Vector3(-2000, 250, 2000);
        mm.gameObject.SetActive(true);
        mm.Generate(true);

        if (PhotonNetwork.IsMasterClient)
        {
            mm.generateRange = 1000;
        }



        Debug.Log("Joined the room");
    }
Exemple #5
0
		public void OnEnable ()
		{
			#if UNITY_EDITOR
			//adding delegates
			UnityEditor.EditorApplication.update -= Update;	

			if (isEditor) 
				UnityEditor.EditorApplication.update += Update;	
			#endif

			//finding singleton instance
			instance = FindObjectOfType<MapMagic>();

			//checking terrains consistency
			if (chunks != null)
			foreach (Chunk chunk in chunks.All())
				if (chunk.terrain == null) chunks.Remove(chunk.coord);

			//changing seed on playmode start
			if (changeSeed && Extensions.isPlaying)
			{
				seed=UnityEngine.Random.Range(0,10000000);
				ClearResults();
				Generate(force:true);
			}
		}
Exemple #6
0
				public void OnCreate (object parentBox)
				{
					MapMagic mapMagic = (MapMagic)parentBox;

					//creating terrain
					GameObject go = new GameObject();
					go.name = "Terrain " + coord.x + "," + coord.z;
					go.transform.parent = mapMagic.transform;
					go.transform.localPosition = coord.ToVector3(mapMagic.terrainSize);
					go.transform.localScale = Vector3.one; //no need to make it every move
					//go.SetActive(false); //enabling/disabling is now in update control

					//creating terrain
					terrain = go.AddComponent<Terrain>();
					terrainCollider = go.AddComponent<TerrainCollider>();

					TerrainData terrainData = new TerrainData();
					terrain.terrainData = terrainData;
					terrainCollider.terrainData = terrainData;
					terrainData.size = new Vector3(mapMagic.terrainSize, mapMagic.terrainHeight, mapMagic.terrainSize);
					
					//settings
					SetSettings();

					InitWorker();
					worker.name = "MMChunk " + coord.x + "," + coord.z;

					MapMagic.CallRepaintWindow(); //if (MapMagic.instance.isEditor) if (RepaintWindow != null) RepaintWindow();
				}
Exemple #7
0
		private void OnEnable ()
		{
			//finding mapmagic object if window is empty (has no gens)
			if (gens==null)
			{
				MapMagic mm = GameObject.FindObjectOfType<MapMagic>();
				if (mm!=null)
				{
					mapMagic = mm;
					gensBiomeHierarchy.Clear();
					gensBiomeHierarchy.Add(mm.gens);
				}

				#if VOXELAND
				else
				{
					Voxeland5.Voxeland voxeland = GameObject.FindObjectOfType<Voxeland5.Voxeland>();
					if (voxeland!=null)
					{
						mapMagic = voxeland;
						gensBiomeHierarchy.Clear();
						if (voxeland.data!=null && voxeland.data.generator!=null && voxeland.data.generator.mapMagicGens!=null) 
							gensBiomeHierarchy.Add(voxeland.data.generator.mapMagicGens);
					}
				}

				#endif
			}

			instance = this;
		}
Exemple #8
0
			public void OnBeforeSerialize () 
			{ 
				if (mapMagic is MapMagic) serializedMM_mapMagic = (MapMagic)mapMagic;
				#if VOXELAND
				if (mapMagic is Voxeland5.Voxeland) serializedMM_voxeland = (Voxeland5.Voxeland)mapMagic;
				#endif
			}
Exemple #9
0
 public static MapMagic.Chunk FindByCoord(this MapMagic.MapMagic MM, int x, int z)
 {
     foreach (MapMagic.Chunk chunk in MM.chunks.All())
     {
         if (chunk.coord.x == x && chunk.coord.z == z)
         {
             return(chunk);
         }
     }
     return(null);
 }
Exemple #10
0
			public void ThreadFn ()  
			{
				Size size = new Size(MapMagic.instance.resolution, MapMagic.instance.terrainSize, MapMagic.instance.terrainHeight);

				try { MapMagic.instance.gens.Calculate(rect, results, size, MapMagic.instance.seed, worker.StopCallback); }
				catch (System.Exception e) 
				{ 
					Debug.LogError("Error generating chunk: " + coord + ": " + e);  
					MapMagic.CallOnGenerateFailed(terrain);
				}
			}
Exemple #11
0
        void OnGUI()
        {
            if (magic == null)
            {
                magic = FindObjectOfType <MapMagic.MapMagic>();
            }

            if (ThreadWorker.IsWorking("MapMagic"))
            {
                GUI.Box(new Rect(Screen.width / 2 - 100, Screen.height - 100, 200, 27), "");
                GUI.Box(new Rect(Screen.width / 2 - 100, Screen.height - 100, 200, 27), "Generating new terrain...");
            }
        }
        void OnGUI()
        {
            if (magic == null)
            {
                magic = FindObjectOfType <MapMagic.MapMagic>();
            }

            if (!magic.terrains.complete)
            {
                GUI.Box(new Rect(Screen.width / 2 - 100, Screen.height - 100, 200, 27), "");
                GUI.Box(new Rect(Screen.width / 2 - 100, Screen.height - 100, 200, 27), "Generating new terrain...");
            }
        }
Exemple #13
0
    void SpawnPlayer()
    {
        var newPlayer = PhotonNetwork.Instantiate("Player", Vector3.zero, Quaternion.identity).GetComponent <PlayerManager>();

        newPlayer.TakeControl();

        MapMagic.MapMagic mm = Resources.FindObjectsOfTypeAll <MapMagic.MapMagic>()[0] as MapMagic.MapMagic;
        if (SpawnPoint.activeSpawnPoints.Count == 0)
        {
            Debug.Log("Is still working");
            Invoke("spawnPlayer", 0.1f);
            return;
        }
        Destroy(tempCamera.gameObject);
    }
		public void OnEnable ()
		{
			#if UNITY_EDITOR
			//adding delegates
			UnityEditor.EditorApplication.update -= Update;	

			if (isEditor) 
				UnityEditor.EditorApplication.update += Update;	
			#endif

			//finding singleton instance
			instance = FindObjectOfType<MapMagic>();

			//checking terrains consistency
			terrains.CheckEmpty();
		}
		static void OnDeselectedSceneGUI(Transform objectTransform, GizmoType gizmoType)
		{
			//updating with 10 fps
			if (lastGizmoFrame == Time.renderedFrameCount) return;
			lastGizmoFrame = Time.renderedFrameCount;
			
			if (MapMagic.instance==null || MapMagic.instance.chunks==null) return; 
			MapMagic mapMagic = MapMagic.instance;

			//previewing
			//foreach (Chunk tw in MapMagic.instance.chunks.All()) tw.Preview(); 

			//update custom shader templates
			if (CustomShaderOutput.instantUpdateMaterial && !mapMagic.assignCustomTerrainMaterial && mapMagic.terrainMaterialType==Terrain.MaterialType.Custom && mapMagic.customTerrainMaterial != null)
				CustomShaderOutput.UpdateCustomShaderMaterials();
		}
Exemple #16
0
			//processing threads
			public void Update ()
			{
				//starting threads
				if (start)
				{		
					//calling before-gen event
					if (MapMagic.OnGenerateStarted != null) MapMagic.OnGenerateStarted(terrain);
								
					//generating
					if (!instance.multiThreaded) ThreadFn();
					else
					{
						//restarting thread if it is still alive
						if (running) stop=true;

						//if dead and thread limit not reached
						else if (instance.runningThreadsCount < instance.maxThreads)
						{ 
							thread = new Thread(ThreadFn);
							thread.IsBackground = true;
							//thread.Priority = System.Threading.ThreadPriority.BelowNormal;
							thread.Start(instance.gens);
							instance.runningThreadsCount++;
						}
					}
				}

				//sending terrain on apply
				if (!instance.applyRunning && apply.Count!=0  &&  !start && !stop && !running) //if apply not running and got something to apply. Do not apply when terrain stopped, restarted or still producing
				{
					//iteraing routine manually in editor (in one frame)
					if (instance.isEditor)
					{
						IEnumerator e = ApplyRoutine();
						while (e.MoveNext());
					}

					//starting routine in playmode
					else instance.StartCoroutine(ApplyRoutine());
				}

				
				//purging
				if (purge) Purge();
			}
Exemple #17
0
			public void SetSettings ()
			{
				MapMagic magic = MapMagic.instance;
				
				terrain.heightmapPixelError = magic.pixelError;
				terrain.basemapDistance = magic.baseMapDist;
				terrain.castShadows = magic.castShadows;
				
				if (terrainCollider==null) terrainCollider = terrain.GetComponent<TerrainCollider>();
				terrainCollider.enabled = MapMagic.instance.applyColliders;

				//material
				if (MapMagic.instance.previewGenerator==null)
				{
					terrain.materialType = MapMagic.ToUnityTerrMatType(MapMagic.instance.terrainMaterialType);

					if (MapMagic.instance.terrainMaterialType == MapMagic.TerrainMaterialType.Custom)
					{
						terrain.materialTemplate = MapMagic.instance.customTerrainMaterial;
					}
					else if (MapMagic.instance.terrainMaterialType == MapMagic.TerrainMaterialType.RTP)
					{
						if (terrain.materialTemplate == null || terrain.materialTemplate.shader.name != "Relief Pack/ReliefTerrain-FirstPass")
						{
							Shader shader = Shader.Find("Relief Pack/ReliefTerrain-FirstPass");
							if (shader != null) terrain.materialTemplate = new Material(shader);
							else Debug.Log ("MapMagic: Could not find Relief Pack/ReliefTerrain-FirstPass shader. Make sure RTP is installed or switch material type to Standard.");
						}
					}
				}

				terrain.drawTreesAndFoliage = magic.detailDraw;
				terrain.detailObjectDistance = magic.detailDistance;
				terrain.detailObjectDensity = magic.detailDensity;
				terrain.treeDistance = magic.treeDistance;
				terrain.treeBillboardDistance = magic.treeBillboardStart;
				terrain.treeCrossFadeLength = magic.treeFadeLength;
				terrain.treeMaximumFullLODCount = magic.treeFullLod;

				terrain.terrainData.wavingGrassSpeed = magic.windSpeed;
				terrain.terrainData.wavingGrassAmount = magic.windSize;
				terrain.terrainData.wavingGrassStrength = magic.windBending;
				terrain.terrainData.wavingGrassTint = magic.grassTint;
			}
Exemple #18
0
		public void OnEnable ()
		{
			#if UNITY_EDITOR
			//adding delegates
			UnityEditor.EditorApplication.update -= Update;	
			//UnityEditor.SceneView.onSceneGUIDelegate -= GetEditorCamPos; 
			
			if (isEditor) 
			{
				//UnityEditor.SceneView.onSceneGUIDelegate += GetEditorCamPos;
				UnityEditor.EditorApplication.update += Update;	
			}
			#endif

			//finding singleton instance
			instance = FindObjectOfType<MapMagic>();

			//checking terrains consistency
			terrains.CheckEmpty();
		}
Exemple #19
0
		public void FocusOnOutput ()
		{
			if (MapMagic.instance == null) MapMagic.instance = FindObjectOfType<MapMagic>();
			MapMagic script = MapMagic.instance;
			if (script == null) return;
			
			//finding height output
			Rect outputRect = new Rect();
			if (script.gens.GetGenerator<HeightOutput>() != null) outputRect = script.gens.GetGenerator<HeightOutput>().guiRect;
			else if (script.gens.list.Length != 0) outputRect = script.gens.list[0].guiRect;

			//focusing
			layout = new Layout();
			outputRect = layout.ToDisplay(outputRect);
			layout.scroll = -outputRect.center;
			layout.scroll.y += this.position.height / 2;
			layout.scroll.x += this.position.width - outputRect.width; 

			//saving
			if (script==null) script = FindObjectOfType<MapMagic>();
			script.guiScroll = layout.scroll; script.guiZoom = layout.zoom; //saving
		}
Exemple #20
0
		public void OnEnable ()
		{
			#if UNITY_EDITOR
			//adding delegates
			UnityEditor.EditorApplication.update -= Update;	

			if (isEditor) 
				UnityEditor.EditorApplication.update += Update;	
			#endif

			//finding singleton instance
			instance = FindObjectOfType<MapMagic>();

			//checking terrains consistency
			if (chunks != null)
			foreach (Chunk chunk in chunks.All())
				if (chunk.terrain == null) chunks.Remove(chunk.coord);

			//changing seed on playmode start
			if (changeSeed && Extensions.isPlaying)
			{
				seed = (int)(System.DateTime.Now.Ticks % 1000000);
				ClearResults();
				Generate(force:true);
			}

			if (previewShader == null) previewShader = Shader.Find("MapMagic/TerrainPreview");

			//assigning default shaders for 2019.2 and later
			#if UNITY_2019_2_OR_NEWER
			if (customTerrainMaterial == null)
			{
				Shader terrainShader = Shader.Find("HDRP/TerrainLit");
				if (terrainShader == null) terrainShader = Shader.Find("Lightweight Render Pipeline/Terrain/Lit");
				if (terrainShader == null) terrainShader = Shader.Find("Nature/Terrain/Standard");
				customTerrainMaterial = new Material(terrainShader);
			}
			#endif
		}
Exemple #21
0
			public void SetSettings (MapMagic magic)
			{
				terrain.heightmapPixelError = magic.pixelError;
				terrain.basemapDistance = magic.baseMapDist;
				terrain.castShadows = magic.castShadows;

				if (magic.terrainMaterial != null) { terrain.materialTemplate=magic.terrainMaterial; terrain.materialType=Terrain.MaterialType.Custom; }
				else terrain.materialType=Terrain.MaterialType.BuiltInStandard;

				terrain.drawTreesAndFoliage = magic.detailDraw;
				terrain.detailObjectDistance = magic.detailDistance;
				terrain.detailObjectDensity = magic.detailDensity;
				terrain.treeDistance = magic.treeDistance;
				terrain.treeBillboardDistance = magic.treeBillboardStart;
				terrain.treeCrossFadeLength = magic.treeFadeLength;
				terrain.treeMaximumFullLODCount = magic.treeFullLod;

				terrain.terrainData.wavingGrassSpeed = magic.windSpeed;
				terrain.terrainData.wavingGrassAmount = magic.windSize;
				terrain.terrainData.wavingGrassStrength = magic.windBending;
				terrain.terrainData.wavingGrassTint = magic.grassTint;
			}
Exemple #22
0
			public void Preview ()
			{
				#if UNITY_EDITOR 
				if (Event.current == null || Event.current.type != EventType.Repaint) return;
					
				//clearing preview if prevew generator is off (or non-map)
				if (MapMagic.instance.previewOutput==null || MapMagic.instance.previewOutput.type!=Generator.InoutType.Map)
				{
					if (terrain.materialTemplate != null && terrain.materialTemplate.shader.name == "MapMagic/TerrainPreviewFirstPass")
					{
						terrain.materialType = MapMagic.ToUnityTerrMatType(MapMagic.instance.terrainMaterialType);
						terrain.materialTemplate = previewBackupMaterial;

						previewBackupMaterial = null;
						lastPreviewedMatrix = null;

						UnityEditor.SceneView.RepaintAll();
					}
				}
						
				if (MapMagic.instance.previewOutput!=null && MapMagic.instance.previewOutput.type == Generator.InoutType.Map)
				{
					//loading preview material from terrain (or creating new)
					Material previewMat = null;
					if (terrain.materialTemplate!=null && terrain.materialTemplate.shader.name=="MapMagic/TerrainPreviewFirstPass") previewMat = terrain.materialTemplate;
					if (previewMat == null) 
					{
						Shader previewShader = Shader.Find("MapMagic/TerrainPreviewFirstPass");
						previewMat = new Material(previewShader);

						previewBackupMaterial = terrain.materialTemplate;
						terrain.materialTemplate = previewMat;
						terrain.materialType = Terrain.MaterialType.Custom;
						
						UnityEditor.SceneView.RepaintAll();
					}

					//loading matrix
					Matrix matrix = MapMagic.instance.previewOutput.GetObject<Matrix>(this);

					//refreshing preview texture
					if (matrix != lastPreviewedMatrix)
					{
						Texture2D tex = null;
						
						//populate
						if (matrix != null) 
						{
							tex = new Texture2D(matrix.rect.size.x, matrix.rect.size.z);
			 
							Color[] line = new Color[matrix.rect.size.z];
							for (int x=0; x<matrix.rect.size.x; x++)
							{
								for (int z=0; z<matrix.rect.size.z; z++)
								{
									float val = matrix[x+matrix.rect.offset.x, z+matrix.rect.offset.z];
									line[z] = new Color(val, val, val);
								}
								tex.SetPixels(x,0,1,line.Length,line);
							}
						}
						else //in case the output is not generated
						{
							tex = Extensions.ColorTexture(2,2,Color.gray);
						}

						//apply
						tex.Apply();
						previewMat.SetTexture("_Preview", tex);
						if (MapMagic.instance.guiDebug) Debug.Log("Preview Applied");

						lastPreviewedMatrix = matrix;

						UnityEditor.SceneView.RepaintAll();
					}
				}

				//spatial hash
				if (MapMagic.instance.previewOutput!=null && MapMagic.instance.previewOutput.type == Generator.InoutType.Objects)
				{
					float pixelSize = 1f * MapMagic.instance.terrainSize / MapMagic.instance.resolution;
					
					SpatialHash objs = MapMagic.instance.previewOutput.GetObject<SpatialHash>(this);

					if (objs != null)
					{
						int objsCount = objs.Count;
						foreach (SpatialObject obj in objs)
						{
							float terrainHeight = 0;
							if (heights != null) terrainHeight = heights.GetInterpolated(obj.pos.x, obj.pos.y);
							Vector3 pos = new Vector3(obj.pos.x*pixelSize, (obj.height+terrainHeight)*MapMagic.instance.terrainHeight, obj.pos.y*pixelSize);
							pos += MapMagic.instance.transform.position;

							UnityEditor.Handles.color = new Color(1,1,1,1);
							UnityEditor.Handles.DrawLine(pos+new Vector3(obj.size/2f,0,0), pos-new Vector3(obj.size/2f,0,0));
							UnityEditor.Handles.DrawLine(pos+new Vector3(0,0,obj.size/2f), pos-new Vector3(0,0,obj.size/2f));

							if (objsCount < 100)
							{
								Vector3 oldPoint = pos;
								foreach (Vector3 point in pos.CircleAround(obj.size/2f, 12, true))
								{
									UnityEditor.Handles.DrawLine(oldPoint,point);
									oldPoint = point;
								}
							}

							UnityEditor.Handles.color = new Color(1,1,1,0.15f); 
							UnityEditor.Handles.DrawLine(new Vector3(pos.x, 0, pos.z), new Vector3(pos.x, MapMagic.instance.terrainHeight, pos.z));
						}
					}
				}

				#endif
			}
		//when selected
		public void OnSceneGUI ()
		{	
			if (script == null) script = (MapMagic)target;
			MapMagic.instance = script;
			if (!script.enabled) return;

			//checking removed terrains
			foreach (Chunk chunk in script.chunks.All())
				if (chunk.terrain == null) script.chunks.Remove(chunk.coord);
			

			#region Drawing Selection

			//drawing frames
			if (Event.current.type == EventType.Repaint)
			foreach(Chunk chunk in MapMagic.instance.chunks.All())
			{
				Handles.color = nailColor*0.8f;
				if (chunk.locked) Handles.color = lockColor*0.8f;
				DrawSelectionFrame(chunk.coord, 5f);
			}

			#endregion
		

			#region Selecting terrains
			if (selectionMode!=SelectionMode.none)
			{
				//disabling selection
				HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));

				//finding aiming ray
				float pixelsPerPoint = 1;
				#if UNITY_5_4_OR_NEWER 
				pixelsPerPoint = EditorGUIUtility.pixelsPerPoint;
				#endif

				SceneView sceneview = UnityEditor.SceneView.lastActiveSceneView;
				if (sceneview==null || sceneview.camera==null) return;
				
				Vector2 mousePos = Event.current.mousePosition;
				mousePos = new Vector2(mousePos.x/sceneview.camera.pixelWidth, 1f/pixelsPerPoint - mousePos.y/sceneview.camera.pixelHeight) * pixelsPerPoint;
				Ray aimRay = sceneview.camera.ViewportPointToRay(mousePos);

				//aiming terrain or empty place
				Vector3 aimPos = Vector3.zero;
				RaycastHit hit;
				if (Physics.Raycast(aimRay, out hit, Mathf.Infinity)) aimPos = hit.point;
				else
				{
					aimRay.direction = aimRay.direction.normalized;
					float aimDist = aimRay.origin.y / (-aimRay.direction.y);
					aimPos = aimRay.origin + aimRay.direction*aimDist;
				}
				aimPos -= MapMagic.instance.transform.position;

				Coord aimCoord = aimPos.FloorToCoord(MapMagic.instance.terrainSize);

				if (selectionMode == SelectionMode.nailing && !Event.current.alt)
				{
					//drawing selection frame
					Handles.color = nailColor;
					DrawSelectionFrame(aimCoord, width:5f);

					//selecting / unselecting
					if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
					{
						if (MapMagic.instance.chunks[aimCoord]==null) //if obj not exists - nail
						{
							Undo.RegisterFullObjectHierarchyUndo(MapMagic.instance, "MapMagic Pin Terrain");
							MapMagic.instance.chunks.Create(aimCoord, script, pin:true); 
							//MapMagic.instance.terrains.maxCount++;
						}
						else 
						{
							Terrain terrain = MapMagic.instance.chunks[aimCoord].terrain;
							if (terrain != null) Undo.DestroyObjectImmediate(terrain.gameObject);
							Undo.RecordObject(MapMagic.instance, "MapMagic Unpin Terrain");
							MapMagic.instance.setDirty = !MapMagic.instance.setDirty;

							MapMagic.instance.chunks.Remove(aimCoord);
							//MapMagic.instance.chunks[aimCoord].pinned = false;
							//MapMagic.instance.terrains.maxCount--;
						}
						//if (MapMagic.instance.terrains.maxCount < MapMagic.instance.terrains.nailedHashes.Count+4) MapMagic.instance.terrains.maxCount = MapMagic.instance.terrains.nailedHashes.Count+4;
						//EditorUtility.SetDirty(MapMagic.instance); //already done via undo
					}
				}

				if (selectionMode == SelectionMode.locking  && !Event.current.alt)
				{
					Chunk aimedTerrain = MapMagic.instance.chunks[aimCoord];
					if (aimedTerrain != null)
					{
						//drawing selection frame
						Handles.color = lockColor;
						DrawSelectionFrame(aimCoord, width:5f);

						//selecting / unselecting
						if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
						{
							Undo.RecordObject(MapMagic.instance, "MapMagic Lock Terrain");
							MapMagic.instance.setDirty = !MapMagic.instance.setDirty;

							aimedTerrain.locked = !aimedTerrain.locked;
							//EditorUtility.SetDirty(MapMagic.instance); //already done via undo
						}
					}
				}

				if (selectionMode == SelectionMode.exporting && !Event.current.alt)
				{
					Chunk aimedTerrain = MapMagic.instance.chunks[aimCoord];
					if (aimedTerrain != null)
					{
						//drawing selection frame
						Handles.color = exportColor;
						DrawSelectionFrame(aimCoord, width:5f);

						//exporting
						if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
						{
							string path= UnityEditor.EditorUtility.SaveFilePanel(
										"Export Terrain Data",
										"",
										"TerrainData.asset", 
										"asset");
							if (path!=null && path.Length!=0)
							{
								path = path.Replace(Application.dataPath, "Assets");
								if (!path.Contains("Assets")) { Debug.LogError("MapMagic: Path is out of the Assets folder"); return; }
								if (AssetDatabase.LoadAssetAtPath(path, typeof(TerrainData)) as TerrainData == aimedTerrain.terrain.terrainData) { Debug.Log("MapMagic: this terrain was already exported at the given path"); return; }
     
								Terrain terrain = aimedTerrain.terrain;
								float[,,] splats = terrain.terrainData.GetAlphamaps(0,0,terrain.terrainData.alphamapResolution, terrain.terrainData.alphamapResolution);
								//else splats = new float[terrain.terrainData.alphamapResolution,terrain.terrainData.alphamapResolution,1];

								if (terrain.terrainData.alphamapLayers==1 && terrain.terrainData.alphamapTextures[0].width==2)
								{
									terrain.terrainData.splatPrototypes = new SplatPrototype[0];
									terrain.terrainData.SetAlphamaps(0,0,new float[0,0,0]);
								}
     
								AssetDatabase.DeleteAsset(path);

								if (AssetDatabase.Contains(terrain.terrainData)) 
								{
									AssetDatabase.CopyAsset(AssetDatabase.GetAssetPath(terrain.terrainData),path);
									terrain.terrainData = AssetDatabase.LoadAssetAtPath(path, typeof(TerrainData)) as TerrainData;
									if (terrain.GetComponent<TerrainCollider>()!=null) terrain.GetComponent<TerrainCollider>().terrainData = terrain.terrainData;
								}
								else AssetDatabase.CreateAsset(terrain.terrainData, path);

								terrain.terrainData.SetAlphamaps(0,0,splats);

								AssetDatabase.SaveAssets();
							}
						}
					}
				}
				
				//redrawing scene by moving temp object
				if (script.sceneRedrawObject==null) { script.sceneRedrawObject = new GameObject(); script.sceneRedrawObject.hideFlags = HideFlags.HideInHierarchy; }
				script.sceneRedrawObject.transform.position = aimPos;
			}
			#endregion
		

		}
		public override void  OnInspectorGUI ()
		{
			script = (MapMagic)target;
			if (MapMagic.instance == null) MapMagic.instance = script;
			
			//checking removed terrains
			foreach (Chunk chunk in script.chunks.All())
				if (chunk.terrain == null) script.chunks.Remove(chunk.coord);

			//assigning mapmagic to mapmagic window
			if (MapMagicWindow.instance != null && MapMagicWindow.instance.mapMagic != (IMapMagic)script)
				MapMagicWindow.Show(script.gens, script, forceOpen:false);
			
			if (layout == null) layout = new Layout();
			layout.margin = 0;
			layout.rightMargin = 0;
			layout.field = Layout.GetInspectorRect();
			layout.cursor = new Rect();
			layout.undoObject = script;
			layout.undoName =  "MapMagic settings change";

			layout.Par(20); bool modeNailing = layout.CheckButton(selectionMode == SelectionMode.nailing, "Pin", rect:layout.Inset(0.3333f), icon:"MapMagic_PinIcon");
				if (layout.lastChange && modeNailing) selectionMode = SelectionMode.nailing;
				if (layout.lastChange && !modeNailing) selectionMode = SelectionMode.none;
			bool modeLocking = layout.CheckButton(selectionMode == SelectionMode.locking, "Lock", rect:layout.Inset(0.3333f), icon:"MapMagic_LockIcon");
				if (layout.lastChange && modeLocking) selectionMode = SelectionMode.locking;
				if (layout.lastChange && !modeLocking) selectionMode = SelectionMode.none;
			bool modeExporting = layout.CheckButton(selectionMode == SelectionMode.exporting, "Save", rect:layout.Inset(0.3333f), icon:"MapMagic_ExportIcon");
				if (layout.lastChange && modeExporting) selectionMode = SelectionMode.exporting;
				if (layout.lastChange && !modeExporting) selectionMode = SelectionMode.none;


			layout.Par(4);
			layout.Par(24); if (layout.Button("Show Editor", rect:layout.Inset(), icon:"MapMagic_EditorIcon"))
				MapMagicWindow.Show(script.gens, script, forceOpen:true);

//			layout.ComplexField(ref MapMagic.instance.seed, "Seed");
//			layout.ComplexSlider(script.terrains.terrainSize, "Terrain Size", max:2048, quadratic:true);
//			layout.ComplexSlider(ref script.terrainHeight, "Terrain Height", max:2048, quadratic:true);

//			layout.Par();

			
//			layout.Par(); if (layout.Button("Generate")) { MapMagic.instance.terrains.start = true; script.ProcessThreads(); }
//			layout.Par(); if (layout.Button("Clear")) MapMagic.instance.generators.ClearGenerators();

//			Undo.RecordObject (script, "MapMagic settings change");

			layout.fieldSize = 0.4f;
			layout.Par(8); layout.Foldout(ref script.guiSettings, "General Settings");
			if (script.guiSettings)
			{
				Rect anchor = layout.lastRect;
				layout.margin += 10; layout.rightMargin += 5;
				
				//layout.Field(ref MapMagic.instance.voxelandMode, "Voxeland Mode");
				layout.Field(ref MapMagic.instance.seed, "Seed");
				layout.Toggle(ref MapMagic.instance.changeSeed, "Change Seed on Playmode Start");
				MapMagic.instance.resolution = (int)layout.Field((Pots)MapMagic.instance.resolution, "Resolution");
				if (layout.lastChange) { MapMagic.instance.ClearResults(); MapMagic.instance.Generate(); }
				layout.Field(ref MapMagic.instance.terrainSize, "Terrain Size");
				if (layout.lastChange) MapMagic.instance.ResetChunks();
				layout.Field(ref MapMagic.instance.terrainHeight, "Terrain Height");
				if (layout.lastChange) MapMagic.instance.ResetChunks();

				layout.Par(5);
				layout.Field(ref MapMagic.instance.generateInfinite, "Generate Infinite Terrain");
				if (MapMagic.instance.generateInfinite)
				{
					layout.Field(ref MapMagic.instance.generateRange, "Generate Range");
					layout.Field(ref MapMagic.instance.removeRange, "Remove Range", min:MapMagic.instance.generateRange);
					layout.Field(ref MapMagic.instance.enableRange, "Enable Range");
					//layout.Field(ref MapMagic.instance.terrains.enableRange, "Low Detail Range");
					//layout.Field(ref MapMagic.instance.terrains.detailRange, "Full Detail Range");
				}

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

				layout.Par(5);
				script.instantGenerate = layout.Field(script.instantGenerate, "Instant Generate");
				layout.Field(ref script.saveIntermediate, "Save Intermediate Results");
				#if WDEBUG
				layout.Label("Ready Count: " +script.chunks.Any().results.ready.Count);
				layout.Label("Results Count: " +script.chunks.Any().results.results.Count);
				layout.Label("Apply Count: " +script.chunks.Any().results.apply.Count); 
				#endif
				
				layout.Field(ref script.guiHideWireframe, "Hide Frame");
				if (layout.lastChange) script.transform.ToggleDisplayWireframe(!script.guiHideWireframe);

				layout.Par(5);
				layout.Field(ref script.heightWeldMargins, "Height Weld Margins", max:100);
				layout.Field(ref script.splatsWeldMargins, "Splats Weld Margins", max:100);
				//layout.ComplexField(ref script.hideWireframe, "Hide Wireframe");
				
				layout.Par(5);
				layout.Toggle(ref script.hideFarTerrains, "Hide Out-of-Range Terrains");
				
				layout.Par(10);
				layout.Par(0,padding:0); layout.Inset();
				Rect internalAnchor = layout.lastRect;
					layout.Toggle(ref script.copyLayersTags, "Copy Layers and Tags to Terrains");
					layout.Toggle(ref script.copyComponents, "Copy Components to Terrains");
				layout.Foreground(internalAnchor);

				layout.Par(10);
				layout.Par(0,padding:0); layout.Inset();
				internalAnchor = layout.lastRect;
					layout.Label("Generate Terrain Markers:");
					layout.Field(ref script.genAroundMainCam, "Around Main Camera");
					layout.Par(); layout.Field(ref script.genAroundObjsTag, "Around Objects Tagged", rect:layout.Inset());	
				
					int tagFieldWidth = (int)(layout.field.width*layout.fieldSize - 25);
					layout.cursor.x -= tagFieldWidth;
					script.genAroundTag = EditorGUI.TagField(layout.Inset(tagFieldWidth), script.genAroundTag);
				layout.Foreground(internalAnchor);

				layout.Par(10);
				layout.Par(0,padding:0); layout.Inset();
				internalAnchor = layout.lastRect;
					layout.Label("Floating Point Origin Solution:");
					layout.Toggle(ref script.shift, "Shift World");
					layout.Field(ref script.shiftThreshold, "Shift Threshold", disabled:!script.shift);
					layout.LayersField(ref script.shiftExcludeLayers, "Exclude Layers", disabled:!script.shift);
				layout.Foreground(internalAnchor);

				//data
				layout.Par(10);
				layout.Par(0,padding:0); layout.Inset();
				internalAnchor = layout.lastRect;
					layout.fieldSize = 0.7f;
					script.gens = layout.ScriptableAssetField(script.gens, construct:GeneratorsAsset.Default, savePath: null);
					if (layout.lastChange) 
						MapMagicWindow.Show(script.gens, script, forceOpen:false, asBiome:false);
				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(7);
				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 -= 10; layout.rightMargin -= 5;
				layout.Foreground(anchor);
			}

			layout.fieldSize = 0.5f; layout.sliderSize = 0.6f;
			layout.Par(8); layout.Foldout(ref script.guiTerrainSettings, "Terrain Settings");
			if (script.guiTerrainSettings)
			{
				Rect anchor = layout.lastRect;
				layout.margin += 10; layout.rightMargin += 5;

				layout.Field(ref script.pixelError, "Pixel Error", min:0, max:200, slider:true);
				layout.Field(ref script.baseMapDist, "Base Map Dist.", min:0, max:2000, slider:true, disabled:!script.showBaseMap);
				layout.Field(ref script.showBaseMap, "Show Base Map");
				layout.Field(ref script.castShadows, "Cast Shadows");
				layout.Field(ref script.applyColliders, "Apply Terrain Colliders");

				layout.Par(5);
				layout.Field(ref script.terrainMaterialType, "Material Type");
				layout.Field(ref script.customTerrainMaterial, "Custom Material", disabled:script.terrainMaterialType!=Terrain.MaterialType.Custom); 
				layout.Toggle(ref script.assignCustomTerrainMaterial, "Assign Material (disable for MegaSplat/RTP)", disabled:script.terrainMaterialType!=Terrain.MaterialType.Custom);
					
				//layout.Toggle(ref script.materialTemplateMode, "Material Template Mode (MegaSplat/RTP)");
				if (Preview.enabled) layout.Label("Terrain Material is disabled in preview mode", helpbox: true);

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

			layout.Par(8); layout.Foldout(ref script.guiTreesGrassSettings, "Trees, Details and Grass Settings");
			if (script.guiTreesGrassSettings)
			{
				Rect anchor = layout.lastRect;
				layout.margin += 10; layout.rightMargin += 5;

				layout.Field(ref script.detailDraw, "Draw");
				layout.Field(ref script.detailDistance, "Detail Distance", min:0, max:250, slider:true);
				layout.Field(ref script.detailDensity, "Detail Density", min:0, max:1, slider:true);
				layout.Field(ref script.treeDistance, "Tree Distance", min:0, max:5000, slider:true);
				layout.Field(ref script.treeBillboardStart, "Billboard Start", min:0, max:2000, slider:true);
				layout.Field(ref script.treeFadeLength, "Fade Length", min:0, max:200, slider:true);
				layout.Field(ref script.treeFullLod, "Max Full LOD Trees", min:0, max:10000, slider:true);
				layout.Field(ref script.bakeLightProbesForTrees, "Bake Light Probes For Trees");

				layout.Par(5);
				layout.Field(ref script.windSpeed, "Wind Amount", min:0, max:1, slider:true);
				layout.Field(ref script.windSize, "Wind Bending", min:0, max:1, slider:true);
				layout.Field(ref script.windBending, "Wind Speed", min:0, max:1, slider:true); //there's no mistake here. Variable names are swapped in unity
				layout.Field(ref script.grassTint, "Grass Tint");

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

			if (layout.change) 
				foreach (Chunk tw in MapMagic.instance.chunks.All()) tw.SetSettings();


			#region Mass Pin
			layout.Par(8); layout.Foldout(ref script.guiMassPin, "Mass Pin/Lock");
			if (script.guiMassPin)
			{
				Rect anchor = layout.lastRect;
				layout.margin += 10; layout.rightMargin += 5;

				layout.Par(52);
				layout.Label("This feature is designed to be used with streaming plugins. Using it in all other purposes is not recommended because of performance reasons", layout.Inset(), helpbox:true);

				layout.Par();
				layout.Label("Offset (chunks):", layout.Inset(0.5f));
				layout.Field(ref script.guiPinRect.offset.x, "X", layout.Inset(0.25f), fieldSize:0.7f);
				layout.Field(ref script.guiPinRect.offset.z, "Z", layout.Inset(0.25f), fieldSize:0.7f);

				layout.Par();
				layout.Label("Area Size (chunks):", layout.Inset(0.5f));
				layout.Field(ref script.guiPinRect.size.x, "X", layout.Inset(0.25f), fieldSize:0.7f);
				layout.Field(ref script.guiPinRect.size.z, "Z", layout.Inset(0.25f), fieldSize:0.7f);

				layout.Par();
				if (layout.Button("Pin", layout.Inset(0.333f)))
				{
					Undo.RegisterFullObjectHierarchyUndo(MapMagic.instance, "MapMagic Mass Pin Terrain");
					Coord min = script.guiPinRect.Min; Coord max = script.guiPinRect.Max;
					for (int x=min.x; x<max.x; x++)
						for (int z=min.z; z<max.z; z++)
							MapMagic.instance.chunks.Create(new Coord(x,z), script, pin:true); 
				}

				if (layout.Button("Lock All", layout.Inset(0.333f)))
				{
					Undo.RegisterFullObjectHierarchyUndo(MapMagic.instance, "MapMagic Mass Lock Terrain");
					foreach (Chunk chunk in MapMagic.instance.chunks.All(pinnedOnly:true))
						chunk.locked = true;
				}

				if (layout.Button("Unpin All", layout.Inset(0.333f)))
				{
					Undo.RegisterFullObjectHierarchyUndo(MapMagic.instance, "MapMagic Mass Pin Terrain");
					MapMagic.instance.chunks.Clear();
				}

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

			#region About
			layout.Par(8); layout.Foldout(ref script.guiAbout, "About");
			if (script.guiAbout)
			{
				Rect anchor = layout.lastRect;
				layout.margin += 10; layout.rightMargin += 5;

				Rect savedCursor = layout.cursor;
				
				layout.Par(100, padding:0);
				layout.Icon("MapMagicAbout", layout.Inset(100,padding:0));

				layout.cursor = savedCursor;
				layout.margin = 115;

				layout.Label("MapMagic " + MapMagic.version.ToVersionString() + " " + MapMagic.versionState.ToVersionString());
				layout.Label("by Denis Pahunov");
				
				layout.Par(10);
				layout.Label(" - Online Documentation", url:"https://gitlab.com/denispahunov/mapmagic/wikis/home");
				layout.Label(" - Video Tutorials", url:"https://www.youtube.com/playlist?list=PL8fjbXLqBxvZb5yqXwp_bn4keyzyg5e0R");
				layout.Label(" - Forum Thread", url:"http://forum.unity3d.com/threads/map-magic-a-node-based-procedural-and-infinite-map-generator-for-asset-store.344440/");
				layout.Label(" - Issues / Ideas", url:"https://gitlab.com/denispahunov/mapmagic/issues");

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

			Layout.SetInspectorRect(layout.field);
		}
		public void  OnSceneGUI ()
		{	
			if (script == null) script = (MapMagic)target;
			MapMagic.instance = script;
			if (!script.enabled) return;
			script.terrains.CheckEmpty();
			

			#region Drawing Selection

			//drawing frames
			if (Event.current.type == EventType.Repaint)
			foreach(Coord coord in MapMagic.instance.terrains.Coords())
			{
				Handles.color = nailColor*0.8f;
				if (MapMagic.instance.terrains[coord].locked) Handles.color = lockColor*0.8f;
				DrawSelectionFrame(coord, 5f);
			}

			#endregion
		

			#region Selecting terrains
			if (selectionMode==SelectionMode.nailing || selectionMode==SelectionMode.locking)
			{
				//disabling selection
				HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));

				//finding aiming ray
				Vector2 mousePos = Event.current.mousePosition;
				mousePos.y = Screen.height - mousePos.y - 40;
				Camera cam = UnityEditor.SceneView.lastActiveSceneView.camera;
				if (cam==null) return;
				Ray aimRay = cam.ScreenPointToRay(mousePos);

				//aiming terrain or empty place
				Vector3 aimPos = Vector3.zero;
				RaycastHit hit;
				if (Physics.Raycast(aimRay, out hit, Mathf.Infinity)) aimPos = hit.point;
				else
				{
					aimRay.direction = aimRay.direction.normalized;
					float aimDist = aimRay.origin.y / (-aimRay.direction.y);
					aimPos = aimRay.origin + aimRay.direction*aimDist;
				}
				aimPos -= MapMagic.instance.transform.position;

				Coord aimCoord = aimPos.FloorToCoord(MapMagic.instance.terrainSize);

				if (selectionMode == SelectionMode.nailing && !Event.current.alt)
				{
					//drawing selection frame
					Handles.color = nailColor;
					DrawSelectionFrame(aimCoord, width:5f);

					//selecting / unselecting
					if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
					{
						if (MapMagic.instance.terrains[aimCoord]==null) //if obj not exists - nail
						{
							Undo.RegisterFullObjectHierarchyUndo(MapMagic.instance, "MapMagic Pin Terrain");
							MapMagic.instance.terrains.Nail(aimCoord); 
							//MapMagic.instance.terrains.maxCount++;
						}
						else 
						{
							Undo.DestroyObjectImmediate(MapMagic.instance.terrains[aimCoord].terrain.gameObject);
							Undo.RecordObject(MapMagic.instance, "MapMagic Unpin Terrain");
							MapMagic.instance.setDirty = !MapMagic.instance.setDirty;

							MapMagic.instance.terrains.Unnail(aimCoord); 
							//MapMagic.instance.terrains.maxCount--;
						}
						//if (MapMagic.instance.terrains.maxCount < MapMagic.instance.terrains.nailedHashes.Count+4) MapMagic.instance.terrains.maxCount = MapMagic.instance.terrains.nailedHashes.Count+4;
						//EditorUtility.SetDirty(MapMagic.instance); //already done via undo
					}
				}

				if (selectionMode == SelectionMode.locking  && !Event.current.alt)
				{
					Chunk aimedTerrain = MapMagic.instance.terrains[aimCoord];
					if (aimedTerrain != null)
					{
						//drawing selection frame
						Handles.color = lockColor;
						DrawSelectionFrame(aimCoord, width:5f);

						//selecting / unselecting
						if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
						{
							Undo.RecordObject(MapMagic.instance, "MapMagic Lock Terrain");
							MapMagic.instance.setDirty = !MapMagic.instance.setDirty;

							aimedTerrain.locked = !aimedTerrain.locked;
							//EditorUtility.SetDirty(MapMagic.instance); //already done via undo
						}
					}
				}
				
				//redrawing scene by moving temp object
				if (script.sceneRedrawObject==null) { script.sceneRedrawObject = new GameObject(); script.sceneRedrawObject.hideFlags = HideFlags.HideInHierarchy; }
				script.sceneRedrawObject.transform.position = aimPos;
			}
			#endregion
		}
		public override void  OnInspectorGUI ()
		{
			script = (MapMagic)target;
			if (MapMagic.instance == null) MapMagic.instance = script;
			script.terrains.CheckEmpty();
			
			if (layout == null) layout = new Layout();
			layout.margin = 0;
			layout.field = Layout.GetInspectorRect();
			layout.cursor = new Rect();
			layout.undoObject = script;
			layout.undoName =  "MapMagic settings change";

			layout.Par(20); bool modeNailing = layout.CheckButton(selectionMode == SelectionMode.nailing, "Pin Terrain", rect:layout.Inset(0.5f), icon:"MapMagic_PinIcon");
				if (layout.lastChange && modeNailing) selectionMode = SelectionMode.nailing;
				if (layout.lastChange && !modeNailing) selectionMode = SelectionMode.none;
			bool modeLocking = layout.CheckButton(selectionMode == SelectionMode.locking, "Lock Terrain", rect:layout.Inset(0.5f), icon:"MapMagic_LockIcon");
				if (layout.lastChange && modeLocking) selectionMode = SelectionMode.locking;
				if (layout.lastChange && !modeLocking) selectionMode = SelectionMode.none;

			layout.Par(4);
			layout.Par(24); if (layout.Button("Show Editor", rect:layout.Inset(), icon:"MapMagic_EditorIcon"))
			{
				MapMagicWindow window = (MapMagicWindow)EditorWindow.GetWindow (typeof (MapMagicWindow));
				//SceneMagicWindow window = EditorWindow.GetWindow<VoxelandCreate>();
				//window.script = script;
				window.Show();
//				window.FocusOnOutput();
			}

//			layout.ComplexField(ref MapMagic.instance.seed, "Seed");
//			layout.ComplexSlider(script.terrains.terrainSize, "Terrain Size", max:2048, quadratic:true);
//			layout.ComplexSlider(ref script.terrainHeight, "Terrain Height", max:2048, quadratic:true);

//			layout.Par();

			
//			layout.Par(); if (layout.Button("Generate")) { MapMagic.instance.terrains.start = true; script.ProcessThreads(); }
//			layout.Par(); if (layout.Button("Clear")) MapMagic.instance.generators.ClearGenerators();

//			Undo.RecordObject (script, "MapMagic settings change");
			layout.margin =10;

			layout.fieldSize = 0.4f;
			layout.Par(5); layout.Foldout(ref script.guiSettings, "General Settings");
			if (script.guiSettings)
			{
				MapMagic.instance.resolution = (int)layout.Field((Pots)MapMagic.instance.resolution, "Resolution");
				if (layout.lastChange && MapMagic.instance.instantGenerate) MapMagic.instance.ForceGenerate();
				layout.Field(ref MapMagic.instance.terrainSize, "Terrain Size");
				if (layout.lastChange) MapMagic.instance.terrains.Reset();
				layout.Field(ref MapMagic.instance.terrainHeight, "Terrain Height");
				if (layout.lastChange) MapMagic.instance.terrains.Reset();

				layout.Par(5);
				layout.Field(ref MapMagic.instance.generateInfinite, "Generate Infinite Terrain");
				if (MapMagic.instance.generateInfinite)
				{
					layout.Field(ref MapMagic.instance.generateRange, "Generate Range");
					layout.Field(ref MapMagic.instance.removeRange, "Remove Range", min:MapMagic.instance.generateRange);
					layout.Field(ref MapMagic.instance.enableRange, "Enable Range");
					//layout.Field(ref MapMagic.instance.terrains.enableRange, "Low Detail Range");
					//layout.Field(ref MapMagic.instance.terrains.detailRange, "Full Detail Range");
				}

				layout.Par(5);
				layout.Field(ref script.multiThreaded, "Multithreaded");
				if (script.multiThreaded) layout.Field(ref script.maxThreads, "Max Threads");
				layout.Field(ref script.instantGenerate, "Instant Generate");
				layout.Field(ref script.saveIntermediate, "Save Intermediate Results");

				layout.Par(5);
				layout.Field(ref script.heightWeldMargins, "Height Weld Margins", max:100);
				layout.Field(ref script.splatsWeldMargins, "Splats Weld Margins", max:100);
				//layout.ComplexField(ref script.hideWireframe, "Hide Wireframe");
				
				layout.Par(5);
				layout.Toggle(ref script.hideFarTerrains, "Hide Out-of-Range Terrains");
				//layout.Toggle(ref script.useAllCameras, "Generate around All Cameras");
				layout.Toggle(ref script.copyLayersTags, "Copy Layers and Tags to Terrains");
				layout.Toggle(ref script.copyComponents, "Copy Components to Terrains");

				layout.Par(5);
				layout.Label("Generate Terrain Markers:");
				layout.Field(ref script.genAroundMainCam, "Around Main Camera");
				
				layout.Par(); layout.Field(ref script.genAroundObjsTag, "Around Objects Tagged", rect:layout.Inset());
				int tagFieldWidth = (int)(layout.field.width*layout.fieldSize - 25);
				layout.cursor.x -= tagFieldWidth;
				script.genAroundTag = EditorGUI.TagField(layout.Inset(tagFieldWidth), script.genAroundTag);

				layout.Par(10);
				layout.Par(); layout.Label("Data", layout.Inset(0.2f));
				GeneratorsAsset newGens = layout.Field<GeneratorsAsset>(script.gens, rect:layout.Inset(0.5f));
				if (newGens != script.gens) { script.gens = newGens; script.guiGens = newGens; }
				if (layout.lastChange) script.gens.OnAfterDeserialize();
				if (script.gens == null)
				{
					if (layout.Button("Create", layout.Inset(0.3f)))
					{
						MapMagic.instance.gens = GeneratorsAsset.Default();
						MapMagic.instance.guiGens = MapMagic.instance.gens;
						EditorUtility.SetDirty(MapMagic.instance); 
					}
				}
                else if (!AssetDatabase.Contains(script.gens))
				{
					if (layout.Button("Save", layout.Inset(0.3f))) 
					{
						MapMagic.instance.gens.SaveAsset();
						EditorUtility.SetDirty(MapMagic.instance); 
					}
				}
				else 
				{
					if (layout.Button("Release", layout.Inset(0.3f))) 
					{ 
						MapMagic.instance.gens = MapMagic.instance.gens.ReleaseAsset(); 
						MapMagic.instance.guiGens = MapMagic.instance.gens;
						EditorUtility.SetDirty(MapMagic.instance); 
					}
				}

				layout.Par(5);
				//layout.Field(ref script.guiGeneratorWidth, "Node Width");
				layout.Toggle(ref script.guiDebug, "Debug");
			}

			layout.fieldSize = 0.5f; layout.sliderSize = 0.6f;
			layout.Par(5); layout.Foldout(ref script.guiTerrainSettings, "Terrain Settings");
			if (script.guiTerrainSettings)
			{
				layout.Field(ref script.pixelError, "Pixel Error", min:0, max:200, slider:true);
				layout.Field(ref script.baseMapDist, "Base Map Dist.", min:0, max:2000, slider:true);
				layout.Field(ref script.castShadows, "Cast Shadows");

				layout.Field(ref script.terrainMaterialType, "Material Type", disabled:script.previewGenerator!=null);
				layout.Field(ref script.customTerrainMaterial, "Custom Material", disabled:script.terrainMaterialType!=MapMagic.TerrainMaterialType.Custom);
				if (script.previewGenerator!=null) layout.Label("Terrain Material is disabled in preview mode", helpbox: true);
			}

			layout.Par(5); layout.Foldout(ref script.guiTreesGrassSettings, "Trees, Details and Grass Settings");
			if (script.guiTreesGrassSettings)
			{
				layout.Field(ref script.detailDraw, "Draw");
				layout.Field(ref script.detailDistance, "Detail Distance", min:0, max:250, slider:true);
				layout.Field(ref script.detailDensity, "Detail Density", min:0, max:1, slider:true);
				layout.Field(ref script.treeDistance, "Tree Distance", min:0, max:5000, slider:true);
				layout.Field(ref script.treeBillboardStart, "Billboard Start", min:0, max:2000, slider:true);
				layout.Field(ref script.treeFadeLength, "Fade Length", min:0, max:200, slider:true);
				layout.Field(ref script.treeFullLod, "Max Full LOD Trees", min:0, max:10000, slider:true);

				layout.Par(5);
				layout.Field(ref script.windSpeed, "Wind Amount", min:0, max:1, slider:true);
				layout.Field(ref script.windSize, "Wind Bending", min:0, max:1, slider:true);
				layout.Field(ref script.windBending, "Wind Speed", min:0, max:1, slider:true); //there's no mistake here. Variable names are swapped in unity
				layout.Field(ref script.grassTint, "Grass Tint");
			}

			if (layout.change) 
				foreach (Chunk tw in MapMagic.instance.terrains.Objects()) tw.SetSettings();


			#region About
			layout.Par(5); layout.Foldout(ref script.guiAbout, "About");
			if (script.guiAbout)
			{
				Rect savedCursor = layout.cursor;
				
				layout.Par(100, padding:0);
				layout.Icon("MapMagicAbout", layout.Inset(100,padding:0));

				layout.cursor = savedCursor;
				layout.margin = 115;

				layout.Label("MapMagic " + (int)(MapMagic.version/10f) + "." + (MapMagic.version - (int)(MapMagic.version/10f)*10));
				layout.Label("by Denis Pahunov");
				
				layout.Par(10);
				layout.Label(" - Online Documentation", url:"https://docs.google.com/document/d/1OX7zYOrPz9qOFNAfO0qawhB7T3M6tLG9VgZSEntRJTA/edit?usp=sharing");
				layout.Label(" - Video Tutorials", url:"https://www.youtube.com/playlist?list=PL8fjbXLqBxvZb5yqXwp_bn4keyzyg5e0R");
				layout.Label(" - Forum Thread", url:"http://forum.unity3d.com/threads/map-magic-a-node-based-procedural-and-infinite-map-generator-for-asset-store.344440/");

				//layout.Par(10);
				//layout.Par(); layout.Label("Review or rating vote on");
				//layout.Par(); layout.Label("Asset Store", url:"--");
				//layout.Par(); layout.Label("would be appreciated.");

				layout.Par(10);
				layout.Label("On any issues related");
				layout.Label("with plugin functioning ");
				layout.Label("you can contact the");
				layout.Label("author by mail:");
				layout.Label("*****@*****.**", url:"mailto:[email protected]");
			}
			#endregion

			Layout.SetInspectorRect(layout.field);
		}
Exemple #27
0
			//switching state, starting generate and apply (called each frame)
			public void Update (float camDist)
			{
				//removing (unpinning) chunk if it's terrain was removed somehow
				if (terrain == null) 
				{
					MapMagic.instance.terrains.Unnail(coord, remove: true);
					return;
				}

				//enabling/disabling
				if ((camDist<MapMagic.instance.enableRange && complete) || MapMagic.instance.isEditor) 
					{ if (!terrain.gameObject.activeSelf) terrain.gameObject.SetActive(true); }
				else
					{ if (terrain.gameObject.activeSelf) terrain.gameObject.SetActive(false); }

				//setting terrain neighbors (they reset after each serialize)
				SetNeighbors();

				//starting generate
				if ((camDist<MapMagic.instance.generateRange || MapMagic.instance.isEditor) && !running && clear) start = true;

				//starting threads
				if (start)
				{		
					//calling before-gen event
					MapMagic.CallOnGenerateStarted(terrain); //if (MapMagic.OnGenerateStarted != null) MapMagic.OnGenerateStarted(terrain);

					//preparing generators
					if (!MapMagic.instance.generatorsPrepared) MapMagic.instance.PrepareGenerators();
								
					//generating
					if (!MapMagic.instance.multiThreaded) ThreadFn();
					else
					{
						//restarting thread if it is still alive
						if (running) stop=true;

						//if dead and thread limit not reached
						else if (MapMagic.instance.runningThreadsCount < MapMagic.instance.maxThreads)
						{ 
							thread = new Thread(ThreadFn);
							thread.IsBackground = true;
							//thread.Priority = System.Threading.ThreadPriority.BelowNormal;
							thread.Start(MapMagic.instance.gens);
							MapMagic.instance.runningThreadsCount++;
						}
					}
				}

				//sending terrain on apply
				if (!MapMagic.instance.applyRunning && queuedApply  &&  !start && !stop && !running) //if apply not running and got something to apply. Do not apply when terrain stopped, restarted or still producing
				//	queuedApply)
				{
					//iteraing routine manually in editor (in one frame)
					if (MapMagic.instance.isEditor)
					{
						IEnumerator e = ApplyRoutine();
						while (e.MoveNext());
					}

					//starting routine in playmode
					else MapMagic.instance.StartCoroutine(ApplyRoutine());
				}
			}
Exemple #28
0
			public void SetSettings ()
			{
				MapMagic magic = MapMagic.instance;

				terrain.heightmapPixelError = magic.pixelError;
				if (magic.showBaseMap) terrain.basemapDistance = magic.baseMapDist;
				else terrain.basemapDistance = 999999;
				terrain.castShadows = magic.castShadows;
				#if UNITY_2017_4_OR_NEWER
				terrain.reflectionProbeUsage = magic.reflectionProbeUsage;
				#endif
				
				if (terrainCollider==null) terrainCollider = terrain.GetComponent<TerrainCollider>();
				if (terrainCollider!=null) terrainCollider.enabled = MapMagic.instance.applyColliders;

				#if UNITY_2018_3_OR_NEWER
				terrain.drawInstanced = magic.drawInstanced;
				terrain.allowAutoConnect = magic.autoConnect;
				#endif

				//material
				if (!Preview.enabled)
				{
					terrain.materialType = MapMagic.instance.terrainMaterialType;

					if (MapMagic.instance.terrainMaterialType == Terrain.MaterialType.Custom && MapMagic.instance.assignCustomTerrainMaterial)
						terrain.materialTemplate = MapMagic.instance.customTerrainMaterial;

					/*if (MapMagic.instance.terrainMaterialType == Terrain.MaterialType.Custom)
					{
						if (MapMagic.instance.materialTemplateMode)
						{
							//assigning new mat only it has different name or shader in template mode
							if (terrain.materialTemplate == null || terrain.materialTemplate.shader != MapMagic.instance.customTerrainMaterial.shader || terrain.materialTemplate.name != MapMagic.instance.customTerrainMaterial.name)
								terrain.materialTemplate = MapMagic.instance.customTerrainMaterial;
						}
						else
							terrain.materialTemplate = MapMagic.instance.customTerrainMaterial;

//						terrain.materialTemplate = MapMagic.instance.customTerrainMaterial;
					}*/
				}

				terrain.drawTreesAndFoliage = magic.detailDraw;
				terrain.detailObjectDistance = magic.detailDistance;
				terrain.detailObjectDensity = magic.detailDensity;
				terrain.treeDistance = magic.treeDistance;
				terrain.treeBillboardDistance = magic.treeBillboardStart;
				terrain.treeCrossFadeLength = magic.treeFadeLength;
				terrain.treeMaximumFullLODCount = magic.treeFullLod;
				#if UNITY_EDITOR
				terrain.bakeLightProbesForTrees = magic.bakeLightProbesForTrees;
				#endif

				terrain.terrainData.wavingGrassSpeed = magic.windSpeed;
				terrain.terrainData.wavingGrassAmount = magic.windSize;
				terrain.terrainData.wavingGrassStrength = magic.windBending;
				terrain.terrainData.wavingGrassTint = magic.grassTint;

				//copy layer, tag, scripts from mm to terrains
				if (MapMagic.instance.copyLayersTags)
				{
					GameObject go = terrain.gameObject;
					go.layer = MapMagic.instance.gameObject.layer;
					go.isStatic = MapMagic.instance.gameObject.isStatic;
					try { go.tag = MapMagic.instance.gameObject.tag; } catch { Debug.LogError("MapMagic: could not copy object tag"); }
				}
				if (MapMagic.instance.copyComponents)
				{
					GameObject go = terrain.gameObject;
					MonoBehaviour[] components = MapMagic.instance.GetComponents<MonoBehaviour>();
					for (int i=0; i<components.Length; i++)
					{
						if (components[i] is MapMagic || components[i] == null) continue; //if MapMagic itself or script not assigned
						if (terrain.gameObject.GetComponent(components[i].GetType()) == null) Extensions.CopyComponent(components[i], go);
					}
				}
			}
Exemple #29
0
			public void SetSettings ()
			{
				MapMagic magic = MapMagic.instance;

				terrain.heightmapPixelError = magic.pixelError;
				if (magic.showBaseMap) terrain.basemapDistance = magic.baseMapDist;
				else terrain.basemapDistance = 999999;
				terrain.castShadows = magic.castShadows;
				#if UNITY_2017_4_OR_NEWER
				terrain.reflectionProbeUsage = magic.reflectionProbeUsage;
				#endif
				
				if (terrainCollider==null) terrainCollider = terrain.GetComponent<TerrainCollider>();
				if (terrainCollider!=null) terrainCollider.enabled = MapMagic.instance.applyColliders;

				#if UNITY_2018_3_OR_NEWER
				terrain.drawInstanced = magic.drawInstanced;
				terrain.allowAutoConnect = magic.autoConnect;
				#endif

				//material
				if (!Preview.enabled)
				{
					#if UNITY_2019_2_OR_NEWER
					if (MapMagic.instance.customTerrainMaterial != null)
					{
						//checking if customTerrainMaterial assigned as a terrain mat
						if (terrain.materialTemplate == MapMagic.instance.customTerrainMaterial)
						{
							Debug.LogError("Terrain material template == MM.customTerrainMaterial (" + terrain.materialTemplate + "," + terrain.materialTemplate.shader + ")");
							terrain.materialTemplate = null;
						}

						//remove previous material if the shader doesn't match
						if (terrain.materialTemplate != null  &&  terrain.materialTemplate.shader != MapMagic.instance.customTerrainMaterial.shader) 
						{
							GameObject.DestroyImmediate(terrain.materialTemplate); //removes custom shader textures as well. Unity does not remove them!
							Resources.UnloadUnusedAssets();
							terrain.materialTemplate = null; //need to reset material template to prevent unity crash
						}
						
						//duplicating material to terrain
						if (terrain.materialTemplate == null) 
						{
							terrain.materialTemplate = new Material(MapMagic.instance.customTerrainMaterial);
							terrain.materialTemplate.name += " (Copy)";
						}
					}
					#else
					terrain.materialType = MapMagic.instance.terrainMaterialType;

					if (MapMagic.instance.terrainMaterialType == Terrain.MaterialType.Custom && MapMagic.instance.assignCustomTerrainMaterial)
						terrain.materialTemplate = MapMagic.instance.customTerrainMaterial;
					#endif
				}

				terrain.drawTreesAndFoliage = magic.detailDraw;
				terrain.detailObjectDistance = magic.detailDistance;
				terrain.detailObjectDensity = magic.detailDensity;
				terrain.treeDistance = magic.treeDistance;
				terrain.treeBillboardDistance = magic.treeBillboardStart;
				terrain.treeCrossFadeLength = magic.treeFadeLength;
				terrain.treeMaximumFullLODCount = magic.treeFullLod;
				#if UNITY_EDITOR
				terrain.bakeLightProbesForTrees = magic.bakeLightProbesForTrees;
				#endif

				terrain.terrainData.wavingGrassSpeed = magic.windSpeed;
				terrain.terrainData.wavingGrassAmount = magic.windSize;
				terrain.terrainData.wavingGrassStrength = magic.windBending;
				terrain.terrainData.wavingGrassTint = magic.grassTint;

				//copy layer, tag, scripts from mm to terrains
				if (MapMagic.instance.copyLayersTags)
				{
					GameObject go = terrain.gameObject;
					go.layer = MapMagic.instance.gameObject.layer;
					go.isStatic = MapMagic.instance.gameObject.isStatic;
					try { go.tag = MapMagic.instance.gameObject.tag; } catch { Debug.LogError("MapMagic: could not copy object tag"); }
				}
				if (MapMagic.instance.copyComponents)
				{
					GameObject go = terrain.gameObject;
					MonoBehaviour[] components = MapMagic.instance.GetComponents<MonoBehaviour>();
					for (int i=0; i<components.Length; i++)
					{
						if (components[i] is MapMagic || components[i] == null) continue; //if MapMagic itself or script not assigned
						if (terrain.gameObject.GetComponent(components[i].GetType()) == null) Extensions.CopyComponent(components[i], go);
					}
				}
			}
Exemple #30
0
			// applying
			public IEnumerator ApplyRoutine ()
			{
				//calling before-apply event
				MapMagic.CallOnGenerateCompleted(terrain); //if (MapMagic.OnGenerateCompleted != null) MapMagic.OnGenerateCompleted(terrain);

				MapMagic.instance.applyRunning = true;

				//apply
				foreach (KeyValuePair<Type,object> kvp in apply)
				{
					//Type output = kvp.Key;
					//if (!(output as Generator).enabled) continue;
					//if (output is SplatOutput && MapMagic.instance.gens.GetGenerator<PreviewOutput>()!=null) continue; //skip splat out if preview exists

					//callback
					MapMagic.CallOnApply(terrain, kvp.Value); //if (OnApply!=null) OnApply(terrain, kvp.Value);

					//selecting apply enumerator (with switch, not reflection)
					IEnumerator e = null;
					System.Type type = kvp.Key;
					if (type == typeof(HeightOutput)) e = HeightOutput.Apply(this);
					else if (type == typeof(SplatOutput)) e = SplatOutput.Apply(this);
					else if (type == typeof(ObjectOutput)) e = ObjectOutput.Apply(this);
					else if (type == typeof(TreesOutput)) e = TreesOutput.Apply(this);
					else if (type == typeof(GrassOutput)) e = GrassOutput.Apply(this);
					else if (type == typeof(RTPOutput)) e = RTPOutput.Apply(this);

					//apply enumerator
					while (e.MoveNext()) 
					{				
						if (terrain==null) yield break; //guard in case max terrains count < actual terrains: terrain destroyed or still processing
						yield return null;
					}
				}

				//purging unused outputs
				HashSet<Type> existingOutputs = MapMagic.instance.gens.GetExistingOutputTypes(onlyEnabled:true, checkBiomes:true);

				if (!existingOutputs.Contains(typeof(HeightOutput)) && terrain.terrainData.heightmapResolution != 33) HeightOutput.Purge(this);
				if (!existingOutputs.Contains(typeof(SplatOutput)) && !existingOutputs.Contains(typeof(RTPOutput)) && terrain.terrainData.alphamapResolution != 16) SplatOutput.Purge(this);
				if (!existingOutputs.Contains(typeof(ObjectOutput)) && terrain.transform.childCount != 0) ObjectOutput.Purge(this);
				if (!existingOutputs.Contains(typeof(TreesOutput)) && terrain.terrainData.treeInstanceCount != 0) TreesOutput.Purge(this);
				if (!existingOutputs.Contains(typeof(GrassOutput)) && terrain.terrainData.detailResolution != 16) GrassOutput.Purge(this);

				//previewing
/*				if (instance.previewOutput != null && previewObject != null) 
				{
					SplatOutput.Preview((Matrix)previewObject, this);
				}*/

				//creating initial texture if splatmap count is 0 - just to look good
				if (terrain.terrainData.splatPrototypes.Length == 0) ClearSplats();

				//clearing intermediate results
				apply.Clear();
				if (!MapMagic.instance.isEditor || !MapMagic.instance.saveIntermediate) { results.Clear(); ready.Clear(); } //this should be done in thread, but thread has no access to isPlaying

				//if (!terrain.gameObject.activeSelf) terrain.gameObject.SetActive(true); //terrain.enabled = true;

				MapMagic.instance.applyRunning = false;

				//copy layer, tag, scripts from mm to terrains
				if (MapMagic.instance.copyLayersTags)
				{
					GameObject go = terrain.gameObject;
					go.layer = MapMagic.instance.gameObject.layer;
					go.isStatic = MapMagic.instance.gameObject.isStatic;
					try { go.tag = MapMagic.instance.gameObject.tag; } catch { Debug.LogError("MapMagic: could not copy object tag"); }
					//#if UNITY_EDITOR
					//UnityEditor.GameObjectUtility.SetStaticEditorFlags(go, UnityEditor.GameObjectUtility.GetStaticEditorFlags(MapMagic.instance.gameObject));
					//#endif
				}
				if (MapMagic.instance.copyComponents)
				{
					GameObject go = terrain.gameObject;
					MonoBehaviour[] components = MapMagic.instance.GetComponents<MonoBehaviour>();
					for (int i=0; i<components.Length; i++)
					{
						if (components[i] is MapMagic || components[i] == null) continue; //if MapMagic itself or script not assigned
						if (terrain.gameObject.GetComponent(components[i].GetType()) == null) Extensions.CopyComponent(components[i], go);
					}
				}

				//calling after-apply event
				MapMagic.CallOnApplyCompleted(terrain); //if (MapMagic.OnApplyCompleted != null) MapMagic.OnApplyCompleted(terrain);
				queuedApply = false;

				//returning preview if it is enabled
				//if (MapMagic.instance.previewOutput != null) Preview(forceRefresh:true);
			}