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