/* INFINITY CODE */ /* https://infinity-code.com */ using System; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace InfinityCode.RealWorldTerrain { /// /// This class is added to each created terrains.\n /// It contains all information about the terrain. /// [Serializable] [AddComponentMenu("")] public class RealWorldTerrainItem : RealWorldTerrainMonoBase { /// /// Reference to RealWorldTerrainContainer instance. /// public RealWorldTerrainContainer container; /// /// X index. /// public int x; /// /// Y index. /// public int y; /// /// Reversed Y index (ry = countY - y - 1). /// public int ry; public bool needUpdate = false; /// /// Reference to MeshFilter, if result is mesh. /// public MeshFilter meshFilter; /// /// Reference to Terrain, if result is terrain. /// public Terrain terrain; /// /// Refetence to texture /// public Texture2D texture { get { if (prefs.resultType == RealWorldTerrainResultType.terrain) { #if !RTP if (terrainData == null || terrainData.terrainLayers.Length == 0) return null; TerrainLayer sp = terrainData.terrainLayers[0]; return sp != null? sp.diffuseTexture: null; #else ReliefTerrain reliefTerrain = GetComponent(); if (reliefTerrain == null) { if (terrainData == null || terrainData.terrainLayers.Length == 0) return null; TerrainLayer sp = terrainData.terrainLayers[0]; return sp.diffuseTexture; } return reliefTerrain.ColorGlobal; #endif } MeshRenderer meshRenderer = GetComponent(); if (meshRenderer == null) { meshRenderer = GetComponentInChildren(); if (meshRenderer == null) return null; } return meshRenderer.sharedMaterial != null? meshRenderer.sharedMaterial.mainTexture as Texture2D: null; } set { if (prefs.resultType == RealWorldTerrainResultType.terrain) { #if !RTP if (terrainData == null) return; TerrainLayer[] tls = terrainData.terrainLayers; if (tls.Length == 0) return; if (tls[0] == null) { tls[0] = new TerrainLayer { tileSize = new Vector2(terrainData.size.x, terrainData.size.z) }; #if UNITY_EDITOR string path = container.folder + terrain.name + ".terrainlayer"; AssetDatabase.CreateAsset(tls[0], path); AssetDatabase.Refresh(); tls[0] = AssetDatabase.LoadAssetAtPath(path); #endif } tls[0].diffuseTexture = value; terrainData.terrainLayers = tls; #else ReliefTerrain reliefTerrain = GetComponent(); if (reliefTerrain == null) return; reliefTerrain.ColorGlobal = value; #endif } else { MeshRenderer meshRenderer = GetComponent(); if (meshRenderer != null) meshRenderer.sharedMaterial.mainTexture = value; else { foreach (MeshRenderer mr in GetComponentsInChildren()) { mr.sharedMaterial.mainTexture = value; } } } } } /// /// Gets TerrainData. /// public TerrainData terrainData { get { return terrain != null? terrain.terrainData: null; } } public float GetHeightmapValueByMercator(double mx, double my) { float rx = (float) ((mx - leftMercator) / (rightMercator - leftMercator)); float ry = (float) ((my - topMercator) / (bottomMercator - topMercator)); return terrainData.GetInterpolatedHeight(rx, 1 - ry); } public override RealWorldTerrainItem GetItemByWorldPosition(Vector3 worldPosition) { return container.GetItemByWorldPosition(worldPosition); } public override bool GetWorldPosition(double lng, double lat, out Vector3 worldPosition) { worldPosition = new Vector3(); if (!Contains(lng, lat)) { Debug.Log("Wrong coordinates"); return false; } Bounds b = new Bounds(bounds.center, bounds.size); double mx, my; RealWorldTerrainGeo.LatLongToMercat(lng, lat, out mx, out my); double lX = RealWorldTerrainMath.Clamp((mx - leftMercator) / width, 0, 1); double lZ = RealWorldTerrainMath.Clamp(1 - (my - topMercator) / height, 0, 1); double px = b.size.x * lX + b.min.x; double pz = b.size.z * lZ + b.min.z; if (prefs.resultType == RealWorldTerrainResultType.terrain) { Terrain tr = terrain; if (tr == null) return false; TerrainData tData = terrainData; Vector3 tSize = tData.size; Vector3 position = transform.position; if (position.x > px || position.z > pz || position.x + tSize.x < px || position.z + tSize.z < pz) { return false; } double ix = (px - terrain.gameObject.transform.position.x) / tData.size.x; double iz = (pz - terrain.gameObject.transform.position.z) / tData.size.z; double py = tData.GetInterpolatedHeight((float)ix, (float)iz) + position.y; worldPosition.x = (float)px; worldPosition.y = (float)py; worldPosition.z = (float)pz; } else { if (b.min.x <= px && b.min.z <= pz && b.max.x >= px && b.max.z >= pz) { float y = 0; RaycastHit[] hits = Physics.RaycastAll(new Vector3((float)px, bounds.max.y + 10, (float)pz), Vector3.down, float.MaxValue); foreach (RaycastHit hit in hits) { if (hit.transform.gameObject.GetComponentInParent() != null) { y = hit.point.y; break; } } worldPosition.x = (float)px; worldPosition.y = y; worldPosition.z = (float)pz; } else return false; } return true; } public override bool GetWorldPosition(Vector2 coordinates, out Vector3 worldPosition) { return GetWorldPosition(coordinates.x, coordinates.y, out worldPosition); } } }