Files
UltimateFishing/Assets/Scripts/Assembly-CSharp/LE_LevelEditor/UI/LE_GUI3dTerrain.cs
2026-02-21 16:45:37 +08:00

506 lines
14 KiB
C#

using LE_LevelEditor.Commands;
using LE_LevelEditor.Core;
using LE_LevelEditor.Events;
using TT_TerrainTools;
using UndoRedo;
using UnityEngine;
namespace LE_LevelEditor.UI
{
public class LE_GUI3dTerrain : LE_GUI3dBase
{
public int TERRAIN_LAYER = 28;
private Terrain m_terrain;
private LE_TerrainManager m_terrainMgr;
private TerrainData m_defaultTerrainDataPrefab;
private Projector m_brushProjector;
private Texture2D m_brushAlphaTexture;
private int m_selectedSplatPrototype;
private float m_amount = 0.1f;
private float m_size = 0.1f;
private float m_targetRelativeValue = 0.5f;
private float m_targetTextureStrengthValue = 0.5f;
private bool m_isReadingTerrainPaintHeight;
private int m_isTerrainPaintHeightReadInFrame = -1;
private bool m_isDirectedSmooth;
private float m_directedSmoothAngle;
private LE_ETerrainEditMode m_editMode;
private LE_GenCmdTerrain m_genCmdTerrain;
private Vector3 m_lastCursorActiveScreenCoords = -1f * Vector3.one;
public Terrain TerrainInstance
{
get
{
return m_terrain;
}
}
public LE_TerrainManager TerrainManager
{
get
{
return m_terrainMgr;
}
}
public TerrainData DefaultTerrainDataPrefab
{
get
{
return m_defaultTerrainDataPrefab;
}
set
{
m_defaultTerrainDataPrefab = value;
}
}
public Projector BrushProjector
{
get
{
return m_brushProjector;
}
set
{
m_brushProjector = value;
m_brushProjector.material = Object.Instantiate(m_brushProjector.material);
m_brushProjector.ignoreLayers = ~(1 << TERRAIN_LAYER);
}
}
public Texture2D BrushAlphaTexture
{
get
{
return m_brushAlphaTexture;
}
set
{
m_brushAlphaTexture = value;
m_brushProjector.material.mainTexture = m_brushAlphaTexture;
}
}
public int SelectedSplatPrototype
{
get
{
return m_selectedSplatPrototype;
}
set
{
m_selectedSplatPrototype = value;
}
}
public float Amount
{
get
{
return m_amount;
}
set
{
m_amount = value;
}
}
public float Size
{
get
{
return m_size;
}
set
{
m_size = value;
if (m_terrainMgr != null)
{
float num = 1f / (float)Mathf.Min(m_terrainMgr.TerrainData.heightmapWidth - 1, m_terrainMgr.TerrainData.heightmapHeight - 1);
m_size = Mathf.Floor(m_size / num) * num;
}
}
}
public float TargetRelativeValue
{
get
{
return m_targetRelativeValue;
}
set
{
m_targetRelativeValue = value;
}
}
public float TargetTextureStrengthValue
{
get
{
return m_targetTextureStrengthValue;
}
set
{
m_targetTextureStrengthValue = value;
}
}
public bool IsReadingTerrainPaintHeight
{
get
{
return m_isReadingTerrainPaintHeight;
}
set
{
m_isReadingTerrainPaintHeight = value;
m_isTerrainPaintHeightReadInFrame = -1;
}
}
public bool IsDirectedSmooth
{
get
{
return m_isDirectedSmooth;
}
set
{
m_isDirectedSmooth = value;
}
}
public float DirectedSmoothAngle
{
get
{
return m_directedSmoothAngle;
}
set
{
m_directedSmoothAngle = value;
if (m_brushProjector.transform.childCount > 0)
{
m_brushProjector.transform.GetChild(0).transform.localRotation = Quaternion.Euler(Vector3.back * m_directedSmoothAngle);
}
}
}
public LE_ETerrainEditMode EditMode
{
get
{
return m_editMode;
}
set
{
m_editMode = value;
if (m_editMode != LE_ETerrainEditMode.CHANGE_HEIGHT_TO_TARGET_VALUE)
{
m_isReadingTerrainPaintHeight = false;
m_isTerrainPaintHeightReadInFrame = -1;
}
}
}
public override LE_EEditMode ActiveEditMode
{
get
{
return LE_EEditMode.TERRAIN;
}
}
public void SetTerrain(Terrain p_terrain)
{
if (m_terrainMgr != null)
{
Debug.LogError("LE_GUI3dTerrain: SetTerrain: a terrain manager was already set and will be overwritten! Use 'RemoveTerrainManager' to reset the instance.");
}
m_terrain = p_terrain;
m_terrainMgr = new LE_TerrainManager(p_terrain.terrainData);
if (LE_EventInterface.OnChangeLevelData != null)
{
LE_EventInterface.OnChangeLevelData(m_terrain.gameObject, new LE_LevelDataChangedEvent(LE_ELevelDataChangeType.TERRAIN_SELECTION));
}
}
public void RemoveTerrainManager()
{
if (m_terrain != null && LE_EventInterface.OnChangeLevelData != null)
{
LE_EventInterface.OnChangeLevelData(m_terrain.gameObject, new LE_LevelDataChangedEvent(LE_ELevelDataChangeType.TERRAIN_SELECTION));
}
m_terrain = null;
m_terrainMgr = null;
}
public override void SetCursorPosition(Vector3 p_cursorScreenCoords)
{
m_cursorScreenCoords = p_cursorScreenCoords;
m_cursorRay = Camera.main.ScreenPointToRay(p_cursorScreenCoords);
if (m_terrain != null)
{
SetIsCursorOverSomething(m_terrain.GetComponent<Collider>().Raycast(m_cursorRay, out m_cursorHitInfo, float.MaxValue));
}
else
{
SetIsCursorOverSomething(false);
}
}
public override void SetIsCursorAction(bool p_isCursorAction)
{
if (m_isTerrainPaintHeightReadInFrame != -1 && !p_isCursorAction && m_isTerrainPaintHeightReadInFrame + 1 < Time.frameCount)
{
m_isReadingTerrainPaintHeight = false;
m_isTerrainPaintHeightReadInFrame = -1;
}
if (base.IsCursorOverSomething && base.IsInteractable && p_isCursorAction && m_lastCursorActiveScreenCoords != m_cursorScreenCoords)
{
m_lastCursorActiveScreenCoords = m_cursorScreenCoords;
if (m_cursorHitInfo.transform.gameObject.GetComponent<Terrain>() != null)
{
if (m_isReadingTerrainPaintHeight)
{
Terrain component = m_cursorHitInfo.transform.gameObject.GetComponent<Terrain>();
float num = component.SampleHeight(m_cursorHitInfo.point);
m_targetRelativeValue = Mathf.Clamp01(num / component.terrainData.size.y);
m_isTerrainPaintHeightReadInFrame = Time.frameCount;
}
else
{
if (m_genCmdTerrain == null)
{
LE_GenCmdTerrain.Mode p_cmdMode = ((m_editMode == LE_ETerrainEditMode.DRAW_TEXTURE) ? LE_GenCmdTerrain.Mode.ALPHAMAPS_CMD : LE_GenCmdTerrain.Mode.HEIGHTS_CMD);
m_genCmdTerrain = new LE_GenCmdTerrain(this, m_terrainMgr, p_cmdMode);
}
switch (m_editMode)
{
case LE_ETerrainEditMode.CHANGE_HEIGHT:
m_genCmdTerrain.ChangeHeight(Mathf.Sign(Amount) * Mathf.Max(0.002f, Amount * Amount) * Time.deltaTime * 2f, BrushAlphaTexture, Size, GetRelativeLocalLocation(m_cursorHitInfo));
break;
case LE_ETerrainEditMode.CHANGE_HEIGHT_TO_TARGET_VALUE:
m_genCmdTerrain.ChangeHeight(Mathf.Max(0.002f, Amount * Amount) * Time.deltaTime * 2f, TargetRelativeValue, BrushAlphaTexture, Size, GetRelativeLocalLocation(m_cursorHitInfo));
break;
case LE_ETerrainEditMode.SMOOTH_HEIGHT:
{
int p_neighbourCount = 3 + 2 * Mathf.RoundToInt(Mathf.Abs(Amount) * 3f);
m_genCmdTerrain.SmoothHeight(Time.deltaTime * 2f, p_neighbourCount, BrushAlphaTexture, Size, GetRelativeLocalLocation(m_cursorHitInfo), m_isDirectedSmooth, m_directedSmoothAngle);
break;
}
case LE_ETerrainEditMode.DRAW_TEXTURE:
m_genCmdTerrain.PaintTexture(SelectedSplatPrototype, Mathf.Abs(Amount) * Time.deltaTime * 8f, TargetTextureStrengthValue, BrushAlphaTexture, Size, GetRelativeLocalLocation(m_cursorHitInfo));
break;
default:
Debug.LogError("LE_GUI3dTerrain: unknown EditMode!");
break;
}
}
}
}
else
{
m_lastCursorActiveScreenCoords = -1f * Vector3.one;
}
if (m_genCmdTerrain != null && m_genCmdTerrain.LastEditedFrame + 1 < Time.frameCount)
{
UR_ICommand cmd = m_genCmdTerrain.GetCmd();
if (cmd != null)
{
UR_CommandMgr.Instance.Add(cmd, true);
}
m_genCmdTerrain = null;
}
}
public void HideCursor()
{
BrushProjector.orthographicSize = 0f;
if (BrushProjector.transform.childCount > 0)
{
BrushProjector.transform.GetChild(0).gameObject.SetActive(false);
}
SetIsCursorOverSomething(false);
}
public void ResetToDefaultOrDestroyTerrain()
{
if (m_terrain != null)
{
if (m_defaultTerrainDataPrefab != null)
{
TerrainData defaultTerrainDataDeepCopy = GetDefaultTerrainDataDeepCopy();
RecycleTerrain(defaultTerrainDataDeepCopy, false);
m_terrain.gameObject.layer = TERRAIN_LAYER;
m_terrain.transform.position = new Vector3((0f - defaultTerrainDataDeepCopy.size.x) * 0.5f, m_terrain.transform.position.y, (0f - defaultTerrainDataDeepCopy.size.z) * 0.5f);
}
else
{
Object.Destroy(m_terrain.gameObject);
RemoveTerrainManager();
SetIsCursorOverSomething(false);
}
}
}
public void RecycleTerrain(TerrainData p_data, bool p_isDefaultTerrainDataApplied)
{
if (m_terrain != null)
{
if (p_isDefaultTerrainDataApplied && m_defaultTerrainDataPrefab != null)
{
ApplyDefaultTerrainData(p_data);
if (p_data.treePrototypes.Length > 0)
{
p_data.SetHeights(0, 0, p_data.GetHeights(0, 0, 0, 0));
}
}
m_terrain.enabled = false;
Object.Destroy(m_terrain.terrainData);
m_terrain.terrainData = p_data;
if (m_terrain.GetComponent<TerrainCollider>() != null)
{
m_terrain.GetComponent<TerrainCollider>().terrainData = p_data;
}
else
{
Debug.LogError("LE_GUI3dTerrain: RecycleTerrain: the CustomDefaultTerrain assigned to LE_ConfigTerrain must have a collider!");
}
m_terrain.Flush();
m_terrain.enabled = true;
TT_Terrain9Patch component = m_terrain.GetComponent<TT_Terrain9Patch>();
if (component != null)
{
component.CrashCheck();
}
Terrain terrain = m_terrain;
RemoveTerrainManager();
SetTerrain(terrain);
}
else
{
Debug.LogError("LE_GUI3dTerrain: RecycleTerrain: there is not terrain that can be recycled. Call this function only if TerrainInstance is not null!");
}
}
public TerrainData GetDefaultTerrainDataDeepCopy()
{
if (m_defaultTerrainDataPrefab != null)
{
TerrainData terrainData = new TerrainData();
terrainData.name = m_defaultTerrainDataPrefab.name + "(DeepCopy)";
terrainData.size = m_defaultTerrainDataPrefab.size;
ApplyDefaultTerrainData(terrainData);
terrainData.splatPrototypes = m_defaultTerrainDataPrefab.splatPrototypes;
terrainData.alphamapResolution = m_defaultTerrainDataPrefab.alphamapResolution;
terrainData.heightmapResolution = m_defaultTerrainDataPrefab.heightmapResolution;
terrainData.SetAlphamaps(0, 0, m_defaultTerrainDataPrefab.GetAlphamaps(0, 0, m_defaultTerrainDataPrefab.alphamapWidth, m_defaultTerrainDataPrefab.alphamapHeight));
terrainData.SetHeights(0, 0, m_defaultTerrainDataPrefab.GetHeights(0, 0, terrainData.heightmapWidth, terrainData.heightmapHeight));
terrainData.size = m_defaultTerrainDataPrefab.size;
return terrainData;
}
Debug.LogError("LE_GUI3dTerrain: GetDefaultTerrainDataDeepCopy: there is no default terrain assigned! Check that DefaultTerrainDataPrefab is not null before calling this function!");
return null;
}
private void ApplyDefaultTerrainData(TerrainData p_terrainData)
{
p_terrainData.hideFlags = m_defaultTerrainDataPrefab.hideFlags;
p_terrainData.detailPrototypes = m_defaultTerrainDataPrefab.detailPrototypes;
p_terrainData.treePrototypes = m_defaultTerrainDataPrefab.treePrototypes;
p_terrainData.treeInstances = m_defaultTerrainDataPrefab.treeInstances;
p_terrainData.wavingGrassAmount = m_defaultTerrainDataPrefab.wavingGrassAmount;
p_terrainData.wavingGrassSpeed = m_defaultTerrainDataPrefab.wavingGrassSpeed;
p_terrainData.wavingGrassStrength = m_defaultTerrainDataPrefab.wavingGrassStrength;
p_terrainData.wavingGrassTint = m_defaultTerrainDataPrefab.wavingGrassTint;
p_terrainData.baseMapResolution = m_defaultTerrainDataPrefab.baseMapResolution;
p_terrainData.SetDetailResolution(m_defaultTerrainDataPrefab.detailResolution, 8);
if (m_defaultTerrainDataPrefab.detailResolution > 0)
{
int[] supportedLayers = m_defaultTerrainDataPrefab.GetSupportedLayers(0, 0, m_defaultTerrainDataPrefab.detailWidth, m_defaultTerrainDataPrefab.detailHeight);
for (int i = 0; i < supportedLayers.Length; i++)
{
p_terrainData.SetDetailLayer(0, 0, supportedLayers[i], m_defaultTerrainDataPrefab.GetDetailLayer(0, 0, m_defaultTerrainDataPrefab.detailWidth, m_defaultTerrainDataPrefab.detailHeight, supportedLayers[i]));
}
}
}
private void Start()
{
if (m_brushProjector == null)
{
Debug.LogError("LE_GUI3dTerrain: m_brushProjector was not initialized!");
}
if (m_brushAlphaTexture == null)
{
Debug.LogError("LE_GUI3dTerrain: m_brushAlphaTexture was not initialized!");
}
}
private void Update()
{
UpdateBrushProjector(base.IsCursorOverSomething, m_cursorHitInfo);
}
private void UpdateBrushProjector(bool p_isHit, RaycastHit p_hitInfo)
{
if (p_isHit && m_terrainMgr != null)
{
Vector3 size = m_terrainMgr.TerrainData.size;
Vector2 relativeLocalLocation = GetRelativeLocalLocation(p_hitInfo);
BrushProjector.transform.position = new Vector3(p_hitInfo.transform.position.x + relativeLocalLocation.y * size.x, p_hitInfo.point.y, p_hitInfo.transform.position.z + relativeLocalLocation.x * size.z);
BrushProjector.orthographicSize = m_terrainMgr.TerrainData.size.z * m_size * 0.5f;
BrushProjector.aspectRatio = m_terrainMgr.TerrainData.size.x / m_terrainMgr.TerrainData.size.z;
if (BrushProjector.transform.childCount > 0)
{
BrushProjector.transform.GetChild(0).gameObject.SetActive(m_editMode == LE_ETerrainEditMode.SMOOTH_HEIGHT && IsDirectedSmooth);
}
}
else
{
BrushProjector.orthographicSize = 0f;
if (BrushProjector.transform.childCount > 0)
{
BrushProjector.transform.GetChild(0).gameObject.SetActive(false);
}
}
}
private Vector2 GetRelativeLocalLocation(RaycastHit hit)
{
Terrain component = hit.transform.gameObject.GetComponent<Terrain>();
Vector3 size = component.terrainData.size;
Vector3 vector = hit.transform.InverseTransformPoint(hit.point);
Vector2 zero = Vector2.zero;
zero.x = vector.z / size.z;
zero.y = vector.x / size.x;
float num = 1f / (float)(component.terrainData.heightmapWidth - 1);
float num2 = 1f / (float)(component.terrainData.heightmapHeight - 1);
zero.x = Mathf.Round(zero.x / num) * num;
zero.y = Mathf.Round(zero.y / num2) * num2;
return zero;
}
}
}