Editor/SubTerrainBrushSettings.cs
// Copyright (c) 2026 SubZero Studios LLC. All rights reserved.
using System;
using System.Collections.Generic;
using Sandbox;
namespace Editor.SubTerrain;
/// <summary>
/// Brush settings for SubTerrain. Higher size cap than the built-in terrain tool.
/// Each sculpt/paint mode keeps its own Size and Opacity.
/// </summary>
public class SubTerrainBrushSettings
{
/// <summary>
/// World-unit brush radius. UI is piecewise (fine under 3500). Clamp with <see cref="SubTerrainBrushSize"/>.
/// </summary>
[Property, Hide]
public int Size { get; set; } = 1000;
[Property, Range( 0.0f, 1.0f ), Step( 0.01f ), WideMode]
public float Opacity { get; set; } = 0.5f;
/// <summary>
/// Raise / Lower only. How fast height accumulates while painting (1 = slow, 100 = fastest).
/// Opacity stays the brush soft strength. Speed scales hold rate and height per stamp.
/// </summary>
[Property, Title( "Speed" ), Range( 1, 100 ), Step( 1 ), WideMode]
public int Speed { get; set; } = 50;
[Property, Range( 0, 360 ), Step( 1 ), WideMode]
public float Rotation { get; set; } = 0;
[Property, Title( "Random Rotation" )]
public bool RandomRotation { get; set; } = false;
[Property, Title( "Show Grid" )]
public bool ShowGridPreview { get; set; } = true;
/// <summary>
/// Absolute world height (Z) used by Set Height mode.
/// </summary>
[Property, WideMode]
public float TargetHeight { get; set; } = 0.0f;
/// <summary>
/// Deck width of the Bridge tool, in world units.
/// </summary>
[Property, Range( 32, 8000 ), Step( 1 ), WideMode]
public int BridgeWidth { get; set; } = 512;
/// <summary>
/// Fraction of the bridge half-width that blends down into the surrounding terrain.
/// </summary>
[Property, Range( 0.0f, 0.95f ), Step( 0.01f ), WideMode]
public float BridgeEdgeFalloff { get; set; } = 0.35f;
/// <summary>
/// Only raise terrain up to the deck, never cut down into ground that is already higher.
/// </summary>
[Property, WideMode]
public bool BridgeRaiseOnly { get; set; } = true;
}
/// <summary>
/// Size and Opacity persist per SubTerrain sub-tool for the editor session.
/// </summary>
internal static class SubTerrainBrushStore
{
static readonly Dictionary<string, SubTerrainBrushSettings> ByMode = new( StringComparer.Ordinal );
public static SubTerrainBrushSettings ForMode( string key )
{
if ( string.IsNullOrEmpty( key ) )
key = nameof( SubRaiseLowerTool );
if ( !ByMode.TryGetValue( key, out var settings ) )
{
settings = new SubTerrainBrushSettings();
ByMode[key] = settings;
}
return settings;
}
}