Code/Waves/WaterDefinition.cs

A GameResource asset defining parameters for water wave profiles. It stores settings for short detail waves and long swell (intensity, speed, scale, direction, octaves, lacunarity, persistence, steepness), provides two static fallback presets, applies those values to a RenderAttributes object, and supplies an icon for the editor.

using Sandbox;

namespace RedSnail.WaterTool2;

/// <summary>
/// A wave profile: two Gerstner wave sums, short detail waves and long swell, each with its own strength, speed, size,
/// direction and octaves. A water network is built on one profile; each river and lake scales it with its own
/// wave strength, so connected water always shares one continuous wave field.
/// </summary>
[AssetType(Name = "Water Definition", Extension = "wtdef2", Category = "Water Tool 2")]
public sealed class WaterDefinition : GameResource
{
	[Property, Group("Detail")] public float WavesIntensity { get; set; } = 4.0f;
	[Property, Group("Detail"), Range(0, 5)] public float WavesSpeed { get; set; } = 0.3f;
	[Property, Group("Detail")] public float WavesScale { get; set; } = 0.05f;
	[Property, Group("Detail")] public Vector2 WavesDirection { get; set; } = new Vector2(1, 0.5f);
	[Property, Group("Detail"), Range(1, 5)] public int WavesOctaves { get; set; } = 3;
	[Property, Group("Detail")] public float WavesLacunarity { get; set; } = 2.0f;
	[Property, Group("Detail"), Range(0, 1)] public float WavesPersistence { get; set; } = 0.5f;
	[Property, Group("Detail"), Range(0, 1)] public float WavesSteepness { get; set; } = 0.5f;

	[Property, Group("Swell")] public float SwellIntensity { get; set; } = 15.0f;
	[Property, Group("Swell"), Range(0, 500)] public float SwellSpeed { get; set; } = 100.0f;
	[Property, Group("Swell")] public float SwellScale { get; set; } = 0.002f;
	[Property, Group("Swell")] public Vector2 SwellDirection { get; set; } = new Vector2(0.7f, 0.3f);
	[Property, Group("Swell"), Range(1, 4)] public int SwellOctaves { get; set; } = 2;
	[Property, Group("Swell")] public float SwellLacunarity { get; set; } = 1.8f;
	[Property, Group("Swell"), Range(0, 1)] public float SwellPersistence { get; set; } = 0.6f;
	[Property, Group("Swell"), Range(0, 1)] public float SwellSteepness { get; set; } = 0.3f;



	/// <summary>
	/// Used when a network has no profile of its own: gentle lake waves.
	/// </summary>
	public static WaterDefinition Fallback { get; } = new()
	{
		WavesIntensity = 0.4f,
		WavesSpeed = 5.0f,
		WavesScale = 0.1f,
		WavesDirection = new Vector2(1.0f, 0.5f),
		WavesOctaves = 3,
		WavesLacunarity = 2.0f,
		WavesPersistence = 1.0f,
		WavesSteepness = 0.5f,
		SwellIntensity = 5.0f,
		SwellSpeed = 80.0f,
		SwellScale = 0.015f,
		SwellDirection = new Vector2(0.7f, 0.3f),
		SwellOctaves = 2,
		SwellLacunarity = 1.8f,
		SwellPersistence = 0.6f,
		SwellSteepness = 0.3f
	};



	/// <summary>
	/// Used when the sea has no profile of its own: long ocean swell under small chop.
	/// </summary>
	public static WaterDefinition SeaFallback { get; } = new()
	{
		WavesIntensity = 1.0f,
		WavesSpeed = 50.0f,
		WavesScale = 0.01f,
		WavesDirection = new Vector2(1.0f, 0.5f),
		WavesOctaves = 3,
		WavesLacunarity = 2.0f,
		WavesPersistence = 0.5f,
		WavesSteepness = 0.5f,
		SwellIntensity = 50.0f,
		SwellSpeed = 400.0f,
		SwellScale = 0.002f,
		SwellDirection = new Vector2(0.7f, 0.3f),
		SwellOctaves = 3,
		SwellLacunarity = 1.8f,
		SwellPersistence = 0.6f,
		SwellSteepness = 0.3f
	};



	/// <summary>
	/// Hands the profile to the water shader. The prefix names which wave set it fills: none for the rivers and lakes,
	/// "Sea" for the sea.
	/// </summary>
	public void ApplyTo(RenderAttributes _Attributes, string _Prefix = "")
	{
		_Attributes.Set(_Prefix + "WavesIntensity", WavesIntensity);
		_Attributes.Set(_Prefix + "WavesSpeed", WavesSpeed);
		_Attributes.Set(_Prefix + "WavesScale", WavesScale);
		_Attributes.Set(_Prefix + "WavesDirection", WavesDirection);
		_Attributes.Set(_Prefix + "WavesOctaves", WavesOctaves);
		_Attributes.Set(_Prefix + "WavesLacunarity", WavesLacunarity);
		_Attributes.Set(_Prefix + "WavesPersistence", WavesPersistence);
		_Attributes.Set(_Prefix + "WavesSteepness", WavesSteepness);

		_Attributes.Set(_Prefix + "SwellIntensity", SwellIntensity);
		_Attributes.Set(_Prefix + "SwellSpeed", SwellSpeed);
		_Attributes.Set(_Prefix + "SwellScale", SwellScale);
		_Attributes.Set(_Prefix + "SwellDirection", SwellDirection);
		_Attributes.Set(_Prefix + "SwellOctaves", SwellOctaves);
		_Attributes.Set(_Prefix + "SwellLacunarity", SwellLacunarity);
		_Attributes.Set(_Prefix + "SwellPersistence", SwellPersistence);
		_Attributes.Set(_Prefix + "SwellSteepness", SwellSteepness);
	}



	protected override Bitmap CreateAssetTypeIcon(int _Width, int _Height)
	{
		return CreateSimpleAssetTypeIcon("water", _Width, _Height, "#4287f5", "white");
	}
}