Effects/CloudShadows.cs
using System;

namespace HC3;

[Icon( "☁️" )]
class CloudShadows : Component, Component.ExecuteInEditor
{
	Texture cloudTexture;

	/// <summary>
	/// 0= Sunny, 1=Overcast
	/// </summary>
	[Property, Range( 0.0f, 1.0f )] float CloudCoverage = 0.4f;
	/// <summary>
	/// How dark cloud shadows are
	/// </summary>
	[Property, Range( 0.0f, 1.0f )] float CloudDensity = 0.7f;

	/// <summary>
	/// How much of the sky is covered by clouds when it rains
	/// </summary>
	[Property, Range( 0.0f, 1.0f )] float RainCoverage = 0.9f;

	float RainAmount = 0.0f;

	protected override void OnEnabled()
	{
		base.OnEnabled();
		var perlin = new PerlinVolumeTexture( 256, 256, 4 );
		perlin.Scale = 4.0f;
		cloudTexture = perlin.Generate();
		Scene.RenderAttributes.Set( "CloudTextureIndex", cloudTexture.Index );

	}

	protected override void OnDisabled()
	{
		base.OnDisabled();
		cloudTexture?.Dispose();
		Scene.RenderAttributes.Set( "CloudTextureIndex", -1 );
	}

	protected override void OnUpdate()
	{
		base.OnUpdate();
		if ( cloudTexture == null )
			return;

		Scene.RenderAttributes.Set( "CloudCoverage", CloudCoverage.LerpTo( RainCoverage, RainAmount ) );
		Scene.RenderAttributes.Set( "CloudDensity", CloudDensity );

		var sunDir = Scene.GetAllComponents<DirectionalLight>().FirstOrDefault().WorldRotation.Forward;
		Scene.RenderAttributes.Set( "SunDirection", sunDir );

		bool rainActive = Scene.GetAllComponents<RainEvent>().Any();
		RainAmount = RainAmount.LerpTo( rainActive ? 1.0f : 0.0f, Time.Delta * 0.5f );
		Scene.RenderAttributes.Set( "RainAmount", RainAmount );
	}
};