Files
2026-02-21 16:45:37 +08:00

253 lines
6.0 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
namespace ErosionBrushPlugin
{
[ExecuteInEditMode]
public class ErosionBrush : MonoBehaviour
{
public struct UndoStep
{
private float[,] heights;
private int heightsOffsetX;
private int heightsOffsetZ;
private float[,,] splats;
private int splatsOffsetX;
private int splatsOffsetZ;
public UndoStep(float[,] heights, float[,,] splats, int heightsOffsetX, int heightsOffsetZ, int splatsOffsetX, int splatsOffsetZ)
{
if (heightsOffsetX < 0)
{
heightsOffsetX = 0;
}
if (heightsOffsetZ < 0)
{
heightsOffsetZ = 0;
}
if (splatsOffsetX < 0)
{
splatsOffsetX = 0;
}
if (splatsOffsetZ < 0)
{
splatsOffsetZ = 0;
}
this.heightsOffsetX = heightsOffsetX;
this.heightsOffsetZ = heightsOffsetZ;
this.splatsOffsetX = splatsOffsetX;
this.splatsOffsetZ = splatsOffsetZ;
this.heights = heights.Clone() as float[,];
if (splats != null)
{
this.splats = splats.Clone() as float[,,];
}
else
{
this.splats = null;
}
}
public void Perform(TerrainData data)
{
data.SetHeights(heightsOffsetX, heightsOffsetZ, heights);
if (splats != null)
{
data.SetAlphamaps(splatsOffsetX, splatsOffsetZ, splats);
}
}
}
private Terrain _terrain;
public Preset preset = new Preset();
public Preset[] presets = new Preset[0];
public int guiSelectedPreset;
public bool paint;
public bool wasPaint;
public bool moveDown;
public Transform moveTfm;
public bool gen;
public bool undo;
[NonSerialized]
public Texture2D guiHydraulicIcon;
[NonSerialized]
public Texture2D guiWindIcon;
[NonSerialized]
public Texture2D guiPluginIcon;
public int guiApplyIterations = 1;
public int[] guiChannels;
public string[] guiChannelNames;
public Color guiBrushColor = new Color(1f, 0.7f, 0.3f);
public float guiBrushThickness = 4f;
public int guiBrushNumCorners = 32;
public bool recordUndo = true;
public bool unity5positioning;
public bool focusOnBrush = true;
public bool preserveDetail = true;
public bool guiShowPreset = true;
public bool guiShowBrush = true;
public bool guiShowGenerator = true;
public bool guiShowTextures = true;
public bool guiShowGlobal;
public bool guiShowSettings;
public bool guiShowAbout;
public int guiMaxBrushSize = 300;
public bool guiSelectPresetsUsingNumkeys = true;
[NonSerialized]
private Matrix.Stacker heights;
[NonSerialized]
private Matrix.Stacker splats;
[NonSerialized]
private Matrix.Stacker sediments;
public List<List<UndoStep>> undoList = new List<List<UndoStep>>();
public bool allowUndo;
public Terrain terrain
{
get
{
if (_terrain == null)
{
_terrain = GetComponent<Terrain>();
}
return _terrain;
}
set
{
_terrain = value;
}
}
public void ApplyBrush(Rect worldRect, bool useFallof = true, bool newUndo = false)
{
TerrainData terrainData = terrain.terrainData;
bool flag = preset.paintSplat;
if (terrainData.alphamapLayers == 0)
{
flag = false;
}
int a = Mathf.Min(terrainData.heightmapResolution - 1, terrainData.alphamapResolution);
int num = Mathf.Max(terrainData.heightmapResolution - 1, terrainData.alphamapResolution);
int num2 = num / preset.downscale;
int num3 = Mathf.Min(a, num2);
int num4 = (terrainData.heightmapResolution - 1) / num3;
int num5 = terrainData.alphamapResolution / num3;
int num6 = num2 / num3;
CoordRect coordRect = new CoordRect(worldRect.x * (float)num3, worldRect.y * (float)num3, worldRect.width * (float)num3, worldRect.height * (float)num3);
CoordRect coordRect2 = coordRect * num4;
CoordRect coordRect3 = coordRect * num5;
CoordRect coordRect4 = coordRect * num6;
if (heights == null || heights.smallRect != coordRect4 || heights.bigRect != coordRect2)
{
heights = new Matrix.Stacker(coordRect4, coordRect2);
}
if (splats == null || splats.smallRect != coordRect4 || splats.bigRect != coordRect3)
{
splats = new Matrix.Stacker(coordRect4, coordRect3);
}
if (sediments == null || sediments.smallRect != coordRect4 || sediments.bigRect != coordRect3)
{
sediments = new Matrix.Stacker(coordRect4, coordRect3);
}
heights.preserveDetail = preserveDetail;
splats.preserveDetail = preserveDetail;
sediments.preserveDetail = preserveDetail;
heights.matrix.ChangeRect(coordRect2);
float[,] array = heights.matrix.ReadHeighmap(terrainData);
splats.matrix.ChangeRect(coordRect3);
sediments.matrix.ChangeRect(coordRect3);
float[,,] array2 = null;
if (flag)
{
array2 = splats.matrix.ReadSplatmap(terrainData, preset.foreground.num);
sediments.matrix.ReadSplatmap(terrainData, preset.background.num, array2);
}
heights.ToSmall();
if (flag)
{
splats.ToSmall();
sediments.ToSmall();
}
heights.ToBig();
splats.ToBig();
sediments.ToBig();
if (recordUndo)
{
if (newUndo)
{
if (undoList.Count > 10)
{
undoList.RemoveAt(0);
}
undoList.Add(new List<UndoStep>());
}
if (undoList.Count == 0)
{
undoList.Add(new List<UndoStep>());
}
undoList[undoList.Count - 1].Add(new UndoStep(array, array2, coordRect2.offset.x, coordRect2.offset.z, coordRect3.offset.x, coordRect3.offset.z));
}
heights.matrix.WriteHeightmap(terrainData, array, (!useFallof) ? (-1f) : preset.brushFallof);
if (flag)
{
TerrainData data = terrainData;
Matrix[] matrices = new Matrix[2] { splats.matrix, sediments.matrix };
int[] channels = new int[2]
{
preset.foreground.num,
preset.background.num
};
float[] opacity = new float[2]
{
(!preset.foreground.apply) ? 0f : preset.foreground.opacity,
(!preset.background.apply) ? 0f : preset.background.opacity
};
float brushFallof = ((!useFallof) ? (-1f) : preset.brushFallof);
Matrix.AddSplatmaps(data, matrices, channels, opacity, array2, brushFallof);
}
}
}
}