Editor/SubTerrainBrushSize.cs
// Copyright (c) 2026 SubZero Studios LLC. All rights reserved.
using System;
namespace Editor.SubTerrain;
/// <summary>
/// Brush Size limits and piecewise track mapping.
/// Fine band stays precise; larger sizes take less track and bigger nudges.
/// </summary>
public static class SubTerrainBrushSize
{
public const int Min = 8;
public const int FineMax = 3500;
public const int MidMax = 18000;
public const int Max = 35000;
public const int FineStep = 50;
public const int MidStep = 500;
public const int CoarseStep = 1000;
/// <summary>Fraction of the slider track for the fine band (8..FineMax).</summary>
public const float FineTrack = 0.70f;
/// <summary>End of mid band on the track (FineMax..MidMax). Coarse is the rest to 1.</summary>
public const float MidTrack = 0.90f;
public static int Clamp( int size ) => Math.Clamp( size, Min, Max );
public static int StepFor( int size )
{
if ( size < FineMax )
return FineStep;
if ( size < MidMax )
return MidStep;
return CoarseStep;
}
public static int Nudge( int size, int direction )
{
if ( direction == 0 )
return Clamp( size );
size = Clamp( size );
int step = StepFor( size );
return Clamp( size + direction * step );
}
public static int SizeFromTrack( float t01 )
{
t01 = Math.Clamp( t01, 0f, 1f );
int raw;
if ( t01 <= FineTrack )
{
float u = FineTrack <= 0f ? 0f : t01 / FineTrack;
raw = (int)MathF.Round( Lerp( Min, FineMax, u ) );
}
else if ( t01 <= MidTrack )
{
float u = (t01 - FineTrack) / (MidTrack - FineTrack);
raw = (int)MathF.Round( Lerp( FineMax, MidMax, u ) );
}
else
{
float u = (t01 - MidTrack) / (1f - MidTrack);
raw = (int)MathF.Round( Lerp( MidMax, Max, u ) );
}
return Snap( raw );
}
public static float TrackFromSize( int size )
{
size = Clamp( size );
if ( size <= FineMax )
{
float u = (size - Min) / (float)(FineMax - Min);
return u * FineTrack;
}
if ( size <= MidMax )
{
float u = (size - FineMax) / (float)(MidMax - FineMax);
return FineTrack + u * (MidTrack - FineTrack);
}
{
float u = (size - MidMax) / (float)(Max - MidMax);
return MidTrack + u * (1f - MidTrack);
}
}
public static int Snap( int size )
{
size = Clamp( size );
int step = StepFor( size );
int snapped = (int)MathF.Round( size / (float)step ) * step;
return Clamp( snapped );
}
static float Lerp( float a, float b, float t ) => a + (b - a) * Math.Clamp( t, 0f, 1f );
}