Terrain/Terraforming/TerraformMode.cs
using System;
using HC3.Terrain;
using Sandbox.Utility;
namespace HC3.Terraforming;
#nullable enable
public abstract class TerraformMode
{
private bool _isActive;
public virtual string Title => GetType().Name.ToTitleCase();
public virtual string Icon => "height";
public virtual string Description => "No description.";
public virtual int Order => 0;
public ITerraformBrush? Brush { get; protected set; }
public int Margin { get; protected set; }
protected Vector2 CursorGridPos { get; private set; }
public bool IsActive
{
get => _isActive;
set
{
if ( _isActive == value ) return;
if ( _isActive ) OnDeactivate();
_isActive = value;
if ( _isActive ) OnActivate();
}
}
public static IEnumerable<TerraformMode> GetAll()
{
return TypeLibrary.GetTypes<TerraformMode>()
.Where( x => !x.IsAbstract )
.Select( x =>
{
try
{
return x.Create<TerraformMode>();
}
catch
{
return null;
}
} )
.OfType<TerraformMode>()
.OrderBy( x => x.Order );
}
protected virtual void OnActivate()
{
}
protected virtual void OnDeactivate()
{
}
public void Update( Vector2 cursorGridPos )
{
CursorGridPos = cursorGridPos;
OnUpdate();
}
protected virtual void OnUpdate()
{
}
public void Apply( TileArraySlice original, TileArraySlice modified, TerraformContext context ) => OnApply( original, modified, context );
protected abstract void OnApply( TileArraySlice original, TileArraySlice modified, TerraformContext context );
}
public sealed record TerraformContext(
ParkTerrain Terrain,
RectInt TileRange,
Vector3 CursorGridPosition,
int Delta );
public interface ITerraformBrush
{
Vector2Int Size { get; }
float GetWeight( Vector2Int tileIndex );
}
public sealed class BoxBrush : ITerraformBrush
{
public Vector2Int Size { get; }
public BoxBrush( Vector2Int size )
{
Size = size;
}
public float GetWeight( Vector2Int tileIndex ) => 1f;
}
public sealed class RadialBrush : ITerraformBrush
{
public float Radius { get; }
public Vector2Int Size { get; }
public RadialBrush( float radius )
{
Radius = radius;
Size = (int)MathF.Ceiling( Radius * 2 );
}
public float GetWeight( Vector2Int tileIndex ) =>
1f - Easing.EaseIn( Math.Clamp( (tileIndex - Size / 2).Length / Radius, 0f, 1f ) );
}