Files
Fishing2/Assets/Infinity Code/Real World Terrain/Scripts/Containers/RealWorldTerrainItem.cs
2025-06-09 00:11:54 +08:00

227 lines
7.7 KiB
C#

/* INFINITY CODE */
/* https://infinity-code.com */
using System;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace InfinityCode.RealWorldTerrain
{
/// <summary>
/// This class is added to each created terrains.\n
/// It contains all information about the terrain.
/// </summary>
[Serializable]
[AddComponentMenu("")]
public class RealWorldTerrainItem : RealWorldTerrainMonoBase
{
/// <summary>
/// Reference to RealWorldTerrainContainer instance.
/// </summary>
public RealWorldTerrainContainer container;
/// <summary>
/// X index.
/// </summary>
public int x;
/// <summary>
/// Y index.
/// </summary>
public int y;
/// <summary>
/// Reversed Y index (ry = countY - y - 1).
/// </summary>
public int ry;
public bool needUpdate = false;
/// <summary>
/// Reference to MeshFilter, if result is mesh.
/// </summary>
public MeshFilter meshFilter;
/// <summary>
/// Reference to Terrain, if result is terrain.
/// </summary>
public Terrain terrain;
/// <summary>
/// Refetence to texture
/// </summary>
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<ReliefTerrain>();
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<MeshRenderer>();
if (meshRenderer == null)
{
meshRenderer = GetComponentInChildren<MeshRenderer>();
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<TerrainLayer>(path);
#endif
}
tls[0].diffuseTexture = value;
terrainData.terrainLayers = tls;
#else
ReliefTerrain reliefTerrain = GetComponent<ReliefTerrain>();
if (reliefTerrain == null) return;
reliefTerrain.ColorGlobal = value;
#endif
}
else
{
MeshRenderer meshRenderer = GetComponent<MeshRenderer>();
if (meshRenderer != null) meshRenderer.sharedMaterial.mainTexture = value;
else
{
foreach (MeshRenderer mr in GetComponentsInChildren<MeshRenderer>())
{
mr.sharedMaterial.mainTexture = value;
}
}
}
}
}
/// <summary>
/// Gets TerrainData.
/// </summary>
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<RealWorldTerrainItem>() != 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);
}
}
}