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 (terrainCollider==null) terrainCollider = terrain.GetComponent<TerrainCollider>(); if (terrainCollider!=null) terrainCollider.enabled = MapMagic.instance.applyColliders; //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); } } }
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 }
// 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); }
public void ClearSplats () //same as SplatOutput.Clear { terrain.terrainData.splatPrototypes = new SplatPrototype[] { new SplatPrototype() { texture = Extensions.ColorTexture(2,2,new Color(0.5f, 0.5f, 0.5f, 0f)) } }; float[,,] emptySplats = new float[16,16,1]; for (int x=0; x<16; x++) for (int z=0; z<16; z++) emptySplats[z,x,0] = 1; terrain.terrainData.alphamapResolution = 16; terrain.terrainData.SetAlphamaps(0,0,emptySplats); if (MapMagic.instance.guiDebug) Debug.Log("Splats Cleared"); }
public void Update () { //shifting world if (!isEditor && shift) WorldShifter.Update(shiftThreshold, shiftExcludeLayers); //checking if instance already exists and disabling if it is another mm if (instance != null && instance != this) { Debug.LogError("MapMagic object already present in scene. Disabling duplicate"); this.enabled = false; return; } //do nothing if chink size is zero if (terrainSize < 0.1f) return; //finding camera positions camPoses = Extensions.GetCamPoses(genAroundMainCam:genAroundMainCam, genAroundTag:genAroundObjsTag? genAroundTag : null, camPoses:camPoses); if (camPoses.Length == 0) return; //no cameras to deploy Voxeland transform.InverseTransformPoint(camPoses); //deploy if (!isEditor && generateInfinite) { //finding deploy rects if (deployRects == null || deployRects.Length!=camPoses.Length) { deployRects = new CoordRect[camPoses.Length]; removeRects = new CoordRect[camPoses.Length]; } for (int r=0; r<camPoses.Length; r++) //TODO: add cam pos change check { deployRects[r] = CoordRect.PickIntersectingCellsByPos(camPoses[r], generateRange, cellSize:terrainSize); removeRects[r] = CoordRect.PickIntersectingCellsByPos(camPoses[r], removeRange, cellSize:terrainSize); } //checking and deploying bool chunksChange = chunks.CheckDeploy(deployRects); if (chunksChange) chunks.Deploy(deployRects, removeRects, parent:this, allowMove:true); } //updating chunks foreach (Chunk chunk in chunks.All()) { //removing (unpinning) chunk if it's terrain was removed somehow if (chunk.terrain==null || chunk.terrain.transform==null || chunk.terrain.terrainData==null) { chunk.pinned = false; return; } //TODO: causes out of sync error //distance, priority and visibility float distance = camPoses.DistToRectAxisAligned(chunk.coord.x*terrainSize, chunk.coord.z*terrainSize, terrainSize); chunk.worker.priority = 1f / distance; //starting generate if ((distance<MapMagic.instance.generateRange || MapMagic.instance.isEditor) && chunk.worker.blank && !chunk.locked && instantGenerate) chunk.worker.Start(); //enabling/disabling (after starting generate to avoid blink) if (!MapMagic.instance.isEditor && //if non-editor ( (!chunk.worker.ready && !chunk.locked) || //if non-ready (MapMagic.instance.hideFarTerrains && distance>MapMagic.instance.enableRange) //or if out of range in playmode ) ) //TODO: it works but I don't like the way it formatted { if (chunk.terrain.gameObject.activeSelf) chunk.terrain.gameObject.SetActive(false); } //disabling else { if (!chunk.terrain.gameObject.activeSelf) chunk.terrain.gameObject.SetActive(true); } //enabling //setting terrain neighbors (they reset after each serialize) chunk.SetNeighbors(); //TODO: try doing in ondeserialize } //updating threads ThreadWorker.multithreading = multithreading; ThreadWorker.maxThreads = maxThreads; ThreadWorker.autoMaxThreads = autoMaxThreads; ThreadWorker.maxApplyTime = maxApplyTime; ThreadWorker.Refresh(); //Water doWater(); }