editor/AdvancedMappingTools/Components/ManualParts.cs

Editor helper that builds a single hand-made part (cube, plane, cylinder, cone, wedge, sphere) from a MeshKit, parents it, and tags it with an AmtPart marked as manually created. Used so mapping tools can create props without a generator and leave them untouched on regeneration.

namespace AdvancedMappingTools;
public enum ManualShape
{
	Cube,
	Plane,
	Cylinder,
	Cone,
	Wedge,
	Sphere
}

/// <summary>
/// Objects made by hand. They work with no generator around them, and
/// regeneration never touches them, even when they sit inside a generated building.
/// </summary>
public static class ManualParts
{
	const int RoundSides = 16;

	public static GameObject Create( ManualShape shape, Vector3 size, Material material, GameObject parent, Transform world )
	{
		var kit = new MeshKit
		{
			Material = material
		};
		var half = size * 0.5f;
		switch ( shape )
		{
			case ManualShape.Plane:
				kit.FacingUp( -half.x, half.x, -half.y, half.y, 0.0f );
				break;
			case ManualShape.Cylinder:
				kit.Cylinder( Vector3.Zero, half.x, half.x, -half.z, half.z, RoundSides );
				break;
			case ManualShape.Cone:
				kit.Cylinder( Vector3.Zero, half.x, 0.0f, -half.z, half.z, RoundSides );
				break;
			case ManualShape.Wedge:
				kit.Profile( [new( -half.x, -half.z ), new( half.x, -half.z ), new( -half.x, half.z )], -half.y, half.y );
				break;
			case ManualShape.Sphere:
				var outline = new List<Vector2>();
				for ( var i = 0; i <= RoundSides / 2; i++ )
				{
					var angle = MathF.PI * (i / (float)(RoundSides / 2) - 0.5f);
					outline.Add( new Vector2( i == 0 || i == RoundSides / 2 ? 0.0f : MathF.Cos( angle ) * half.x, MathF.Sin( angle ) * half.z ) );
				}

				kit.Lathe( Vector3.Zero, outline, RoundSides );
				break;
			default:
				kit.Box( -half, half );
				break;
		}

		var go = parent.IsValid() ? new GameObject( parent, true, shape.ToString() ) : new GameObject( true, shape.ToString() );
		go.WorldTransform = world;
		var mesh = go.Components.Create<MeshComponent>( false );
		mesh.Mesh = kit.Finish();
		mesh.SmoothingAngle = 40.0f;
		mesh.Enabled = true;
		var part = go.Components.Create<AmtPart>();
		part.PartId = $"manual/{Guid.NewGuid():N}";
		part.Kind = $"Manual{shape}";
		part.Category = "manual";
		part.State = PartState.ManuallyCreated;
		part.Dimensions = size;
		part.GeneratedTransform = go.LocalTransform;
		part.GeneratedGeometry = PartHash.Geometry( mesh.Mesh );
		part.GeneratedMaterial = PartHash.Materials( mesh.Mesh );
		part.GeneratedFaceMaterials = PartHash.FaceMaterials( mesh.Mesh );
		return go;
	}
}