Code/TerrainSetup.cs
// Copyright (c) 2026 SubZero Studios LLC. All rights reserved.

using System;
using Sandbox;

namespace SubZero.SubTerrain;

/// <summary>
/// Re-enable Terrain after Storage is assigned, and optionally centre / clipmap.
/// Origin and lookdev clipmap are opt-in so island maps keep their authored pose.
/// </summary>
[Title( "Terrain Setup" )]
[Category( "SubTerrain" )]
[Icon( "terrain" )]
public sealed class TerrainSetup : Component, Component.ExecuteInEditor
{
	public const int LookdevClipMapExtent = 256;
	public const int LookdevClipMapLevels = 5;

	[Property] public bool EnableOnStart { get; set; } = true;

	[Property, Title( "Center On Origin" )]
	public bool CenterOnOrigin { get; set; }

	[Property, Title( "Apply Lookdev Clipmap" )]
	public bool ApplyLookdevClipmap { get; set; }

	protected override void OnEnabled()
	{
		if ( EnableOnStart )
			Apply();
	}

	protected override void OnStart()
	{
		if ( EnableOnStart )
			Apply();
	}

	[Button( "Apply Setup Now" )]
	public void Apply()
	{
		foreach ( var terrain in Components.GetAll<Terrain>( FindMode.EverythingInSelfAndDescendants ) )
		{
			if ( terrain == null || !terrain.IsValid() )
				continue;
			if ( terrain.Storage == null )
				continue;

			if ( ApplyLookdevClipmap )
			{
				terrain.ClipMapLodExtentTexels = LookdevClipMapExtent;
				terrain.ClipMapLodLevels = LookdevClipMapLevels;
				terrain.SubdivisionFactor = 1;
				terrain.RenderType = ModelRenderer.ShadowRenderType.On;
			}

			if ( CenterOnOrigin )
			{
				var size = terrain.TerrainSize > 1f ? terrain.TerrainSize : 1f;
				var half = size * 0.5f;
				GameObject.WorldPosition = new Vector3( -half, -half, GameObject.WorldPosition.z );
			}

			if ( !terrain.Enabled )
				terrain.Enabled = true;
		}
	}
}