Files
2025-06-09 23:23:13 +08:00

263 lines
9.5 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace JBooth.MicroVerseCore
{
[ExecuteAlways]
public class ClearStamp : Stamp, ITreeModifier, IDetailModifier
#if __MICROVERSE_OBJECTS__
, IObjectModifier
#endif
{
public bool clearTrees = true;
public bool clearDetails = true;
#if __MICROVERSE_OBJECTS__
public bool clearObjects = false;
#endif
public FilterSet filterSet = new FilterSet();
Material material;
public bool NeedCurvatureMap() { return filterSet.NeedCurvatureMap(); }
public bool NeedFlowMap() { return filterSet.NeedFlowMap(); }
public bool NeedTreeClear() { return clearTrees; }
public bool NeedDetailClear() { return clearDetails; }
#if __MICROVERSE_OBJECTS__
public bool NeedObjectClear() { return clearObjects; }
#endif
public override FilterSet GetFilterSet()
{
return filterSet;
}
public override Bounds GetBounds()
{
FalloffOverride fo = GetComponentInParent<FalloffOverride>();
var foType = filterSet.falloffFilter.filterType;
var filter = filterSet.falloffFilter;
if (fo != null && fo.enabled)
{
foType = fo.filter.filterType;
filter = fo.filter;
}
#if __MICROVERSE_SPLINES__
if (foType == FalloffFilter.FilterType.SplineArea && filterSet.falloffFilter.splineArea != null)
{
return filterSet.falloffFilter.splineArea.GetBounds();
}
#endif
if (foType == FalloffFilter.FilterType.Global && filter != null && filter.paintArea != null && filter.paintArea.clampOutsideOfBounds)
{
return filter.paintArea.GetBounds();
}
if (foType == FalloffFilter.FilterType.Global)
return new Bounds(Vector3.zero, new Vector3(99999, 999999, 99999));
else
{
return TerrainUtil.GetBounds(transform);
}
}
public bool OccludesOthers()
{
return false;
}
public bool NeedSDF()
{
return false;
}
public bool UsesOtherTreeSDF() { return false; }
public bool UsesOtherObjectSDF() { return false; }
public bool NeedParentSDF() { return false; }
public bool NeedToGenerateSDFForChilden() { return false; }
public void SetSDF(Terrain t, RenderTexture rt) { }
public RenderTexture GetSDF(Terrain t) { return null; }
static Shader clearShader = null;
public void Initialize()
{
if (clearShader == null)
{
clearShader = Shader.Find("Hidden/MicroVerse/ClearFilter");
}
if (material == null)
{
material = new Material(clearShader);
}
keywordBuilder.ClearInitial();
filterSet.PrepareMaterial(this.transform, material, keywordBuilder.initialKeywords);
}
public void InqTreePrototypes(List<TreePrototypeSerializable> trees)
{
}
static int _Heightmap = Shader.PropertyToID("_Heightmap");
static int _Normalmap = Shader.PropertyToID("_Normalmap");
static int _Curvemap = Shader.PropertyToID("_Curvemap");
static int _Flowmap = Shader.PropertyToID("_Flowmap");
static int _IndexMap = Shader.PropertyToID("_IndexMap");
static int _WeightMap = Shader.PropertyToID("_WeightMap");
public void ApplyTreeClear(TreeData td)
{
if (!clearTrees)
return;
keywordBuilder.Clear();
keywordBuilder.Add("_RECONSTRUCTNORMAL");
var textureLayerWeights = filterSet.GetTextureWeights(td.terrain.terrainData.terrainLayers);
material.SetVectorArray("_TextureLayerWeights", textureLayerWeights);
material.SetTexture(_Heightmap, td.heightMap);
material.SetTexture(_Normalmap, td.normalMap);
material.SetTexture(_Curvemap, td.curveMap);
material.SetTexture(_Flowmap, td.flowMap);
filterSet.PrepareTransform(this.transform, td.terrain, material, keywordBuilder.keywords, GetTerrainScalingFactor(td.terrain));
keywordBuilder.Assign(material);
RenderTexture temp = RenderTexture.GetTemporary(td.treeClearMap.descriptor);
material.SetFloat("_LayerIndex", td.layerIndex);
material.SetTexture(_IndexMap, td.dataCache.indexMaps[td.terrain]);
material.SetTexture(_WeightMap, td.dataCache.weightMaps[td.terrain]);
temp.name = "TreeClear";
Graphics.Blit(td.treeClearMap, temp, material);
RenderTexture.active = null;
RenderTexture.ReleaseTemporary(td.treeClearMap);
td.treeClearMap = temp;
td.layerIndex++;
}
public void ApplyDetailClear(DetailData dd)
{
if (!clearDetails)
return;
keywordBuilder.Clear();
keywordBuilder.Add("_RECONSTRUCTNORMAL");
var textureLayerWeights = filterSet.GetTextureWeights(dd.terrain.terrainData.terrainLayers);
material.SetVectorArray("_TextureLayerWeights", textureLayerWeights);
material.SetTexture(_Heightmap, dd.heightMap);
material.SetTexture(_Normalmap, dd.normalMap);
material.SetTexture(_Curvemap, dd.curveMap);
material.SetTexture(_Flowmap, dd.flowMap);
filterSet.PrepareTransform(this.transform, dd.terrain, material, keywordBuilder.keywords, GetTerrainScalingFactor(dd.terrain));
keywordBuilder.Assign(material);
RenderTexture temp = RenderTexture.GetTemporary(dd.clearMap.descriptor);
material.SetFloat("_LayerIndex", dd.layerIndex);
material.SetTexture(_IndexMap, dd.dataCache.indexMaps[dd.terrain]);
material.SetTexture(_WeightMap, dd.dataCache.weightMaps[dd.terrain]);
temp.name = "DetailClear";
Graphics.Blit(dd.clearMap, temp, material);
RenderTexture.active = null;
RenderTexture.ReleaseTemporary(dd.clearMap);
dd.clearMap = temp;
dd.layerIndex++;
}
public void ApplyTreeStamp(TreeData td, Dictionary<Terrain, List<TreeJobHolder>> jobs, OcclusionData od)
{
if (clearTrees)
td.layerIndex++;
}
public void ProcessTreeStamp(TreeData vd, Dictionary<Terrain, List<TreeJobHolder>> jobs, OcclusionData od)
{
}
public void Dispose()
{
}
protected override void OnDestroy()
{
if (material != null) DestroyImmediate(material);
base.OnDestroy();
}
void OnDrawGizmosSelected()
{
if (filterSet.falloffFilter.filterType != FalloffFilter.FilterType.Global &&
filterSet.falloffFilter.filterType != FalloffFilter.FilterType.SplineArea)
{
if (MicroVerse.instance != null)
{
Gizmos.color = MicroVerse.instance.options.colors.treeStampColor;
Gizmos.matrix = transform.localToWorldMatrix;
Gizmos.DrawWireCube(new Vector3(0, 0.5f, 0), Vector3.one);
}
}
}
public void ApplyDetailStamp(DetailData dd, Dictionary<Terrain, Dictionary<int, List<RenderTexture>>> resultBuffers, OcclusionData od)
{
if (!clearDetails)
return;
dd.layerIndex++;
}
public void InqDetailPrototypes(List<DetailPrototypeSerializable> prototypes)
{
}
#if __MICROVERSE_OBJECTS__
public void ApplyObjectClear(ObjectData td)
{
if (!clearObjects)
return;
keywordBuilder.Clear();
keywordBuilder.Add("_RECONSTRUCTNORMAL");
var textureLayerWeights = filterSet.GetTextureWeights(td.terrain.terrainData.terrainLayers);
material.SetVectorArray("_TextureLayerWeights", textureLayerWeights);
material.SetTexture(_Heightmap, td.heightMap);
material.SetTexture(_Normalmap, td.normalMap);
material.SetTexture(_Curvemap, td.curveMap);
material.SetTexture(_Flowmap, td.flowMap);
material.SetTexture(_IndexMap, td.indexMap);
material.SetTexture(_WeightMap, td.weightMap);
filterSet.PrepareTransform(this.transform, td.terrain, material, keywordBuilder.keywords, GetTerrainScalingFactor(td.terrain));
keywordBuilder.Assign(material);
RenderTexture temp = RenderTexture.GetTemporary(td.clearMap.descriptor);
material.SetFloat("_LayerIndex", td.layerIndex);
temp.name = "ObjectClear";
Graphics.Blit(td.clearMap, temp, material);
RenderTexture.active = null;
RenderTexture.ReleaseTemporary(td.clearMap);
td.clearMap = temp;
td.layerIndex++;
}
public void ApplyObjectStamp(ObjectData vd, Dictionary<Terrain, List<ObjectJobHolder>> jobs, OcclusionData od)
{
if (!clearObjects)
return;
vd.layerIndex++;
}
public void ProcessObjectStamp(ObjectData vd, Dictionary<Terrain, List<ObjectJobHolder>> jobs, OcclusionData od)
{
}
#endif // MV Objects
}
}