253 lines
6.0 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|