static void DrawMatrices() { //refreshing matrices if needed if (RefreshMatricesNeeded()) { RefreshMatrices(); } //getting pixel size float pixelSize = GetPixelSize(); //preparing shader Shader previewShader = MapMagic.instance.previewShader; //Shader.Find("MapMagic/TerrainPreview"); //apply matrix textures to all objects foreach (Transform tfm in mapMagic.Transforms()) { MeshRenderer renderer = tfm.GetComponent <MeshRenderer>(); Terrain terrain = tfm.GetComponent <Terrain>(); if (renderer == null && terrain == null) { continue; } //finding object rect Rect worldRect = new Rect(0, 0, 0, 0); if (renderer != null) { worldRect = new Rect(renderer.bounds.min.x, renderer.bounds.min.z, renderer.bounds.size.x, renderer.bounds.size.z); } else if (terrain != null) { worldRect = new Rect(terrain.transform.localPosition.x, terrain.transform.localPosition.z, terrain.terrainData.size.x, terrain.terrainData.size.z); } CoordRect matrixRect = CoordRect.PickIntersectingCellsByPos(worldRect, pixelSize); //finding a matrix/texture that object should use Coord center = matrixRect.Center; foreach (KeyValuePair <Matrix, Texture2D> kvp in matrices) { Matrix matrix = kvp.Key; // Using the matrix that contains center - it would be the biggest intersection if (matrix.rect.Contains(center.x, center.z)) { Texture2D texture = kvp.Value; //assigning material Material material = null; if (renderer != null) { if (renderer.sharedMaterial.shader != previewShader) { if (!originalMaterials.ContainsKey(tfm)) { originalMaterials.Add(tfm, renderer.sharedMaterial); } renderer.sharedMaterial = new Material(previewShader); } material = renderer.sharedMaterial; } else if (terrain != null) { if (terrain.materialTemplate == null || terrain.materialTemplate.shader != previewShader) { if (terrain.materialType == Terrain.MaterialType.Custom && !originalMaterials.ContainsKey(tfm)) { originalMaterials.Add(tfm, terrain.materialTemplate); } terrain.materialTemplate = new Material(previewShader); } terrain.materialType = Terrain.MaterialType.Custom; material = terrain.materialTemplate; } //assigning texture and params material.name = tfm.name + " Preview"; //calculate parent MM object offset //Vector3 offset = tfm.parent.position / (worldRect.size.x/matrix.rect.size.x); // /pixelsize material.SetTexture("_Preview", texture); material.SetVector("_Rect", new Vector4(matrix.rect.offset.x, matrix.rect.offset.z, matrix.rect.size.x, matrix.rect.size.z)); material.SetFloat("_Scale", pixelSize); break; //interrupting when texture assigned (to center) } } } }
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(); }