Files
riversong-code-showcase/Source/Riversong/Tools/WaterFlowMapBaker.cs
2026-05-21 16:04:49 +02:00

91 lines
2.8 KiB
C#

using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Splines;
#if UNITY_EDITOR
using System.IO;
using UnityEditor;
#endif
namespace DanieleMarotta.RiversongCodeShowcase
{
[RequireComponent(typeof(SplineContainer))]
public class WaterFlowMapBaker : MonoBehaviour
{
#if UNITY_EDITOR
public int WorldSize = 100;
public int MapSize = 512;
public float InfluenceRadius = 10;
public Texture2D OutputTexture;
[Button(ButtonSizes.Large)]
[GUIColor("cyan")]
public void BakeFlowMap()
{
var splineContainer = GetComponent<SplineContainer>();
var texture = new Texture2D(MapSize, MapSize, TextureFormat.RGBA32, false, true)
{
wrapMode = TextureWrapMode.Clamp,
filterMode = FilterMode.Bilinear
};
for (var y = 0; y < MapSize; y++)
for (var x = 0; x < MapSize; x++)
{
var c = new Color(0.5f, 0.5f, 0, 0);
var uv = new Vector2((x + 0.5f) / MapSize, (y + 0.5f) / MapSize);
var world = new Vector3(uv.x * WorldSize, 0, uv.y * WorldSize);
var distance = SplineUtility.GetNearestPoint(splineContainer.Spline, world, out _, out var t);
if (distance <= InfluenceRadius)
{
var tangent = splineContainer.Spline.EvaluateTangent(t);
var direction = new Vector2(tangent.x, tangent.z);
if (direction.sqrMagnitude > 0.0001f) direction.Normalize();
var influence = Mathf.Clamp01(1 - distance / InfluenceRadius);
c.r = direction.x * 0.5f + 0.5f;
c.g = direction.y * 0.5f + 0.5f;
c.b = influence;
}
texture.SetPixel(x, y, c);
}
texture.Apply(false, false);
var textureDirty = false;
if (!OutputTexture)
{
var path = EditorUtility.SaveFilePanelInProject("Save Flow Map", "WaterFlowMap", "asset", string.Empty);
if (!string.IsNullOrEmpty(path))
{
texture.name = Path.GetFileNameWithoutExtension(path);
AssetDatabase.CreateAsset(texture, path);
OutputTexture = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
textureDirty = true;
}
}
else
{
texture.name = OutputTexture.name;
EditorUtility.CopySerialized(texture, OutputTexture);
textureDirty = true;
}
if (textureDirty)
{
EditorUtility.SetDirty(OutputTexture);
AssetDatabase.SaveAssets();
}
}
#endif
}
}