Code/Water/WaterExclusionVolume.cs
using Sandbox;
using Sandbox.Volumes;

namespace RedSnail.WaterTool;

/// <summary>
/// Suppresses water surface rendering inside a volume. Has no effect on the physical water hull
/// so buoyancy and swimming still work within the excluded area.
/// Intended for enclosed spaces that sit in water, such as the interior of a boat or submarine.
/// </summary>
[Title("Water Exclusion Volume")]
[Category("Volumes")]
[Icon("water")]
public sealed class WaterExclusionVolume : VolumeComponent, Component.ExecuteInEditor
{
	private bool m_CalledOnValidate;

	protected override void OnEnabled()
	{
		WaterManager.Get(Scene)?.Register(this);
	}

	protected override void OnValidate()
	{
		m_CalledOnValidate = true;
	}

	protected override void OnDisabled()
	{
		// We don't want to unregister if OnValidate() was called — that means we just saved the scene.
		if (m_CalledOnValidate)
		{
			m_CalledOnValidate = false;
			return;
		}

		WaterManager.Get(Scene)?.Unregister(this);
	}

	protected override void DrawGizmos()
	{
		base.DrawGizmos();

		/*
		SceneVolume sceneVolume = SceneVolume;
		Gizmo.Draw.IgnoreDepth = false;
		Gizmo.Draw.Color = Gizmo.Colors.Blue.WithAlpha(0.8f);
		Gizmo.Draw.SolidBox(sceneVolume.Box);
		Gizmo.Draw.IgnoreDepth = true;
		Gizmo.Draw.Color = global::Color.White.WithAlpha(0.05f);
		Gizmo.Draw.SolidBox(sceneVolume.Box);
		
		SceneVolume = sceneVolume;
		*/
	}

	protected override void OnUpdate()
	{
		// DebugOverlay.Box(GetWorldBounds(), Color.Cyan, overlay: true);
	}

	public (Vector3 Center, Vector3 Forward, Vector3 Up, Vector3 HalfExtents) GetWorldOBB()
	{
		BBox local = SceneVolume.GetBounds();
		Vector3 center = WorldTransform.PointToWorld(local.Center);
		Vector3 halfExtents = local.Size * 0.5f;

		return (center, WorldRotation.Forward, WorldTransform.Up, halfExtents);
	}

	public void SetLocalBounds(BBox localBounds)
	{
		var sv = SceneVolume;
		sv.Box = localBounds;
		SceneVolume = sv;
	}
}