Editor tool classes for the Advanced Mapping Tools addon. PropEditor is a shared base for primitive stamping tools that builds a preview mesh from a part generator and places each prop as a separate object. StreetPropEditor, FurnitureEditor, EquipmentEditor and BarricadeEditor bind it to the street, interior, industrial and defense generators.
namespace AdvancedMappingTools;
/// <summary>
/// Every click places one prop as an object of its own, made of independent parts.
/// </summary>
public abstract class PropEditor( PrimitiveTool tool ) : StampEditor( tool )
{
public override IReadOnlySet<string> UnusedOptions { get; } = new HashSet<string> { "Surface", "Trim", "Variation" };
protected abstract IPartGenerator Generator { get; }
public abstract PropSettings Props { get; }
public override object ExtraSettings => Props;
protected override bool PlacesObjects => true;
protected override void Stamp( MeshKit kit, Transform frame, Random random ) { }
void Prepare()
{
Props.MainMaterial = PartTool.Pick( Props.MainMaterial, SurfaceMaterial );
Props.MetalMaterial = PartTool.Pick( Props.MetalMaterial, TrimMaterial );
Props.DetailMaterial = PartTool.Pick( Props.DetailMaterial, TrimMaterial );
}
IEnumerable<Transform> Frames()
{
var random = new Random( Seed );
foreach ( var point in Points )
yield return new Transform( point.Position, Rotation.FromYaw( Yaw + ((float)random.NextDouble() - 0.5f) * RandomTurn * 2.0f ) );
}
protected override PolygonMesh BuildPreview()
{
Prepare();
var plan = Props is IAnchorAwareSettings { MountsEnabled: true } ? null : PartService.Plan( Generator, Props );
var result = new PolygonMesh();
foreach ( var frame in Frames() )
result.MergeMesh( (plan ?? PartService.Plan( Generator, Props, surface: SurfaceIntegration.Context( Props, SceneEditorSession.Active?.Scene, frame ) )).Flatten( frame ), Transform.Zero, out _, out _, out _ );
return result;
}
public override bool ChangesOtherSettings( string property ) => Props is IAnchorAwareSettings && property is "MountsEnabled" or "MountBolts" or "MountConnector";
public override void OnUpdate( SceneTrace trace )
{
base.OnUpdate( trace );
if ( Props is IAnchorAwareSettings { MountsEnabled: true, ShowMountDebug: true } aware )
SurfaceDebug.Draw( aware.MountOwner );
}
protected override void PlaceObjects()
{
Prepare();
foreach ( var frame in Frames() )
PartTool.Place( Generator, GeneratorRegistry.Load( Generator, GeneratorRegistry.Save( Props ) ), frame );
}
}
/// <summary>
/// Lamps, signs, benches, bins, wrecks and everything else along a street.
/// </summary>
[ToolCategory( "Street" )]
[Title( "Street Prop" ), Icon( "signpost" )]
public sealed class StreetPropEditor( PrimitiveTool tool ) : PropEditor( tool )
{
readonly StreetGenerator _generator = new();
public StreetSettings Settings { get; } = new();
protected override IPartGenerator Generator => _generator;
public override PropSettings Props => Settings;
}
/// <summary>
/// Tables, beds, shelves, kitchens and bathrooms.
/// </summary>
[ToolCategory( "Interior" )]
[Title( "Furniture" ), Icon( "chair" )]
public sealed class FurnitureEditor( PrimitiveTool tool ) : PropEditor( tool )
{
readonly InteriorGenerator _generator = new();
public InteriorSettings Settings { get; } = new();
protected override IPartGenerator Generator => _generator;
public override PropSettings Props => Settings;
}
/// <summary>
/// Barrels, pallets, generators, tanks, scaffolds and roof equipment.
/// </summary>
[ToolCategory( "Industrial" )]
[Title( "Equipment" ), Icon( "precision_manufacturing" )]
public sealed class EquipmentEditor( PrimitiveTool tool ) : PropEditor( tool )
{
readonly IndustrialGenerator _generator = new();
public IndustrialSettings Settings { get; } = new();
protected override IPartGenerator Generator => _generator;
public override PropSettings Props => Settings;
}
/// <summary>
/// Barricades, boarded windows, concrete blocks and guard booths.
/// </summary>
[ToolCategory( "Defense" )]
[Title( "Barricade" ), Icon( "fence" )]
public sealed class BarricadeEditor( PrimitiveTool tool ) : PropEditor( tool )
{
readonly DefenseGenerator _generator = new();
public DefenseSettings Settings { get; } = new();
protected override IPartGenerator Generator => _generator;
public override PropSettings Props => Settings;
}