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;
}
}
}